pax_global_header00006660000000000000000000000064136056732020014516gustar00rootroot0000000000000052 comment=286486fffca2a98745a62d92f836746ff6bebf9c pvr.mythtv-5.10.15-Leia/000077500000000000000000000000001360567320200147005ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/.gitignore000066400000000000000000000007631360567320200166760ustar00rootroot00000000000000# build artifacts build/ debian/changelog debian/files debian/kodi-pvr-mythtv-dbg.debhelper.log debian/kodi-pvr-mythtv-dbg.substvars debian/kodi-pvr-mythtv-dbg/ debian/kodi-pvr-mythtv.debhelper.log debian/kodi-pvr-mythtv.postinst.debhelper debian/kodi-pvr-mythtv.postrm.debhelper debian/kodi-pvr-mythtv.substvars debian/kodi-pvr-mythtv/ debian/tmp/ obj-x86_64-linux-gnu/ pvr.mythtv/addon.xml # clion .idea/ # Eclipse/CDT .cproject .project .settings/ # others nbproject cppmyth_config.h *.swp *~ pvr.mythtv-5.10.15-Leia/.travis.yml000066400000000000000000000023221360567320200170100ustar00rootroot00000000000000language: cpp # # Define the build matrix # # Travis defaults to building on Ubuntu Precise when building on # Linux. We need Trusty in order to get up to date versions of # cmake and g++. # env: global: - app_id=pvr.mythtv matrix: include: - os: linux dist: xenial sudo: required compiler: gcc - os: linux dist: xenial sudo: required compiler: clang - os: osx osx_image: xcode9 # # Some of the OS X images don't have cmake, contrary to what people # on the Internet say # before_install: - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then which cmake || brew update ; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then which cmake || brew install cmake ; fi # # The addon source is automatically checked out in $TRAVIS_BUILD_DIR, # we'll put the Kodi source on the same level # before_script: - cd $TRAVIS_BUILD_DIR/.. - git clone --branch Leia --depth=1 https://github.com/xbmc/xbmc.git - cd ${app_id} && mkdir build && cd build - cmake -DADDONS_TO_BUILD=${app_id} -DADDON_SRC_PREFIX=$TRAVIS_BUILD_DIR/.. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=$TRAVIS_BUILD_DIR/../xbmc/addons -DPACKAGE_ZIP=1 $TRAVIS_BUILD_DIR/../xbmc/cmake/addons script: make pvr.mythtv-5.10.15-Leia/CMakeLists.txt000066400000000000000000000023141360567320200174400ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.5) project(pvr.mythtv) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(Kodi REQUIRED) include_directories(${KODI_INCLUDE_DIR}/.. # Hack way with "/..", need bigger Kodi cmake rework to match right include ways ${PROJECT_SOURCE_DIR}/lib/cppmyth/src) add_definitions(-DUSE_DEMUX -D__STDC_FORMAT_MACROS) if(NOT WIN32) add_options(ALL_LANGUAGES ALL_BUILDS "-fPIC -Wall") endif() file (GLOB MYTHTV_SOURCES src/demuxer/*.cpp src/cppmyth/*.cpp src/*.cpp) file (GLOB MYTHTV_HEADERS src/demuxer/*.h src/cppmyth/*.h src/*.h) add_subdirectory(lib/cppmyth) set(DEPLIBS cppmyth) if(WIN32) list(APPEND DEPLIBS ws2_32) else() list(APPEND DEPLIBS m) endif() if(NOT WIN32 AND (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)) if(HAS_BUILTIN_SYNC_ADD_AND_FETCH) add_options(ALL_LANGUAGES ALL_BUILDS "-DHAS_BUILTIN_SYNC_ADD_AND_FETCH") endif() if(HAS_BUILTIN_SYNC_SUB_AND_FETCH) add_options(ALL_LANGUAGES ALL_BUILDS "-DHAS_BUILTIN_SYNC_SUB_AND_FETCH") endif() endif() set(BUILD_SHARED_LIBS ON) build_addon(pvr.mythtv MYTHTV DEPLIBS) include(CPack) pvr.mythtv-5.10.15-Leia/Jenkinsfile000066400000000000000000000000351360567320200170620ustar00rootroot00000000000000buildPlugin(version: "Leia") pvr.mythtv-5.10.15-Leia/README.md000066400000000000000000000025231360567320200161610ustar00rootroot00000000000000[![Build Status](https://travis-ci.org/janbar/pvr.mythtv.svg?branch=master)](https://travis-ci.org/janbar/pvr.mythtv) [![Coverity Scan Build Status](https://scan.coverity.com/projects/3115/badge.svg)](https://scan.coverity.com/projects/3115) # MythTV PVR MythTV PVR client addon for [Kodi](http://kodi.tv) ## Build instructions When building the addon you have to use the correct branch depending on which version of Kodi you're building against. For example, if you're building the `master` branch of Kodi you should checkout the `master` branch of this repository. Also make sure you follow this README from the branch in question. ### Linux git clone --branch Leia --depth=1 https://github.com/xbmc/xbmc.git git clone --branch Leia https://github.com/janbar/pvr.mythtv.git cd pvr.mythtv && mkdir build && cd build cmake -DADDONS_TO_BUILD=pvr.mythtv -DADDON_SRC_PREFIX=../.. -DCMAKE_BUILD_TYPE=Debug \ -DCMAKE_INSTALL_PREFIX=../../xbmc/addons -DPACKAGE_ZIP=ON ../../xbmc/cmake/addons make The addon files will be placed in `../../xbmc/kodi-build/addons` so if you build Kodi from source and run it directly the addon will be available as a system addon. ##### Useful links * [Kodi's PVR user support](http://forum.kodi.tv/forumdisplay.php?fid=170) * [Kodi's PVR development support](http://forum.kodi.tv/forumdisplay.php?fid=136) pvr.mythtv-5.10.15-Leia/debian/000077500000000000000000000000001360567320200161225ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/debian/changelog.in000066400000000000000000000002641360567320200204030ustar00rootroot00000000000000kodi-pvr-mythtv (#PACKAGEVERSION#-#TAGREV#~#DIST#) #DIST#; urgency=low [ kodi ] * autogenerated dummy changelog -- Nobody Sat, 01 Jun 2013 00:59:22 +0200 pvr.mythtv-5.10.15-Leia/debian/compat000066400000000000000000000000021360567320200173200ustar00rootroot000000000000009 pvr.mythtv-5.10.15-Leia/debian/control000066400000000000000000000011131360567320200175210ustar00rootroot00000000000000Source: kodi-pvr-mythtv Priority: extra Maintainer: janbar Build-Depends: debhelper (>= 9.0.0), cmake, kodi-addon-dev, zlib1g-dev Standards-Version: 3.9.4 Section: libs Homepage: http://kodi.tv Package: kodi-pvr-mythtv Section: libs Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: MythTV PVR for Kodi MythTV PVR for Kodi Package: kodi-pvr-mythtv-dbg Section: libs Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: debug symbols for MythTV PVR for Kodi debug symbols for MythTV PVR for Kodi pvr.mythtv-5.10.15-Leia/debian/copyright000066400000000000000000000077761360567320200200760ustar00rootroot00000000000000Format: http://dep.debian.net/deps/dep5 Upstream-Name: pvr.mythtv Source: https://github.com/janbar/pvr.mythtv Files: * Copyright: 2012-2015 Jean-Luc Barriere 2012-2013 Christian Fetzer 2005-2013 Team XBMC License: GPL-2+ This package is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. . This package 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 . On Debian systems, the complete text of the GNU General Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". Files: lib/platform/* Copyright: 2011-2015 Pulse-Eight License: dual-licensed This program is dual-licensed; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. . This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. . You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . Alternatively, you can license this library under a commercial license, please contact Pulse-Eight Licensing for more information. . For more information contact: Pulse-Eight Licensing http://www.pulse-eight.com/ http://www.pulse-eight.net/ Files: lib/cppmyth/src/private/sajson.h Copyright: 2012, 2013, 2014 Chad Austin 2015 Jean-Luc Barriere License: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: . The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. . THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Files: debian/* Copyright: 2015 Jean-Luc Barriere 2015 wsnipex License: GPL-2+ This package is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. . This package 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 . On Debian systems, the complete text of the GNU General Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". pvr.mythtv-5.10.15-Leia/debian/kodi-pvr-mythtv.install000066400000000000000000000000261360567320200225740ustar00rootroot00000000000000usr/lib/* usr/share/* pvr.mythtv-5.10.15-Leia/debian/rules000077500000000000000000000013151360567320200172020ustar00rootroot00000000000000#!/usr/bin/make -f # -*- makefile -*- # Sample debian/rules that uses debhelper. # This file was originally written by Joey Hess and Craig Small. # As a special exception, when this file is copied by dh-make into a # dh-make output file, you may use that output file without restriction. # This special exception was added by Craig Small in version 0.37 of dh-make. # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 %: dh $@ override_dh_auto_configure: # USE_LTO breaks build dh_auto_configure -- -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=1 override_dh_strip: dh_strip -pkodi-pvr-mythtv --dbg-package=kodi-pvr-mythtv-dbg override_dh_installdocs: dh_installdocs --link-doc=kodi-pvr-mythtv pvr.mythtv-5.10.15-Leia/debian/source/000077500000000000000000000000001360567320200174225ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/debian/source/format000066400000000000000000000000141360567320200206300ustar00rootroot000000000000003.0 (quilt) pvr.mythtv-5.10.15-Leia/depends/000077500000000000000000000000001360567320200163225ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/depends/common/000077500000000000000000000000001360567320200176125ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/depends/common/zlib/000077500000000000000000000000001360567320200205525ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/depends/common/zlib/01-build-static.patch000066400000000000000000000027411360567320200244010ustar00rootroot00000000000000--- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -183,10 +183,11 @@ set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj) endif(MINGW) -add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) -add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) -set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL) -set_target_properties(zlib PROPERTIES SOVERSION 1) +add_library(zlib ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) +if(BUILD_SHARED_LIBS) + set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL) + set_target_properties(zlib PROPERTIES SOVERSION 1) +endif() if(NOT CYGWIN) # This property causes shared libraries on Linux to have the full version @@ -201,7 +202,7 @@ if(UNIX) # On unix-like platforms the library is almost always called libz - set_target_properties(zlib zlibstatic PROPERTIES OUTPUT_NAME z) + set_target_properties(zlib PROPERTIES OUTPUT_NAME z) if(NOT APPLE) set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib.map\"") endif() @@ -211,7 +212,7 @@ endif() if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL ) - install(TARGETS zlib zlibstatic + install(TARGETS zlib RUNTIME DESTINATION "${INSTALL_BIN_DIR}" ARCHIVE DESTINATION "${INSTALL_LIB_DIR}" LIBRARY DESTINATION "${INSTALL_LIB_DIR}" ) pvr.mythtv-5.10.15-Leia/depends/common/zlib/zlib.txt000066400000000000000000000001021360567320200222440ustar00rootroot00000000000000zlib http://mirrors.kodi.tv/build-deps/sources/zlib-1.2.11.tar.gz pvr.mythtv-5.10.15-Leia/docs/000077500000000000000000000000001360567320200156305ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/docs/doxygen-dev.cfg000066400000000000000000002353651360567320200205600ustar00rootroot00000000000000# Doxyfile 1.8.4 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed # in front of the TAG it is preceding . # All text after a hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" "). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or sequence of words) that should # identify the project. Note that if you do not use Doxywizard you need # to put quotes around the project name if it contains spaces. PROJECT_NAME = "PVR.MythTV" # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer # a quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = "MythTV PVR addon for Kodi" # With the PROJECT_LOGO tag one can specify an logo or icon that is # included in the documentation. The maximum height of the logo should not # exceed 55 pixels and the maximum width should not exceed 200 pixels. # Doxygen will copy the logo to the output directory. PROJECT_LOGO = logo.png # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = doxygen-dev-docs # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English # messages), Korean, Korean-en, Latvian, Lithuanian, Norwegian, Macedonian, # Persian, Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, # Slovak, Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. Note that you specify absolute paths here, but also # relative paths, which will be relative from the directory where doxygen is # started. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful if your file system # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding # "class=itcl::class" will allow you to use the command class in the # itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, # and language is one of the parsers supported by doxygen: IDL, Java, # Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, # C++. For instance to make doxygen treat .inc files as Fortran files (default # is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note # that for custom extensions you also need to set FILE_PATTERNS otherwise the # files are not read by doxygen. EXTENSION_MAPPING = # If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all # comments according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you # can mix doxygen, HTML, and XML commands with Markdown formatting. # Disable only in case of backward compatibilities issues. MARKDOWN_SUPPORT = YES # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by by putting a % sign in front of the word # or globally by setting AUTOLINK_SUPPORT to NO. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also makes the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = YES # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES (the # default) will make doxygen replace the get and set methods by a property in # the documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and # unions are shown inside the group in which they are included (e.g. using # @ingroup) instead of on a separate page (for HTML and Man pages) or # section (for LaTeX and RTF). INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and # unions with only public data fields or simple typedef fields will be shown # inline in the documentation of the scope in which they are defined (i.e. file, # namespace, or group documentation), provided this scope is documented. If set # to NO (the default), structs, classes, and unions are shown on a separate # page (for HTML and Man pages) or section (for LaTeX and RTF). INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can # be an expensive process and often the same symbol appear multiple times in # the code, doxygen keeps a cache of pre-resolved symbols. If the cache is too # small doxygen will become slower. If the cache is too large, memory is wasted. # The cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid # range is 0..9, the default is 0, corresponding to a cache size of 2^16 = 65536 # symbols. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = YES # If the EXTRACT_PACKAGE tag is set to YES all members with package or internal # scope will be included in the documentation. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespaces are hidden. EXTRACT_ANON_NSPACES = YES # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen # will list include files with double quotes in the documentation # rather than with sharp brackets. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen # will sort the (brief and detailed) documentation of class members so that # constructors and destructors are listed first. If set to NO (the default) # the constructors will appear in the respective orders defined by # SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. # This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO # and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to # do proper type resolution of all parameters of a function it will reject a # match between the prototype and the implementation of a member function even # if there is only one candidate or it is obvious which candidate to choose # by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen # will still accept a match between prototype and implementation in such cases. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if section-label ... \endif # and \cond section-label ... \endcond blocks. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or macro consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and macros in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. # This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. # You can optionally specify a file name after the option, if omitted # DoxygenLayout.xml will be used as the name of the layout file. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files # containing the references data. This must be a list of .bib files. The # .bib extension is automatically appended if omitted. Using this command # requires the bibtex tool to be installed. See also # http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style # of the bibliography can be controlled using LATEX_BIB_STYLE. To use this # feature you need bibtex and perl available in the search path. Do not use # file names with spaces, bibtex cannot handle them. CITE_BIB_FILES = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_NO_PARAMDOC option can be enabled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = ../src # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh # *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py # *.f90 *.f *.for *.vhd *.vhdl FILE_PATTERNS = *.c *.cpp *.h # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. # If FILTER_PATTERNS is specified, this tag will be ignored. # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. # Doxygen will compare the file name with each pattern and apply the # filter if there is a match. # The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty or if # non of the patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) # and it is also possible to disable source filtering for a specific pattern # using *.ext= (so without naming a filter). This option only has effect when # FILTER_SOURCE_FILES is enabled. FILTER_SOURCE_PATTERNS = # If the USE_MD_FILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want reuse the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C, C++ and Fortran comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. # Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = YES # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. Note that when using a custom header you are responsible # for the proper inclusion of any scripts and style sheets that doxygen # needs, which is dependent on the configuration options used. # It is advised to generate a default header using "doxygen -w html # header.html footer.html stylesheet.css YourConfigFile" and then modify # that header. Note that the header is subject to change so you typically # have to redo this when upgrading to a newer version of doxygen or when # changing the value of configuration settings such as GENERATE_TREEVIEW! HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If left blank doxygen will # generate a default style sheet. Note that it is recommended to use # HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this # tag will in the future become obsolete. HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify an additional # user-defined cascading style sheet that is included after the standard # style sheets created by doxygen. Using this option one can overrule # certain style aspects. This is preferred over using HTML_STYLESHEET # since it does not replace the standard style sheet and is therefor more # robust against future updates. Doxygen will copy the style sheet file to # the output directory. HTML_EXTRA_STYLESHEET = extradoxygen.css # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that # the files will be copied as-is; there are no commands or markers available. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. # Doxygen will adjust the colors in the style sheet and background images # according to this color. Hue is specified as an angle on a colorwheel, # see http://en.wikipedia.org/wiki/Hue for more information. # For instance the value 0 represents red, 60 is yellow, 120 is green, # 180 is cyan, 240 is blue, 300 purple, and 360 is red again. # The allowed range is 0 to 359. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of # the colors in the HTML output. For a value of 0 the output will use # grayscales only. A value of 255 will produce the most vivid colors. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to # the luminance component of the colors in the HTML output. Values below # 100 gradually make the output lighter, whereas values above 100 make # the output darker. The value divided by 100 is the actual gamma applied, # so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, # and 100 does not change the gamma. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting # this to NO can help when comparing the output of multiple runs. HTML_TIMESTAMP = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. HTML_DYNAMIC_SECTIONS = NO # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of # entries shown in the various tree structured indices initially; the user # can expand and collapse entries dynamically later on. Doxygen will expand # the tree to such a level that at most the specified number of entries are # visible (unless a fully collapsed tree already exceeds this amount). # So setting the number of entries 1 will produce a full collapsed tree by # default. 0 is a special value representing an infinite number of entries # and will result in a full expanded tree by default. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely # identify the documentation publisher. This should be a reverse domain-name # style string, e.g. com.mycompany.MyDocSet.documentation. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated # that can be used as input for Qt's qhelpgenerator to generate a # Qt Compressed Help (.qch) of the generated HTML documentation. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to # add. For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see # # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's # filter section matches. # # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files # will be generated, which together with the HTML files, form an Eclipse help # plugin. To install this plugin and make it available under the help contents # menu in Eclipse, the contents of the directory containing the HTML and XML # files needs to be copied into the plugins directory of eclipse. The name of # the directory within the plugins directory should be the same as # the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before # the help appears. GENERATE_ECLIPSEHELP = NO # A unique identifier for the eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have # this name. ECLIPSE_DOC_ID = org.doxygen.Project # The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) # at top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. Since the tabs have the same information as the # navigation tree you can set this option to NO if you already set # GENERATE_TREEVIEW to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to YES, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. # Since the tree basically has the same information as the tab index you # could consider to set DISABLE_INDEX to NO when enabling this option. GENERATE_TREEVIEW = YES # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values # (range [0,1..20]) that doxygen will group on one line in the generated HTML # documentation. Note that a value of 0 will completely suppress the enum # values from appearing in the overview section. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open # links to external symbols imported via tag files in a separate window. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are # not supported properly for IE 6.0, but are supported on all modern browsers. # Note that when changing this option you need to delete any form_*.png files # in the HTML output before the changes have effect. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax # (see http://www.mathjax.org) which uses client side Javascript for the # rendering instead of using prerendered bitmaps. Use this if you do not # have LaTeX installed or if you want to formulas look prettier in the HTML # output. When enabled you may also need to install MathJax separately and # configure the path to it using the MATHJAX_RELPATH option. USE_MATHJAX = NO # When MathJax is enabled you can set the default output format to be used for # the MathJax output. Supported types are HTML-CSS, NativeMML (i.e. MathML) and # SVG. The default value is HTML-CSS, which is slower, but has the best # compatibility. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the # HTML output directory using the MATHJAX_RELPATH option. The destination # directory should contain the MathJax.js script. For instance, if the mathjax # directory is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to # the MathJax Content Delivery Network so you can quickly see the result without # installing MathJax. # However, it is strongly recommended to install a local # copy of MathJax from http://www.mathjax.org before deployment. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest # The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension # names that should be enabled during MathJax rendering. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript # pieces of code that will be used on startup of the MathJax code. MATHJAX_CODEFILE = # When the SEARCHENGINE tag is enabled doxygen will generate a search box # for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using # HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets # (GENERATE_DOCSET) there is already a search function so this one should # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a web server instead of a web client using Javascript. # There are two flavours of web server based search depending on the # EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for # searching and an index file used by the script. When EXTERNAL_SEARCH is # enabled the indexing and searching needs to be provided by external tools. # See the manual for details. SERVER_BASED_SEARCH = NO # When EXTERNAL_SEARCH is enabled doxygen will no longer generate the PHP # script for searching. Instead the search results are written to an XML file # which needs to be processed by an external indexer. Doxygen will invoke an # external search engine pointed to by the SEARCHENGINE_URL option to obtain # the search results. Doxygen ships with an example indexer (doxyindexer) and # search engine (doxysearch.cgi) which are based on the open source search # engine library Xapian. See the manual for configuration details. EXTERNAL_SEARCH = NO # The SEARCHENGINE_URL should point to a search engine hosted by a web server # which will returned the search results when EXTERNAL_SEARCH is enabled. # Doxygen ships with an example search engine (doxysearch) which is based on # the open source search engine library Xapian. See the manual for configuration # details. SEARCHENGINE_URL = # When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed # search data is written to a file for indexing by an external tool. With the # SEARCHDATA_FILE tag the name of this file can be specified. SEARCHDATA_FILE = searchdata.xml # When SERVER_BASED_SEARCH AND EXTERNAL_SEARCH are both enabled the # EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is # useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple # projects and redirect the results back to the right project. EXTERNAL_SEARCH_ID = # The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen # projects other than the one defined by this configuration file, but that are # all added to the same external search index. Each project needs to have a # unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id # of to a relative location where the documentation can be found. # The format is: EXTRA_SEARCH_MAPPINGS = id1=loc1 id2=loc2 ... EXTRA_SEARCH_MAPPINGS = #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. # Note that when enabling USE_PDFLATEX this option is only used for # generating bitmaps for formulas in the HTML output, but not in the # Makefile that is written to the output directory. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, letter, legal and # executive. If left blank a4 will be used. PAPER_TYPE = a4 # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for # the generated latex document. The footer should contain everything after # the last chapter. If it is left blank doxygen will generate a # standard footer. Notice: only use this tag if you know what you are doing! LATEX_FOOTER = # The LATEX_EXTRA_FILES tag can be used to specify one or more extra images # or other source files which should be copied to the LaTeX output directory. # Note that the files will be copied as-is; there are no commands or markers # available. LATEX_EXTRA_FILES = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO # If LATEX_SOURCE_CODE is set to YES then doxygen will include # source code with syntax highlighting in the LaTeX output. # Note that which sources are shown also depends on other settings # such as SOURCE_BROWSER. LATEX_SOURCE_CODE = NO # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See # http://en.wikipedia.org/wiki/BibTeX for more info. LATEX_BIB_STYLE = plain #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load style sheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options related to the DOCBOOK output #--------------------------------------------------------------------------- # If the GENERATE_DOCBOOK tag is set to YES Doxygen will generate DOCBOOK files # that can be used to generate PDF. GENERATE_DOCBOOK = NO # The DOCBOOK_OUTPUT tag is used to specify where the DOCBOOK pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be put in # front of it. If left blank docbook will be used as the default path. DOCBOOK_OUTPUT = docbook #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. # This is useful # if you want to understand what is going on. # On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # pointed to by INCLUDE_PATH will be searched when a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition that # overrules the definition found in the source code. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all references to function-like macros # that are alone on a line, have an all uppercase name, and do not end with a # semicolon, because these will confuse the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. For each # tag file the location of the external documentation should be added. The # format of a tag file without this location is as follows: # # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths # or URLs. Note that each tag file must have a unique name (where the name does # NOT include the path). If a tag file is not located in the directory in which # doxygen is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # If the EXTERNAL_PAGES tag is set to YES all external pages will be listed # in the related pages index. If set to NO, only the current project's # pages will be listed. EXTERNAL_PAGES = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option also works with HAVE_DOT disabled, but it is recommended to # install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = YES # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is # allowed to run in parallel. When set to 0 (the default) doxygen will # base this on the number of processors available in the system. You can set it # explicitly to a value larger than 0 to get control over the balance # between CPU load and processing speed. DOT_NUM_THREADS = 0 # By default doxygen will use the Helvetica font for all dot files that # doxygen generates. When you want a differently looking font you can specify # the font name using DOT_FONTNAME. You need to make sure dot is able to find # the font, which can be done by putting it in a standard location or by setting # the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the # directory containing the font. DOT_FONTNAME = Lucida # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 8 # By default doxygen will tell dot to use the Helvetica font. # If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to # set the path where dot can find it. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = NO # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If the UML_LOOK tag is enabled, the fields and methods are shown inside # the class node. If there are many fields or methods and many nodes the # graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS # threshold limits the number of items for each type to make the size more # manageable. Set this to 0 for no limit. Note that the threshold may be # exceeded by 50% before the limit is enforced. UML_LIMIT_NUM_FIELDS = 10 # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = NO # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = YES # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will generate a graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are svg, png, jpg, or gif. # If left blank png will be used. If you choose svg you need to set # HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible in IE 9+ (other browsers do not have this requirement). DOT_IMAGE_FORMAT = png # If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to # enable generation of interactive SVG images that allow zooming and panning. # Note that this requires a modern browser other than Internet Explorer. # Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you # need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible. Older versions of IE do not have SVG support. INTERACTIVE_SVG = YES # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MSCFILE_DIRS tag can be used to specify one or more directories that # contain msc files that are included in the documentation (see the # \mscfile command). MSCFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = YES # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES pvr.mythtv-5.10.15-Leia/docs/extradoxygen.css000066400000000000000000000357251360567320200210770ustar00rootroot00000000000000/* The standard CSS for doxygen */ body, table, div, p, dl { font: 300 14px/22px lato,sans-serif; } /* @group Heading Levels */ h1 { font-size: 150%; } .title { font: 200 14px/28px lato,sans-serif; font-size: 150%; font-weight: bold; margin: 10px 2px; } h2 { font-size: 120%; } h3 { font-size: 100%; } .tabs, .tabs2, .tabs3 { font-family: lato,Arial,sans-serif; } table.directory { font: 400 14px lato,Arial,sans-serif; } dt { font-weight: bold; } div.multicol { -moz-column-gap: 1em; -webkit-column-gap: 1em; -moz-column-count: 3; -webkit-column-count: 3; } p.startli, p.startdd, p.starttd { margin-top: 2px; } p.endli { margin-bottom: 0px; } p.enddd { margin-bottom: 4px; } p.endtd { margin-bottom: 2px; } /* @end */ caption { font-weight: bold; } span.legend { font-size: 70%; text-align: center; } h3.version { font-size: 90%; text-align: center; } div.qindex, div.navtab{ background-color: #EBEFF6; border: 1px solid #A3B4D7; text-align: center; } div.qindex, div.navpath { width: 100%; line-height: 140%; } div.navtab { margin-right: 15px; } /* @group Link Styling */ a { color: #3D578C; font-weight: normal; text-decoration: none; } .contents a:visited { color: #4665A2; } a:hover { text-decoration: underline; } a.qindex { font-weight: bold; } a.qindexHL { font-weight: bold; background-color: #9CAFD4; color: #ffffff; border: 1px double #869DCA; } .contents a.qindexHL:visited { color: #ffffff; } a.el { font-weight: bold; } a.elRef { } a.code, a.code:visited { color: #4665A2; } a.codeRef, a.codeRef:visited { color: #4665A2; } /* @end */ dl.el { margin-left: -1cm; } div.line { font-family: monospace, fixed; font-size: 100%; min-height: 18px; line-height: 1.0; } div.fragment { border: none; padding: 0px 0px; margin: 0px 0px 0px 0px; } pre.fragment { border: 1px solid #C4CFE5; background-color: #FBFCFD; padding: 4px 6px; margin: 4px 8px 4px 2px; overflow: auto; word-wrap: break-word; font-size: 9pt; line-height: 125%; } div.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px; padding: 0.2em; border: solid thin #333; border-radius: 0.5em; -webkit-border-radius: .5em; -moz-border-radius: .5em; box-shadow: 2px 2px 3px #999; -webkit-box-shadow: 2px 2px 3px #999; -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000); } div.groupHeader { margin-left: 16px; margin-top: 12px; font-weight: bold; } div.groupText { margin-left: 16px; font-style: italic; } body { background-color: white; color: black; margin: 0; } div.contents { margin-top: 4px; margin-left: 4px; margin-right: 4px; } td.indexkey { background-color: #EBEFF6; font-weight: bold; border: 1px solid #C4CFE5; margin: 2px 0px 2px 0; padding: 2px 10px; white-space: nowrap; vertical-align: top; } td.indexvalue { background-color: #EBEFF6; border: 1px solid #C4CFE5; padding: 2px 10px; margin: 2px 0px; } tr.memlist { background-color: #EEF1F7; } p.formulaDsp { text-align: center; } img.formulaDsp { } img.formulaInl { vertical-align: middle; } div.center { text-align: center; margin-top: 0px; margin-bottom: 0px; padding: 0px; } div.center img { border: 0px; } address.footer { text-align: right; padding-right: 12px; } img.footer { border: 0px; vertical-align: middle; } /* @group Code Colorization */ span.keyword { color: #008000 } span.keywordtype { color: #604020 } span.keywordflow { color: #e08000 } span.comment { color: #800000 } span.preprocessor { color: #806020 } span.stringliteral { color: #002080 } span.charliteral { color: #008080 } span.vhdldigit { color: #ff00ff } span.vhdlchar { color: #000000 } span.vhdlkeyword { color: #700070 } span.vhdllogic { color: #ff0000 } /* @end */ /* .search { color: #003399; font-weight: bold; } form.search { margin-bottom: 0px; margin-top: 0px; } input.search { font-size: 75%; color: #000080; font-weight: normal; background-color: #e8eef2; } */ td.tiny { font-size: 75%; } .dirtab { padding: 4px; border-collapse: collapse; border: 1px solid #A3B4D7; } th.dirtab { background: #EBEFF6; font-weight: bold; } hr { height: 0px; border: none; border-top: 1px solid #4A6AAA; } hr.footer { height: 1px; } /* @group Member Descriptions */ table.memberdecls { border-spacing: 0px; padding: 0px; } .mdescLeft, .mdescRight, .memItemLeft, .memItemRight, .memTemplItemLeft, .memTemplItemRight, .memTemplParams { background-color: #F9FAFC; border: none; margin: 4px; padding: 1px 0 0 8px; } .mdescLeft, .mdescRight { padding: 0px 8px 4px 8px; color: #555; } .memItemLeft, .memItemRight, .memTemplParams { border-top: 1px solid #C4CFE5; } .memItemLeft, .memTemplItemLeft { white-space: nowrap; } .memItemRight { width: 100%; } .memTemplParams { color: #4665A2; white-space: nowrap; } /* @end */ /* @group Member Details */ /* Styles for detailed member documentation */ .memtemplate { font-size: 80%; color: #4665A2; font-weight: normal; margin-left: 9px; } .memnav { background-color: #EBEFF6; border: 1px solid #A3B4D7; text-align: center; margin: 2px; margin-right: 15px; padding: 2px; } .mempage { width: 100%; } .memitem { padding: 0; margin-bottom: 10px; margin-right: 5px; } .memname { white-space: nowrap; font-weight: bold; margin-left: 6px; } .memproto, dl.reflist dt { border-top: 1px solid #A8B8D9; border-left: 1px solid #A8B8D9; border-right: 1px solid #A8B8D9; padding: 6px 0px 6px 0px; color: #253555; font-weight: bold; text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); /* opera specific markup */ box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); border-top-right-radius: 8px; border-top-left-radius: 8px; /* firefox specific markup */ -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; -moz-border-radius-topright: 8px; -moz-border-radius-topleft: 8px; /* webkit specific markup */ -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); -webkit-border-top-right-radius: 8px; -webkit-border-top-left-radius: 8px; background-image:url('nav_f.png'); background-repeat:repeat-x; background-color: #E2E8F2; } .memdoc, dl.reflist dd { border-bottom: 1px solid #A8B8D9; border-left: 1px solid #A8B8D9; border-right: 1px solid #A8B8D9; padding: 2px 5px; background-color: #FBFCFD; border-top-width: 0; /* opera specific markup */ border-bottom-left-radius: 8px; border-bottom-right-radius: 8px; box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); /* firefox specific markup */ -moz-border-radius-bottomleft: 8px; -moz-border-radius-bottomright: 8px; -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; background-image: -moz-linear-gradient(center top, #FFFFFF 0%, #FFFFFF 60%, #F7F8FB 95%, #EEF1F7); /* webkit specific markup */ -webkit-border-bottom-left-radius: 8px; -webkit-border-bottom-right-radius: 8px; -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); background-image: -webkit-gradient(linear,center top,center bottom,from(#FFFFFF), color-stop(0.6,#FFFFFF), color-stop(0.60,#FFFFFF), color-stop(0.95,#F7F8FB), to(#EEF1F7)); } dl.reflist dt { padding: 5px; } dl.reflist dd { margin: 0px 0px 10px 0px; padding: 5px; } .paramkey { text-align: right; } .paramtype { white-space: nowrap; } .paramname { color: #602020; white-space: nowrap; } .paramname em { font-style: normal; } .params, .retval, .exception, .tparams { border-spacing: 6px 2px; } .params .paramname, .retval .paramname { font-weight: bold; vertical-align: top; } .params .paramtype { font-style: italic; vertical-align: top; } .params .paramdir { font-family: "courier new",courier,monospace; vertical-align: top; } /* @end */ /* @group Directory (tree) */ /* for the tree view */ #nav-tree .label { margin:0px; padding:0px; font: 14px lato,Arial,sans-serif; } .ftvtree { font-family: lato,Arial,sans-serif; margin: 0px; } /* these are for tree view when used as main index */ .directory { font-size: 9pt; font-weight: bold; margin: 5px; } .directory h3 { margin: 0px; margin-top: 1em; font-size: 11pt; } /* The following two styles can be used to replace the root node title with an image of your choice. Simply uncomment the next two styles, specify the name of your image and be sure to set 'height' to the proper pixel height of your image. */ /* .directory h3.swap { height: 61px; background-repeat: no-repeat; background-image: url("yourimage.gif"); } .directory h3.swap span { display: none; } */ .directory > h3 { margin-top: 0; } .directory p { margin: 0px; white-space: nowrap; } .directory div { display: none; margin: 0px; } .directory img { vertical-align: -30%; } /* these are for tree view when not used as main index */ .directory-alt { font-size: 100%; font-weight: bold; } .directory-alt h3 { margin: 0px; margin-top: 1em; font-size: 11pt; } .directory-alt > h3 { margin-top: 0; } .directory-alt p { margin: 0px; white-space: nowrap; } .directory-alt div { display: none; margin: 0px; } .directory-alt img { vertical-align: -30%; } /* @end */ div.dynheader { margin-top: 8px; } address { font-style: normal; color: #2A3D61; } table.doxtable { border-collapse:collapse; } table.doxtable td, table.doxtable th { border: 1px solid #2D4068; padding: 3px 7px 2px; } table.doxtable th { background-color: #374F7F; color: #FFFFFF; font-size: 110%; padding-bottom: 4px; padding-top: 5px; text-align:left; } table.fieldtable { width: 100%; margin-bottom: 10px; border: 1px solid #A8B8D9; border-spacing: 0px; -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); } .fieldtable td, .fieldtable th { padding: 3px 7px 2px; } .fieldtable td.fieldtype, .fieldtable td.fieldname { white-space: nowrap; border-right: 1px solid #A8B8D9; border-bottom: 1px solid #A8B8D9; vertical-align: top; } .fieldtable td.fielddoc { border-bottom: 1px solid #A8B8D9; width: 100%; } .fieldtable tr:last-child td { border-bottom: none; } .fieldtable th { background-image:url('nav_f.png'); background-repeat:repeat-x; background-color: #E2E8F2; font-size: 90%; color: #253555; padding-bottom: 4px; padding-top: 5px; text-align:left; -moz-border-radius-topleft: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-left-radius: 4px; -webkit-border-top-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom: 1px solid #A8B8D9; } .tabsearch { top: 0px; left: 10px; height: 36px; background-image: url('tab_b.png'); z-index: 101; overflow: hidden; font-size: 13px; } .navpath ul { font-size: 11px; background-image:url('tab_b.png'); background-repeat:repeat-x; height:30px; line-height:30px; color:#8AA0CC; border:solid 1px #C2CDE4; overflow:hidden; margin:0px; padding:0px; } .navpath li { list-style-type:none; float:left; padding-left:10px; padding-right:15px; background-image:url('bc_s.png'); background-repeat:no-repeat; background-position:right; color:#364D7C; } .navpath li.navelem a { height:32px; display:block; text-decoration: none; outline: none; font-family: lato,Arial,sans-serif; } .navpath li.navelem a:hover { color:#6884BD; } .navpath li.footer { list-style-type:none; float:right; padding-left:10px; padding-right:15px; background-image:none; background-repeat:no-repeat; background-position:right; color:#364D7C; font-size: 8pt; } div.summary { float: right; font-size: 8pt; padding-right: 5px; width: 50%; text-align: right; } div.summary a { white-space: nowrap; } div.ingroups { margin-left: 5px; font-size: 8pt; padding-left: 5px; width: 50%; text-align: left; } div.ingroups a { white-space: nowrap; } div.header { background-image:url('nav_h.png'); background-repeat:repeat-x; background-color: #F9FAFC; margin: 0px; border-bottom: 1px solid #C4CFE5; } div.headertitle { padding: 5px 5px 5px 7px; } dl { padding: 0 0 0 10px; } dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug { border-left:4px solid; padding: 0 0 0 6px; } dl.note { border-color: #D0C000; } dl.warning, dl.attention { border-color: #FF0000; } dl.pre, dl.post, dl.invariant { border-color: #00D000; } dl.deprecated { border-color: #505050; } dl.todo { border-color: #00C0E0; } dl.test { border-color: #3030E0; } dl.bug { border-color: #C08050; } #projectlogo { text-align: center; vertical-align: bottom; border-collapse: separate; } #projectlogo img { border: 0px none; } #projectname { font: 200% lato, Arial,sans-serif; margin: 0px; padding: 2px 0px; } #projectbrief { font: 120% lato, Arial,sans-serif; margin: 0px; padding: 0px; } #projectnumber { font: 50% lato, Arial,sans-serif; margin: 0px; padding: 0px; } #titlearea { padding: 0px; margin: 0px; width: 100%; border-bottom: 1px solid #5373B4; } .image { text-align: center; } .dotgraph { text-align: center; } .mscgraph { text-align: center; } .caption { font-weight: bold; } div.zoom { border: 1px solid #90A5CE; } dl.citelist { margin-bottom:50px; } dl.citelist dt { color:#334975; float:left; font-weight:bold; margin-right:10px; padding:5px; } dl.citelist dd { margin:2px 0; padding:5px 0; } @media print { #top { display: none; } #side-nav { display: none; } #nav-path { display: none; } body { overflow:visible; } h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } .summary { display: none; } .memitem { page-break-inside: avoid; } #doc-content { margin-left:0 !important; height:auto !important; width:auto !important; overflow:inherit; display:inline; } pre.fragment { overflow: visible; text-wrap: unrestricted; white-space: -moz-pre-wrap; /* Moz */ white-space: -pre-wrap; /* Opera 4-6 */ white-space: -o-pre-wrap; /* Opera 7 */ white-space: pre-wrap; /* CSS3 */ word-wrap: break-word; /* IE 5.5+ */ } } pvr.mythtv-5.10.15-Leia/docs/logo.png000066400000000000000000000221721360567320200173020ustar00rootroot00000000000000‰PNG  IHDR@@ªiqÞ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛbKGDÿÿÿ ½§“ pHYs  šœtIMEá %ÊO¾¬IDATxÚ­›{eG}ß?ÝçqŸ3wfgvwvWZI«z"½ Ù’¶±0%ˆB 'Æ¡HâªBâı‰¥r…Ø®‚Ä8‰‘±c`I–‘ÄÃÆv Äz"íjW•vçuç¾Î³;t÷9}ïÎÈ)—oÕ­™{nŸ>Ýßß÷÷ý=ιâª;¾ Ã0$‚ Àý†!a „@J¹ãgÿí^RÊ©ÏZk´Ö(¥ÐZS–åÔ_­5BˆjLY–”e‰R ¥€ù¬5hMQEQ©Çkʲ¨æ)Šbê{wNY–„naW/.SÛsoT÷r ùß+¥ ¨h³×uÓ8 ÿ¦µÊí _as;}7ûvV«ÎÛæ;^a®Ù1Ž¥>@nŒPk±Ã ·…;Zeë¹ÿ…Ö`Þ_·0|Y–ÞâôŽ qÇUgçB ¥¬ék؉>è¯Ä¼pöÀì`¥5R4 ¼ï%òÅ“$!Š"&“ N‡ápH«Õb<#„ Š¢j“nCyž3I’Ê AEÍf“õõõÓô#Š¢jó~èÚÎ(;¹òvZàÿ/gCŽ€o•ñx|šêúqÔÏóœ(Šˆ¢ˆ$IȲ¬ŠÅ£Ñˆ<Ï«k8 Ü9ÎUÂ0¬Æ¸x?k=·öÓÖ¿ vr¹SˆÒ6Ñ(Ë’ápH§Óa4177Çp8¤Ûí’ç9aVFAP ×p8d<žLÍ™eyžS–%Y–!„`00??O’$Uæ'/þÚ„•ÈÍZß×ß…}@¦¢€Sm?ÑpÇÜÎÂív{Ššý<Ï«ñQUè6’¦ B4éõz ‡CÒ4­†!ƒÁ Šn.?kó-,¥´@–+^‰þ>C¶c‹œÀ]¸,Ëj3­V«ò}G? ÝÚÚª,Ñl6ɲ¬¢{·Û`2™°µµÅüü2îåbu•’gYæŠápHQý‡Ã!yžWñ}kk‹ „,..VÀ¼ôÒKEÁÂÂF¥qÓh4è÷ûAÀúúú+X¾˜ŠÛQ»rcOð¦3Çz\å¾ïGQ„”’ÉdR‰‘Só¢(P¥b2™T,i·Û¤iJ’$4 šÍ&J)F£KKKÌÍÍ!¥dkk‹õõõŠ-.yFh­éõz¬®®²oß¾Jñ{M³b¶Vصø® ,_Û‡üêΩ²£¤”²òOG¿,ËRV¡k~~ž0 ™L&äyN´Z-²,#Ë2Ò4¥ÕjÑh4èt:ÄqŒ‚0 +H)«°Ún·§ôhÖ%üÍúávÖ ¶ûlÆzÌòÃï7þ¤‰Ãûý>0nQί×××é÷û„aÈÞ½{év»dYÆñãÇ9yòdåZív›8Ž ‚€¹¹9‚  ( 666²×îʹv1c´þ2E‘ŸF{_‹NóýmJïéœÆs?íÍóÇ•²»‰’$!â8&MÓ*,ÎÏϳ±±Áp8$Š"F$IÂ`0 ÝnWùþÖ֣шõõuZ­ív›0 +ð'“ «««,..2xéý•°üÆ÷pðõo† :Íß‘fé?«ú~OaVC?äù'eYV4.f;—(Š‚~¿Ïòò2‹‹‹L&Š¢`qq‘ýû÷süøqÖ××™››cee…ÅÅŪ>ØÚÚ"MSò<¯„q8"„`ee…8ŽyùØÀÊ´b²ú<édŒˆ[ÛZvvݳ Üì¸ÓªA€'Jn€¿igiÖŠ¢ Óé0 HÓ”4Mét:ìÞ½»bÂóÏ?O¯×£Óé½^o* ÃååeÂ(­ÙÚÚ¢( ³ž²mÔÜu€vÊèvŠûSb* 8¥w©¨ q3™LÇ,,,°°°Àææ&ãñ˜0 Y\\ä¹çž«Pßµk ÖÖÖ8~üxµùùùyÚí¶§Ò N<Á(Z`RÂÖ`ÈâÜœßG3y|¥W;¤ñ;%@³Q¡À©¼‚ÒêA†¤i¤Ä& IšåL&Úí6óóóŒF#²<§Ùj³ge?£A¿J€z½Q±´´Äx<&I’*tV"&«OsÏ/¼Cÿðv–.¼†ÅåÝ”§VA9Õ7Ùa6Ñ20`”ªbçNåï¬KlË¥ .ó“R¤n:§M–lðY“tu•7-/qÞe‹õ.äòË.áKþUâI>øþŸg8òëý-âF!>ö8Ÿù½;Ùì÷À>ô«|þ+_§”ÿä–á?ÿò/‚KÿþûÉϾ-‚©Ínfs”Iì¤ßd0Õ˜ÉÞpí-ïäûƒ+Þ—¼‰|â~4ç:‡õ>ÄGîþ\ð:¯}þÒ“<úè÷ÑJñà7¾IÇÜöÖŸdaóæ;-âFƒsô)®¹ò ´R¼ï—~ß½ÿ!‚ñhÄo~îË|ò;'ùÃÃë|ýDA–¥„AÀÍo{'<±ÊÒµoaïÿ4Ÿ9¢øâ—¿ÂÖ`Ľú ù¨RåÿWì÷©o>”µ¢TdyÆÆúƒænZç^M÷ŒóÑíEÒ¥s9vôhÍÑÕ!ͳ¯ Xû'w±±Ùçç~üjŠQŸ¹Þÿü¦ Y[ßàã¿÷´Î¾œÆÊ¹diJže´–öÑ<ç5d{. Ü{ˆ,MI&žzyDëÜ«wŸì,Ò=xß~v$IXÙÕ£œ )Kuš ÌÖU¡§•*zš.–¥kXd·É´ ŠbÓÝmÍsb­oš™qo™Riúý>Y^²:ÎɲŒ¥¥e>üûwÇ·½åÇØzü!Š£óÆë¯% ~óSwÓ>paËøu–e$iJk€ cZíYš’e)4;Èö|Õ†G sN»S¤É¶~¾m˜´~6´ºLÐQ#L˜Éóœ,Ë)KE’fÈ(§ÑˆÉЉ-p”RÄ7ȲŒþVŸ|·É K­IV.áî{ïã†ë^ÇÏÜxfƒõ­zï}$sû™›ÛM6X#Ë2 ›{t:mâv—ÁÉ Yž“å9X1CØœ_S5CTQ Ê|ÛÍŸöl<Ë€Ðù¿{EB’Z„ƒ0¨ZÙB´È"ÏI3“Ê–EIÜMeÅäùišRd9qw‘=ð?zÃõÜrÓë ¤$‚ßúô=Ì]t¹ Qª¬2È(Ž ‚ÍÍ „½w¥)Ø4]T5¾ai’$äEŽ~…ÍW ö7¯ê¿«ýŽki•eiÕ¬(Š¢J}³<'MSJU2Ém|o¶š¨Ò0 /sú[6_Å=÷=€°T¼÷ ÷“.œIkïYDqL4Ȳ”R+Š¢dss)%Íf“4MHÒaK⢰-2[“dYfÖ­ô+n^Û íY_•(Ò¯“dYFšeèRQ*ÓôÈóœÑhhfc&ã±­ù³ <]j¢8¢ÙÛÅï|õQ ’ÿù黉÷œÃ8WŒGc3è÷‰MtâV›°Ñd°úYfôD—%ÊÖðÆÒÓàÝIö£@½yÏú•*‚*øý¶²,™$ÒÄÔíy–0·Ë'™Ñ†4MPJ†!¥½è`k‹,2tÎË‚V³…Œ›ÜpÉÙlöûöž"¹þµWsã뮢( ïQ{sh­ ÈÒŒ(h+ ÁÖæ&Ï?ÆÚê©íŸÚ§½¿y Xh€·Þ®ýv˜P9ù‘G`xŠÆÁKWÎCcŠ¥( É_zšôùLj{{ˆÏ¾‚¨3OÇh4ÉËÇ=ý0"è^x7ôúüô¯áÈ3ÏðKô®x´æ«B&Š#òÑñ O¢^x”n0O(‚&XF6W!ö]HI€”ÆPùú‹¨gƒ_ê.{žOyÏâÊ~V TQý­p-&)B+d#ÂFÕ‘ª@ê„H²êú:KA6Úâ7Þ¸Bw¾ÇÿíãoœÅö£E€¥R”EQŸWææÆ§AˆÖ „hRh…0÷¤Mwÿ_ÐØ>eØääê[Kü»WîÕlµ¹rÌÃYa<¥öÛ)ŸˆS«kÕø»î½ñh ½:-¶HÐF`Ûá"ÄìQ~ë\Øó/‹Vi¶Îã¥'8ü€è’=(ÛøL’äomño=ò.½èBšÍ&I’𮛯âá?> ½ÝµØ)Í?ýÑ‹Y]ߨÎí´Û|ä½C ã†(í3¨ê@ø·²ü¿þÞl<ä’ùÏ;ÆWÿïa•sÑÍ9H|êϾB2ÜšÚÔÒb×_}å”e_xñßþþã)§Îxêèq¾óØx×Ûn©ßøº«‘¿}jn—yxCÄè$·\÷V&“šm_{èëœ Xšó"„®]ÀÈ¥¡A;FÈjR·¿'?û|@E|ê¬?‚lug@ÈÑšç—ï}=Z3—°§\¾¿Ë5W¼ÚäýöõÍÃòkŸý+èìòüZƒ 舓¼ûí·0š$ÕS&·^sŸ;6†¸ ÞqÕAúÃqµÖf³Éÿ_ K¬ïë*# +4„¨Ã†°Oi÷Y˜s¼çþfïÆV€I°rì="@D ó\‚`×X܇ÒáNOÍ%ÛñuÍP–š·Öî$КQ:æ¿|ˆ«^}Q5þ–ë.çsßú3ØwŒ¼íš¦¬ôèQ{ö$œs†u“ÒF MhGaâ¯Ótµyw¢FL±b;@tqý¼¦²šHàžq)•> €ê&l5] ->ù×òšK. µãöìÞÍÁ¹’ãEÊí‹h´šaò»Ÿ¹ öœaTטð(«"ÁåÍUñ ¼wéÓ¹´. ´*«¢ã´'5Ü{öé ¥Ð6‡O#ŽîmZó^Ñ¢TÚ*ÅúGŽ­Æolöù‰:†}~것aõÝÚÚ_{äÉÚÜœei(s( »1¿bRSbQ…¿À`,í¨åÞeQ¿ýcnºD•E\ë<˲úºjÖ@%Ìõøìƒ™®‘=ïµ—_È|ÿ)Î?ë@u,MSþ÷ŸÞËgBÜò²Á²ZˆM„(@xõ³¥¾Ð³ÙûNÔUVESQÛ]È*²T¾,dE?¨ª¶¯ûîæLÍ@{žÖ&|iøë§7xÇu´ªPýoßõ“llökA$÷?xιª6ZéÍ© BTa&—ZHé?pkåÚú¬Væ³ðÆ8Å6ÑVàh÷¤¥´þ¬Š‚ñxb„Ï×€Šu®ª&~# L`n‰/~ãû\ùu3' §ÄïÁo> û!jAQL©ù Ô¥¥‰¬Š|áRV0+„´Úä@^.î-§«1é€5ÔV¶ãäÛV˜¡¼[°"s® A¥|鉗¹îÒsI½ê^8毆ÝÚ¼¿€FÒ±WÛ§Å+j isÒPÅg‚õFUi¬¡UMi]„õ]!̺ý¶”Rµk¨EA’L(J5Í%ÍÚêFY%·l˜4–xä±§8tæ¾ÓøÞc3-³Î"…Î2d#È'ž;•6r¡N[¤…)êl1]c«D "°~å[@xlÑÖ¥, JêdX‡ÁÂÜoôÈóJÊÎ+“­ê eÏ—7ù˧_àÌ•% OCâ(âÏ¿q:ûÌÞZ PfP$§µ›kMHY@`}«ÊøJ#ŠÕã”AmEÔQBxà8•bïXi,FÓ=y¥ªjL—¥}Št™Åa­XUZ÷“œÈ;¼ôòIºNuþó/¾ÈZ"ay š=c "…Œ¡½ãM3W‘#xý?ÒÈÀSvQ/xVÈÊÂX³´ôv˜^šÕÀZׂåÂ_`3Ã2«ï÷‡±Y؉'a²U³-Œaù,ht¬6…Kí:dhÀI‡0îo=™­‚,ŸcÖêº?QÚ=ÈR¯C‘ƒ„S7 |œú jõW¥MqµÀóo„ñÑÒÏ ¨YP?š\3ªÈ̆WÎ7ÿ;= c«ô–QE*„04…šfÞ27ãš]2y¶×jÊP ½hæLÇæXžA£eEP)#x.yqI‡C[y?Ãp·–\s±H lÔúQ5ñÜÃÎ[dõX¿ †1BPuYç B˜ÿÃØ,Zf^8íˆ7ëð‰4¬ ›æ:éȬ!š±íEØzÙFåemÛýpÈÏúª4ÖÅgi…Š:DYÍ )!Œ…D`Ž©Ü\7ŸX`´1D‰VGDÁ”Pç^GIF¶x“5kà*Ë„<1_¥“@… ˜ÛmæQ…sS«¡\5XÖVg:q©X CÈ& S³)áæÂaìåd¥±Âø5iš:vhmÍ&ÆÚ. U6ʉ9³z#kkå©wë+©ÇÊ¢6Ì-›µ$ók”ÊÏ|j2ݙڜ.m\ö”_¦uN ¥±XQXñ”u¥µÙXÔð4A™E;Pe`˜· ]E`A°@æIíçª4~íUŠuùìýÌG•¦YÒ]2`d#sÍFÇCvá~ÐbÚÜMÿ]AfS¶×?°ãÒ±ÙˆíæPX?vÄ1KÊš124V-R³è,1t•a}Žôêz¾½û}U1„Ðèš{ù/[SÃÄÎ.ç^êªe]ØTÍ‹j‘C`•·,ë4S(³ÐÀËÕˉ9/÷Ž;QË&Yªað¤£ZuÖX6䉹¦”¦À @Ê´>ǯ:eP뀶‘«H î@w”¹÷«±ªdÕuB¤=W(S›TD •W#¸T´«ú!0aÊi‚ ­›äÆB™e‡Ñ"5,J b/ŠØpµÌ|éÐÌŒŒÂKë"Qls=Mÿ<µu„Í?šófùòÉôÏæ¦ÂV¥êº¦®ð³9»ù ªU>t݆ËÌ6@ ˆ»õx¥ìfF&Aq–Ê&fãM6ã:9*s3Oبç-¶j×aÝ×T3ÑÊU®í“ ŒÖ!K¶À™MPlxqáÊïÔj›åå‰÷‰MDìq51‹Í†­êÎl‘ˆ–¶$Cã³ÉÈDu4 ãZà´í^û­³ªÞ`º)5MÜG Ë )v@•Þ ÀPu¶>ðYâTº,¡›Ö¹‡´ÅL‘šñQ£>/­*;lMܺ0é[hZ 0î5k+óº7AP³&°¹„Ll}’§æûÞ^©x¯]Æfý/n{IÎìþmcĹLÔª/’?kÌFœ*6ÜE^ö7-Cs]—é +‚9s^aczЀ(²õAd³½hFg¨…\»:¥4@*e®ß]4ÿq[¤%” 9IEND®B`‚pvr.mythtv-5.10.15-Leia/lib/000077500000000000000000000000001360567320200154465ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/lib/cppmyth/000077500000000000000000000000001360567320200171325ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/lib/cppmyth/CMakeLists.txt000066400000000000000000000117441360567320200217010ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.5) project (cppmyth) set (CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") # Options OPTION (BUILD_SHARED_LIBS "Build shared libraries." OFF) if (MSVC) # This option must match the settings used in your program, in particular if you # are linking statically OPTION (STATIC_CRT "Link the static CRT libraries" OFF) endif () if (NOT MSVC) OPTION (REQUIRE_CXX_98 "Require standard c++98" OFF) endif () ############################################################################### # set lib version here set (CPPMYTH_LIB_VERSION "2.13.0") set (CPPMYTH_LIB_SOVERSION "2") ############################################################################### # add definitions if (MSVC) add_definitions ("/D_CRT_SECURE_NO_WARNINGS") if (STATIC_CRT) set (CMAKE_C_FLAGS_RELEASE "/MT") set (CMAKE_C_FLAGS_DEBUG "/MTd") set (CMAKE_CXX_FLAGS_RELEASE "/MT") set (CMAKE_CXX_FLAGS_DEBUG "/MTd") endif () set (CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /W3") set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /W3") set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /W3 /EHsc /nologo") set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /W3 /EHsc /nologo") if(CMAKE_SYSTEM_NAME STREQUAL WindowsStore) set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /O2") set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /O2") else() set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Od /RTC1") set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Od /RTC1") endif() endif () if (NOT MSVC) if (NOT CYGWIN) add_definitions ("-fPIC") endif () add_definitions ("-Wall") include(CheckCXXCompilerFlag) CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) if(NOT REQUIRE_CXX_98 AND COMPILER_SUPPORTS_CXX11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") message(STATUS "Using standard c++11") else() CHECK_CXX_COMPILER_FLAG("-std=c++98" COMPILER_SUPPORTS_CXX98) if(COMPILER_SUPPORTS_CXX98) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++98") message(STATUS "Using standard c++98") endif() include (CheckLibraryExists) include (CheckAtomic) if (HAS_BUILTIN_SYNC_ADD_AND_FETCH) add_definitions ("-DHAS_BUILTIN_SYNC_ADD_AND_FETCH") endif () if (HAS_BUILTIN_SYNC_SUB_AND_FETCH) add_definitions ("-DHAS_BUILTIN_SYNC_SUB_AND_FETCH") endif () endif () endif () ############################################################################### # configure include (CheckFunctionExists) include (CheckFunctionKeywords) find_package (Threads REQUIRED) check_function_exists (timegm CHK_TIMEGM) if (CHK_TIMEGM) set (HAVE_TIMEGM 1) else () set (HAVE_TIMEGM 0) endif () check_function_exists (localtime_r CHK_LOCALTIME_R) if (CHK_LOCALTIME_R) set (HAVE_LOCALTIME_R 1) else () set (HAVE_LOCALTIME_R 0) endif () check_function_exists (gmtime_r CHK_GMTIME_R) if (CHK_GMTIME_R) set (HAVE_GMTIME_R 1) else () set (HAVE_GMTIME_R 0) endif () find_package (ZLIB REQUIRED) if (ZLIB_FOUND) include_directories (${ZLIB_INCLUDE_DIRS}) set (HAVE_ZLIB 1) else () set (HAVE_ZLIB 0) endif () set (HAVE_OPENSSL 0) # Check what the inline keyword is. check_function_keywords ("inline") check_function_keywords ("__inline") check_function_keywords ("__inline__") if (HAVE_INLINE) set (CC_INLINE inline) elseif (HAVE___INLINE) set (CC_INLINE __inline) elseif (HAVE___INLINE__) set (CC_INLINE __inline__) else () # no inline on this platform set (CC_INLINE) endif () # configure the public config file configure_file (${CMAKE_CURRENT_SOURCE_DIR}/src/cppmyth_config.h.in ${CMAKE_CURRENT_BINARY_DIR}/src/cppmyth_config.h) include_directories (${CMAKE_CURRENT_BINARY_DIR}/src/ ${CMAKE_CURRENT_SOURCE_DIR}/src/.) ############################################################################### # add sources file (GLOB SRC_FILES src/private/mythdto/*.cpp src/private/*.c src/private/*.cpp src/proto/*.cpp src/*.cpp) file (GLOB OS_SRC_FILES src/private/os/threads/threadpool.cpp) if (MSVC) list (APPEND OS_SRC_FILES src/private/os/windows/winpthreads.c) endif () set (CPPMYTH_SOURCES ${SRC_FILES} ${OS_SRC_FILES}) file (GLOB HDR_FILES src/private/mythdto/*.h src/private/*.h src/proto/*.h src/*.h) file (GLOB OS_HDR_FILES src/private/os/threads/*.h) set (CPPMYTH_HEADERS ${HDR_FILES} ${OS_HDR_FILES}) ############################################################################### # add targets set (cppmyth_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) if (ZLIB_FOUND) list (APPEND cppmyth_LIBRARIES ${ZLIB_LIBRARIES}) endif () #if (OPENSSL_FOUND) # list (APPEND cppmyth_LIBRARIES ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY}) #endif () if (MSVC) list (APPEND cppmyth_LIBRARIES ws2_32) else () list (APPEND cppmyth_LIBRARIES m) find_library (LIBRT rt) if (LIBRT) list (APPEND cppmyth_LIBRARIES rt) endif () endif () add_library (cppmyth STATIC ${CPPMYTH_SOURCES}) target_link_libraries (cppmyth ${cppmyth_LIBRARIES}) pvr.mythtv-5.10.15-Leia/lib/cppmyth/cmake/000077500000000000000000000000001360567320200202125ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/lib/cppmyth/cmake/CheckAtomic.cmake000066400000000000000000000011461360567320200233700ustar00rootroot00000000000000include(CheckCXXSourceCompiles) check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC) if (HAVE_LIBATOMIC) list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") endif() CHECK_CXX_SOURCE_COMPILES("int main() { long* temp=0; long ret=__sync_add_and_fetch(temp, 1); return 0; }" HAS_BUILTIN_SYNC_ADD_AND_FETCH) CHECK_CXX_SOURCE_COMPILES("int main() { long* temp=0; long ret=__sync_sub_and_fetch(temp, 1); return 0; }" HAS_BUILTIN_SYNC_SUB_AND_FETCH) CHECK_CXX_SOURCE_COMPILES("int main() { long *temp = 0; long ret=__sync_val_compare_and_swap(temp, 1, 1); return 0; }" HAS_BUILTIN_SYNC_VAL_COMPARE_AND_SWAP)pvr.mythtv-5.10.15-Leia/lib/cppmyth/cmake/CheckFunctionKeywords.cmake000066400000000000000000000010601360567320200254640ustar00rootroot00000000000000include(CheckCSourceCompiles) macro(check_function_keywords _wordlist) set(${_result} "") foreach(flag ${_wordlist}) string(REGEX REPLACE "[-+/ ()]" "_" flagname "${flag}") string(TOUPPER "${flagname}" flagname) set(have_flag "HAVE_${flagname}") check_c_source_compiles("${flag} void func(); void func() { } int main() { func(); return 0; }" ${have_flag}) if(${have_flag} AND NOT ${_result}) set(${_result} "${flag}") # break() endif(${have_flag} AND NOT ${_result}) endforeach(flag) endmacro(check_function_keywords) pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/000077500000000000000000000000001360567320200177215ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/cppmyth_config.h.in000066400000000000000000000007551360567320200235170ustar00rootroot00000000000000 #ifndef CPPMYTH_CONFIG_H #define CPPMYTH_CONFIG_H #undef HAVE_TIMEGM #define HAVE_TIMEGM @HAVE_TIMEGM@ #undef HAVE_LOCALTIME_R #define HAVE_LOCALTIME_R @HAVE_LOCALTIME_R@ #undef HAVE_GMTIME_R #define HAVE_GMTIME_R @HAVE_GMTIME_R@ #undef HAVE_ZLIB #define HAVE_ZLIB @HAVE_ZLIB@ #undef HAVE_OPENSSL #define HAVE_OPENSSL @HAVE_OPENSSL@ #undef CC_INLINE #define CC_INLINE @CC_INLINE@ #undef NSROOT #define NSROOT Myth #undef LIBTAG #define LIBTAG "CPPMyth" #endif /* CPPMYTH_CONFIG_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/mythcontrol.cpp000066400000000000000000000057561360567320200230240ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "mythcontrol.h" using namespace Myth; Control::Control(const std::string& server, unsigned protoPort, unsigned wsapiPort, const std::string& wsapiSecurityPin) : m_monitor(server, protoPort) , m_wsapi(server, wsapiPort, wsapiSecurityPin) { Open(); } Control::Control(const std::string& server, unsigned protoPort, unsigned wsapiPort, const std::string& wsapiSecurityPin, bool frontend) : m_monitor(server, protoPort, frontend) , m_wsapi(server, wsapiPort, wsapiSecurityPin) { Open(); } Control::~Control() { Close(); } bool Control::Open() { if (m_monitor.IsOpen()) return true; return m_monitor.Open(); } void Control::Close() { m_monitor.Close(); m_wsapi.InvalidateService(); } std::string Control::GetBackendServerIP(const std::string& hostName) { std::string backend_addr; // Query backend server IP Myth::SettingPtr settingAddr = this->GetSetting("BackendServerIP", hostName); if (settingAddr && !settingAddr->value.empty()) backend_addr = settingAddr->value; return backend_addr; } std::string Control::GetBackendServerIP6(const std::string& hostName) { std::string backend_addr; // Query backend server IP6 Myth::SettingPtr settingAddr = this->GetSetting("BackendServerIP6", hostName); if (settingAddr && !settingAddr->value.empty() && settingAddr->value != "::1") backend_addr = settingAddr->value; return backend_addr; } unsigned Control::GetBackendServerPort(const std::string& hostName) { int backend_port; // Query backend server port Myth::SettingPtr settingPort = this->GetSetting("BackendServerPort", hostName); if (settingPort && !settingPort->value.empty() && (backend_port = Myth::StringToInt(settingPort->value)) > 0) return backend_port; return 0; } bool Control::RefreshRecordedArtwork(Program& program) { program.artwork.clear(); if (program.inetref.empty()) return false; ArtworkListPtr artworks(GetRecordingArtworkList(program.channel.chanId, program.recording.startTs)); program.artwork.reserve(artworks->size()); for (ArtworkList::const_iterator it = artworks->begin(); it < artworks->end(); ++it) { program.artwork.push_back(*(it->get())); } return (program.artwork.empty() ? false : true); } pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/mythcontrol.h000066400000000000000000000412241360567320200224570ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHCONTROL_H #define MYTHCONTROL_H #include "proto/mythprotomonitor.h" #include "mythtypes.h" #include "mythwsapi.h" namespace Myth { class Control { public: Control(const std::string& server, unsigned protoPort, unsigned wsapiPort, const std::string& wsapiSecurityPin); Control(const std::string& server, unsigned protoPort, unsigned wsapiPort, const std::string& wsapiSecurityPin, bool frontend); ~Control(); bool Open(); void Close(); bool IsOpen() { return m_monitor.IsOpen(); } bool HasHanging() const { return m_monitor.HasHanging(); } void CleanHanging() { m_monitor.CleanHanging(); } ProtoBase::ERROR_t GetProtoError() const { return m_monitor.GetProtoError(); } /** * @brief Check availability of API services * @return If unavailable then 0 else the backend protocol number */ unsigned CheckService() { return m_wsapi.CheckService(); } /** * @brief Query server host name * @return string */ std::string GetServerHostName() { return m_wsapi.GetServerHostName(); } /** * @brief Query server version infos * @return VersionPtr */ VersionPtr GetVersion() { return m_wsapi.GetVersion(); } /** * @brief Queries the backend for free space summary * @param total * @param used * @return bool */ bool QueryFreeSpaceSummary(int64_t *total, int64_t *used) { return m_monitor.QueryFreeSpaceSummary(total, used); } /** * @brief Triggers preview image generation on the backend for a specified show * @param program * @return bool */ bool QueryGenPixmap(const Program& program) { return m_monitor.QueryGenpixmap(program); } /** * @brief Ask the backend to cancel/continue next recording * @param rnum recorder Id * @param cancel * @return bool */ bool CancelNextRecording(int rnum, bool cancel) { return m_monitor.CancelNextRecording(rnum, cancel); } /** * @brief Query setting by its key * @param key * @param hostname * @return SettingPtr */ SettingPtr GetSetting(const std::string& key, const std::string& hostname) { return m_wsapi.GetSetting(key, hostname); } /** * @brief Query setting by its key * @param key * @param myhost * @return SettingPtr */ SettingPtr GetSetting(const std::string& key, bool myhost) { return m_wsapi.GetSetting(key, myhost); } /** * @brief Query all settings * @param hostname * @return SettingMapPtr */ SettingMapPtr GetSettings(const std::string& hostname) { return m_wsapi.GetSettings(hostname); } /** * @brief Query all settings * @param myhost * @return SettingMapPtr */ SettingMapPtr GetSettings(bool myhost) { return m_wsapi.GetSettings(myhost); } /** * @brief Put setting * @param key * @param value * @param myhost * @return bool */ bool PutSetting(const std::string& key, const std::string& value, bool myhost) { return m_wsapi.PutSetting(key, value, myhost); } /** * @brief Query backend server IP * @param hostName * @return string containing found IP or nil */ std::string GetBackendServerIP(const std::string& hostName); /** * @brief Query backend server IP6 * @param hostName * @return string containing found IP6 or nil */ std::string GetBackendServerIP6(const std::string& hostName); /** * @brief Query backend server port for protocol commands * @param hostName * @return unsigned more than 0 else invalid */ unsigned GetBackendServerPort(const std::string& hostName); /** * @brief Query information on all recorded programs * @param n * @param descending * @return ProgramListPtr */ ProgramListPtr GetRecordedList(unsigned n = 0, bool descending = false) { return m_wsapi.GetRecordedList(n, descending); } /** * @brief Query information on a single item from recordings * @param chanid * @param recstartts * @return ProgramPtr */ ProgramPtr GetRecorded(uint32_t chanid, time_t recstartts) { return m_wsapi.GetRecorded(chanid, recstartts); } /** * @brief Query information on a single item from recordings * @param recordedid * @return ProgramPtr */ ProgramPtr GetRecorded(uint32_t recordedid) { return m_wsapi.GetRecorded(recordedid); } /** * @brief Update watched status for a recorded * @param chanid * @param recstartts * @return bool */ bool UpdateRecordedWatchedStatus(const Program& program, bool watched) { WSServiceVersion_t wsv = m_wsapi.CheckService(WS_Dvr); if (wsv.ranking >= 0x00060000) return m_wsapi.UpdateRecordedWatchedStatus(program.recording.recordedId, watched); return m_wsapi.UpdateRecordedWatchedStatus(program.channel.chanId, program.recording.startTs, watched); } /** * @brief Remove a Recording from the database and disk. * @param program * @param forceDelete (default false) * @param allowRerecord (default false) * @return bool */ bool DeleteRecording(const Program& program, bool forceDelete = false, bool allowRerecord = false) { WSServiceVersion_t wsv = m_wsapi.CheckService(WS_Dvr); if (wsv.ranking >= 0x00060000) return m_wsapi.DeleteRecording(program.recording.recordedId, forceDelete, allowRerecord); if (wsv.ranking >= 0x00020001) return m_wsapi.DeleteRecording(program.channel.chanId, program.recording.startTs, forceDelete, allowRerecord); return m_monitor.DeleteRecording(program, forceDelete, allowRerecord); } bool UndeleteRecording(const Program& program) { WSServiceVersion_t wsv = m_wsapi.CheckService(WS_Dvr); if (wsv.ranking >= 0x00060000) return m_wsapi.UnDeleteRecording(program.recording.recordedId); if (wsv.ranking >= 0x00020001) return m_wsapi.UnDeleteRecording(program.channel.chanId, program.recording.startTs); return m_monitor.UndeleteRecording(program); } bool StopRecording(const Program& program) { return m_monitor.StopRecording(program); } /** * @brief Get all configured capture devices * @return CaptureCardListPtr */ CaptureCardListPtr GetCaptureCardList() { return m_wsapi.GetCaptureCardList(); } /** * @brief Get all video sources * @return VideoSourceListPtr */ VideoSourceListPtr GetVideoSourceList() { return m_wsapi.GetVideoSourceList(); } /** * @brief Get all configured channels for a video source * @param sourceid * @param onlyVisible (default true) * @return ChannelListPtr */ ChannelListPtr GetChannelList(uint32_t sourceid, bool onlyVisible = true) { return m_wsapi.GetChannelList(sourceid, onlyVisible); } /** * @brief Retrieve a single channel, by channel id * @param chanid * @return ChannelPtr */ ChannelPtr GetChannel(uint32_t chanid) { return m_wsapi.GetChannel(chanid); } /** * @brief Query the guide information for a particular time period and a channel * @param chanid * @param starttime * @param endtime * @return ProgramMapPtr */ ProgramMapPtr GetProgramGuide(uint32_t chanid, time_t starttime, time_t endtime) { return m_wsapi.GetProgramGuide(chanid, starttime, endtime); } /** * @brief Query the guide information for a particular time period * @param starttime * @param endtime * @return map */ std::map GetProgramGuide(time_t starttime, time_t endtime) { return m_wsapi.GetProgramGuide(starttime, endtime); } /** * @brief Query all configured recording rules * @return RecordScheduleListPtr */ RecordScheduleListPtr GetRecordScheduleList() { return m_wsapi.GetRecordScheduleList(); } /** * @brief Get a single recording rule, by record id * @param recordid * @return RecordSchedulePtr */ RecordSchedulePtr GetRecordSchedule(uint32_t recordid) { return m_wsapi.GetRecordSchedule(recordid); } /** * @brief Add a new recording rule * @param record * @return status. On success Id is updated with the new. */ bool AddRecordSchedule(RecordSchedule& record) { return m_wsapi.AddRecordSchedule(record); } /** * @brief Update a recording rule * @param record * @return status */ bool UpdateRecordSchedule(RecordSchedule& record) { return m_wsapi.UpdateRecordSchedule(record); } /** * @brief Disable a recording rule * @param recordid * @return status */ bool DisableRecordSchedule(uint32_t recordid) { return m_wsapi.DisableRecordSchedule(recordid); } /** * @brief Enable a recording rule * @param recordid * @return status */ bool EnableRecordSchedule(uint32_t recordid) { return m_wsapi.EnableRecordSchedule(recordid); } /** * @brief Remove a recording rule * @param recordid * @return status */ bool RemoveRecordSchedule(uint32_t recordid) { return m_wsapi.RemoveRecordSchedule(recordid); } /** * @brief Query information on all upcoming programs matching recording rules * @return ProgramListPtr */ ProgramListPtr GetUpcomingList() { return m_wsapi.GetUpcomingList(); } /** * @brief Query information on upcoming items which will not record due to conflicts * @return ProgramListPtr */ ProgramListPtr GetConflictList() { return m_wsapi.GetConflictList(); } /** * @brief Query information on recorded programs which are set to expire * @return ProgramListPtr */ ProgramListPtr GetExpiringList() { return m_wsapi.GetExpiringList(); } /** * @brief Get list of recording group * @return StringListPtr */ StringListPtr GetRecGroupList() { return m_wsapi.GetRecGroupList(); } /** * @brief Download a given file from a given storage group * @param filename * @param sgname * @return WSStreamPtr */ WSStreamPtr GetFile(const std::string& filename, const std::string& sgname) { return m_wsapi.GetFile(filename, sgname); } /** * @brief Get the icon file for a given channel * @param chanid * @param width (default 0) * @param height (default 0) * @return WSStreamPtr */ WSStreamPtr GetChannelIcon(uint32_t chanid, unsigned width = 0, unsigned height = 0) { return m_wsapi.GetChannelIcon(chanid, width, height); } /** * @brief Get URL of icon for a given channel * @param chanid * @param width (default 0) * @param height (default 0) * @return url */ std::string GetChannelIconUrl(uint32_t chanid, unsigned width = 0, unsigned height = 0) { return m_wsapi.GetChannelIconUrl(chanid, width, height); } /** * @brief Get, and optionally scale, an preview thumbnail for a given recording by timestamp, chanid and starttime * @param program * @param width (default 0) * @param height (default 0) * @return WSStreamPtr */ WSStreamPtr GetPreviewImage(const Program& program, unsigned width = 0, unsigned height = 0) { return m_wsapi.GetPreviewImage(program.channel.chanId, program.recording.startTs, width, height); } /** * @brief Get URL of preview thumbnail for a given recording by timestamp, chanid and starttime * @param program * @param width (default 0) * @param height (default 0) * @return url */ std::string GetPreviewImageUrl(const Program& program, unsigned width = 0, unsigned height = 0) { return m_wsapi.GetPreviewImageUrl(program.channel.chanId, program.recording.startTs, width, height); } /** * @brief Get, and optionally scale, an image file of a given type (coverart, banner, fanart) for a given recording's inetref and season number. * @param type * @param program * @param width (default 0) * @param height (default 0) * @return WSStreamPtr */ WSStreamPtr GetRecordingArtwork(const std::string& type, const Program& program, unsigned width = 0, unsigned height = 0) { return m_wsapi.GetRecordingArtwork(type, program.inetref, program.season, width, height); } /** * @brief Get an image URL of a given type (coverart, banner, fanart) for a given recording's inetref and season number. * @param type * @param program * @param width (default 0) * @param height (default 0) * @return WSStreamPtr */ std::string GetRecordingArtworkUrl(const std::string& type, const Program& program, unsigned width = 0, unsigned height = 0) { return m_wsapi.GetRecordingArtworkUrl(type, program.inetref, program.season, width, height); } /** * @brief Get a list of artwork available for a recording by start time and channel id. * @param chanid * @param recstartts * @return ArtworkListPtr */ ArtworkListPtr GetRecordingArtworkList(uint32_t chanid, time_t recstartts) { return m_wsapi.GetRecordingArtworkList(chanid, recstartts); } /** * @brief Refresh artwork available for a recording. * @param program * @return bool Return true if any artwork found */ bool RefreshRecordedArtwork(Program& program); /** * @brief Request a set of cut list marks for a recording * @param program * @param unit 0 = Frame count, 1 = Position, 2 = Duration ms * @return MarkListPtr */ MarkListPtr GetCutList(const Program& program, int unit = 0) { WSServiceVersion_t wsv = m_wsapi.CheckService(WS_Dvr); if (wsv.ranking >= 0x00060001) return m_wsapi.GetRecordedCutList(program.recording.recordedId, unit); if (unit == 0) return m_monitor.GetCutList(program); else return MarkListPtr(new MarkList); } /** * @brief Request a set of commercial break marks for a recording * @param program * @param unit 0 = Frame count, 1 = Position, 2 = Duration ms * @return MarkListPtr */ MarkListPtr GetCommBreakList(const Program& program, int unit = 0) { WSServiceVersion_t wsv = m_wsapi.CheckService(WS_Dvr); if (wsv.ranking >= 0x00060001) return m_wsapi.GetRecordedCommBreak(program.recording.recordedId, unit); if (unit == 0) return m_monitor.GetCommBreakList(program); else return MarkListPtr(new MarkList); } /** * @brief Prevents backend from shutting down until a the next call to AllowShutdown(). * @return bool */ bool BlockShutdown() { return m_monitor.BlockShutdown(); } /** * @brief Allows backend to shut down again after a previous call to BlockShutdown(). * @return bool */ bool AllowShutdown() { return m_monitor.AllowShutdown(); } /** * @brief Set saved bookmark for a program * @param program * @param unit 1 = Position, 2 = Duration ms * @return bool */ bool SetSavedBookmark(const Program& program, int unit, int64_t value) { return m_wsapi.SetSavedBookmark(program.recording.recordedId, unit, value); } /** * @brief Retrieve saved bookmark for a program * @param program * @param unit 1 = Position, 2 = Duration ms * @return value */ int64_t GetSavedBookmark(const Program& program, int unit) { return m_wsapi.GetSavedBookmark(program.recording.recordedId, unit); } private: ProtoMonitor m_monitor; WSAPI m_wsapi; }; } #endif /* MYTHCONTROL_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/mythdebug.h000066400000000000000000000023211360567320200220600ustar00rootroot00000000000000/* * Copyright (C) 2014-2015 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHDEBUG_H #define MYTHDEBUG_H #define MYTH_DBG_NONE -1 #define MYTH_DBG_ERROR 0 #define MYTH_DBG_WARN 1 #define MYTH_DBG_INFO 2 #define MYTH_DBG_DEBUG 3 #define MYTH_DBG_PROTO 4 #define MYTH_DBG_ALL 6 namespace Myth { void DBGLevel(int l); void DBGAll(void); void DBGNone(void); void SetDBGMsgCallback(void (*msgcb)(int level, char*)); } #endif /* MYTHDEBUG_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/mytheventhandler.cpp000066400000000000000000000251451360567320200240150ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "mytheventhandler.h" #include "private/debug.h" #include "proto/mythprotoevent.h" #include "private/os/threads/thread.h" #include "private/os/threads/event.h" #include "private/cppdef.h" #include "private/builtin.h" #include #include #include using namespace Myth; /////////////////////////////////////////////////////////////////////////////// //// //// EventHandlerThread //// EventHandler::EventHandlerThread::EventHandlerThread(const std::string& server, unsigned port) : m_server(server) , m_port(port) { } EventHandler::EventHandlerThread::~EventHandlerThread() { } /////////////////////////////////////////////////////////////////////////////// //// //// SubscriptionHandlerThread //// namespace Myth { class SubscriptionHandlerThread : private OS::CThread { public: SubscriptionHandlerThread(EventSubscriber *handle, unsigned subid); virtual ~SubscriptionHandlerThread(); EventSubscriber *GetHandle() { return m_handle; } bool IsRunning() { return OS::CThread::IsRunning(); } void PostMessage(const EventMessagePtr& msg); private: EventSubscriber *m_handle; unsigned m_subId; mutable OS::CMutex m_mutex; OS::CEvent m_queueContent; std::list m_msgQueue; bool Start(); void Stop(); void *Process(); }; } SubscriptionHandlerThread::SubscriptionHandlerThread(EventSubscriber *handle, unsigned subid) : OS::CThread() , m_handle(handle) , m_subId(subid) , m_mutex() , m_queueContent() , m_msgQueue() { if (m_handle && Start()) DBG(DBG_DEBUG, "%s: subscription is started (%p:%u)\n", __FUNCTION__, m_handle, m_subId); else DBG(DBG_ERROR, "%s: subscription failed (%p:%u)\n", __FUNCTION__, m_handle, m_subId); } SubscriptionHandlerThread::~SubscriptionHandlerThread() { Stop(); m_handle = NULL; } bool SubscriptionHandlerThread::Start() { if (OS::CThread::IsRunning()) return true; return OS::CThread::StartThread(); } void SubscriptionHandlerThread::Stop() { if (OS::CThread::IsRunning()) { DBG(DBG_DEBUG, "%s: subscription thread (%p:%u)\n", __FUNCTION__, m_handle, m_subId); // Set stopping. don't wait as we need to signal the thread first OS::CThread::StopThread(false); m_queueContent.Signal(); // Wait for thread to stop OS::CThread::StopThread(true); DBG(DBG_DEBUG, "%s: subscription thread (%p:%u) stopped\n", __FUNCTION__, m_handle, m_subId); } } void SubscriptionHandlerThread::PostMessage(const EventMessagePtr& msg) { // Critical section OS::CLockGuard lock(m_mutex); m_msgQueue.push_back(msg); m_queueContent.Signal(); } void *SubscriptionHandlerThread::Process() { while (!IsStopped()) { while (!m_msgQueue.empty() && !IsStopped()) { // Critical section OS::CLockGuard lock(m_mutex); EventMessagePtr msg = m_msgQueue.front(); m_msgQueue.pop_front(); lock.Unlock(); // Do work m_handle->HandleBackendMessage(msg); } // The tread is woken up by m_queueContent.Signal(); m_queueContent.Wait(); } return NULL; } /////////////////////////////////////////////////////////////////////////////// //// //// BasicEventHandler //// namespace Myth { class BasicEventHandler : public EventHandler::EventHandlerThread, private OS::CThread { public: BasicEventHandler(const std::string& server, unsigned port); virtual ~BasicEventHandler(); // Implements MythEventHandlerThread virtual bool Start(); virtual void Stop(); virtual void Reset(); virtual bool IsRunning(); virtual bool IsConnected(); virtual unsigned CreateSubscription(EventSubscriber *sub); virtual bool SubscribeForEvent(unsigned subid, EVENT_t event); virtual void RevokeSubscription(unsigned subid); virtual void RevokeAllSubscriptions(EventSubscriber *sub); private: OS::CMutex m_mutex; ProtoEvent *m_event; bool m_reset; // About subscriptions typedef std::map > subscriptionsByEvent_t; subscriptionsByEvent_t m_subscriptionsByEvent; typedef std::map subscriptions_t; subscriptions_t m_subscriptions; void DispatchEvent(const EventMessagePtr& msg); virtual void* Process(void); void AnnounceStatus(const char *status); void AnnounceTimer(); void RetryConnect(); }; } BasicEventHandler::BasicEventHandler(const std::string& server, unsigned port) : EventHandlerThread(server, port), OS::CThread() , m_event(new ProtoEvent(server,port)) , m_reset(false) { } BasicEventHandler::~BasicEventHandler() { Stop(); { OS::CLockGuard lock(m_mutex); for (subscriptions_t::iterator it = m_subscriptions.begin(); it != m_subscriptions.end(); ++it) delete it->second; m_subscriptions.clear(); m_subscriptionsByEvent.clear(); } SAFE_DELETE(m_event); } bool BasicEventHandler::Start() { if (OS::CThread::IsRunning()) return true; return OS::CThread::StartThread(); } void BasicEventHandler::Stop() { if (OS::CThread::IsRunning()) { DBG(DBG_DEBUG, "%s: event handler thread (%p)\n", __FUNCTION__, this); OS::CThread::StopThread(true); DBG(DBG_DEBUG, "%s: event handler thread (%p) stopped\n", __FUNCTION__, this); } if (m_event->IsOpen()) m_event->Close(); } void BasicEventHandler::Reset() { // Hold reset m_reset = true; } bool BasicEventHandler::IsRunning() { return OS::CThread::IsRunning(); } bool BasicEventHandler::IsConnected() { return m_event->IsOpen(); } unsigned BasicEventHandler::CreateSubscription(EventSubscriber* sub) { unsigned id = 0; OS::CLockGuard lock(m_mutex); subscriptions_t::const_reverse_iterator it = m_subscriptions.rbegin(); if (it != m_subscriptions.rend()) id = it->first; SubscriptionHandlerThread *handler = new SubscriptionHandlerThread(sub, ++id); if (handler->IsRunning()) { m_subscriptions.insert(std::make_pair(id, handler)); return id; } // Handler didn't start delete handler; return 0; } bool BasicEventHandler::SubscribeForEvent(unsigned subid, EVENT_t event) { OS::CLockGuard lock(m_mutex); // Only for registered subscriber subscriptions_t::const_iterator it1 = m_subscriptions.find(subid); if (it1 == m_subscriptions.end()) return false; std::list::const_iterator it2 = m_subscriptionsByEvent[event].begin(); while (it2 != m_subscriptionsByEvent[event].end()) { if (*it2 == subid) return true; ++it2; } m_subscriptionsByEvent[event].push_back(subid); return true; } void BasicEventHandler::RevokeSubscription(unsigned subid) { OS::CLockGuard lock(m_mutex); subscriptions_t::iterator it; it = m_subscriptions.find(subid); if (it != m_subscriptions.end()) { delete it->second; m_subscriptions.erase(it); } } void BasicEventHandler::RevokeAllSubscriptions(EventSubscriber *sub) { OS::CLockGuard lock(m_mutex); std::vector its; for (subscriptions_t::iterator it = m_subscriptions.begin(); it != m_subscriptions.end(); ++it) { if (sub == it->second->GetHandle()) its.push_back(it); } for (std::vector::const_iterator it = its.begin(); it != its.end(); ++it) { delete (*it)->second; m_subscriptions.erase(*it); } } void BasicEventHandler::DispatchEvent(const EventMessagePtr& msg) { OS::CLockGuard lock(m_mutex); std::vector::iterator> revoked; std::list::iterator it1 = m_subscriptionsByEvent[msg->event].begin(); while (it1 != m_subscriptionsByEvent[msg->event].end()) { subscriptions_t::const_iterator it2 = m_subscriptions.find(*it1); if (it2 != m_subscriptions.end()) it2->second->PostMessage(msg); else revoked.push_back(it1); ++it1; } std::vector::iterator>::const_iterator itr; for (itr = revoked.begin(); itr != revoked.end(); ++itr) m_subscriptionsByEvent[msg->event].erase(*itr); } void *BasicEventHandler::Process() { // Try to connect if (m_event->Open()) AnnounceStatus(EVENTHANDLER_CONNECTED); while (!OS::CThread::IsStopped()) { int r; EventMessage *msg = NULL; r = m_event->RcvBackendMessage(EVENTHANDLER_TIMEOUT, &msg); if (r > 0) DispatchEvent(EventMessagePtr(msg)); else if (r < 0) { AnnounceStatus(EVENTHANDLER_DISCONNECTED); RetryConnect(); } else { AnnounceTimer(); // Reconnect if any held reset if (m_reset) { m_reset = false; m_event->Close(); RetryConnect(); } } } AnnounceStatus(EVENTHANDLER_STOPPED); // Close connection m_event->Close(); return NULL; } void BasicEventHandler::AnnounceStatus(const char *status) { DBG(DBG_DEBUG, "%s: (%p) %s\n", __FUNCTION__, this, status); EventMessage *msg = new EventMessage(); msg->event = EVENT_HANDLER_STATUS; msg->subject.push_back(status); msg->subject.push_back(m_server); DispatchEvent(EventMessagePtr(msg)); } void BasicEventHandler::AnnounceTimer() { EventMessage *msg = new EventMessage(); msg->event = EVENT_HANDLER_TIMER; msg->subject.push_back(""); DispatchEvent(EventMessagePtr(msg)); } void BasicEventHandler::RetryConnect() { int c = 0; while (!OS::CThread::IsStopped()) { if (--c < 0) { if (m_event->Open()) { AnnounceStatus(EVENTHANDLER_CONNECTED); m_reset = false; // Release to break any loop break; } c = 10; // Retry after 5 seconds DBG(DBG_INFO, "%s: could not open event socket (%d)\n", __FUNCTION__, m_event->GetSocketErrNo()); AnnounceStatus(EVENTHANDLER_NOTCONNECTED); } usleep(500000); } } /////////////////////////////////////////////////////////////////////////////// //// //// EventHandler //// EventHandler::EventHandler(const std::string& server, unsigned port) : m_imp() { // Choose implementation m_imp = EventHandlerThreadPtr(new BasicEventHandler(server, port)); } pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/mytheventhandler.h000066400000000000000000000061041360567320200234540ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHEVENTHANDLER_H #define MYTHEVENTHANDLER_H #include "mythtypes.h" #include #define EVENTHANDLER_CONNECTED "CONNECTED" #define EVENTHANDLER_DISCONNECTED "DISCONNECTED" #define EVENTHANDLER_STOPPED "STOPPED" #define EVENTHANDLER_NOTCONNECTED "NOTCONNECTED" #define EVENTHANDLER_TIMEOUT 1 // 1 sec namespace Myth { class EventSubscriber { public: virtual ~EventSubscriber() {}; virtual void HandleBackendMessage(EventMessagePtr msg) = 0; }; class EventHandler { public: EventHandler(const std::string& server, unsigned port); bool Start() { return m_imp->Start(); } void Stop() { m_imp->Stop(); } void Reset() { m_imp->Reset(); } std::string GetServer() const { return m_imp->GetServer(); } unsigned GetPort() const { return m_imp->GetPort(); } bool IsRunning() { return m_imp->IsRunning(); } bool IsConnected() { return m_imp->IsConnected(); } unsigned CreateSubscription(EventSubscriber *sub) { return m_imp->CreateSubscription(sub); } bool SubscribeForEvent(unsigned subid, EVENT_t event) { return m_imp->SubscribeForEvent(subid, event);} void RevokeSubscription(unsigned subid) { m_imp->RevokeSubscription(subid); } void RevokeAllSubscriptions(EventSubscriber *sub) { m_imp->RevokeAllSubscriptions(sub); } class EventHandlerThread { friend class EventHandler; public: EventHandlerThread(const std::string& server, unsigned port); virtual ~EventHandlerThread(); virtual std::string GetServer() const { return m_server; } virtual unsigned GetPort() const { return m_port; } virtual bool Start() = 0; virtual void Stop() = 0; virtual void Reset() = 0; virtual bool IsRunning() = 0; virtual bool IsConnected() = 0; virtual unsigned CreateSubscription(EventSubscriber *sub) = 0; virtual bool SubscribeForEvent(unsigned subid, EVENT_t event) = 0; virtual void RevokeSubscription(unsigned subid) = 0; virtual void RevokeAllSubscriptions(EventSubscriber *sub) = 0; protected: std::string m_server; unsigned m_port; }; typedef MYTH_SHARED_PTR EventHandlerThreadPtr; private: EventHandlerThreadPtr m_imp; }; } #endif /* MYTHEVENTHANDLER_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/mythfileplayback.cpp000066400000000000000000000063561360567320200237670ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "mythfileplayback.h" #include "mythlivetvplayback.h" #include "private/debug.h" #include "private/os/threads/mutex.h" #include "private/builtin.h" #include #include using namespace Myth; /////////////////////////////////////////////////////////////////////////////// //// //// Protocol connection to control playback //// FilePlayback::FilePlayback(const std::string& server, unsigned port) : ProtoPlayback(server, port) , m_transfer(NULL) { ProtoPlayback::Open(); } FilePlayback::~FilePlayback() { Close(); } bool FilePlayback::Open() { // Begin critical section OS::CLockGuard lock(*m_mutex); if (ProtoPlayback::IsOpen()) return true; return ProtoPlayback::Open(); } void FilePlayback::Close() { // Begin critical section OS::CLockGuard lock(*m_mutex); CloseTransfer(); ProtoPlayback::Close(); } bool FilePlayback::OpenTransfer(const std::string& pathname, const std::string& sgname) { // Begin critical section OS::CLockGuard lock(*m_mutex); if (!ProtoPlayback::IsOpen()) return false; CloseTransfer(); m_transfer.reset(new ProtoTransfer(m_server, m_port, pathname, sgname)); if (m_transfer->Open()) return true; return false; } void FilePlayback::CloseTransfer() { // Begin critical section OS::CLockGuard lock(*m_mutex); if (m_transfer) { TransferDone(*m_transfer); m_transfer->Close(); m_transfer.reset(); } } bool FilePlayback::TransferIsOpen() { ProtoTransferPtr transfer(m_transfer); if (transfer) return ProtoPlayback::TransferIsOpen(*transfer); return false; } int64_t FilePlayback::GetSize() const { ProtoTransferPtr transfer(m_transfer); if (transfer) return transfer->GetSize(); return 0; } int FilePlayback::Read(void *buffer, unsigned n) { ProtoTransferPtr transfer(m_transfer); if (transfer) { int r = 0; int64_t s = transfer->GetRemaining(); // Acceptable block size if (s > 0) { if (s < (int64_t)n) n = (unsigned)s ; // Request block data from transfer socket r = TransferRequestBlock(*transfer, buffer, n); } return r; } return -1; } int64_t FilePlayback::Seek(int64_t offset, WHENCE_t whence) { ProtoTransferPtr transfer(m_transfer); if (transfer) return TransferSeek(*transfer, offset, whence); return -1; } int64_t FilePlayback::GetPosition() const { ProtoTransferPtr transfer(m_transfer); if (transfer) return transfer->GetPosition(); return 0; } pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/mythfileplayback.h000066400000000000000000000031551360567320200234260ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHFILEPLAYBACK_H #define MYTHFILEPLAYBACK_H #include "proto/mythprotoplayback.h" #include "proto/mythprototransfer.h" #include "mythstream.h" namespace Myth { class FilePlayback : private ProtoPlayback, public Stream { public: FilePlayback(const std::string& server, unsigned port); ~FilePlayback(); bool Open(); void Close(); bool IsOpen() { return ProtoPlayback::IsOpen(); } bool OpenTransfer(const std::string& pathname, const std::string& sgname); void CloseTransfer(); bool TransferIsOpen(); // Implement Stream int64_t GetSize() const; int Read(void *buffer, unsigned n); int64_t Seek(int64_t offset, WHENCE_t whence); int64_t GetPosition() const; private: ProtoTransferPtr m_transfer; }; } #endif /* MYTHFILEPLAYBACK_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/mythintrinsic.cpp000066400000000000000000000056301360567320200233350ustar00rootroot00000000000000/* * Copyright (C) 2015 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "mythintrinsic.h" #include #if __cplusplus >= 201103L #include typedef std::atomic counter_t; #define GETVALUE(p) (p)->load() #define INCREMENT(p) ((p)->fetch_add(1, std::memory_order_relaxed) + 1) #define DECREMENT(p) ((p)->fetch_sub(1, std::memory_order_relaxed) - 1) #elif defined _MSC_VER #define WIN32_LEAN_AND_MEAN #include typedef volatile LONG counter_t; #define GETVALUE(p) (*(p)) #define INCREMENT(p) InterlockedIncrement(p) #define DECREMENT(p) InterlockedDecrement(p) #elif defined __APPLE__ #include typedef volatile int32_t counter_t; #define GETVALUE(p) (*(p)) #define INCREMENT(p) OSAtomicIncrement32(p) #define DECREMENT(p) OSAtomicDecrement32(p) #elif defined HAS_BUILTIN_SYNC_ADD_AND_FETCH typedef volatile int counter_t; #define GETVALUE(p) (*(p)) #define INCREMENT(p) __sync_add_and_fetch(p, 1) #if defined HAS_BUILTIN_SYNC_SUB_AND_FETCH #define DECREMENT(p) __sync_sub_and_fetch(p, 1) #else #define DECREMENT(p) __sync_add_and_fetch(p, -1) #endif #else #include "private/atomic.h" #ifndef ATOMIC_NOATOMIC typedef Myth::atomic counter_t; #define GETVALUE(p) (p)->load() #define INCREMENT(p) (p)->add_fetch(1) #define DECREMENT(p) (p)->sub_fetch(1) // // Don't know how to do atomic operation for the architecture // #elif defined USE_LOCKED #include "mythlocked.h" typedef Myth::LockedNumber counter_t; #define GETVALUE(p) (p)->Load() #define INCREMENT(p) (p)->Add(1) #define DECREMENT(p) (p)->Sub(1) #else #error Atomic add/sub are not. Overcome using definition USE_LOCKED. #endif #endif using namespace Myth; namespace Myth { struct IntrinsicCounter::Counter { counter_t counter; Counter(int val) : counter(val) {} }; } IntrinsicCounter::IntrinsicCounter(int val) : m_ptr(new Counter(val)) { } IntrinsicCounter::~IntrinsicCounter() { delete m_ptr; } int IntrinsicCounter::GetValue() { return GETVALUE(&m_ptr->counter); } int IntrinsicCounter::Increment() { return INCREMENT(&m_ptr->counter); } int IntrinsicCounter::Decrement() { return DECREMENT(&m_ptr->counter); } pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/mythintrinsic.h000066400000000000000000000024071360567320200230010ustar00rootroot00000000000000/* * Copyright (C) 2015 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHINTRINSIC_H #define MYTHINTRINSIC_H namespace Myth { class IntrinsicCounter { public: IntrinsicCounter(int val); ~IntrinsicCounter(); int GetValue(); int Increment(); int Decrement(); private: struct Counter; Counter* m_ptr; // Prevent copy IntrinsicCounter(const IntrinsicCounter& other); IntrinsicCounter& operator=(const IntrinsicCounter& other); }; } #endif /* MYTHINTRINSIC_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/mythlivetvplayback.cpp000066400000000000000000000620721360567320200243560ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "mythlivetvplayback.h" #include "private/debug.h" #include "private/socket.h" #include "private/os/threads/mutex.h" #include "private/os/threads/timeout.h" #include "private/builtin.h" #include #include #include #define MIN_TUNE_DELAY 5 #define MAX_TUNE_DELAY 60 #define TICK_USEC 100000 // valid range: 10000 - 999999 #define START_TIMEOUT 2000 // millisec #define AHEAD_TIMEOUT 10000 // millisec #define BREAK_TIMEOUT 4000 // millisec using namespace Myth; /////////////////////////////////////////////////////////////////////////////// //// //// Protocol connection to control LiveTV playback //// LiveTVPlayback::LiveTVPlayback(EventHandler& handler) : ProtoMonitor(handler.GetServer(), handler.GetPort()), EventSubscriber() , m_eventHandler(handler) , m_eventSubscriberId(0) , m_tuneDelay(MIN_TUNE_DELAY) , m_limitTuneAttempts(true) , m_recorder() , m_signal() , m_chain() , m_chunk(MYTH_LIVETV_CHUNK_SIZE) { m_buffer.pos = 0; m_buffer.len = 0; m_buffer.data = new unsigned char[m_chunk]; m_eventSubscriberId = m_eventHandler.CreateSubscription(this); m_eventHandler.SubscribeForEvent(m_eventSubscriberId, EVENT_SIGNAL); m_eventHandler.SubscribeForEvent(m_eventSubscriberId, EVENT_LIVETV_CHAIN); m_eventHandler.SubscribeForEvent(m_eventSubscriberId, EVENT_LIVETV_WATCH); m_eventHandler.SubscribeForEvent(m_eventSubscriberId, EVENT_DONE_RECORDING); m_eventHandler.SubscribeForEvent(m_eventSubscriberId, EVENT_UPDATE_FILE_SIZE); Open(); } LiveTVPlayback::LiveTVPlayback(const std::string& server, unsigned port) : ProtoMonitor(server, port), EventSubscriber() , m_eventHandler(server, port) , m_eventSubscriberId(0) , m_tuneDelay(MIN_TUNE_DELAY) , m_recorder() , m_signal() , m_chain() , m_chunk(MYTH_LIVETV_CHUNK_SIZE) { m_buffer.pos = 0; m_buffer.len = 0; m_buffer.data = new unsigned char[m_chunk]; // Private handler will be stopped and closed by destructor. m_eventSubscriberId = m_eventHandler.CreateSubscription(this); m_eventHandler.SubscribeForEvent(m_eventSubscriberId, EVENT_SIGNAL); m_eventHandler.SubscribeForEvent(m_eventSubscriberId, EVENT_LIVETV_CHAIN); m_eventHandler.SubscribeForEvent(m_eventSubscriberId, EVENT_LIVETV_WATCH); m_eventHandler.SubscribeForEvent(m_eventSubscriberId, EVENT_DONE_RECORDING); m_eventHandler.SubscribeForEvent(m_eventSubscriberId, EVENT_UPDATE_FILE_SIZE); Open(); } LiveTVPlayback::~LiveTVPlayback() { if (m_eventSubscriberId) m_eventHandler.RevokeSubscription(m_eventSubscriberId); Close(); delete[] m_buffer.data; } bool LiveTVPlayback::Open() { // Begin critical section OS::CLockGuard lock(*m_mutex); if (ProtoMonitor::IsOpen()) return true; if (ProtoMonitor::Open()) { if (!m_eventHandler.IsRunning()) { OS::CTimeout timeout(START_TIMEOUT); m_eventHandler.Start(); do { usleep(TICK_USEC); } while (!m_eventHandler.IsConnected() && timeout.TimeLeft() > 0); if (!m_eventHandler.IsConnected()) DBG(DBG_WARN, "%s: event handler is not connected in time\n", __FUNCTION__); else DBG(DBG_DEBUG, "%s: event handler is connected\n", __FUNCTION__); } return true; } return false; } void LiveTVPlayback::Close() { // Begin critical section OS::CLockGuard lock(*m_mutex); m_recorder.reset(); ProtoMonitor::Close(); } void LiveTVPlayback::SetTuneDelay(unsigned delay) { if (delay < MIN_TUNE_DELAY) m_tuneDelay = MIN_TUNE_DELAY; else if (delay > MAX_TUNE_DELAY) m_tuneDelay = MAX_TUNE_DELAY; else m_tuneDelay = delay; } void LiveTVPlayback::SetLimitTuneAttempts(bool limit) { // true : Try first tunable card in prefered order // false: Try all tunable cards in prefered order m_limitTuneAttempts = limit; } bool LiveTVPlayback::SpawnLiveTV(const std::string& chanNum, const ChannelList& channels) { // Begin critical section OS::CLockGuard lock(*m_mutex); if (!ProtoMonitor::IsOpen() || !m_eventHandler.IsConnected()) { DBG(DBG_ERROR, "%s: not connected\n", __FUNCTION__); return false; } StopLiveTV(); preferredCards_t preferredCards = FindTunableCardIds(chanNum, channels); preferredCards_t::const_iterator card = preferredCards.begin(); while (card != preferredCards.end()) { InitChain(); // Setup chain const CardInputPtr& input = card->second.first; const ChannelPtr& channel = card->second.second; DBG(DBG_DEBUG, "%s: trying recorder num (%" PRIu32 ") channum (%s)\n", __FUNCTION__, input->cardId, channel->chanNum.c_str()); m_recorder = GetRecorderFromNum((int) input->cardId); // Setup the chain m_chain.switchOnCreate = true; m_chain.watch = true; if (m_recorder->SpawnLiveTV(m_chain.UID, channel->chanNum)) { // Wait chain update until time limit uint32_t delayMs = m_tuneDelay * 1000; OS::CTimeout timeout(delayMs); do { lock.Unlock(); // Release the latch to allow chain update usleep(TICK_USEC); lock.Lock(); if (!m_chain.switchOnCreate) { DBG(DBG_DEBUG, "%s: tune delay (%" PRIu32 "ms)\n", __FUNCTION__, (delayMs - timeout.TimeLeft())); return true; } } while (timeout.TimeLeft() > 0); DBG(DBG_ERROR, "%s: tune delay exceeded (%" PRIu32 "ms)\n", __FUNCTION__, delayMs); m_recorder->StopLiveTV(); } ClearChain(); // Check if we need to stop after first attempt at tuning if (m_limitTuneAttempts) { DBG(DBG_DEBUG, "%s: limiting tune attempts to first tunable card\n", __FUNCTION__); break; } // Retry the next preferred card ++card; } return false; } bool LiveTVPlayback::SpawnLiveTV(const ChannelPtr& thisChannel) { ChannelList list; list.push_back(thisChannel); return SpawnLiveTV(thisChannel->chanNum, list); } void LiveTVPlayback::StopLiveTV() { // Begin critical section OS::CLockGuard lock(*m_mutex); if (m_recorder && m_recorder->IsPlaying()) { m_recorder->StopLiveTV(); // If recorder is keeping recording then release it to clear my instance status. // Otherwise next program would be considered as preserved. if (m_recorder->IsLiveRecording()) m_recorder.reset(); } } void LiveTVPlayback::InitChain() { char buf[32]; // Begin critical section OS::CLockGuard lock(*m_mutex); time_to_iso8601(time(NULL), buf); m_chain.UID = m_socket->GetMyHostName(); m_chain.UID.append("-").append(buf); m_chain.currentSequence = 0; m_chain.lastSequence = 0; m_chain.watch = false; m_chain.switchOnCreate = true; m_chain.chained.clear(); m_chain.currentTransfer.reset(); } void LiveTVPlayback::ClearChain() { // Begin critical section OS::CLockGuard lock(*m_mutex); m_chain.currentSequence = 0; m_chain.lastSequence = 0; m_chain.watch = false; m_chain.switchOnCreate = false; m_chain.chained.clear(); m_chain.currentTransfer.reset(); } bool LiveTVPlayback::IsChained(const Program& program) { for (chained_t::const_iterator it = m_chain.chained.begin(); it != m_chain.chained.end(); ++it) { if (it->first && it->first->GetPathName() == program.fileName) return true; } return false; } void LiveTVPlayback::HandleChainUpdate() { OS::CLockGuard lock(*m_mutex); // Lock chain ProtoRecorderPtr recorder(m_recorder); if (!recorder) return; ProgramPtr prog = recorder->GetCurrentRecording(); /* * If program file doesn't exist in the recorder chain then create a new * transfer and add it to the chain. */ if (prog && !prog->fileName.empty() && !IsChained(*prog)) { DBG(DBG_DEBUG, "%s: liveTV (%s): adding new transfer %s\n", __FUNCTION__, m_chain.UID.c_str(), prog->fileName.c_str()); ProtoTransferPtr transfer(new ProtoTransfer(recorder->GetServer(), recorder->GetPort(), prog->fileName, prog->recording.storageGroup)); // Pop previous dummy file if exists then add the new into the chain if (m_chain.lastSequence && m_chain.chained[m_chain.lastSequence - 1].first->GetSize() == 0) { --m_chain.lastSequence; m_chain.chained.pop_back(); } m_chain.chained.push_back(std::make_pair(transfer, prog)); m_chain.lastSequence = m_chain.chained.size(); /* * If switchOnCreate flag and file is filled then switch immediatly. * Else we will switch later on the next event 'UPDATE_FILE_SIZE' */ if (m_chain.switchOnCreate && transfer->GetSize() > 0 && SwitchChainLast()) m_chain.switchOnCreate = false; m_chain.watch = false; // Chain update done. Restore watch flag DBG(DBG_DEBUG, "%s: liveTV (%s): chain last (%u), watching (%u)\n", __FUNCTION__, m_chain.UID.c_str(), m_chain.lastSequence, m_chain.currentSequence); } } bool LiveTVPlayback::SwitchChain(unsigned sequence) { OS::CLockGuard lock(*m_mutex); // Check for out of range if (sequence < 1 || sequence > m_chain.lastSequence) return false; // If closed then try to open if (!m_chain.chained[sequence - 1].first->IsOpen() && !m_chain.chained[sequence - 1].first->Open()) return false; m_chain.currentTransfer = m_chain.chained[sequence - 1].first; m_chain.currentSequence = sequence; DBG(DBG_DEBUG, "%s: switch to file (%u) %s\n", __FUNCTION__, (unsigned)m_chain.currentTransfer->GetFileId(), m_chain.currentTransfer->GetPathName().c_str()); return true; } bool LiveTVPlayback::SwitchChainLast() { if (SwitchChain(m_chain.lastSequence)) { ProtoRecorderPtr recorder(m_recorder); ProtoTransferPtr transfer(m_chain.currentTransfer); if (recorder && transfer && recorder->TransferSeek(*transfer, 0, WHENCE_SET) == 0) return true; } return false; } void LiveTVPlayback::HandleBackendMessage(EventMessagePtr msg) { ProtoRecorderPtr recorder(m_recorder); if (!recorder || !recorder->IsPlaying()) return; switch (msg->event) { /* * Event: LIVETV_CHAIN UPDATE * * Called in response to the backend's notification of a chain update. * The recorder is supplied and will be queried for the current recording * to determine if a new file needs to be added to the chain of files * in the live tv instance. */ case EVENT_LIVETV_CHAIN: if (msg->subject.size() >= 3) { if (msg->subject[1] == "UPDATE" && msg->subject[2] == m_chain.UID) HandleChainUpdate(); } break; /* * Event: LIVETV_WATCH * * Called in response to the backend's notification of a livetv watch. * The recorder is supplied and will be updated for the watch signal. * This event is used to manage program breaks while watching live tv. * When the guide data marks the end of one show and the beginning of * the next, which will be recorded to a new file, this instructs the * frontend to terminate the existing playback, and change channel to * the new file. Before updating livetv chain and switching to new file * we must to wait for event DONE_RECORDING that informs the current * show is completed. Then we will call livetv chain update to get * current program info. Watch signal will be down during this period. */ case EVENT_LIVETV_WATCH: if (msg->subject.size() >= 3) { int32_t rnum; int8_t flag; if (string_to_int32(msg->subject[1].c_str(), &rnum) == 0 && string_to_int8(msg->subject[2].c_str(), &flag) == 0) { if (recorder->GetNum() == (int)rnum) { OS::CLockGuard lock(*m_mutex); // Lock chain m_chain.watch = true; } } } break; /* * Event: DONE_RECORDING * * Indicates that an active recording has completed on the specified * recorder. used to manage program breaks while watching live tv. * When receive event for recorder, we force an update of livetv chain * to get current program info when chain is not yet updated. * Watch signal is used when up, to mark the break period and * queuing the frontend for reading file buffer. */ case EVENT_DONE_RECORDING: if (msg->subject.size() >= 2) { int32_t rnum; if (string_to_int32(msg->subject[1].c_str(), &rnum) == 0 && recorder->GetNum() == (int)rnum) { // Recorder is not subscriber. So callback event to it recorder->DoneRecordingCallback(); // Manage program break if (m_chain.watch) { /* * Last recording is now completed but watch signal is ON. * Then force live tv chain update for the new current * program. We will retry for a short period before returning. */ OS::CTimeout timeout(BREAK_TIMEOUT); do { usleep(500000); // wait for 500 ms HandleChainUpdate(); } while (m_chain.watch && timeout.TimeLeft() > 0); } } } break; case EVENT_UPDATE_FILE_SIZE: if (msg->subject.size() >= 3) { OS::CLockGuard lock(*m_mutex); // Lock chain if (m_chain.lastSequence > 0) { int64_t newsize; // Message contains chanid + starttime as recorded key if (msg->subject.size() >= 4) { uint32_t chanid; time_t startts; if (string_to_uint32(msg->subject[1].c_str(), &chanid) || string_to_time(msg->subject[2].c_str(), &startts) || m_chain.chained[m_chain.lastSequence -1].second->channel.chanId != chanid || m_chain.chained[m_chain.lastSequence -1].second->recording.startTs != startts || string_to_int64(msg->subject[3].c_str(), &newsize) || m_chain.chained[m_chain.lastSequence - 1].first->GetSize() >= newsize) break; } // Message contains recordedid as key else { uint32_t recordedid; if (string_to_uint32(msg->subject[1].c_str(), &recordedid) || m_chain.chained[m_chain.lastSequence -1].second->recording.recordedId != recordedid || string_to_int64(msg->subject[2].c_str(), &newsize) || m_chain.chained[m_chain.lastSequence - 1].first->GetSize() >= newsize) break; } // Update transfer file size m_chain.chained[m_chain.lastSequence - 1].first->SetSize(newsize); // Is wait the filling before switching ? if (m_chain.switchOnCreate && SwitchChainLast()) m_chain.switchOnCreate = false; DBG(DBG_DEBUG, "%s: liveTV (%s): chain last (%u) filesize %" PRIi64 "\n", __FUNCTION__, m_chain.UID.c_str(), m_chain.lastSequence, newsize); } } break; case EVENT_SIGNAL: if (msg->subject.size() >= 2) { int32_t rnum; if (string_to_int32(msg->subject[1].c_str(), &rnum) == 0 && recorder->GetNum() == (int)rnum) m_signal = msg->signal; } break; //case EVENT_HANDLER_STATUS: // if (msg->subject[0] == EVENTHANDLER_DISCONNECTED) // closeTransfer(); // break; default: break; } } void LiveTVPlayback::SetChunk(unsigned size) { if (size < MYTH_LIVETV_CHUNK_MIN) size = MYTH_LIVETV_CHUNK_MIN; else if (size > MYTH_LIVETV_CHUNK_MAX) size = MYTH_LIVETV_CHUNK_MAX; m_buffer.pos = m_buffer.len = 0; delete[] m_buffer.data; m_buffer.data = new unsigned char[size]; m_chunk = size; } int64_t LiveTVPlayback::GetSize() const { int64_t size = 0; OS::CLockGuard lock(*m_mutex); // Lock chain for (chained_t::const_iterator it = m_chain.chained.begin(); it != m_chain.chained.end(); ++it) size += it->first->GetSize(); return size; } int LiveTVPlayback::Read(void* buffer, unsigned n) { int c = 0; bool refill = true; for (;;) { // all requested data are in the buffer if (m_buffer.len >= n) { memcpy(static_cast(buffer) + c, m_buffer.data + m_buffer.pos, n); c += n; m_buffer.pos += n; m_buffer.len -= n; return c; } // fill with the rest of data before read a new chunk if (m_buffer.len > 0) { memcpy(static_cast(buffer) + c, m_buffer.data + m_buffer.pos, m_buffer.len); c += m_buffer.len; n -= m_buffer.len; m_buffer.len = 0; } if (!refill) break; m_buffer.pos = 0; int r = _read(m_buffer.data, m_chunk); if (r < 0) return -1; m_buffer.len += r; refill = false; // won't read again } return c; } int LiveTVPlayback::_read(void* buffer, unsigned n) { int r = 0; bool retry; int64_t s, fp; // Begin critical section // First of all i hold my shared resources using copies ProtoRecorderPtr recorder(m_recorder); if (!m_chain.currentTransfer || !recorder) return -1; fp = m_chain.currentTransfer->GetPosition(); do { retry = false; s = m_chain.currentTransfer->GetRemaining(); // Acceptable block size if (s == 0) { OS::CTimeout timeout(AHEAD_TIMEOUT); for (;;) { // Reading ahead if (m_chain.currentSequence == m_chain.lastSequence) { int64_t rp = recorder->GetFilePosition(); if (rp > fp) { m_chain.currentTransfer->SetSize(rp); retry = true; break; } if (!timeout.TimeLeft()) { DBG(DBG_WARN, "%s: read position is ahead (%" PRIi64 ")\n", __FUNCTION__, fp); return 0; } usleep(500000); } // Switch next file transfer is required to continue else { if (!SwitchChain(m_chain.currentSequence + 1)) return -1; if (m_chain.currentTransfer->GetPosition() != 0) recorder->TransferSeek(*(m_chain.currentTransfer), 0, WHENCE_SET); DBG(DBG_DEBUG, "%s: liveTV (%s): chain last (%u), watching (%u)\n", __FUNCTION__, m_chain.UID.c_str(), m_chain.lastSequence, m_chain.currentSequence); retry = true; break; } } } else if (s < 0) return -1; } while (retry); if (s < (int64_t)n) n = (unsigned)s ; r = recorder->TransferRequestBlock(*(m_chain.currentTransfer), buffer, n); return r; } int64_t LiveTVPlayback::Seek(int64_t offset, WHENCE_t whence) { if (whence == WHENCE_CUR) { if (offset == 0) { int64_t p = _seek(offset, whence); // it returns the current position of the first byte in buffer return (p >= m_buffer.len ? p - m_buffer.len : p); } // rebase to the first position in the buffer offset -= m_buffer.len; } m_buffer.len = 0; // clear data in buffer return _seek(offset, whence); } int64_t LiveTVPlayback::_seek(int64_t offset, WHENCE_t whence) { OS::CLockGuard lock(*m_mutex); // Lock chain if (!m_recorder || !m_chain.currentSequence) return -1; unsigned ci = m_chain.currentSequence - 1; // current sequence index int64_t size = GetSize(); // total stream size int64_t position = GetPosition(); // absolute position in stream int64_t p = 0; switch (whence) { case WHENCE_SET: p = offset; break; case WHENCE_END: p = size + offset; break; case WHENCE_CUR: p = position + offset; break; default: return -1; } if (p > size || p < 0) { DBG(DBG_WARN, "%s: invalid seek (%" PRId64 ")\n", __FUNCTION__, p); return -1; } if (p > position) { for (;;) { if (position + m_chain.chained[ci].first->GetRemaining() >= p) { // Try seek file to desired position. On success switch chain if (m_recorder->TransferSeek(*(m_chain.chained[ci].first), p - position, WHENCE_CUR) < 0 || !SwitchChain(++ci)) return -1; return p; } position += m_chain.chained[ci].first->GetRemaining(); ++ci; // switch next if (ci < m_chain.lastSequence) position += m_chain.chained[ci].first->GetPosition(); else return -1; } } if (p < position) { for (;;) { if (position - m_chain.chained[ci].first->GetPosition() <= p) { // Try seek file to desired position. On success switch chain if (m_recorder->TransferSeek(*(m_chain.chained[ci].first), p - position, WHENCE_CUR) < 0 || !SwitchChain(++ci)) return -1; return p; } position -= m_chain.chained[ci].first->GetPosition(); if (ci > 0) { --ci; // switch previous position -= m_chain.chained[ci].first->GetRemaining(); } else return -1; } } // p == position return p; } int64_t LiveTVPlayback::GetPosition() const { int64_t pos = 0; OS::CLockGuard lock(*m_mutex); // Lock chain if (m_chain.currentSequence) { unsigned s = m_chain.currentSequence - 1; for (unsigned i = 0; i < s; ++i) pos += m_chain.chained[i].first->GetSize(); pos += m_chain.currentTransfer->GetPosition(); } // it returns the current position of first byte in buffer return pos - m_buffer.len; } bool LiveTVPlayback::IsPlaying() const { ProtoRecorderPtr recorder(m_recorder); return (recorder ? recorder->IsPlaying() : false); } bool LiveTVPlayback::IsLiveRecording() const { ProtoRecorderPtr recorder(m_recorder); return (recorder ? recorder->IsLiveRecording() : false); } bool LiveTVPlayback::KeepLiveRecording(bool keep) { ProtoRecorderPtr recorder(m_recorder); // Begin critical section OS::CLockGuard lock(*m_mutex); if (recorder && recorder->IsPlaying()) { ProgramPtr prog = recorder->GetCurrentRecording(); if (prog) { if (keep) { if (UndeleteRecording(*prog) && recorder->SetLiveRecording(keep)) { QueryGenpixmap(*prog); return true; } } else { if (recorder->SetLiveRecording(keep) && recorder->FinishRecording()) return true; } } } return false; } ProgramPtr LiveTVPlayback::GetPlayedProgram() const { OS::CLockGuard lock(*m_mutex); // Lock chain if (m_chain.currentSequence > 0) return m_chain.chained[m_chain.currentSequence - 1].second; return ProgramPtr(); } time_t LiveTVPlayback::GetLiveTimeStart() const { OS::CLockGuard lock(*m_mutex); // Lock chain if (m_chain.lastSequence) return m_chain.chained[0].second->recording.startTs; return (time_t)(-1); } unsigned LiveTVPlayback::GetChainedCount() const { OS::CLockGuard lock(*m_mutex); // Lock chain return m_chain.lastSequence; } ProgramPtr LiveTVPlayback::GetChainedProgram(unsigned sequence) const { OS::CLockGuard lock(*m_mutex); // Lock chain if (sequence > 0 && sequence <= m_chain.lastSequence) return m_chain.chained[sequence - 1].second; return ProgramPtr(); } uint32_t LiveTVPlayback::GetCardId() const { ProtoRecorderPtr recorder(m_recorder); return (recorder ? recorder->GetNum() : 0); } SignalStatusPtr LiveTVPlayback::GetSignal() const { return (m_recorder ? m_signal : SignalStatusPtr()); } LiveTVPlayback::preferredCards_t LiveTVPlayback::FindTunableCardIds(const std::string& chanNum, const ChannelList& channels) { // Make the set of channels matching the desired channel number ChannelList chanset; for (ChannelList::const_iterator it = channels.begin(); it != channels.end(); ++it) { if ((*it)->chanNum == chanNum) chanset.push_back(*it); } // Retrieve unlocked encoders and fill the list of preferred cards. // It is ordered by its key liveTVOrder and contains matching between channels // and card inputs using their respective sourceId and mplexId preferredCards_t preferredCards; CardInputListPtr inputs = GetFreeInputs(0); for (CardInputList::const_iterator iti = inputs->begin(); iti != inputs->end(); ++iti) { for (ChannelList::const_iterator itchan = chanset.begin(); itchan != chanset.end(); ++itchan) { if ((*itchan)->sourceId == (*iti)->sourceId && ( (*iti)->mplexId == 0 || (*iti)->mplexId == (*itchan)->mplexId )) { preferredCards.insert(std::make_pair((*iti)->liveTVOrder, std::make_pair(*iti, *itchan))); DBG(DBG_DEBUG, "%s: [%u] channel=%s(%" PRIu32 ") card=%" PRIu32 " input=%s(%" PRIu32 ") mplex=%" PRIu32 " source=%" PRIu32 "\n", __FUNCTION__, (*iti)->liveTVOrder, (*itchan)->callSign.c_str(), (*itchan)->chanId, (*iti)->cardId, (*iti)->inputName.c_str(), (*iti)->inputId, (*iti)->mplexId, (*iti)->sourceId); break; } } } return preferredCards; } pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/mythlivetvplayback.h000066400000000000000000000071221360567320200240160ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHLIVETVPLAYBACK_H #define MYTHLIVETVPLAYBACK_H #include "proto/mythprotorecorder.h" #include "proto/mythprototransfer.h" #include "proto/mythprotomonitor.h" #include "mythstream.h" #include "mytheventhandler.h" #include "mythtypes.h" #include #define MYTH_LIVETV_CHUNK_SIZE 64000 #define MYTH_LIVETV_CHUNK_MIN 8000 #define MYTH_LIVETV_CHUNK_MAX 128000 namespace Myth { class LiveTVPlayback : private ProtoMonitor, public Stream, private EventSubscriber { public: LiveTVPlayback(EventHandler& handler); LiveTVPlayback(const std::string& server, unsigned port); ~LiveTVPlayback(); bool Open(); void Close(); bool IsOpen() { return ProtoMonitor::IsOpen(); } void SetTuneDelay(unsigned delay); void SetLimitTuneAttempts(bool limit); bool SpawnLiveTV(const std::string& chanNum, const ChannelList& channels); bool SpawnLiveTV(const ChannelPtr& thisChannel); void StopLiveTV(); void SetChunk(unsigned size); // to change the size of read chunk // Implement Stream int64_t GetSize() const; int Read(void *buffer, unsigned n); int64_t Seek(int64_t offset, WHENCE_t whence); int64_t GetPosition() const; bool IsPlaying() const; bool IsLiveRecording() const; bool KeepLiveRecording(bool keep); ProgramPtr GetPlayedProgram() const; time_t GetLiveTimeStart() const; unsigned GetChainedCount() const; ProgramPtr GetChainedProgram(unsigned sequence) const; uint32_t GetCardId() const; SignalStatusPtr GetSignal() const; // Implement EventSubscriber void HandleBackendMessage(EventMessagePtr msg); private: EventHandler m_eventHandler; unsigned m_eventSubscriberId; unsigned m_tuneDelay; bool m_limitTuneAttempts; ProtoRecorderPtr m_recorder; SignalStatusPtr m_signal; typedef std::vector > chained_t; struct { std::string UID; chained_t chained; ProtoTransferPtr currentTransfer; volatile unsigned currentSequence; volatile unsigned lastSequence; volatile bool watch; volatile bool switchOnCreate; } m_chain; void InitChain(); void ClearChain(); bool IsChained(const Program& program); void HandleChainUpdate(); bool SwitchChain(unsigned sequence); bool SwitchChainLast(); typedef std::multimap > preferredCards_t; preferredCards_t FindTunableCardIds(const std::string& chanNum, const ChannelList& channels); int _read(void *buffer, unsigned n); int64_t _seek(int64_t offset, WHENCE_t whence); // data buffer unsigned m_chunk; // the size of block to read struct { unsigned pos; unsigned len; unsigned char * data; } m_buffer; }; } #endif /* MYTHLIVETVPLAYBACK_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/mythlocked.cpp000066400000000000000000000027021360567320200225710ustar00rootroot00000000000000/* * Copyright (C) 2015 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "mythlocked.h" #include "private/os/threads/mutex.h" using namespace Myth; namespace Myth { struct LockGuard::Lockable { OS::CMutex mutex; }; } LockGuard::LockGuard(Lockable* lock) : m_lock(lock) { m_lock->mutex.Lock(); } LockGuard::~LockGuard() { m_lock->mutex.Unlock(); } LockGuard::Lockable* LockGuard::CreateLock() { return new Lockable(); } void LockGuard::DestroyLock(Lockable* lock) { delete lock; } void LockGuard::Lock(Lockable* lock) { lock->mutex.Lock(); } void LockGuard::Unlock(Lockable* lock) { lock->mutex.Unlock(); } void LockGuard::ClearLock(Lockable* lock) { lock->mutex.Clear(); } pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/mythlocked.h000066400000000000000000000067441360567320200222500ustar00rootroot00000000000000/* * Copyright (C) 2015 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHLOCKED_H #define MYTHLOCKED_H namespace Myth { /** * This implements a "guard" pattern */ class LockGuard { public: struct Lockable; /** * Initialize a guard which hold the lock. The lock will be released by the * destructor. * @param lock The pointer to lockable object */ LockGuard(Lockable* lock); ~LockGuard(); /** * Create a new lockable object. The allocated resource must be freed by * calling DestroyLock. * @return The pointer to the new lockable object */ static Lockable* CreateLock(); /** * Destroy lockable object previously allocated with CreateLock. * @param lock The pointer to lockable object */ static void DestroyLock(Lockable* lock); /** * Return once the lock is held and recursive count has been incremented. * @param lock The pointer to lockable object */ static void Lock(Lockable* lock); /** * Return once the lock is released or recursive count has been decremented. * @param lock The pointer to lockable object */ static void Unlock(Lockable* lock); /** * Return once recursive count has been cleared and the lock is released. * @param lock */ static void ClearLock(Lockable* lock); private: Lockable* m_lock; }; template class Locked { public: Locked(const T& val) : m_val(val) , m_lock(LockGuard::CreateLock()) {} ~Locked() { LockGuard::DestroyLock(m_lock); } T Load() { LockGuard g(m_lock); return m_val; // return copy } const T& Store(const T& newval) { LockGuard g(m_lock); m_val = newval; return newval; // return input } class value { public: value(T& val, LockGuard::Lockable*& lock) : m_val(val), m_g(lock) {} T& operator()() const { return m_val; } private: T& m_val; LockGuard m_g; }; value Get() { return value(m_val, m_lock); } protected: T m_val; LockGuard::Lockable* m_lock; // Prevent copy Locked(const Locked& other); Locked& operator=(const Locked& other); }; template class LockedNumber : public Locked { public: LockedNumber(T val) : Locked(val) {} T Add(T amount) { LockGuard g(Locked::m_lock); return Locked::m_val += amount; } T operator+=(T amount) { return Add(amount); } T Sub(T amount) { LockGuard g(Locked::m_lock); return Locked::m_val -= amount; } T operator-=(T amount) { return Sub(amount); } }; } #endif /* MYTHLOCKED_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/mythrecordingplayback.cpp000066400000000000000000000201251360567320200250120ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "mythrecordingplayback.h" #include "private/debug.h" #include "private/os/threads/mutex.h" #include "private/builtin.h" #include #include using namespace Myth; /////////////////////////////////////////////////////////////////////////////// //// //// Protocol connection to control playback //// RecordingPlayback::RecordingPlayback(EventHandler& handler) : ProtoPlayback(handler.GetServer(), handler.GetPort()), EventSubscriber() , m_eventHandler(handler) , m_eventSubscriberId(0) , m_transfer(NULL) , m_recording(NULL) , m_readAhead(false) , m_chunk(MYTH_RECORDING_CHUNK_SIZE) { m_buffer.pos = 0; m_buffer.len = 0; m_buffer.data = new unsigned char[m_chunk]; m_eventSubscriberId = m_eventHandler.CreateSubscription(this); m_eventHandler.SubscribeForEvent(m_eventSubscriberId, EVENT_UPDATE_FILE_SIZE); Open(); } RecordingPlayback::RecordingPlayback(const std::string& server, unsigned port) : ProtoPlayback(server, port), EventSubscriber() , m_eventHandler(server, port) , m_eventSubscriberId(0) , m_transfer(NULL) , m_recording(NULL) , m_readAhead(false) , m_chunk(MYTH_RECORDING_CHUNK_SIZE) { m_buffer.pos = 0; m_buffer.len = 0; m_buffer.data = new unsigned char[m_chunk]; // Private handler will be stopped and closed by destructor. m_eventSubscriberId = m_eventHandler.CreateSubscription(this); m_eventHandler.SubscribeForEvent(m_eventSubscriberId, EVENT_UPDATE_FILE_SIZE); Open(); } RecordingPlayback::~RecordingPlayback() { if (m_eventSubscriberId) m_eventHandler.RevokeSubscription(m_eventSubscriberId); Close(); delete[] m_buffer.data; } bool RecordingPlayback::Open() { // Begin critical section OS::CLockGuard lock(*m_mutex); if (ProtoPlayback::IsOpen()) return true; if (ProtoPlayback::Open()) { if (!m_eventHandler.IsRunning()) m_eventHandler.Start(); return true; } return false; } void RecordingPlayback::Close() { // Begin critical section OS::CLockGuard lock(*m_mutex); CloseTransfer(); ProtoPlayback::Close(); } bool RecordingPlayback::OpenTransfer(ProgramPtr recording) { // Begin critical section OS::CLockGuard lock(*m_mutex); if (!ProtoPlayback::IsOpen()) return false; CloseTransfer(); if (recording) { m_transfer.reset(new ProtoTransfer(m_server, m_port, recording->fileName, recording->recording.storageGroup)); if (m_transfer->Open()) { m_recording.swap(recording); m_recording->fileSize = m_transfer->GetSize(); return true; } m_transfer.reset(); } return false; } void RecordingPlayback::CloseTransfer() { // Begin critical section OS::CLockGuard lock(*m_mutex); m_recording.reset(); if (m_transfer) { TransferDone(*m_transfer); m_transfer->Close(); m_transfer.reset(); } } bool RecordingPlayback::TransferIsOpen() { ProtoTransferPtr transfer(m_transfer); if (transfer) return ProtoPlayback::TransferIsOpen(*transfer); return false; } void RecordingPlayback::SetChunk(unsigned size) { if (size < MYTH_RECORDING_CHUNK_MIN) size = MYTH_RECORDING_CHUNK_MIN; else if (size > MYTH_RECORDING_CHUNK_MAX) size = MYTH_RECORDING_CHUNK_MAX; m_buffer.pos = m_buffer.len = 0; delete[] m_buffer.data; m_buffer.data = new unsigned char[size]; m_chunk = size; } int64_t RecordingPlayback::GetSize() const { ProtoTransferPtr transfer(m_transfer); if (transfer) return transfer->GetSize(); return 0; } int RecordingPlayback::Read(void* buffer, unsigned n) { int c = 0; bool refill = true; for (;;) { // all requested data are in the buffer if (m_buffer.len >= n) { memcpy(static_cast(buffer) + c, m_buffer.data + m_buffer.pos, n); c += n; m_buffer.pos += n; m_buffer.len -= n; return c; } // fill with the rest of data before read a new chunk if (m_buffer.len > 0) { memcpy(static_cast(buffer) + c, m_buffer.data + m_buffer.pos, m_buffer.len); c += m_buffer.len; n -= m_buffer.len; m_buffer.len = 0; } if (!refill) break; m_buffer.pos = 0; int r = _read(m_buffer.data, m_chunk); if (r < 0) return -1; m_buffer.len += r; refill = false; // won't read again } return c; } int RecordingPlayback::_read(void *buffer, unsigned n) { ProtoTransferPtr transfer(m_transfer); if (transfer) { if (!m_readAhead) { int64_t s = transfer->GetRemaining(); // Acceptable block size if (s > 0) { if (s < (int64_t)n) n = (unsigned)s; // Request block data from transfer socket return TransferRequestBlock(*transfer, buffer, n); } return 0; } else { // Request block data from transfer socket return TransferRequestBlock(*transfer, buffer, n); } } return -1; } int64_t RecordingPlayback::Seek(int64_t offset, WHENCE_t whence) { if (whence == WHENCE_CUR) { if (offset == 0) { int64_t p = _seek(offset, whence); // it returns the current position of the first byte in buffer return (p >= m_buffer.len ? p - m_buffer.len : p); } // rebase to the first position in the buffer offset -= m_buffer.len; } m_buffer.len = 0; // clear data in buffer return _seek(offset, whence); } int64_t RecordingPlayback::_seek(int64_t offset, WHENCE_t whence) { ProtoTransferPtr transfer(m_transfer); if (transfer) return TransferSeek(*transfer, offset, whence); return -1; } int64_t RecordingPlayback::GetPosition() const { ProtoTransferPtr transfer(m_transfer); if (transfer) { // it returns the current position of first byte in buffer return transfer->GetPosition() - m_buffer.len; } return 0; } void RecordingPlayback::HandleBackendMessage(EventMessagePtr msg) { // First of all i hold shared resources using copies ProgramPtr recording(m_recording); ProtoTransferPtr transfer(m_transfer); switch (msg->event) { case EVENT_UPDATE_FILE_SIZE: if (msg->subject.size() >= 3 && recording && transfer) { int64_t newsize; // Message contains chanid + starttime as recorded key if (msg->subject.size() >= 4) { uint32_t chanid; time_t startts; if (string_to_uint32(msg->subject[1].c_str(), &chanid) || string_to_time(msg->subject[2].c_str(), &startts) || recording->channel.chanId != chanid || recording->recording.startTs != startts || string_to_int64(msg->subject[3].c_str(), &newsize)) break; } // Message contains recordedid as key else { uint32_t recordedid; if (string_to_uint32(msg->subject[1].c_str(), &recordedid) || recording->recording.recordedId != recordedid || string_to_int64(msg->subject[2].c_str(), &newsize)) break; } // The file grows. Allow reading ahead m_readAhead = true; transfer->SetSize(newsize); recording->fileSize = newsize; DBG(DBG_DEBUG, "%s: (%d) %s %" PRIi64 "\n", __FUNCTION__, msg->event, recording->fileName.c_str(), newsize); } break; //case EVENT_HANDLER_STATUS: // if (msg->subject[0] == EVENTHANDLER_DISCONNECTED) // closeTransfer(); // break; default: break; } } pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/mythrecordingplayback.h000066400000000000000000000045211360567320200244610ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHRECORDINGPLAYBACK_H #define MYTHRECORDINGPLAYBACK_H #include "proto/mythprotoplayback.h" #include "proto/mythprototransfer.h" #include "mythstream.h" #include "mytheventhandler.h" #define MYTH_RECORDING_CHUNK_SIZE 64000 #define MYTH_RECORDING_CHUNK_MIN 8000 #define MYTH_RECORDING_CHUNK_MAX 128000 namespace Myth { class RecordingPlayback : private ProtoPlayback, public Stream, private EventSubscriber { public: RecordingPlayback(EventHandler& handler); RecordingPlayback(const std::string& server, unsigned port); ~RecordingPlayback(); bool Open(); void Close(); bool IsOpen() { return ProtoPlayback::IsOpen(); } bool OpenTransfer(ProgramPtr recording); void CloseTransfer(); bool TransferIsOpen(); void SetChunk(unsigned size); // to change the size of read chunk // Implement Stream int64_t GetSize() const; int Read(void *buffer, unsigned n); int64_t Seek(int64_t offset, WHENCE_t whence); int64_t GetPosition() const; // Implement EventSubscriber void HandleBackendMessage(EventMessagePtr msg); private: EventHandler m_eventHandler; unsigned m_eventSubscriberId; ProtoTransferPtr m_transfer; ProgramPtr m_recording; volatile bool m_readAhead; int _read(void *buffer, unsigned n); int64_t _seek(int64_t offset, WHENCE_t whence); // data buffer unsigned m_chunk; // the size of block to read struct { unsigned pos; unsigned len; unsigned char * data; } m_buffer; }; } #endif /* MYTHRECORDINGPLAYBACK_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/mythsharedptr.h000066400000000000000000000055101360567320200227710ustar00rootroot00000000000000/* * Copyright (C) 2015 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHSHAREDPTR_H #define MYTHSHAREDPTR_H #include "mythintrinsic.h" #include // for NULL namespace Myth { template class shared_ptr { public: shared_ptr() : p(NULL), c(NULL) { } explicit shared_ptr(T* s) : p(s), c(NULL) { if (p != NULL) { c = new IntrinsicCounter(1); } } shared_ptr(const shared_ptr& s) : p(s.p), c(s.c) { if (c != NULL) if (c->Increment() < 2) { c = NULL; p = NULL; } } shared_ptr& operator=(const shared_ptr& s) { if (this != &s) { reset(); p = s.p; c = s.c; if (c != NULL) if (c->Increment() < 2) { c = NULL; p = NULL; } } return *this; } #if __cplusplus >= 201103L shared_ptr& operator=(shared_ptr&& s) { if (this != &s) swap(s); return *this; } #endif ~shared_ptr() { reset(); } void reset() { if (c != NULL) if (c->Decrement() == 0) { delete p; delete c; } c = NULL; p = NULL; } void reset(T* s) { if (p != s) { reset(); if (s != NULL) { p = s; c = new IntrinsicCounter(1); } } } T *get() const { return (c != NULL) ? p : NULL; } void swap(shared_ptr& s) { T *tmp_p = p; IntrinsicCounter *tmp_c = c; p = s.p; c = s.c; s.p = tmp_p; s.c = tmp_c; } unsigned use_count() const { return (unsigned) (c != NULL ? c->GetValue() : 0); } T *operator->() const { return get(); } T& operator*() const { return *get(); } operator bool() const { return p != NULL; } bool operator!() const { return p == NULL; } protected: T *p; IntrinsicCounter *c; }; } #endif /* MYTHSHAREDPTR_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/mythstream.h000066400000000000000000000023271360567320200222730ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHSTREAM_H #define MYTHSTREAM_H #include "mythtypes.h" namespace Myth { class Stream { public: virtual ~Stream() {}; virtual int64_t GetSize() const = 0; // Returns -1 for undefined size virtual int Read(void *buffer, unsigned n) = 0; virtual int64_t Seek(int64_t offset, WHENCE_t whence) = 0; virtual int64_t GetPosition() const = 0; }; } #endif /* MYTHSTREAM_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/mythtypes.cpp000066400000000000000000000274251360567320200225050ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "mythtypes.h" #include "private/builtin.h" using namespace Myth; /////////////////////////////////////////////////////////////////////////////// //// //// Helpers //// uint32_t Myth::StringToId(const std::string& str) { uint32_t id = 0; string_to_uint32(str.c_str(), &id); return id; } std::string Myth::IdToString(uint32_t id) { char buf[32]; *buf = '\0'; uint32_to_string(id, buf); return std::string(buf); } time_t Myth::StringToTime(const std::string& isotime) { time_t time = INVALID_TIME; string_to_time(isotime.c_str(), &time); return time; } std::string Myth::TimeToString(time_t time, bool utc) { if (utc) { char buf[TIMESTAMP_UTC_LEN + 1]; *buf = '\0'; time_to_iso8601utc(time, buf); return std::string(buf); } else { char buf[TIMESTAMP_LEN + 1]; *buf = '\0'; time_to_iso8601(time, buf); return std::string(buf); } } int Myth::StringToInt(const std::string& str) { int32_t i = 0; string_to_int32(str.c_str(), &i); return (int)i; } std::string Myth::IntToString(int i) { char buf[32]; *buf = '\0'; int32_to_string(i, buf); return std::string(buf); } /////////////////////////////////////////////////////////////////////////////// //// //// Generic mapper //// typedef struct { unsigned protoVer; int tVal; int iVal; const char *sVal; } protoref_t; static int __tValFromString(protoref_t *map, unsigned sz, unsigned proto, const std::string& sVal, int unk) { for (unsigned i = 0; i < sz; ++i) { if (proto >= map[i].protoVer && sVal.compare(map[i].sVal) == 0) return map[i].tVal; } return unk; } static int __tValFromNum(protoref_t *map, unsigned sz, unsigned proto, int iVal, int unk) { for (unsigned i = 0; i < sz; ++i) { if (proto >= map[i].protoVer && iVal == map[i].iVal) return map[i].tVal; } return unk; } static const char *__tValToString(protoref_t *map, unsigned sz, unsigned proto, int tVal, const char *unk) { for (unsigned i = 0; i < sz; ++i) { if (proto >= map[i].protoVer && tVal == map[i].tVal) return map[i].sVal; } return unk; } static int __tValToNum(protoref_t *map, unsigned sz, unsigned proto, int tVal, int unk) { for (unsigned i = 0; i < sz; ++i) { if (proto >= map[i].protoVer && tVal == map[i].tVal) return map[i].iVal; } return unk; } /////////////////////////////////////////////////////////////////////////////// //// //// ruleType mapper //// static protoref_t ruleType[] = { { 79, RT_TemplateRecord, 11, "Recording Template" }, { 79, RT_NotRecording, 0, "Not Recording" }, { 76, RT_OneRecord, 6, "Record One" }, { 75, RT_SingleRecord, 1, "Single Record" }, { 75, RT_DailyRecord, 2, "Record Daily" }, { 75, RT_ChannelRecord, 3, "Channel Record" }, { 75, RT_AllRecord, 4, "Record All" }, { 75, RT_WeeklyRecord, 5, "Record Weekly" }, { 75, RT_OneRecord, 6, "Find One" }, { 75, RT_OverrideRecord, 7, "Override Recording" }, { 75, RT_DontRecord, 8, "Do not Record" }, { 75, RT_FindDailyRecord, 9, "Find Daily" }, { 75, RT_FindWeeklyRecord, 10, "Find Weekly" }, { 75, RT_TemplateRecord, 11, "Not Recording" }, { 75, RT_NotRecording, 0, "Not Recording" }, }; RT_t Myth::RuleTypeFromString(unsigned proto, const std::string& type) { static unsigned sz = sizeof(ruleType) / sizeof(protoref_t); return (RT_t)__tValFromString(ruleType, sz, proto, type, (int)RT_UNKNOWN); } RT_t Myth::RuleTypeFromNum(unsigned proto, int type) { static unsigned sz = sizeof(ruleType) / sizeof(protoref_t); return (RT_t)__tValFromNum(ruleType, sz, proto, type, (int)RT_UNKNOWN); } const char *Myth::RuleTypeToString(unsigned proto, RT_t type) { static unsigned sz = sizeof(ruleType) / sizeof(protoref_t); return __tValToString(ruleType, sz, proto, (int)type, ""); } int Myth::RuleTypeToNum(unsigned proto, RT_t type) { static unsigned sz = sizeof(ruleType) / sizeof(protoref_t); return __tValToNum(ruleType, sz, proto, (int)type, 0); } /////////////////////////////////////////////////////////////////////////////// //// //// dupIn mapper //// static protoref_t dupIn[] = { { 75, DI_InRecorded, 0x01, "Current Recordings" }, { 75, DI_InOldRecorded, 0x02, "Previous Recordings" }, { 75, DI_InAll, 0x0F, "All Recordings" }, { 75, DI_NewEpi, 0x10, "New Episodes Only" }, }; DI_t Myth::DupInFromString(unsigned proto, const std::string& type) { static unsigned sz = sizeof(dupIn) / sizeof(protoref_t); return (DI_t)__tValFromString(dupIn, sz, proto, type, (int)DI_UNKNOWN); } DI_t Myth::DupInFromNum(unsigned proto, int type) { static unsigned sz = sizeof(dupIn) / sizeof(protoref_t); return (DI_t)__tValFromNum(dupIn, sz, proto, type, (int)DI_UNKNOWN); } const char *Myth::DupInToString(unsigned proto, DI_t type) { static unsigned sz = sizeof(dupIn) / sizeof(protoref_t); return __tValToString(dupIn, sz, proto, (int)type, ""); } int Myth::DupInToNum(unsigned proto, DI_t type) { static unsigned sz = sizeof(dupIn) / sizeof(protoref_t); return __tValToNum(dupIn, sz, proto, (int)type, 0); } /////////////////////////////////////////////////////////////////////////////// //// //// dupMethod mapper //// static protoref_t dupMethod[] = { { 75, DM_CheckNone, 0x01, "None" }, { 75, DM_CheckSubtitle, 0x02, "Subtitle" }, { 75, DM_CheckDescription, 0x04, "Description" }, { 75, DM_CheckSubtitleAndDescription, 0x06, "Subtitle and Description" }, { 75, DM_CheckSubtitleThenDescription, 0x08, "Subtitle then Description" }, }; DM_t Myth::DupMethodFromString(unsigned proto, const std::string& type) { static unsigned sz = sizeof(dupMethod) / sizeof(protoref_t); return (DM_t)__tValFromString(dupMethod, sz, proto, type, (int)DM_UNKNOWN); } DM_t Myth::DupMethodFromNum(unsigned proto, int type) { static unsigned sz = sizeof(dupMethod) / sizeof(protoref_t); return (DM_t)__tValFromNum(dupMethod, sz, proto, type, (int)DM_UNKNOWN); } const char *Myth::DupMethodToString(unsigned proto, DM_t type) { static unsigned sz = sizeof(dupMethod) / sizeof(protoref_t); return __tValToString(dupMethod, sz, proto, (int)type, ""); } int Myth::DupMethodToNum(unsigned proto, DM_t type) { static unsigned sz = sizeof(dupMethod) / sizeof(protoref_t); return __tValToNum(dupMethod, sz, proto, (int)type, 0); } /////////////////////////////////////////////////////////////////////////////// //// //// searchType mapper //// static protoref_t searchType[] = { { 75, ST_NoSearch, 0, "None" }, { 75, ST_PowerSearch, 1, "Power Search" }, { 75, ST_TitleSearch, 2, "Title Search" }, { 75, ST_KeywordSearch, 3, "Keyword Search" }, { 75, ST_PeopleSearch, 4, "People Search" }, { 75, ST_ManualSearch, 5, "Manual Search" }, }; ST_t Myth::SearchTypeFromString(unsigned proto, const std::string& type) { static unsigned sz = sizeof(searchType) / sizeof(protoref_t); return (ST_t)__tValFromString(searchType, sz, proto, type, (int)ST_UNKNOWN); } ST_t Myth::SearchTypeFromNum(unsigned proto, int type) { static unsigned sz = sizeof(searchType) / sizeof(protoref_t); return (ST_t)__tValFromNum(searchType, sz, proto, type, (int)ST_UNKNOWN); } const char *Myth::SearchTypeToString(unsigned proto, ST_t type) { static unsigned sz = sizeof(searchType) / sizeof(protoref_t); return __tValToString(searchType, sz, proto, (int)type, ""); } int Myth::SearchTypeToNum(unsigned proto, ST_t type) { static unsigned sz = sizeof(searchType) / sizeof(protoref_t); return __tValToNum(searchType, sz, proto, (int)type, 0); } /////////////////////////////////////////////////////////////////////////////// //// //// CategoryType mapper //// static protoref_t categoryType[] = { { 79, CATT_CategoryNone, 0, "" }, { 79, CATT_CategoryMovie, 1, "movie" }, { 79, CATT_CategorySeries, 2, "series" }, { 79, CATT_CategorySports, 3, "sports" }, { 79, CATT_CategoryTVShow, 4, "tvshow" }, }; CATT_t Myth::CategoryTypeFromString(unsigned proto, const std::string& type) { static unsigned sz = sizeof(categoryType) / sizeof(protoref_t); if (type.empty()) return CATT_CategoryNone; return (CATT_t)__tValFromString(categoryType, sz, proto, type, (int)CATT_UNKNOWN); } CATT_t Myth::CategoryTypeFromNum(unsigned proto, int type) { static unsigned sz = sizeof(categoryType) / sizeof(protoref_t); return (CATT_t)__tValFromNum(categoryType, sz, proto, type, (int)CATT_UNKNOWN); } const char *Myth::CategoryTypeToString(unsigned proto, CATT_t type) { static unsigned sz = sizeof(categoryType) / sizeof(protoref_t); return __tValToString(categoryType, sz, proto, (int)type, ""); } int Myth::CategoryTypeToNum(unsigned proto, CATT_t type) { static unsigned sz = sizeof(categoryType) / sizeof(protoref_t); return __tValToNum(categoryType, sz, proto, (int)type, 0); } /////////////////////////////////////////////////////////////////////////////// //// //// recStatus mapper //// static protoref_t recStatus[] = { { 75, RS_TUNING, -10, "Tuning" }, { 75, RS_FAILED, -9, "Failed" }, { 75, RS_TUNER_BUSY, -8, "Tuner busy" }, { 75, RS_LOW_DISKSPACE, -7, "Low disk space" }, { 75, RS_CANCELLED, -6, "Cancelled" }, { 75, RS_MISSED, -5, "Missed" }, { 75, RS_ABORTED, -4, "Aborted" }, { 75, RS_RECORDED, -3, "Recorded" }, { 75, RS_RECORDING, -2, "Recording" }, { 75, RS_WILL_RECORD, -1, "Will record" }, { 75, RS_UNKNOWN, 0, "Unknown" }, { 75, RS_DONT_RECORD, 1, "Don't record" }, { 75, RS_PREVIOUS_RECORDING, 2, "Previous recording" }, { 75, RS_CURRENT_RECORDING, 3, "Current recording" }, { 75, RS_EARLIER_RECORDING, 4, "Earlier recording" }, { 75, RS_TOO_MANY_RECORDINGS, 5, "Too many recordings" }, { 75, RS_NOT_LISTED, 6, "Not listed" }, { 75, RS_CONFLICT, 7, "Conflict" }, { 75, RS_LATER_SHOWING, 8, "Later showing" }, { 75, RS_REPEAT, 9, "Repeat" }, { 75, RS_INACTIVE, 10, "Inactive" }, { 75, RS_NEVER_RECORD, 11, "Never record" }, { 75, RS_OFFLINE, 12, "Offline" }, { 75, RS_OTHER_SHOWING, 13, "Other showing" }, }; RS_t Myth::RecStatusFromString(unsigned proto, const std::string& type) { static unsigned sz = sizeof(recStatus) / sizeof(protoref_t); return (RS_t)__tValFromString(recStatus, sz, proto, type, (int)RT_UNKNOWN); } RS_t Myth::RecStatusFromNum(unsigned proto, int type) { static unsigned sz = sizeof(recStatus) / sizeof(protoref_t); return (RS_t)__tValFromNum(recStatus, sz, proto, type, (int)RT_UNKNOWN); } const char *Myth::RecStatusToString(unsigned proto, RS_t type) { static unsigned sz = sizeof(recStatus) / sizeof(protoref_t); return __tValToString(recStatus, sz, proto, (int)type, ""); } int Myth::RecStatusToNum(unsigned proto, RS_t type) { static unsigned sz = sizeof(recStatus) / sizeof(protoref_t); return __tValToNum(recStatus, sz, proto, (int)type, 0); } pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/mythtypes.h000066400000000000000000000376311360567320200221520ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHTYPES_H #define MYTHTYPES_H #include "mythsharedptr.h" #define MYTH_SHARED_PTR Myth::shared_ptr #include #include #include #include #include /** * @namespace Myth * @brief This is the main namespace that encloses all public classes */ namespace Myth { uint32_t StringToId(const std::string& str); std::string IdToString(uint32_t id); time_t StringToTime(const std::string& isotime); std::string TimeToString(time_t time, bool utc = false); int StringToInt(const std::string& str); std::string IntToString(int i); typedef enum { RT_NotRecording = 0, // (0x00) RT_SingleRecord = 1, // (0x01) RT_DailyRecord, // (0x02) RT_ChannelRecord, // (0x03) obsolete since 76 RT_AllRecord, // (0x04) RT_WeeklyRecord, // (0x05) RT_OneRecord, // (0x06) RT_OverrideRecord, // (0x07) RT_DontRecord, // (0x08) RT_FindDailyRecord, // (0x09) obsolete since 76 RT_FindWeeklyRecord, // (0x0a) obsolete since 76 RT_TemplateRecord, // (0x0b) RT_UNKNOWN // Keep at last } RT_t; RT_t RuleTypeFromString(unsigned proto, const std::string& type); RT_t RuleTypeFromNum(unsigned proto, int type); const char *RuleTypeToString(unsigned proto, RT_t type); int RuleTypeToNum(unsigned proto, RT_t type); typedef enum { DI_InRecorded = 0, // (0x01) DI_InOldRecorded = 1, // (0x02) DI_InAll, // (0x0F) DI_NewEpi, // (0x10) DI_UNKNOWN // Keep at last } DI_t; DI_t DupInFromString(unsigned proto, const std::string& type); DI_t DupInFromNum(unsigned proto, int type); const char *DupInToString(unsigned proto, DI_t type); int DupInToNum(unsigned proto, DI_t type); typedef enum { DM_CheckNone = 0, // (0x01) DM_CheckSubtitle = 1, // (0x02) DM_CheckDescription, // (0x04) DM_CheckSubtitleAndDescription, // (0x06) DM_CheckSubtitleThenDescription, // (0x08) DM_UNKNOWN // Keep at last } DM_t; DM_t DupMethodFromString(unsigned proto, const std::string& type); DM_t DupMethodFromNum(unsigned proto, int type); const char *DupMethodToString(unsigned proto, DM_t type); int DupMethodToNum(unsigned proto, DM_t type); typedef enum { ST_NoSearch = 0, // (0x00) ST_PowerSearch = 1, // (0x01) ST_TitleSearch, // (0x02) ST_KeywordSearch, // (0x03) ST_PeopleSearch, // (0x04) ST_ManualSearch, // (0x05) ST_UNKNOWN // Keep at last } ST_t; ST_t SearchTypeFromString(unsigned proto, const std::string& type); ST_t SearchTypeFromNum(unsigned proto, int type); const char *SearchTypeToString(unsigned proto, ST_t type); int SearchTypeToNum(unsigned proto, ST_t type); typedef enum { CATT_CategoryNone = 0, CATT_CategoryMovie, CATT_CategorySeries, CATT_CategorySports, CATT_CategoryTVShow, CATT_UNKNOWN // Keep at last } CATT_t; CATT_t CategoryTypeFromString(unsigned proto, const std::string& type); CATT_t CategoryTypeFromNum(unsigned proto, int type); const char *CategoryTypeToString(unsigned proto, CATT_t type); int CategoryTypeToNum(unsigned proto, CATT_t type); typedef enum { FM_NewEpisode = 0x001, FM_IdentifiableEpisode = 0x002, FM_FirstShowing = 0x004, FM_PrimeTime = 0x008, FM_CommercialFree = 0x010, FM_HighDefinition = 0x020, FM_ThisEpisode = 0x040, FM_ThisSeries = 0x080, FM_ThisTime = 0x100, FM_ThisDayAndTime = 0x200, FM_ThisChannel = 0x400 } FM_t; typedef enum { EVENT_HANDLER_STATUS = 0, // Internal event: Backend status change EVENT_HANDLER_TIMER, // Internal event: Every cycle without event EVENT_UNKNOWN, EVENT_UPDATE_FILE_SIZE, EVENT_LIVETV_WATCH, EVENT_LIVETV_CHAIN, EVENT_DONE_RECORDING, EVENT_QUIT_LIVETV, EVENT_RECORDING_LIST_CHANGE, EVENT_SCHEDULE_CHANGE, EVENT_SIGNAL, EVENT_ASK_RECORDING, EVENT_CLEAR_SETTINGS_CACHE, EVENT_GENERATED_PIXMAP, EVENT_SYSTEM_EVENT, } EVENT_t; typedef enum { WHENCE_SET = 0, WHENCE_CUR = 1, WHENCE_END = 2, } WHENCE_t; typedef enum { RS_TUNING = -10, RS_FAILED = -9, RS_TUNER_BUSY = -8, RS_LOW_DISKSPACE = -7, RS_CANCELLED = -6, RS_MISSED = -5, RS_ABORTED = -4, RS_RECORDED = -3, RS_RECORDING = -2, RS_WILL_RECORD = -1, RS_UNKNOWN = 0, RS_DONT_RECORD = 1, RS_PREVIOUS_RECORDING = 2, RS_CURRENT_RECORDING = 3, RS_EARLIER_RECORDING = 4, RS_TOO_MANY_RECORDINGS = 5, RS_NOT_LISTED = 6, RS_CONFLICT = 7, RS_LATER_SHOWING = 8, RS_REPEAT = 9, RS_INACTIVE = 10, RS_NEVER_RECORD = 11, RS_OFFLINE = 12, RS_OTHER_SHOWING = 13, } RS_t; RS_t RecStatusFromString(unsigned proto, const std::string& type); RS_t RecStatusFromNum(unsigned proto, int type); const char *RecStatusToString(unsigned proto, RS_t type); int RecStatusToNum(unsigned proto, RS_t type); struct ItemList { uint32_t count; uint32_t protoVer; ItemList() : count(0) , protoVer(0) {} }; typedef std::vector StringList; typedef MYTH_SHARED_PTR StringListPtr; struct Version { std::string version; uint32_t protocol; uint32_t schema; Version() : protocol(0) , schema(0) {} }; typedef MYTH_SHARED_PTR VersionPtr; struct Setting { std::string key; std::string value; }; typedef MYTH_SHARED_PTR SettingPtr; typedef std::map SettingMap; typedef MYTH_SHARED_PTR SettingMapPtr; struct Artwork { std::string url; std::string fileName; std::string storageGroup; std::string type; }; typedef MYTH_SHARED_PTR ArtworkPtr; typedef std::vector ArtworkList; typedef MYTH_SHARED_PTR ArtworkListPtr; struct Channel { uint32_t chanId; std::string chanNum; std::string callSign; std::string iconURL; std::string channelName; uint32_t mplexId; std::string commFree; std::string chanFilters; uint32_t sourceId; uint32_t inputId; bool visible; Channel() : chanId(0) , mplexId(0) , sourceId(0) , inputId(0) , visible(true) {} }; typedef MYTH_SHARED_PTR ChannelPtr; typedef std::vector ChannelList; typedef MYTH_SHARED_PTR ChannelListPtr; struct Recording { uint32_t recordId; int32_t priority; int8_t status; uint32_t encoderId; uint8_t recType; uint8_t dupInType; uint8_t dupMethod; time_t startTs; time_t endTs; std::string profile; std::string recGroup; std::string storageGroup; std::string playGroup; uint32_t recordedId; // Since proto 82 Recording() : recordId(0) , priority(0) , status(0) , encoderId(0) , recType(0) , dupInType(DI_InRecorded) , dupMethod(DM_CheckNone) , startTs(0) , endTs(0) , recordedId(0) {} }; typedef MYTH_SHARED_PTR RecordingPtr; typedef std::vector RecordingList; typedef MYTH_SHARED_PTR RecordingListPtr; struct Program { time_t startTime; time_t endTime; std::string title; std::string subTitle; std::string description; uint16_t season; uint16_t episode; std::string category; std::string catType; std::string hostName; std::string fileName; int64_t fileSize; bool repeat; uint32_t programFlags; std::string seriesId; std::string programId; std::string inetref; time_t lastModified; std::string stars; time_t airdate; uint16_t audioProps; uint16_t videoProps; uint16_t subProps; Channel channel; Recording recording; std::vector artwork; Program() : startTime(0) , endTime(0) , season(0) , episode(0) , fileSize(0) , repeat(false) , programFlags(0) , lastModified(0) , airdate(0) , audioProps(0) , videoProps(0) , subProps(0) {} }; typedef MYTH_SHARED_PTR ProgramPtr; typedef std::vector ProgramList; typedef MYTH_SHARED_PTR ProgramListPtr; typedef std::map ProgramMap; typedef MYTH_SHARED_PTR ProgramMapPtr; struct CaptureCard { uint32_t cardId; std::string cardType; std::string hostName; CaptureCard() : cardId(0) {} }; typedef MYTH_SHARED_PTR CaptureCardPtr; typedef std::vector CaptureCardList; typedef MYTH_SHARED_PTR CaptureCardListPtr; struct CardInput { uint32_t inputId; uint32_t cardId; uint32_t sourceId; uint32_t mplexId; std::string inputName; uint8_t liveTVOrder; CardInput() : inputId(0) , cardId(0) , sourceId(0) , mplexId(0) , liveTVOrder(0) {} }; typedef MYTH_SHARED_PTR CardInputPtr; typedef std::vector CardInputList; typedef MYTH_SHARED_PTR CardInputListPtr; struct VideoSource { uint32_t sourceId; std::string sourceName; VideoSource() : sourceId(0) {} }; typedef MYTH_SHARED_PTR VideoSourcePtr; typedef std::vector VideoSourceList; typedef MYTH_SHARED_PTR VideoSourceListPtr; struct RecordSchedule { uint32_t recordId; std::string title; std::string subtitle; std::string description; std::string category; time_t startTime; time_t endTime; std::string seriesId; std::string programId; uint32_t chanId; std::string callSign; int8_t findDay; std::string findTime; uint32_t parentId; bool inactive; uint16_t season; uint16_t episode; std::string inetref; std::string type; RT_t type_t; std::string searchType; ST_t searchType_t; int8_t recPriority; uint32_t preferredInput; uint8_t startOffset; uint8_t endOffset; std::string dupMethod; DM_t dupMethod_t; std::string dupIn; DI_t dupIn_t; uint32_t filter; std::string recProfile; std::string recGroup; std::string storageGroup; std::string playGroup; bool autoExpire; uint32_t maxEpisodes; bool maxNewest; bool autoCommflag; bool autoTranscode; bool autoMetaLookup; bool autoUserJob1; bool autoUserJob2; bool autoUserJob3; bool autoUserJob4; uint32_t transcoder; time_t nextRecording; time_t lastRecorded; time_t lastDeleted; uint32_t averageDelay; RecordSchedule() : recordId(0) , startTime(0) , endTime(0) , chanId(0) , findDay(0) , parentId(0) , inactive(false) , season(0) , episode(0) , type_t(RT_NotRecording) , searchType_t(ST_NoSearch) , recPriority(0) , preferredInput(0) , startOffset(0) , endOffset(0) , dupMethod_t(DM_CheckNone) , dupIn_t(DI_InRecorded) , filter(0) , autoExpire(false) , maxEpisodes(0) , maxNewest(false) , autoCommflag(false) , autoTranscode(false) , autoMetaLookup(false) , autoUserJob1(false) , autoUserJob2(false) , autoUserJob3(false) , autoUserJob4(false) , transcoder(0) , nextRecording(0) , lastRecorded(0) , lastDeleted(0) , averageDelay(0) {} }; typedef MYTH_SHARED_PTR RecordSchedulePtr; typedef std::vector RecordScheduleList; typedef MYTH_SHARED_PTR RecordScheduleListPtr; struct SignalStatus { bool lock; int signal; int snr; long ber; long ucb; SignalStatus() : lock(false) , signal(0) , snr(0) , ber(0) , ucb(0) {} }; typedef MYTH_SHARED_PTR SignalStatusPtr; struct EventMessage { EVENT_t event; std::vector subject; ProgramPtr program; SignalStatusPtr signal; EventMessage() : event(EVENT_UNKNOWN) {} }; typedef MYTH_SHARED_PTR EventMessagePtr; struct StorageGroupFile { std::string fileName; std::string storageGroup; std::string hostName; time_t lastModified; int64_t size; StorageGroupFile() : lastModified(0) , size(0) {} }; typedef MYTH_SHARED_PTR StorageGroupFilePtr; typedef enum { MARK_CUT_END = 0, MARK_CUT_START = 1, MARK_BOOKMARK = 2, MARK_BLANK_FRAME = 3, MARK_COMM_START = 4, MARK_COMM_END = 5, MARK_GOP_START = 6, MARK_KEYFRAME = 7, MARK_SCENE_CHANGE = 8, MARK_GOP_BYFRAME = 9, MARK_ASPECT_1_1 = 10, MARK_ASPECT_4_3 = 11, MARK_ASPECT_16_9 = 12, MARK_ASPECT_2_21_1 = 13, MARK_ASPECT_CUSTOM = 14, MARK_VIDEO_WIDTH = 30, MARK_VIDEO_HEIGHT = 31, MARK_VIDEO_RATE = 32, MARK_DURATION_MS = 33, MARK_TOTAL_FRAMES = 34, } MARK_t; struct Mark { MARK_t markType; int64_t markValue; Mark() : markType(MARK_CUT_END) , markValue(0) {} }; typedef MYTH_SHARED_PTR MarkPtr; typedef std::vector MarkList; typedef MYTH_SHARED_PTR MarkListPtr; } #endif /* MYTHTYPES_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/mythwsapi.cpp000066400000000000000000002600371360567320200224620ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "mythwsapi.h" #include "private/debug.h" #include "private/socket.h" #include "private/wsrequest.h" #include "private/wsresponse.h" #include "private/jsonparser.h" #include "private/mythjsonbinder.h" #include "private/os/threads/mutex.h" #include "private/cppdef.h" #include "private/builtin.h" #include "private/uriparser.h" #define BOOLSTR(a) ((a) ? "true" : "false") #define FETCHSIZE 100 #define FETCHSIZE_L 1000 using namespace Myth; #define WS_ROOT_MYTH "/Myth" #define WS_ROOT_CAPTURE "/Capture" #define WS_ROOT_CHANNEL "/Channel" #define WS_ROOT_GUIDE "/Guide" #define WS_ROOT_CONTENT "/Content" #define WS_ROOT_DVR "/Dvr" static std::string encodeParam(const std::string& str); WSAPI::WSAPI(const std::string& server, unsigned port, const std::string& securityPin) : m_mutex(new OS::CMutex) , m_server(server) , m_port(port) , m_securityPin(securityPin) , m_checked(false) , m_version() , m_serverHostName() { m_checked = InitWSAPI(); } WSAPI::~WSAPI() { SAFE_DELETE(m_mutex); } bool WSAPI::InitWSAPI() { bool status = false; // Reset array of version memset(m_serviceVersion, 0, sizeof(m_serviceVersion)); // Check the core service Myth WSServiceVersion_t& mythwsv = m_serviceVersion[WS_Myth]; if (!GetServiceVersion(WS_Myth, mythwsv)) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return false; } if (mythwsv.ranking > MYTH_API_VERSION_MAX_RANKING) {} else if (mythwsv.ranking >= 0x00020000) status = CheckServerHostName2_0() & CheckVersion2_0(); // If everything is fine then check other services if (status) { if (GetServiceVersion(WS_Capture, m_serviceVersion[WS_Capture]) && GetServiceVersion(WS_Channel, m_serviceVersion[WS_Channel]) && GetServiceVersion(WS_Guide, m_serviceVersion[WS_Guide]) && GetServiceVersion(WS_Content, m_serviceVersion[WS_Content]) && GetServiceVersion(WS_Dvr, m_serviceVersion[WS_Dvr])) { DBG(DBG_INFO, "%s: MythTV API service is available: %s:%d(%s) protocol(%d) schema(%d)\n", __FUNCTION__, m_serverHostName.c_str(), m_port, m_version.version.c_str(), (unsigned)m_version.protocol, (unsigned)m_version.schema); return true; } } DBG(DBG_ERROR, "%s: MythTV API service is not supported or unavailable: %s:%d (%u.%u)\n", __FUNCTION__, m_server.c_str(), m_port, mythwsv.major, mythwsv.minor); return false; } bool WSAPI::GetServiceVersion(WSServiceId_t id, WSServiceVersion_t& wsv) { static const char * WSServiceRoot[WS_INVALID + 1] = { WS_ROOT_MYTH, ///< WS_Myth WS_ROOT_CAPTURE, ///< WS_Capture WS_ROOT_CHANNEL, ///< WS_Channel WS_ROOT_GUIDE, ///< WS_Guide WS_ROOT_CONTENT, ///< WS_Content WS_ROOT_DVR, ///< WS_Dvr "/?", ///< WS_INVALID }; std::string url(WSServiceRoot[id]); url.append("/version"); WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService(url); WSResponse resp(req); if (resp.IsSuccessful()) { // Parse content response const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (json.IsValid() && root.IsObject()) { const JSON::Node& field = root.GetObjectValue("String"); if (field.IsString()) { const std::string& val = field.GetStringValue(); if (sscanf(val.c_str(), "%d.%d", &(wsv.major), &(wsv.minor)) == 2) { wsv.ranking = ((wsv.major & 0xFFFF) << 16) | (wsv.minor & 0xFFFF); return true; } } } } wsv.major = 0; wsv.minor = 0; wsv.ranking = 0; return false; } bool WSAPI::CheckServerHostName2_0() { m_serverHostName.clear(); WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Myth/GetHostName"); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return false; } // Parse content response const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (json.IsValid() && root.IsObject()) { const JSON::Node& field = root.GetObjectValue("String"); if (field.IsString()) { const std::string& val = field.GetStringValue(); m_serverHostName = val; m_namedCache[val] = m_server; return true; } } return false; } bool WSAPI::CheckVersion2_0() { m_version.protocol = 0; m_version.schema = 0; m_version.version.clear(); WSServiceVersion_t& wsv = m_serviceVersion[WS_Myth]; WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Myth/GetConnectionInfo"); if (!m_securityPin.empty()) { // Skip if null or empty req.SetContentParam("Pin", m_securityPin); } WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return false; } // Parse content response const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (json.IsValid() && root.IsObject()) { const JSON::Node& con = root.GetObjectValue("ConnectionInfo"); if (con.IsObject()) { const JSON::Node& ver = con.GetObjectValue("Version"); JSON::BindObject(ver, &m_version, MythDTO::getVersionBindArray(wsv.ranking)); if (m_version.protocol) return true; } } return false; } unsigned WSAPI::CheckService() { OS::CLockGuard lock(*m_mutex); if (m_checked || (m_checked = InitWSAPI())) return (unsigned)m_version.protocol; return 0; } WSServiceVersion_t WSAPI::CheckService(WSServiceId_t id) { OS::CLockGuard lock(*m_mutex); if (m_checked || (m_checked = InitWSAPI())) return m_serviceVersion[id]; return m_serviceVersion[WS_INVALID]; } void WSAPI::InvalidateService() { if (m_checked) m_checked = false; } std::string WSAPI::GetServerHostName() { return m_serverHostName; } VersionPtr WSAPI::GetVersion() { return VersionPtr(new Version(m_version)); } std::string WSAPI::ResolveHostName(const std::string& hostname) { OS::CLockGuard lock(*m_mutex); std::map::const_iterator it = m_namedCache.find(hostname); if (it != m_namedCache.end()) return it->second; Myth::SettingPtr addr = this->GetSetting("BackendServerIP6", hostname); if (addr && !addr->value.empty() && addr->value != "::1") { std::string& ret = m_namedCache[hostname]; ret.assign(addr->value); DBG(DBG_DEBUG, "%s: resolving hostname %s as %s\n", __FUNCTION__, hostname.c_str(), ret.c_str()); return ret; } addr = this->GetSetting("BackendServerIP", hostname); if (addr && !addr->value.empty()) { std::string& ret = m_namedCache[hostname]; ret.assign(addr->value); DBG(DBG_DEBUG, "%s: resolving hostname %s as %s\n", __FUNCTION__, hostname.c_str(), ret.c_str()); return ret; } DBG(DBG_ERROR, "%s: unknown host (%s)\n", __FUNCTION__, hostname.c_str()); return std::string(); } /////////////////////////////////////////////////////////////////////////////// //// //// Service operations //// SettingPtr WSAPI::GetSetting2_0(const std::string& key, const std::string& hostname) { SettingPtr ret; // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Myth/GetSetting"); req.SetContentParam("HostName", hostname); req.SetContentParam("Key", key); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return ret; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); return ret; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); // Object: SettingList const JSON::Node& slist = root.GetObjectValue("SettingList"); // Object: Settings const JSON::Node& sts = slist.GetObjectValue("Settings"); if (sts.IsObject()) { if (sts.Size()) { const JSON::Node& val = sts.GetObjectValue(static_cast(0)); if (val.IsString()) { ret.reset(new Setting()); // Using default constructor ret->key = sts.GetObjectKey(0); ret->value = val.GetStringValue(); } } } return ret; } SettingPtr WSAPI::GetSetting5_0(const std::string& key, const std::string& hostname) { SettingPtr ret; // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Myth/GetSetting"); req.SetContentParam("HostName", hostname); req.SetContentParam("Key", key); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return ret; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); return ret; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); // Object: String const JSON::Node& val = root.GetObjectValue("String"); if (val.IsString()) { ret.reset(new Setting()); // Using default constructor ret->key = key; ret->value = val.GetStringValue(); } return ret; } SettingPtr WSAPI::GetSetting(const std::string& key, bool myhost) { std::string hostname; if (myhost) hostname = TcpSocket::GetMyHostName(); return GetSetting(key, hostname); } SettingMapPtr WSAPI::GetSettings2_0(const std::string& hostname) { SettingMapPtr ret(new SettingMap); // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Myth/GetSetting"); req.SetContentParam("HostName", hostname); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return ret; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); return ret; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); // Object: SettingList const JSON::Node& slist = root.GetObjectValue("SettingList"); // Object: Settings const JSON::Node& sts = slist.GetObjectValue("Settings"); if (sts.IsObject()) { size_t s = sts.Size(); for (size_t i = 0; i < s; ++i) { const JSON::Node& val = sts.GetObjectValue(i); if (val.IsString()) { SettingPtr setting(new Setting()); // Using default constructor setting->key = sts.GetObjectKey(i); setting->value = val.GetStringValue(); ret->insert(SettingMap::value_type(setting->key, setting)); } } } return ret; } SettingMapPtr WSAPI::GetSettings5_0(const std::string& hostname) { SettingMapPtr ret(new SettingMap); // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Myth/GetSettingList"); req.SetContentParam("HostName", hostname); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return ret; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); return ret; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); // Object: SettingList const JSON::Node& slist = root.GetObjectValue("SettingList"); // Object: Settings const JSON::Node& sts = slist.GetObjectValue("Settings"); if (sts.IsObject()) { size_t s = sts.Size(); for (size_t i = 0; i < s; ++i) { const JSON::Node& val = sts.GetObjectValue(i); if (val.IsString()) { SettingPtr setting(new Setting()); // Using default constructor setting->key = sts.GetObjectKey(i); setting->value = val.GetStringValue(); ret->insert(SettingMap::value_type(setting->key, setting)); } } } return ret; } SettingMapPtr WSAPI::GetSettings(bool myhost) { std::string hostname; if (myhost) hostname = TcpSocket::GetMyHostName(); return GetSettings(hostname); } bool WSAPI::PutSetting2_0(const std::string& key, const std::string& value, bool myhost) { // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Myth/PutSetting", HRM_POST); std::string hostname; if (myhost) hostname = TcpSocket::GetMyHostName(); req.SetContentParam("HostName", hostname); req.SetContentParam("Key", key); req.SetContentParam("Value", value); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return false; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); return false; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); const JSON::Node& field = root.GetObjectValue("bool"); if (!field.IsString() || strcmp(field.GetStringValue().c_str(), "true")) return false; return true; } /////////////////////////////////////////////////////////////////////////////// //// //// Capture service //// CaptureCardListPtr WSAPI::GetCaptureCardList1_4() { CaptureCardListPtr ret(new CaptureCardList); unsigned proto = (unsigned)m_version.protocol; // Get bindings for protocol version const bindings_t *bindcard = MythDTO::getCaptureCardBindArray(proto); // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Capture/GetCaptureCardList"); req.SetContentParam("HostName", m_serverHostName.c_str()); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return ret; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); return ret; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); // Object: CaptureCardList const JSON::Node& clist = root.GetObjectValue("CaptureCardList"); // Object: CaptureCards[] const JSON::Node& cards = clist.GetObjectValue("CaptureCards"); // Iterates over the sequence elements. size_t cs = cards.Size(); for (size_t ci = 0; ci < cs; ++ci) { const JSON::Node& card = cards.GetArrayElement(ci); CaptureCardPtr captureCard(new CaptureCard()); // Using default constructor // Bind the new captureCard JSON::BindObject(card, captureCard.get(), bindcard); ret->push_back(captureCard); } return ret; } /////////////////////////////////////////////////////////////////////////////// //// //// Channel Service //// VideoSourceListPtr WSAPI::GetVideoSourceList1_2() { VideoSourceListPtr ret(new VideoSourceList); unsigned proto = (unsigned)m_version.protocol; // Get bindings for protocol version const bindings_t *bindvsrc = MythDTO::getVideoSourceBindArray(proto); // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Channel/GetVideoSourceList"); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return ret; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); return ret; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); // Object: VideoSourceList const JSON::Node& slist = root.GetObjectValue("VideoSourceList"); // Object: VideoSources[] const JSON::Node& vsrcs = slist.GetObjectValue("VideoSources"); // Iterates over the sequence elements. size_t vs = vsrcs.Size(); for (size_t vi = 0; vi < vs; ++vi) { const JSON::Node& vsrc = vsrcs.GetArrayElement(vi); VideoSourcePtr videoSource(new VideoSource()); // Using default constructor // Bind the new videoSource JSON::BindObject(vsrc, videoSource.get(), bindvsrc); ret->push_back(videoSource); } return ret; } ChannelListPtr WSAPI::GetChannelList1_2(uint32_t sourceid, bool onlyVisible) { ChannelListPtr ret(new ChannelList); char buf[32]; int32_t req_index = 0, req_count = FETCHSIZE, count = 0; unsigned proto = (unsigned)m_version.protocol; // Get bindings for protocol version const bindings_t *bindlist = MythDTO::getListBindArray(proto); const bindings_t *bindchan = MythDTO::getChannelBindArray(proto); // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Channel/GetChannelInfoList"); do { req.ClearContent(); uint32_to_string(sourceid, buf); req.SetContentParam("SourceID", buf); int32_to_string(req_index, buf); req.SetContentParam("StartIndex", buf); int32_to_string(req_count, buf); req.SetContentParam("Count", buf); DBG(DBG_DEBUG, "%s: request index(%d) count(%d)\n", __FUNCTION__, req_index, req_count); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); break; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); break; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); // Object: ChannelInfoList const JSON::Node& clist = root.GetObjectValue("ChannelInfoList"); ItemList list = ItemList(); // Using default constructor JSON::BindObject(clist, &list, bindlist); // List has ProtoVer. Check it or sound alarm if (list.protoVer != proto) { InvalidateService(); break; } count = 0; // Object: ChannelInfos[] const JSON::Node& chans = clist.GetObjectValue("ChannelInfos"); // Iterates over the sequence elements. size_t cs = chans.Size(); for (size_t ci = 0; ci < cs; ++ci) { ++count; const JSON::Node& chan = chans.GetArrayElement(ci); ChannelPtr channel(new Channel()); // Using default constructor // Bind the new channel JSON::BindObject(chan, channel.get(), bindchan); if (channel->chanId && (!onlyVisible || channel->visible)) ret->push_back(channel); } DBG(DBG_DEBUG, "%s: received count(%d)\n", __FUNCTION__, count); req_index += count; // Set next requested index } while (count == req_count); return ret; } ChannelListPtr WSAPI::GetChannelList1_5(uint32_t sourceid, bool onlyVisible) { ChannelListPtr ret(new ChannelList); char buf[32]; int32_t req_index = 0, /*req_count = FETCHSIZE,*/ count = 0; unsigned proto = (unsigned)m_version.protocol; // Get bindings for protocol version const bindings_t *bindlist = MythDTO::getListBindArray(proto); const bindings_t *bindchan = MythDTO::getChannelBindArray(proto); // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Channel/GetChannelInfoList"); do { req.ClearContent(); req.SetContentParam("Details", "true"); req.SetContentParam("OnlyVisible", BOOLSTR(onlyVisible)); uint32_to_string(sourceid, buf); req.SetContentParam("SourceID", buf); // W.A. for bug tracked by ticket 12461 //int32_to_string(req_index, buf); //req.SetContentParam("StartIndex", buf); //int32_to_string(req_count, buf); //req.SetContentParam("Count", buf); //DBG(DBG_DEBUG, "%s: request index(%d) count(%d)\n", __FUNCTION__, req_index, req_count); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); break; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); break; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); // Object: ChannelInfoList const JSON::Node& clist = root.GetObjectValue("ChannelInfoList"); ItemList list = ItemList(); // Using default constructor JSON::BindObject(clist, &list, bindlist); // List has ProtoVer. Check it or sound alarm if (list.protoVer != proto) { InvalidateService(); break; } count = 0; // Object: ChannelInfos[] const JSON::Node& chans = clist.GetObjectValue("ChannelInfos"); // Iterates over the sequence elements. size_t cs = chans.Size(); for (size_t ci = 0; ci < cs; ++ci) { ++count; const JSON::Node& chan = chans.GetArrayElement(ci); ChannelPtr channel(new Channel()); // Using default constructor // Bind the new channel JSON::BindObject(chan, channel.get(), bindchan); if (channel->chanId) ret->push_back(channel); } DBG(DBG_DEBUG, "%s: received count(%d)\n", __FUNCTION__, count); req_index += count; // Set next requested index } //while (count == req_count); while (false); // W.A. for bug tracked by ticket 12461 return ret; } ChannelPtr WSAPI::GetChannel1_2(uint32_t chanid) { ChannelPtr ret; char buf[32]; unsigned proto = (unsigned)m_version.protocol; // Get bindings for protocol version const bindings_t *bindchan = MythDTO::getChannelBindArray(proto); // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Channel/GetChannelInfo"); uint32_to_string(chanid, buf); req.SetContentParam("ChanID", buf); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return ret; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); return ret; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); // Object: ChannelInfo const JSON::Node& chan = root.GetObjectValue("ChannelInfo"); ChannelPtr channel(new Channel()); // Using default constructor // Bind the new channel JSON::BindObject(chan, channel.get(), bindchan); if (channel->chanId == chanid) ret = channel; return ret; } /////////////////////////////////////////////////////////////////////////////// //// //// Guide service //// std::map WSAPI::GetProgramGuide1_0(time_t starttime, time_t endtime) { std::map ret; char buf[32]; int32_t count = 0; unsigned proto = (unsigned)m_version.protocol; // Get bindings for protocol version const bindings_t *bindlist = MythDTO::getListBindArray(proto); const bindings_t *bindchan = MythDTO::getChannelBindArray(proto); const bindings_t *bindprog = MythDTO::getProgramBindArray(proto); // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Guide/GetProgramGuide"); req.SetContentParam("StartChanId", "0"); req.SetContentParam("NumChannels", "0"); time_to_iso8601utc(starttime, buf); req.SetContentParam("StartTime", buf); time_to_iso8601utc(endtime, buf); req.SetContentParam("EndTime", buf); req.SetContentParam("Details", "true"); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return ret; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); return ret; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); // Object: ProgramGuide const JSON::Node& glist = root.GetObjectValue("ProgramGuide"); ItemList list = ItemList(); // Using default constructor JSON::BindObject(glist, &list, bindlist); // List has ProtoVer. Check it or sound alarm if (list.protoVer != proto) { InvalidateService(); return ret; } // Object: Channels[] const JSON::Node& chans = glist.GetObjectValue("Channels"); // Iterates over the sequence elements. size_t cs = chans.Size(); for (size_t ci = 0; ci < cs; ++ci) { const JSON::Node& chan = chans.GetArrayElement(ci); Channel channel; JSON::BindObject(chan, &channel, bindchan); ProgramMapPtr pmap(new ProgramMap); ret.insert(std::make_pair(channel.chanId, pmap)); // Object: Programs[] const JSON::Node& progs = chan.GetObjectValue("Programs"); // Iterates over the sequence elements. size_t ps = progs.Size(); for (size_t pi = 0; pi < ps; ++pi) { ++count; const JSON::Node& prog = progs.GetArrayElement(pi); ProgramPtr program(new Program()); // Using default constructor // Bind the new program JSON::BindObject(prog, program.get(), bindprog); program->channel = channel; pmap->insert(std::make_pair(program->startTime, program)); } } DBG(DBG_DEBUG, "%s: received count(%d)\n", __FUNCTION__, count); return ret; } ProgramMapPtr WSAPI::GetProgramGuide1_0(uint32_t chanid, time_t starttime, time_t endtime) { ProgramMapPtr ret(new ProgramMap); char buf[32]; int32_t count = 0; unsigned proto = (unsigned)m_version.protocol; // Get bindings for protocol version const bindings_t *bindlist = MythDTO::getListBindArray(proto); const bindings_t *bindchan = MythDTO::getChannelBindArray(proto); const bindings_t *bindprog = MythDTO::getProgramBindArray(proto); // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Guide/GetProgramGuide"); uint32_to_string(chanid, buf); req.SetContentParam("StartChanId", buf); req.SetContentParam("NumChannels", "1"); time_to_iso8601utc(starttime, buf); req.SetContentParam("StartTime", buf); time_to_iso8601utc(endtime, buf); req.SetContentParam("EndTime", buf); req.SetContentParam("Details", "true"); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return ret; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); return ret; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); // Object: ProgramGuide const JSON::Node& glist = root.GetObjectValue("ProgramGuide"); ItemList list = ItemList(); // Using default constructor JSON::BindObject(glist, &list, bindlist); // List has ProtoVer. Check it or sound alarm if (list.protoVer != proto) { InvalidateService(); return ret; } // Object: Channels[] const JSON::Node& chans = glist.GetObjectValue("Channels"); // Iterates over the sequence elements. size_t cs = chans.Size(); for (size_t ci = 0; ci < cs; ++ci) { const JSON::Node& chan = chans.GetArrayElement(ci); Channel channel; JSON::BindObject(chan, &channel, bindchan); if (channel.chanId != chanid) continue; // Object: Programs[] const JSON::Node& progs = chan.GetObjectValue("Programs"); // Iterates over the sequence elements. size_t ps = progs.Size(); for (size_t pi = 0; pi < ps; ++pi) { ++count; const JSON::Node& prog = progs.GetArrayElement(pi); ProgramPtr program(new Program()); // Using default constructor // Bind the new program JSON::BindObject(prog, program.get(), bindprog); program->channel = channel; ret->insert(std::make_pair(program->startTime, program)); } break; } DBG(DBG_DEBUG, "%s: received count(%d)\n", __FUNCTION__, count); return ret; } std::map WSAPI::GetProgramGuide2_2(time_t starttime, time_t endtime) { std::map ret; char buf[32]; uint32_t req_index = 0, req_count = FETCHSIZE, count = 0, total = 0; unsigned proto = (unsigned)m_version.protocol; // Adjust the fetch count according to the number of requested days double d = difftime(endtime, starttime); if (d > 0) req_count = FETCHSIZE / (int)(1.0 + d / (3 * 86400)); // Get bindings for protocol version const bindings_t *bindlist = MythDTO::getListBindArray(proto); const bindings_t *bindprog = MythDTO::getProgramBindArray(proto); const bindings_t *bindchan = MythDTO::getChannelBindArray(proto); // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Guide/GetProgramGuide"); do { req.ClearContent(); uint32_to_string(req_index, buf); req.SetContentParam("StartIndex", buf); uint32_to_string(req_count, buf); req.SetContentParam("Count", buf); time_to_iso8601utc(starttime, buf); req.SetContentParam("StartTime", buf); time_to_iso8601utc(endtime, buf); req.SetContentParam("EndTime", buf); req.SetContentParam("Details", "true"); DBG(DBG_DEBUG, "%s: request index(%d) count(%d)\n", __FUNCTION__, req_index, req_count); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); break; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); break; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); // Object: ProgramGuide const JSON::Node& glist = root.GetObjectValue("ProgramGuide"); ItemList list = ItemList(); // Using default constructor JSON::BindObject(glist, &list, bindlist); // List has ProtoVer. Check it or sound alarm if (list.protoVer != proto) { InvalidateService(); break; } count = 0; // Object: Channels[] const JSON::Node& chans = glist.GetObjectValue("Channels"); // Iterates over the sequence elements. size_t cs = chans.Size(); for (size_t ci = 0; ci < cs; ++ci) { ++count; const JSON::Node& chan = chans.GetArrayElement(ci); Channel channel; JSON::BindObject(chan, &channel, bindchan); ProgramMapPtr pmap(new ProgramMap); ret.insert(std::make_pair(channel.chanId, pmap)); // Object: Programs[] const JSON::Node& progs = chan.GetObjectValue("Programs"); // Iterates over the sequence elements. size_t ps = progs.Size(); for (size_t pi = 0; pi < ps; ++pi) { const JSON::Node& prog = progs.GetArrayElement(pi); ProgramPtr program(new Program()); // Using default constructor // Bind the new program JSON::BindObject(prog, program.get(), bindprog); program->channel = channel; pmap->insert(std::make_pair(program->startTime, program)); } ++total; } DBG(DBG_DEBUG, "%s: received count(%d)\n", __FUNCTION__, count); req_index += count; // Set next requested index } while (count == req_count); return ret; } ProgramMapPtr WSAPI::GetProgramList2_2(uint32_t chanid, time_t starttime, time_t endtime) { ProgramMapPtr ret(new ProgramMap); char buf[32]; uint32_t req_index = 0, req_count = FETCHSIZE_L, count = 0, total = 0; unsigned proto = (unsigned)m_version.protocol; // Get bindings for protocol version const bindings_t *bindlist = MythDTO::getListBindArray(proto); const bindings_t *bindprog = MythDTO::getProgramBindArray(proto); const bindings_t *bindchan = MythDTO::getChannelBindArray(proto); // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Guide/GetProgramList"); do { req.ClearContent(); uint32_to_string(req_index, buf); req.SetContentParam("StartIndex", buf); uint32_to_string(req_count, buf); req.SetContentParam("Count", buf); uint32_to_string(chanid, buf); req.SetContentParam("ChanId", buf); time_to_iso8601utc(starttime, buf); req.SetContentParam("StartTime", buf); time_to_iso8601utc(endtime, buf); req.SetContentParam("EndTime", buf); req.SetContentParam("Details", "true"); DBG(DBG_DEBUG, "%s: request index(%d) count(%d)\n", __FUNCTION__, req_index, req_count); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); break; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); break; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); // Object: ProgramList const JSON::Node& plist = root.GetObjectValue("ProgramList"); ItemList list = ItemList(); // Using default constructor JSON::BindObject(plist, &list, bindlist); // List has ProtoVer. Check it or sound alarm if (list.protoVer != proto) { InvalidateService(); break; } count = 0; // Object: Programs[] const JSON::Node& progs = plist.GetObjectValue("Programs"); // Iterates over the sequence elements. size_t ps = progs.Size(); for (size_t pi = 0; pi < ps; ++pi) { ++count; const JSON::Node& prog = progs.GetArrayElement(pi); ProgramPtr program(new Program()); // Using default constructor // Bind the new program JSON::BindObject(prog, program.get(), bindprog); // Bind channel of program const JSON::Node& chan = prog.GetObjectValue("Channel"); JSON::BindObject(chan, &(program->channel), bindchan); ret->insert(std::make_pair(program->startTime, program)); ++total; } DBG(DBG_DEBUG, "%s: received count(%d)\n", __FUNCTION__, count); req_index += count; // Set next requested index } while (count == req_count); return ret; } /////////////////////////////////////////////////////////////////////////////// //// //// Dvr service //// ProgramListPtr WSAPI::GetRecordedList1_5(unsigned n, bool descending) { ProgramListPtr ret(new ProgramList); char buf[32]; uint32_t req_index = 0, req_count = FETCHSIZE, count = 0, total = 0; unsigned proto = (unsigned)m_version.protocol; // Get bindings for protocol version const bindings_t *bindlist = MythDTO::getListBindArray(proto); const bindings_t *bindprog = MythDTO::getProgramBindArray(proto); const bindings_t *bindchan = MythDTO::getChannelBindArray(proto); const bindings_t *bindreco = MythDTO::getRecordingBindArray(proto); const bindings_t *bindartw = MythDTO::getArtworkBindArray(proto); // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Dvr/GetRecordedList"); do { // Adjust the packet size if (n && req_count > (n - total)) req_count = (n - total); req.ClearContent(); uint32_to_string(req_index, buf); req.SetContentParam("StartIndex", buf); uint32_to_string(req_count, buf); req.SetContentParam("Count", buf); req.SetContentParam("Descending", BOOLSTR(descending)); DBG(DBG_DEBUG, "%s: request index(%d) count(%d)\n", __FUNCTION__, req_index, req_count); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); break; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); break; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); // Object: ProgramList const JSON::Node& plist = root.GetObjectValue("ProgramList"); ItemList list = ItemList(); // Using default constructor JSON::BindObject(plist, &list, bindlist); // List has ProtoVer. Check it or sound alarm if (list.protoVer != proto) { InvalidateService(); break; } count = 0; // Object: Programs[] const JSON::Node& progs = plist.GetObjectValue("Programs"); // Iterates over the sequence elements. size_t ps = progs.Size(); for (size_t pi = 0; pi < ps; ++pi) { ++count; const JSON::Node& prog = progs.GetArrayElement(pi); ProgramPtr program(new Program()); // Using default constructor // Bind the new program JSON::BindObject(prog, program.get(), bindprog); // Bind channel of program const JSON::Node& chan = prog.GetObjectValue("Channel"); JSON::BindObject(chan, &(program->channel), bindchan); // Bind recording of program const JSON::Node& reco = prog.GetObjectValue("Recording"); JSON::BindObject(reco, &(program->recording), bindreco); // Bind artwork list of program const JSON::Node& arts = prog.GetObjectValue("Artwork").GetObjectValue("ArtworkInfos"); size_t as = arts.Size(); for (size_t pa = 0; pa < as; ++pa) { const JSON::Node& artw = arts.GetArrayElement(pa); Artwork artwork = Artwork(); // Using default constructor JSON::BindObject(artw, &artwork, bindartw); program->artwork.push_back(artwork); } ret->push_back(program); ++total; } DBG(DBG_DEBUG, "%s: received count(%d)\n", __FUNCTION__, count); req_index += count; // Set next requested index } while (count == req_count && (!n || n > total)); return ret; } ProgramPtr WSAPI::GetRecorded1_5(uint32_t chanid, time_t recstartts) { ProgramPtr ret; char buf[32]; unsigned proto = (unsigned)m_version.protocol; // Get bindings for protocol version const bindings_t *bindprog = MythDTO::getProgramBindArray(proto); const bindings_t *bindchan = MythDTO::getChannelBindArray(proto); const bindings_t *bindreco = MythDTO::getRecordingBindArray(proto); const bindings_t *bindartw = MythDTO::getArtworkBindArray(proto); WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Dvr/GetRecorded"); uint32_to_string(chanid, buf); req.SetContentParam("ChanId", buf); time_to_iso8601utc(recstartts, buf); req.SetContentParam("StartTime", buf); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return ret; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); return ret; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); const JSON::Node& prog = root.GetObjectValue("Program"); ProgramPtr program(new Program()); // Using default constructor // Bind the new program JSON::BindObject(prog, program.get(), bindprog); // Bind channel of program const JSON::Node& chan = prog.GetObjectValue("Channel"); JSON::BindObject(chan, &(program->channel), bindchan); // Bind recording of program const JSON::Node& reco = prog.GetObjectValue("Recording"); JSON::BindObject(reco, &(program->recording), bindreco); // Bind artwork list of program const JSON::Node& arts = prog.GetObjectValue("Artwork").GetObjectValue("ArtworkInfos"); size_t as = arts.Size(); for (size_t pa = 0; pa < as; ++pa) { const JSON::Node& artw = arts.GetArrayElement(pa); Artwork artwork = Artwork(); // Using default constructor JSON::BindObject(artw, &artwork, bindartw); program->artwork.push_back(artwork); } // Return valid program if (program->recording.startTs != INVALID_TIME) ret = program; return ret; } ProgramPtr WSAPI::GetRecorded6_0(uint32_t recordedid) { ProgramPtr ret; char buf[32]; unsigned proto = (unsigned)m_version.protocol; // Get bindings for protocol version const bindings_t *bindprog = MythDTO::getProgramBindArray(proto); const bindings_t *bindchan = MythDTO::getChannelBindArray(proto); const bindings_t *bindreco = MythDTO::getRecordingBindArray(proto); const bindings_t *bindartw = MythDTO::getArtworkBindArray(proto); WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Dvr/GetRecorded"); uint32_to_string(recordedid, buf); req.SetContentParam("RecordedId", buf); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return ret; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); return ret; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); const JSON::Node& prog = root.GetObjectValue("Program"); ProgramPtr program(new Program()); // Using default constructor // Bind the new program JSON::BindObject(prog, program.get(), bindprog); // Bind channel of program const JSON::Node& chan = prog.GetObjectValue("Channel"); JSON::BindObject(chan, &(program->channel), bindchan); // Bind recording of program const JSON::Node& reco = prog.GetObjectValue("Recording"); JSON::BindObject(reco, &(program->recording), bindreco); // Bind artwork list of program const JSON::Node& arts = prog.GetObjectValue("Artwork").GetObjectValue("ArtworkInfos"); size_t as = arts.Size(); for (size_t pa = 0; pa < as; ++pa) { const JSON::Node& artw = arts.GetArrayElement(pa); Artwork artwork = Artwork(); // Using default constructor JSON::BindObject(artw, &artwork, bindartw); program->artwork.push_back(artwork); } // Return valid program if (program->recording.startTs != INVALID_TIME) ret = program; return ret; } bool WSAPI::DeleteRecording2_1(uint32_t chanid, time_t recstartts, bool forceDelete, bool allowRerecord) { char buf[32]; // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Dvr/DeleteRecording", HRM_POST); uint32_to_string(chanid, buf); req.SetContentParam("ChanId", buf); time_to_iso8601utc(recstartts, buf); req.SetContentParam("StartTime", buf); req.SetContentParam("ForceDelete", BOOLSTR(forceDelete)); req.SetContentParam("AllowRerecord", BOOLSTR(allowRerecord)); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return false; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); return false; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); const JSON::Node& field = root.GetObjectValue("bool"); if (!field.IsString() || strcmp(field.GetStringValue().c_str(), "true")) return false; return true; } bool WSAPI::DeleteRecording6_0(uint32_t recordedid, bool forceDelete, bool allowRerecord) { char buf[32]; // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Dvr/DeleteRecording", HRM_POST); uint32_to_string(recordedid, buf); req.SetContentParam("RecordedId", buf); req.SetContentParam("ForceDelete", BOOLSTR(forceDelete)); req.SetContentParam("AllowRerecord", BOOLSTR(allowRerecord)); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return false; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); return false; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); const JSON::Node& field = root.GetObjectValue("bool"); if (!field.IsString() || strcmp(field.GetStringValue().c_str(), "true")) return false; return true; } bool WSAPI::UnDeleteRecording2_1(uint32_t chanid, time_t recstartts) { char buf[32]; // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Dvr/UnDeleteRecording", HRM_POST); uint32_to_string(chanid, buf); req.SetContentParam("ChanId", buf); time_to_iso8601utc(recstartts, buf); req.SetContentParam("StartTime", buf); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return false; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); return false; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); const JSON::Node& field = root.GetObjectValue("bool"); if (!field.IsString() || strcmp(field.GetStringValue().c_str(), "true")) return false; return true; } bool WSAPI::UnDeleteRecording6_0(uint32_t recordedid) { char buf[32]; // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Dvr/UnDeleteRecording", HRM_POST); uint32_to_string(recordedid, buf); req.SetContentParam("RecordedId", buf); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return false; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); return false; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); const JSON::Node& field = root.GetObjectValue("bool"); if (!field.IsString() || strcmp(field.GetStringValue().c_str(), "true")) return false; return true; } bool WSAPI::UpdateRecordedWatchedStatus4_5(uint32_t chanid, time_t recstartts, bool watched) { char buf[32]; // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Dvr/UpdateRecordedWatchedStatus", HRM_POST); uint32_to_string(chanid, buf); req.SetContentParam("ChanId", buf); time_to_iso8601utc(recstartts, buf); req.SetContentParam("StartTime", buf); req.SetContentParam("Watched", BOOLSTR(watched)); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return false; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); return false; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); const JSON::Node& field = root.GetObjectValue("bool"); if (!field.IsString() || strcmp(field.GetStringValue().c_str(), "true")) return false; return true; } bool WSAPI::UpdateRecordedWatchedStatus6_0(uint32_t recordedid, bool watched) { char buf[32]; // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Dvr/UpdateRecordedWatchedStatus", HRM_POST); uint32_to_string(recordedid, buf); req.SetContentParam("RecordedId", buf); req.SetContentParam("Watched", BOOLSTR(watched)); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return false; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); return false; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); const JSON::Node& field = root.GetObjectValue("bool"); if (!field.IsString() || strcmp(field.GetStringValue().c_str(), "true")) return false; return true; } MarkListPtr WSAPI::GetRecordedCommBreak6_1(uint32_t recordedid, int unit) { char buf[32]; MarkListPtr ret(new MarkList); unsigned proto = (unsigned)m_version.protocol; // Get bindings for protocol version const bindings_t *bindcut = MythDTO::getCuttingBindArray(proto); // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Dvr/GetRecordedCommBreak"); uint32_to_string(recordedid, buf); req.SetContentParam("RecordedId", buf); if (unit == 1) req.SetContentParam("OffsetType", "Position"); else if (unit == 2) req.SetContentParam("OffsetType", "Duration"); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return ret; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); return ret; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); // Object: CutList const JSON::Node& slist = root.GetObjectValue("CutList"); // Object: Cuttings[] const JSON::Node& vcuts = slist.GetObjectValue("Cuttings"); // Iterates over the sequence elements. size_t vs = vcuts.Size(); for (size_t vi = 0; vi < vs; ++vi) { const JSON::Node& vcut = vcuts.GetArrayElement(vi); MarkPtr mark(new Mark()); // Using default constructor // Bind the new mark JSON::BindObject(vcut, mark.get(), bindcut); ret->push_back(mark); } return ret; } MarkListPtr WSAPI::GetRecordedCutList6_1(uint32_t recordedid, int unit) { char buf[32]; MarkListPtr ret(new MarkList); unsigned proto = (unsigned)m_version.protocol; // Get bindings for protocol version const bindings_t *bindcut = MythDTO::getCuttingBindArray(proto); // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Dvr/GetRecordedCutList"); uint32_to_string(recordedid, buf); req.SetContentParam("RecordedId", buf); if (unit == 1) req.SetContentParam("OffsetType", "Position"); else if (unit == 2) req.SetContentParam("OffsetType", "Duration"); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return ret; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); return ret; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); // Object: CutList const JSON::Node& slist = root.GetObjectValue("CutList"); // Object: Cuttings[] const JSON::Node& vcuts = slist.GetObjectValue("Cuttings"); // Iterates over the sequence elements. size_t vs = vcuts.Size(); for (size_t vi = 0; vi < vs; ++vi) { const JSON::Node& vcut = vcuts.GetArrayElement(vi); MarkPtr mark(new Mark()); // Using default constructor // Bind the new mark JSON::BindObject(vcut, mark.get(), bindcut); ret->push_back(mark); } return ret; } bool WSAPI::SetSavedBookmark6_2(uint32_t recordedid, int unit, int64_t value) { char buf[32]; // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Dvr/SetSavedBookmark", HRM_POST); uint32_to_string(recordedid, buf); req.SetContentParam("RecordedId", buf); if (unit == 2) req.SetContentParam("OffsetType", "Duration"); else req.SetContentParam("OffsetType", "Position"); int64_to_string(value, buf); req.SetContentParam("Offset", buf); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return false; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); return false; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); const JSON::Node& field = root.GetObjectValue("bool"); if (!field.IsString() || strcmp(field.GetStringValue().c_str(), "true")) return false; return true; } int64_t WSAPI::GetSavedBookmark6_2(uint32_t recordedid, int unit) { char buf[32]; // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Dvr/GetSavedBookmark", HRM_POST); uint32_to_string(recordedid, buf); req.SetContentParam("RecordedId", buf); if (unit == 2) req.SetContentParam("OffsetType", "Duration"); else req.SetContentParam("OffsetType", "Position"); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return false; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); return false; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); int64_t value = 0; const JSON::Node& field = root.GetObjectValue("long"); if (!field.IsString() || string_to_int64(field.GetStringValue().c_str(), &value)) return -1; return value; } static void ProcessRecordIN(unsigned proto, RecordSchedule& record) { // Converting API codes to internal types record.type_t = RuleTypeFromString(proto, record.type); record.searchType_t = SearchTypeFromString(proto, record.searchType); record.dupMethod_t = DupMethodFromString(proto, record.dupMethod); record.dupIn_t = DupInFromString(proto, record.dupIn); } RecordScheduleListPtr WSAPI::GetRecordScheduleList1_5() { RecordScheduleListPtr ret(new RecordScheduleList); char buf[32]; int32_t req_index = 0, req_count = FETCHSIZE, count = 0; unsigned proto = (unsigned)m_version.protocol; // Get bindings for protocol version const bindings_t *bindlist = MythDTO::getListBindArray(proto); const bindings_t *bindrec = MythDTO::getRecordScheduleBindArray(proto); // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Dvr/GetRecordScheduleList"); do { req.ClearContent(); int32_to_string(req_index, buf); req.SetContentParam("StartIndex", buf); int32_to_string(req_count, buf); req.SetContentParam("Count", buf); DBG(DBG_DEBUG, "%s: request index(%d) count(%d)\n", __FUNCTION__, req_index, req_count); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); break; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); break; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); // Object: RecRuleList const JSON::Node& rlist = root.GetObjectValue("RecRuleList"); ItemList list = ItemList(); // Using default constructor JSON::BindObject(rlist, &list, bindlist); // List has ProtoVer. Check it or sound alarm if (list.protoVer != proto) { InvalidateService(); break; } count = 0; // Object: RecRules[] const JSON::Node& recs = rlist.GetObjectValue("RecRules"); // Iterates over the sequence elements. size_t rs = recs.Size(); for (size_t ri = 0; ri < rs; ++ri) { ++count; const JSON::Node& rec = recs.GetArrayElement(ri); RecordSchedulePtr record(new RecordSchedule()); // Using default constructor // Bind the new record JSON::BindObject(rec, record.get(), bindrec); ProcessRecordIN(proto, *record); ret->push_back(record); } DBG(DBG_DEBUG, "%s: received count(%d)\n", __FUNCTION__, count); req_index += count; // Set next requested index } while (count == req_count); return ret; } RecordSchedulePtr WSAPI::GetRecordSchedule1_5(uint32_t recordid) { RecordSchedulePtr ret; char buf[32]; unsigned proto = (unsigned)m_version.protocol; // Get bindings for protocol version const bindings_t *bindrec = MythDTO::getRecordScheduleBindArray(proto); WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Dvr/GetRecordSchedule"); uint32_to_string(recordid, buf); req.SetContentParam("RecordId", buf); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return ret; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); return ret; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); const JSON::Node& rec = root.GetObjectValue("RecRule"); RecordSchedulePtr record(new RecordSchedule()); // Using default constructor // Bind the new record JSON::BindObject(rec, record.get(), bindrec); // Return valid record if (record->recordId > 0) { ProcessRecordIN(proto, *record); ret = record; } return ret; } static void ProcessRecordOUT(unsigned proto, RecordSchedule& record) { char buf[10]; struct tm stm; time_t st = record.startTime; localtime_r(&st, &stm); // Set find time & day sprintf(buf, "%.2d:%.2d:%.2d", stm.tm_hour, stm.tm_min, stm.tm_sec); record.findTime = buf; record.findDay = (stm.tm_wday + 1) % 7; // Converting internal types to API codes record.type = RuleTypeToString(proto, record.type_t); record.searchType = SearchTypeToString(proto, record.searchType_t); record.dupMethod = DupMethodToString(proto, record.dupMethod_t); record.dupIn = DupInToString(proto, record.dupIn_t); } bool WSAPI::AddRecordSchedule1_5(RecordSchedule& record) { char buf[32]; uint32_t recordid; unsigned proto = (unsigned)m_version.protocol; ProcessRecordOUT(proto, record); // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Dvr/AddRecordSchedule", HRM_POST); req.SetContentParam("Title", record.title); req.SetContentParam("Subtitle", record.subtitle); req.SetContentParam("Description", record.description); req.SetContentParam("Category", record.category); time_to_iso8601utc(record.startTime, buf); req.SetContentParam("StartTime", buf); time_to_iso8601utc(record.endTime, buf); req.SetContentParam("EndTime", buf); req.SetContentParam("SeriesId", record.seriesId); req.SetContentParam("ProgramId", record.programId); uint32_to_string(record.chanId, buf); req.SetContentParam("ChanId", buf); uint32_to_string(record.parentId, buf); req.SetContentParam("ParentId", buf); req.SetContentParam("Inactive", BOOLSTR(record.inactive)); uint16_to_string(record.season, buf); req.SetContentParam("Season", buf); uint16_to_string(record.episode, buf); req.SetContentParam("Episode", buf); req.SetContentParam("Inetref", record.inetref); req.SetContentParam("Type", record.type); req.SetContentParam("SearchType", record.searchType); int8_to_string(record.recPriority, buf); req.SetContentParam("RecPriority", buf); uint32_to_string(record.preferredInput, buf); req.SetContentParam("PreferredInput", buf); uint8_to_string(record.startOffset, buf); req.SetContentParam("StartOffset", buf); uint8_to_string(record.endOffset, buf); req.SetContentParam("EndOffset", buf); req.SetContentParam("DupMethod", record.dupMethod); req.SetContentParam("DupIn", record.dupIn); uint32_to_string(record.filter, buf); req.SetContentParam("Filter", buf); req.SetContentParam("RecProfile", record.recProfile); req.SetContentParam("RecGroup", record.recGroup); req.SetContentParam("StorageGroup", record.storageGroup); req.SetContentParam("PlayGroup", record.playGroup); req.SetContentParam("AutoExpire", BOOLSTR(record.autoExpire)); uint32_to_string(record.maxEpisodes, buf); req.SetContentParam("MaxEpisodes", buf); req.SetContentParam("MaxNewest", BOOLSTR(record.maxNewest)); req.SetContentParam("AutoCommflag", BOOLSTR(record.autoCommflag)); req.SetContentParam("AutoTranscode", BOOLSTR(record.autoTranscode)); req.SetContentParam("AutoMetaLookup", BOOLSTR(record.autoMetaLookup)); req.SetContentParam("AutoUserJob1", BOOLSTR(record.autoUserJob1)); req.SetContentParam("AutoUserJob2", BOOLSTR(record.autoUserJob2)); req.SetContentParam("AutoUserJob3", BOOLSTR(record.autoUserJob3)); req.SetContentParam("AutoUserJob4", BOOLSTR(record.autoUserJob4)); uint32_to_string(record.transcoder, buf); req.SetContentParam("Transcoder", buf); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return false; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); return false; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); const JSON::Node& field = root.GetObjectValue("int"); if (!field.IsString() || string_to_uint32(field.GetStringValue().c_str(), &recordid)) return false; record.recordId = recordid; return true; } bool WSAPI::AddRecordSchedule1_7(RecordSchedule& record) { char buf[32]; uint32_t recordid; unsigned proto = (unsigned)m_version.protocol; ProcessRecordOUT(proto, record); // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Dvr/AddRecordSchedule", HRM_POST); req.SetContentParam("Title", record.title); req.SetContentParam("Subtitle", record.subtitle); req.SetContentParam("Description", record.description); req.SetContentParam("Category", record.category); time_to_iso8601utc(record.startTime, buf); req.SetContentParam("StartTime", buf); time_to_iso8601utc(record.endTime, buf); req.SetContentParam("EndTime", buf); req.SetContentParam("SeriesId", record.seriesId); req.SetContentParam("ProgramId", record.programId); uint32_to_string(record.chanId, buf); req.SetContentParam("ChanId", buf); req.SetContentParam("Station", record.callSign); int8_to_string(record.findDay, buf); req.SetContentParam("FindDay", buf); req.SetContentParam("FindTime", record.findTime); uint32_to_string(record.parentId, buf); req.SetContentParam("ParentId", buf); req.SetContentParam("Inactive", BOOLSTR(record.inactive)); uint16_to_string(record.season, buf); req.SetContentParam("Season", buf); uint16_to_string(record.episode, buf); req.SetContentParam("Episode", buf); req.SetContentParam("Inetref", record.inetref); req.SetContentParam("Type", record.type); req.SetContentParam("SearchType", record.searchType); int8_to_string(record.recPriority, buf); req.SetContentParam("RecPriority", buf); uint32_to_string(record.preferredInput, buf); req.SetContentParam("PreferredInput", buf); uint8_to_string(record.startOffset, buf); req.SetContentParam("StartOffset", buf); uint8_to_string(record.endOffset, buf); req.SetContentParam("EndOffset", buf); req.SetContentParam("DupMethod", record.dupMethod); req.SetContentParam("DupIn", record.dupIn); uint32_to_string(record.filter, buf); req.SetContentParam("Filter", buf); req.SetContentParam("RecProfile", record.recProfile); req.SetContentParam("RecGroup", record.recGroup); req.SetContentParam("StorageGroup", record.storageGroup); req.SetContentParam("PlayGroup", record.playGroup); req.SetContentParam("AutoExpire", BOOLSTR(record.autoExpire)); uint32_to_string(record.maxEpisodes, buf); req.SetContentParam("MaxEpisodes", buf); req.SetContentParam("MaxNewest", BOOLSTR(record.maxNewest)); req.SetContentParam("AutoCommflag", BOOLSTR(record.autoCommflag)); req.SetContentParam("AutoTranscode", BOOLSTR(record.autoTranscode)); req.SetContentParam("AutoMetaLookup", BOOLSTR(record.autoMetaLookup)); req.SetContentParam("AutoUserJob1", BOOLSTR(record.autoUserJob1)); req.SetContentParam("AutoUserJob2", BOOLSTR(record.autoUserJob2)); req.SetContentParam("AutoUserJob3", BOOLSTR(record.autoUserJob3)); req.SetContentParam("AutoUserJob4", BOOLSTR(record.autoUserJob4)); uint32_to_string(record.transcoder, buf); req.SetContentParam("Transcoder", buf); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return false; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); return false; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); const JSON::Node& field = root.GetObjectValue("uint"); if (!field.IsString() || string_to_uint32(field.GetStringValue().c_str(), &recordid)) return false; record.recordId = recordid; return true; } bool WSAPI::UpdateRecordSchedule1_7(RecordSchedule& record) { char buf[32]; unsigned proto = (unsigned)m_version.protocol; ProcessRecordOUT(proto, record); // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Dvr/UpdateRecordSchedule", HRM_POST); uint32_to_string(record.recordId, buf); req.SetContentParam("RecordId", buf); req.SetContentParam("Title", record.title); req.SetContentParam("Subtitle", record.subtitle); req.SetContentParam("Description", record.description); req.SetContentParam("Category", record.category); time_to_iso8601utc(record.startTime, buf); req.SetContentParam("StartTime", buf); time_to_iso8601utc(record.endTime, buf); req.SetContentParam("EndTime", buf); req.SetContentParam("SeriesId", record.seriesId); req.SetContentParam("ProgramId", record.programId); uint32_to_string(record.chanId, buf); req.SetContentParam("ChanId", buf); req.SetContentParam("Station", record.callSign); int8_to_string(record.findDay, buf); req.SetContentParam("FindDay", buf); req.SetContentParam("FindTime", record.findTime); uint32_to_string(record.parentId, buf); req.SetContentParam("ParentId", buf); req.SetContentParam("Inactive", BOOLSTR(record.inactive)); uint16_to_string(record.season, buf); req.SetContentParam("Season", buf); uint16_to_string(record.episode, buf); req.SetContentParam("Episode", buf); req.SetContentParam("Inetref", record.inetref); req.SetContentParam("Type", record.type); req.SetContentParam("SearchType", record.searchType); int8_to_string(record.recPriority, buf); req.SetContentParam("RecPriority", buf); uint32_to_string(record.preferredInput, buf); req.SetContentParam("PreferredInput", buf); uint8_to_string(record.startOffset, buf); req.SetContentParam("StartOffset", buf); uint8_to_string(record.endOffset, buf); req.SetContentParam("EndOffset", buf); req.SetContentParam("DupMethod", record.dupMethod); req.SetContentParam("DupIn", record.dupIn); uint32_to_string(record.filter, buf); req.SetContentParam("Filter", buf); req.SetContentParam("RecProfile", record.recProfile); req.SetContentParam("RecGroup", record.recGroup); req.SetContentParam("StorageGroup", record.storageGroup); req.SetContentParam("PlayGroup", record.playGroup); req.SetContentParam("AutoExpire", BOOLSTR(record.autoExpire)); uint32_to_string(record.maxEpisodes, buf); req.SetContentParam("MaxEpisodes", buf); req.SetContentParam("MaxNewest", BOOLSTR(record.maxNewest)); req.SetContentParam("AutoCommflag", BOOLSTR(record.autoCommflag)); req.SetContentParam("AutoTranscode", BOOLSTR(record.autoTranscode)); req.SetContentParam("AutoMetaLookup", BOOLSTR(record.autoMetaLookup)); req.SetContentParam("AutoUserJob1", BOOLSTR(record.autoUserJob1)); req.SetContentParam("AutoUserJob2", BOOLSTR(record.autoUserJob2)); req.SetContentParam("AutoUserJob3", BOOLSTR(record.autoUserJob3)); req.SetContentParam("AutoUserJob4", BOOLSTR(record.autoUserJob4)); uint32_to_string(record.transcoder, buf); req.SetContentParam("Transcoder", buf); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return false; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); return false; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); const JSON::Node& field = root.GetObjectValue("bool"); if (!field.IsString() || strcmp(field.GetStringValue().c_str(), "true")) return false; return true; } bool WSAPI::DisableRecordSchedule1_5(uint32_t recordid) { char buf[32]; // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Dvr/DisableRecordSchedule", HRM_POST); uint32_to_string(recordid, buf); req.SetContentParam("RecordId", buf); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return false; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); return false; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); const JSON::Node& field = root.GetObjectValue("bool"); if (!field.IsString() || strcmp(field.GetStringValue().c_str(), "true")) return false; return true; } bool WSAPI::EnableRecordSchedule1_5(uint32_t recordid) { char buf[32]; // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Dvr/EnableRecordSchedule", HRM_POST); uint32_to_string(recordid, buf); req.SetContentParam("RecordId", buf); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return false; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); return false; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); const JSON::Node& field = root.GetObjectValue("bool"); if (!field.IsString() || strcmp(field.GetStringValue().c_str(), "true")) return false; return true; } bool WSAPI::RemoveRecordSchedule1_5(uint32_t recordid) { char buf[32]; // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Dvr/RemoveRecordSchedule", HRM_POST); uint32_to_string(recordid, buf); req.SetContentParam("RecordId", buf); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return false; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); return false; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); const JSON::Node& field = root.GetObjectValue("bool"); if (!field.IsString() || strcmp(field.GetStringValue().c_str(), "true")) return false; return true; } ProgramListPtr WSAPI::GetUpcomingList1_5() { // Only for backward compatibility (0.27) ProgramListPtr ret = GetUpcomingList2_2(); // Add being recorded (https://code.mythtv.org/trac/changeset/3084ebc/mythtv) ProgramListPtr recordings = GetRecordedList(20, true); for (Myth::ProgramList::iterator it = recordings->begin(); it != recordings->end(); ++it) { if ((*it)->recording.status == RS_RECORDING) ret->push_back(*it); } return ret; } ProgramListPtr WSAPI::GetUpcomingList2_2() { ProgramListPtr ret(new ProgramList); char buf[32]; int32_t req_index = 0, req_count = FETCHSIZE, count = 0; unsigned proto = (unsigned)m_version.protocol; // Get bindings for protocol version const bindings_t *bindlist = MythDTO::getListBindArray(proto); const bindings_t *bindprog = MythDTO::getProgramBindArray(proto); const bindings_t *bindchan = MythDTO::getChannelBindArray(proto); const bindings_t *bindreco = MythDTO::getRecordingBindArray(proto); // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Dvr/GetUpcomingList"); do { req.ClearContent(); int32_to_string(req_index, buf); req.SetContentParam("StartIndex", buf); int32_to_string(req_count, buf); req.SetContentParam("Count", buf); req.SetContentParam("ShowAll", "true"); DBG(DBG_DEBUG, "%s: request index(%d) count(%d)\n", __FUNCTION__, req_index, req_count); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); break; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); break; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); // Object: ProgramList const JSON::Node& plist = root.GetObjectValue("ProgramList"); ItemList list = ItemList(); // Using default constructor JSON::BindObject(plist, &list, bindlist); // List has ProtoVer. Check it or sound alarm if (list.protoVer != proto) { InvalidateService(); break; } count = 0; // Object: Programs[] const JSON::Node& progs = plist.GetObjectValue("Programs"); // Iterates over the sequence elements. size_t ps = progs.Size(); for (size_t pi = 0; pi < ps; ++pi) { ++count; const JSON::Node& prog = progs.GetArrayElement(pi); ProgramPtr program(new Program()); // Using default constructor // Bind the new program JSON::BindObject(prog, program.get(), bindprog); // Bind channel of program const JSON::Node& chan = prog.GetObjectValue("Channel"); JSON::BindObject(chan, &(program->channel), bindchan); // Bind recording of program const JSON::Node& reco = prog.GetObjectValue("Recording"); JSON::BindObject(reco, &(program->recording), bindreco); ret->push_back(program); } DBG(DBG_DEBUG, "%s: received count(%d)\n", __FUNCTION__, count); req_index += count; // Set next requested index } while (count == req_count); return ret; } ProgramListPtr WSAPI::GetConflictList1_5() { ProgramListPtr ret(new ProgramList); char buf[32]; int32_t req_index = 0, req_count = FETCHSIZE, count = 0; unsigned proto = (unsigned)m_version.protocol; // Get bindings for protocol version const bindings_t *bindlist = MythDTO::getListBindArray(proto); const bindings_t *bindprog = MythDTO::getProgramBindArray(proto); const bindings_t *bindchan = MythDTO::getChannelBindArray(proto); const bindings_t *bindreco = MythDTO::getRecordingBindArray(proto); // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Dvr/GetConflictList"); do { req.ClearContent(); int32_to_string(req_index, buf); req.SetContentParam("StartIndex", buf); int32_to_string(req_count, buf); req.SetContentParam("Count", buf); DBG(DBG_DEBUG, "%s: request index(%d) count(%d)\n", __FUNCTION__, req_index, req_count); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); break; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); break; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); // Object: ProgramList const JSON::Node& plist = root.GetObjectValue("ProgramList"); ItemList list = ItemList(); // Using default constructor JSON::BindObject(plist, &list, bindlist); // List has ProtoVer. Check it or sound alarm if (list.protoVer != proto) { InvalidateService(); break; } count = 0; // Object: Programs[] const JSON::Node& progs = plist.GetObjectValue("Programs"); // Iterates over the sequence elements. size_t ps = progs.Size(); for (size_t pi = 0; pi < ps; ++pi) { ++count; const JSON::Node& prog = progs.GetArrayElement(pi); ProgramPtr program(new Program()); // Using default constructor // Bind the new program JSON::BindObject(prog, program.get(), bindprog); // Bind channel of program const JSON::Node& chan = prog.GetObjectValue("Channel"); JSON::BindObject(chan, &(program->channel), bindchan); // Bind recording of program const JSON::Node& reco = prog.GetObjectValue("Recording"); JSON::BindObject(reco, &(program->recording), bindreco); ret->push_back(program); } DBG(DBG_DEBUG, "%s: received count(%d)\n", __FUNCTION__, count); req_index += count; // Set next requested index } while (count == req_count); return ret; } ProgramListPtr WSAPI::GetExpiringList1_5() { ProgramListPtr ret(new ProgramList); char buf[32]; int32_t req_index = 0, req_count = FETCHSIZE, count = 0; unsigned proto = (unsigned)m_version.protocol; // Get bindings for protocol version const bindings_t *bindlist = MythDTO::getListBindArray(proto); const bindings_t *bindprog = MythDTO::getProgramBindArray(proto); const bindings_t *bindchan = MythDTO::getChannelBindArray(proto); const bindings_t *bindreco = MythDTO::getRecordingBindArray(proto); // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Dvr/GetExpiringList"); do { req.ClearContent(); int32_to_string(req_index, buf); req.SetContentParam("StartIndex", buf); int32_to_string(req_count, buf); req.SetContentParam("Count", buf); DBG(DBG_DEBUG, "%s: request index(%d) count(%d)\n", __FUNCTION__, req_index, req_count); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); break; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); break; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); // Object: ProgramList const JSON::Node& plist = root.GetObjectValue("ProgramList"); ItemList list = ItemList(); // Using default constructor JSON::BindObject(plist, &list, bindlist); // List has ProtoVer. Check it or sound alarm if (list.protoVer != proto) { InvalidateService(); break; } count = 0; // Object: Programs[] const JSON::Node& progs = plist.GetObjectValue("Programs"); // Iterates over the sequence elements. size_t ps = progs.Size(); for (size_t pi = 0; pi < ps; ++pi) { ++count; const JSON::Node& prog = progs.GetArrayElement(pi); ProgramPtr program(new Program()); // Using default constructor // Bind the new program JSON::BindObject(prog, program.get(), bindprog); // Bind channel of program const JSON::Node& chan = prog.GetObjectValue("Channel"); JSON::BindObject(chan, &(program->channel), bindchan); // Bind recording of program const JSON::Node& reco = prog.GetObjectValue("Recording"); JSON::BindObject(reco, &(program->recording), bindreco); ret->push_back(program); } DBG(DBG_DEBUG, "%s: received count(%d)\n", __FUNCTION__, count); req_index += count; // Set next requested index } while (count == req_count); return ret; } StringListPtr WSAPI::GetRecGroupList1_5() { StringListPtr ret(new StringList); // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Dvr/GetRecGroupList"); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return ret; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); return ret; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); // Object: Strings const JSON::Node& list = root.GetObjectValue("StringList"); if (list.IsArray()) { size_t s = list.Size(); for (size_t i = 0; i < s; ++i) { const JSON::Node& val = list.GetArrayElement(i); if (val.IsString()) { ret->push_back(val.GetStringValue()); } } } return ret; } /////////////////////////////////////////////////////////////////////////////// //// //// Content service //// WSStreamPtr WSAPI::GetFile1_32(const std::string& filename, const std::string& sgname) { WSStreamPtr ret; // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestService("/Content/GetFile"); req.SetContentParam("StorageGroup", sgname); req.SetContentParam("FileName", filename); WSResponse *resp = new WSResponse(req); /* try redirection if any */ if (resp->GetStatusCode() == 301 && !resp->Redirection().empty()) { URIParser uri(resp->Redirection()); WSRequest rreq(ResolveHostName(uri.Host()), uri.Port()); rreq.RequestService(std::string("/").append(uri.Path())); delete resp; resp = new WSResponse(rreq); } if (!resp->IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); delete resp; return ret; } ret.reset(new WSStream(resp)); return ret; } WSStreamPtr WSAPI::GetChannelIcon1_32(uint32_t chanid, unsigned width, unsigned height) { WSStreamPtr ret; char buf[32]; // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestService("/Guide/GetChannelIcon"); uint32_to_string(chanid, buf); req.SetContentParam("ChanId", buf); if (width) { uint32_to_string(width, buf); req.SetContentParam("Width", buf); } if (height) { uint32_to_string(height, buf); req.SetContentParam("Height", buf); } WSResponse *resp = new WSResponse(req); /* try redirection if any */ if (resp->GetStatusCode() == 301 && !resp->Redirection().empty()) { URIParser uri(resp->Redirection()); WSRequest rreq(ResolveHostName(uri.Host()), uri.Port()); rreq.RequestService(std::string("/").append(uri.Path())); delete resp; resp = new WSResponse(rreq); } if (!resp->IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); delete resp; return ret; } ret.reset(new WSStream(resp)); return ret; } std::string WSAPI::GetChannelIconUrl1_32(uint32_t chanid, unsigned width, unsigned height) { char buf[32]; std::string uri; uri.reserve(95); uri.append("http://").append(m_server); if (m_port != 80) { uint32_to_string(m_port, buf); uri.append(":").append(buf); } uri.append("/Guide/GetChannelIcon"); uint32_to_string(chanid, buf); uri.append("?ChanId=").append(buf); if (width) { uint32_to_string(width, buf); uri.append("&Width=").append(buf); } if (height) { uint32_to_string(height, buf); uri.append("&Height=").append(buf); } return uri; } WSStreamPtr WSAPI::GetPreviewImage1_32(uint32_t chanid, time_t recstartts, unsigned width, unsigned height) { WSStreamPtr ret; char buf[32]; // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestService("/Content/GetPreviewImage"); uint32_to_string(chanid, buf); req.SetContentParam("ChanId", buf); time_to_iso8601utc(recstartts, buf); req.SetContentParam("StartTime", buf); if (width) { uint32_to_string(width, buf); req.SetContentParam("Width", buf); } if (height) { uint32_to_string(height, buf); req.SetContentParam("Height", buf); } WSResponse *resp = new WSResponse(req); /* try redirection if any */ if (resp->GetStatusCode() == 301 && !resp->Redirection().empty()) { URIParser uri(resp->Redirection()); WSRequest rreq(ResolveHostName(uri.Host()), uri.Port()); rreq.RequestService(std::string("/").append(uri.Path())); delete resp; resp = new WSResponse(rreq); } if (!resp->IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); delete resp; return ret; } ret.reset(new WSStream(resp)); return ret; } std::string WSAPI::GetPreviewImageUrl1_32(uint32_t chanid, time_t recstartts, unsigned width, unsigned height) { char buf[32]; std::string uri; uri.reserve(95); uri.append("http://").append(m_server); if (m_port != 80) { uint32_to_string(m_port, buf); uri.append(":").append(buf); } uri.append("/Content/GetPreviewImage"); uint32_to_string(chanid, buf); uri.append("?ChanId=").append(buf); time_to_iso8601utc(recstartts, buf); uri.append("&StartTime=").append(encodeParam(buf)); if (width) { uint32_to_string(width, buf); uri.append("&Width=").append(buf); } if (height) { uint32_to_string(height, buf); uri.append("&Height=").append(buf); } return uri; } WSStreamPtr WSAPI::GetRecordingArtwork1_32(const std::string& type, const std::string& inetref, uint16_t season, unsigned width, unsigned height) { WSStreamPtr ret; char buf[32]; // Initialize request header WSRequest req = WSRequest(m_server, m_port); req.RequestService("/Content/GetRecordingArtwork"); req.SetContentParam("Type", type.c_str()); req.SetContentParam("Inetref", inetref.c_str()); uint16_to_string(season, buf); req.SetContentParam("Season", buf); if (width) { uint32_to_string(width, buf); req.SetContentParam("Width", buf); } if (height) { uint32_to_string(height, buf); req.SetContentParam("Height", buf); } WSResponse *resp = new WSResponse(req); /* try redirection if any */ if (resp->GetStatusCode() == 301 && !resp->Redirection().empty()) { URIParser uri(resp->Redirection()); WSRequest rreq(ResolveHostName(uri.Host()), uri.Port()); rreq.RequestService(std::string("/").append(uri.Path())); delete resp; resp = new WSResponse(rreq); } if (!resp->IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); delete resp; return ret; } ret.reset(new WSStream(resp)); return ret; } std::string WSAPI::GetRecordingArtworkUrl1_32(const std::string& type, const std::string& inetref, uint16_t season, unsigned width, unsigned height) { char buf[32]; std::string uri; uri.reserve(127); uri.append("http://").append(m_server); if (m_port != 80) { uint32_to_string(m_port, buf); uri.append(":").append(buf); } uri.append("/Content/GetRecordingArtwork"); uri.append("?Type=").append(encodeParam(type)); uri.append("&Inetref=").append(encodeParam(inetref)); uint16_to_string(season, buf); uri.append("&Season=").append(buf); if (width) { uint32_to_string(width, buf); uri.append("&Width=").append(buf); } if (height) { uint32_to_string(height, buf); uri.append("&Height=").append(buf); } return uri; } ArtworkListPtr WSAPI::GetRecordingArtworkList1_32(uint32_t chanid, time_t recstartts) { ArtworkListPtr ret(new ArtworkList); char buf[32]; unsigned proto = (unsigned)m_version.protocol; // Get bindings for protocol version const bindings_t *bindartw = MythDTO::getArtworkBindArray(proto); WSRequest req = WSRequest(m_server, m_port); req.RequestAccept(CT_JSON); req.RequestService("/Content/GetRecordingArtworkList"); uint32_to_string(chanid, buf); req.SetContentParam("ChanId", buf); time_to_iso8601utc(recstartts, buf); req.SetContentParam("StartTime", buf); WSResponse resp(req); if (!resp.IsSuccessful()) { DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); return ret; } const JSON::Document json(resp); const JSON::Node& root = json.GetRoot(); if (!json.IsValid() || !root.IsObject()) { DBG(DBG_ERROR, "%s: unexpected content\n", __FUNCTION__); return ret; } DBG(DBG_DEBUG, "%s: content parsed\n", __FUNCTION__); const JSON::Node& list = root.GetObjectValue("ArtworkInfoList"); // Bind artwork list const JSON::Node& arts = list.GetObjectValue("ArtworkInfos"); size_t as = arts.Size(); for (size_t pa = 0; pa < as; ++pa) { const JSON::Node& artw = arts.GetArrayElement(pa); ArtworkPtr artwork(new Artwork()); // Using default constructor JSON::BindObject(artw, artwork.get(), bindartw); ret->push_back(artwork); } return ret; } // Internal #include "private/urlencoder.h" static std::string encodeParam(const std::string& str) { return urlencode(str); } pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/mythwsapi.h000066400000000000000000000464651360567320200221360ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHWSAPI_H #define MYTHWSAPI_H #include "mythtypes.h" #include "mythwsstream.h" #define MYTH_API_VERSION_MIN_RANKING 0x00020000 #define MYTH_API_VERSION_MAX_RANKING 0x0005FFFF namespace Myth { namespace OS { class CMutex; } typedef enum { WS_Myth = 0, WS_Capture = 1, WS_Channel, WS_Guide, WS_Content, WS_Dvr, WS_INVALID, // Keep at last } WSServiceId_t; typedef struct { unsigned major; unsigned minor; unsigned ranking; } WSServiceVersion_t; class WSAPI { public: WSAPI(const std::string& server, unsigned port, const std::string& securityPin); ~WSAPI(); unsigned CheckService(); WSServiceVersion_t CheckService(WSServiceId_t id); void InvalidateService(); std::string GetServerHostName(); VersionPtr GetVersion(); std::string ResolveHostName(const std::string& hostname); /** * @brief GET Myth/GetSetting */ SettingPtr GetSetting(const std::string& key, const std::string& hostname) { WSServiceVersion_t wsv = CheckService(WS_Myth); if (wsv.ranking >= 0x00050000) return GetSetting5_0(key, hostname); if (wsv.ranking >= 0x00020000) return GetSetting2_0(key, hostname); return SettingPtr(); } /** * @brief GET Myth/GetSetting */ SettingPtr GetSetting(const std::string& key, bool myhost); /** * @brief GET Myth/GetSetting */ SettingMapPtr GetSettings(const std::string& hostname) { WSServiceVersion_t wsv = CheckService(WS_Myth); if (wsv.ranking >= 0x00050000) return GetSettings5_0(hostname); if (wsv.ranking >= 0x00020000) return GetSettings2_0(hostname); return SettingMapPtr(new SettingMap); } /** * @brief GET Myth/GetSetting */ SettingMapPtr GetSettings(bool myhost); /** * @brief POST Myth/PutSetting */ bool PutSetting(const std::string& key, const std::string& value, bool myhost) { WSServiceVersion_t wsv = CheckService(WS_Myth); if (wsv.ranking >= 0x00020000) return PutSetting2_0(key, value, myhost); return false; } /** * @brief GET Capture/GetCaptureCardList */ CaptureCardListPtr GetCaptureCardList() { WSServiceVersion_t wsv = CheckService(WS_Capture); if (wsv.ranking >= 0x00010004) return GetCaptureCardList1_4(); return CaptureCardListPtr(new CaptureCardList); } /** * @brief GET Channel/GetVideoSourceList */ VideoSourceListPtr GetVideoSourceList() { WSServiceVersion_t wsv = CheckService(WS_Channel); if (wsv.ranking >= 0x00010002) return GetVideoSourceList1_2(); return VideoSourceListPtr(new VideoSourceList); } /** * @brief GET Channel/GetChannelInfoList */ ChannelListPtr GetChannelList(uint32_t sourceid, bool onlyVisible = true) { WSServiceVersion_t wsv = CheckService(WS_Channel); if (wsv.ranking >= 0x00010005) return GetChannelList1_5(sourceid, onlyVisible); if (wsv.ranking >= 0x00010002) return GetChannelList1_2(sourceid, onlyVisible); return ChannelListPtr(new ChannelList); }; /** * @brief GET Channel/GetChannelInfo */ ChannelPtr GetChannel(uint32_t chanid) { WSServiceVersion_t wsv = CheckService(WS_Channel); if (wsv.ranking >= 0x00010002) return GetChannel1_2(chanid); return ChannelPtr(); }; /** * @brief GET Guide/GetProgramGuide for the given channel */ ProgramMapPtr GetProgramGuide(uint32_t chanid, time_t starttime, time_t endtime) { WSServiceVersion_t wsv = CheckService(WS_Guide); if (wsv.ranking >= 0x00020002) return GetProgramList2_2(chanid, starttime, endtime); if (wsv.ranking >= 0x00010000) return GetProgramGuide1_0(chanid, starttime, endtime); return ProgramMapPtr(new ProgramMap); } /** * @brief GET Guide/GetProgramGuide */ std::map GetProgramGuide(time_t starttime, time_t endtime) { WSServiceVersion_t wsv = CheckService(WS_Guide); if (wsv.ranking >= 0x00020002) return GetProgramGuide2_2(starttime, endtime); if (wsv.ranking >= 0x00010000) return GetProgramGuide1_0(starttime, endtime); return std::map(); } /** * @brief GET Dvr/GetRecordedList */ ProgramListPtr GetRecordedList(unsigned n = 0, bool descending = false) { WSServiceVersion_t wsv = CheckService(WS_Dvr); if (wsv.ranking >= 0x00010005) return GetRecordedList1_5(n, descending); return ProgramListPtr(new ProgramList); } /** * @brief GET Dvr/GetRecorded */ ProgramPtr GetRecorded(uint32_t chanid, time_t recstartts) { WSServiceVersion_t wsv = CheckService(WS_Dvr); if (wsv.ranking >= 0x00010005) return GetRecorded1_5(chanid, recstartts); return ProgramPtr(); } /** * @brief GET Dvr/GetRecorded */ ProgramPtr GetRecorded(uint32_t recordedid) { WSServiceVersion_t wsv = CheckService(WS_Dvr); if (wsv.ranking >= 0x00060000) return GetRecorded6_0(recordedid); return ProgramPtr(); } /** * @brief POST Dvr/UpdateRecordedWatchedStatus */ bool UpdateRecordedWatchedStatus(uint32_t chanid, time_t recstartts, bool watched) { WSServiceVersion_t wsv = CheckService(WS_Dvr); if (wsv.ranking >= 0x00040005) return UpdateRecordedWatchedStatus4_5(chanid, recstartts, watched); return false; } /** * @brief POST Dvr/UpdateRecordedWatchedStatus */ bool UpdateRecordedWatchedStatus(uint32_t recordedid, bool watched) { WSServiceVersion_t wsv = CheckService(WS_Dvr); if (wsv.ranking >= 0x00060000) return UpdateRecordedWatchedStatus6_0(recordedid, watched); return false; } /** * @brief POST Dvr/DeleteRecording */ bool DeleteRecording(uint32_t chanid, time_t recstartts, bool forceDelete = false, bool allowRerecord = false) { WSServiceVersion_t wsv = CheckService(WS_Dvr); if (wsv.ranking >= 0x00020001) return DeleteRecording2_1(chanid, recstartts, forceDelete, allowRerecord); return false; } /** * @brief POST Dvr/DeleteRecording */ bool DeleteRecording(uint32_t recordedid, bool forceDelete = false, bool allowRerecord = false) { WSServiceVersion_t wsv = CheckService(WS_Dvr); if (wsv.ranking >= 0x00060000) return DeleteRecording6_0(recordedid, forceDelete, allowRerecord); return false; } /** * @brief POST Dvr/UnDeleteRecording */ bool UnDeleteRecording(uint32_t chanid, time_t recstartts) { WSServiceVersion_t wsv = CheckService(WS_Dvr); if (wsv.ranking >= 0x00020001) return UnDeleteRecording2_1(chanid, recstartts); return false; } /** * @brief POST Dvr/UnDeleteRecording */ bool UnDeleteRecording(uint32_t recordedid) { WSServiceVersion_t wsv = CheckService(WS_Dvr); if (wsv.ranking >= 0x00060000) return UnDeleteRecording6_0(recordedid); return false; } /** * @brief GET Dvr/GetRecordScheduleList */ RecordScheduleListPtr GetRecordScheduleList() { WSServiceVersion_t wsv = CheckService(WS_Dvr); if (wsv.ranking >= 0x00010005) return GetRecordScheduleList1_5(); return RecordScheduleListPtr(new RecordScheduleList); } /** * @brief GET Dvr/GetRecordSchedule */ RecordSchedulePtr GetRecordSchedule(uint32_t recordid) { WSServiceVersion_t wsv = CheckService(WS_Dvr); if (wsv.ranking >= 0x00010005) return GetRecordSchedule1_5(recordid); return RecordSchedulePtr(); } /** * @brief POST Dvr/AddRecordSchedule */ bool AddRecordSchedule(RecordSchedule& record) { WSServiceVersion_t wsv = CheckService(WS_Dvr); if (wsv.ranking >= 0x00010007) return AddRecordSchedule1_7(record); if (wsv.ranking >= 0x00010005) return AddRecordSchedule1_5(record); return false; } /** * @brief POST Dvr/UpdateRecordSchedule */ bool UpdateRecordSchedule(RecordSchedule& record) { WSServiceVersion_t wsv = CheckService(WS_Dvr); if (wsv.ranking >= 0x00010007) return UpdateRecordSchedule1_7(record); return false; } /** * @brief POST Dvr/DisableRecordSchedule */ bool DisableRecordSchedule(uint32_t recordid) { WSServiceVersion_t wsv = CheckService(WS_Dvr); if (wsv.ranking >= 0x00010005) return DisableRecordSchedule1_5(recordid); return false; } /** * @brief POST Dvr/EnableRecordSchedule */ bool EnableRecordSchedule(uint32_t recordid) { WSServiceVersion_t wsv = CheckService(WS_Dvr); if (wsv.ranking >= 0x00010005) return EnableRecordSchedule1_5(recordid); return false; } /** * @brief POST Dvr/RemoveRecordSchedule */ bool RemoveRecordSchedule(uint32_t recordid) { WSServiceVersion_t wsv = CheckService(WS_Dvr); if (wsv.ranking >= 0x00010005) return RemoveRecordSchedule1_5(recordid); return false; } /** * @brief GET Dvr/GetUpcomingList */ ProgramListPtr GetUpcomingList() { WSServiceVersion_t wsv = CheckService(WS_Dvr); if (wsv.ranking >= 0x00020002) return GetUpcomingList2_2(); if (wsv.ranking >= 0x00010005) return GetUpcomingList1_5(); return ProgramListPtr(new ProgramList); } /** * @brief GET Dvr/GetConflictList */ ProgramListPtr GetConflictList() { WSServiceVersion_t wsv = CheckService(WS_Dvr); if (wsv.ranking >= 0x00010005) return GetConflictList1_5(); return ProgramListPtr(new ProgramList); } /** * @brief GET Dvr/GetExpiringList */ ProgramListPtr GetExpiringList() { WSServiceVersion_t wsv = CheckService(WS_Dvr); if (wsv.ranking >= 0x00010005) return GetExpiringList1_5(); return ProgramListPtr(new ProgramList); } /** * @brief GET Dvr/GetRecGroupList */ StringListPtr GetRecGroupList() { WSServiceVersion_t wsv = CheckService(WS_Dvr); if (wsv.ranking >= 0x00010005) return GetRecGroupList1_5(); return StringListPtr(new StringList); } /** * @brief GET Content/GetFile */ WSStreamPtr GetFile(const std::string& filename, const std::string& sgname) { WSServiceVersion_t wsv = CheckService(WS_Content); if (wsv.ranking >= 0x00010020) return GetFile1_32(filename, sgname); return WSStreamPtr(); } /** * @brief GET Guide/GetChannelIcon */ WSStreamPtr GetChannelIcon(uint32_t chanid, unsigned width = 0, unsigned height = 0) { WSServiceVersion_t wsv = CheckService(WS_Content); if (wsv.ranking >= 0x00010020) return GetChannelIcon1_32(chanid, width, height); return WSStreamPtr(); } /** * @brief Returns URL for channel icon */ std::string GetChannelIconUrl(uint32_t chanid, unsigned width = 0, unsigned height = 0) { WSServiceVersion_t wsv = CheckService(WS_Content); if (wsv.ranking >= 0x00010020) return GetChannelIconUrl1_32(chanid, width, height); return ""; } /** * @brief GET Content/GetPreviewImage */ WSStreamPtr GetPreviewImage(uint32_t chanid, time_t recstartts, unsigned width = 0, unsigned height = 0) { WSServiceVersion_t wsv = CheckService(WS_Content); if (wsv.ranking >= 0x00010020) return GetPreviewImage1_32(chanid, recstartts, width, height); return WSStreamPtr(); } /** * @brief Returns URL for preview image */ std::string GetPreviewImageUrl(uint32_t chanid, time_t recstartts, unsigned width = 0, unsigned height = 0) { WSServiceVersion_t wsv = CheckService(WS_Content); if (wsv.ranking >= 0x00010020) return GetPreviewImageUrl1_32(chanid, recstartts, width, height); return ""; } /** * @brief GET Content/GetRecordingArtwork */ WSStreamPtr GetRecordingArtwork(const std::string& type, const std::string& inetref, uint16_t season, unsigned width = 0, unsigned height = 0) { WSServiceVersion_t wsv = CheckService(WS_Content); if (wsv.ranking >= 0x00010020) return GetRecordingArtwork1_32(type, inetref, season, width, height); return WSStreamPtr(); } /** * @brief Returns URL for recording artwork */ std::string GetRecordingArtworkUrl(const std::string& type, const std::string& inetref, uint16_t season, unsigned width = 0, unsigned height = 0) { WSServiceVersion_t wsv = CheckService(WS_Content); if (wsv.ranking >= 0x00010020) return GetRecordingArtworkUrl1_32(type, inetref, season, width, height); return ""; } /** * @brief GET Content/GetRecordingArtworkList */ ArtworkListPtr GetRecordingArtworkList(uint32_t chanid, time_t recstartts) { WSServiceVersion_t wsv = CheckService(WS_Content); if (wsv.ranking >= 0x00010020) return GetRecordingArtworkList1_32(chanid, recstartts); return ArtworkListPtr(new ArtworkList); } /** * @brief GET Dvr/GetRecordedCommBreak * @param recordedid * @param unit 0 = Frame count, 1 = Position, 2 = Duration ms * @return MarkListPtr */ MarkListPtr GetRecordedCommBreak(uint32_t recordedid, int unit) { WSServiceVersion_t wsv = CheckService(WS_Dvr); if (wsv.ranking >= 0x00060001) return GetRecordedCommBreak6_1(recordedid, unit); return MarkListPtr(new MarkList); } /** * @brief GET Dvr/GetRecordedCutList * @param recordedid * @param unit 0 = Frame count, 1 = Position, 2 = Duration ms * @return MarkListPtr */ MarkListPtr GetRecordedCutList(uint32_t recordedid, int unit) { WSServiceVersion_t wsv = CheckService(WS_Dvr); if (wsv.ranking >= 0x00060001) return GetRecordedCutList6_1(recordedid, unit); return MarkListPtr(new MarkList); } /** * @brief POST Dvr/SetSavedBookmark * @param recordedid * @param unit 1 = Position, 2 = Duration ms * @param value of mark * @return boolean */ bool SetSavedBookmark(uint32_t recordedid, int unit, int64_t value) { WSServiceVersion_t wsv = CheckService(WS_Dvr); if (wsv.ranking >= 0x00060002) return SetSavedBookmark6_2(recordedid, unit, value); return false; } /** * @brief GET Dvr/GetSavedBookmark * @param recordedid * @param unit 1 = Position, 2 = Duration ms * @return value */ int64_t GetSavedBookmark(uint32_t recordedid, int unit) { WSServiceVersion_t wsv = CheckService(WS_Dvr); if (wsv.ranking >= 0x00060002) return GetSavedBookmark6_2(recordedid, unit); return 0; } private: OS::CMutex *m_mutex; std::string m_server; unsigned m_port; std::string m_securityPin; bool m_checked; Version m_version; std::string m_serverHostName; WSServiceVersion_t m_serviceVersion[WS_INVALID + 1]; std::map m_namedCache; // prevent copy WSAPI(const WSAPI&); WSAPI& operator=(const WSAPI&); bool InitWSAPI(); bool GetServiceVersion(WSServiceId_t id, WSServiceVersion_t& version); bool CheckServerHostName2_0(); bool CheckVersion2_0(); SettingPtr GetSetting2_0(const std::string& key, const std::string& hostname); SettingPtr GetSetting5_0(const std::string& key, const std::string& hostname); SettingMapPtr GetSettings2_0(const std::string& hostname); SettingMapPtr GetSettings5_0(const std::string& hostname); bool PutSetting2_0(const std::string& key, const std::string& value, bool myhost); CaptureCardListPtr GetCaptureCardList1_4(); VideoSourceListPtr GetVideoSourceList1_2(); ChannelListPtr GetChannelList1_2(uint32_t sourceid, bool onlyVisible); ChannelListPtr GetChannelList1_5(uint32_t sourceid, bool onlyVisible); ChannelPtr GetChannel1_2(uint32_t chanid); std::map GetProgramGuide1_0(time_t starttime, time_t endtime); ProgramMapPtr GetProgramGuide1_0(uint32_t chanid, time_t starttime, time_t endtime); std::map GetProgramGuide2_2(time_t starttime, time_t endtime); ProgramMapPtr GetProgramList2_2(uint32_t chanid, time_t starttime, time_t endtime); ProgramListPtr GetRecordedList1_5(unsigned n, bool descending); ProgramPtr GetRecorded1_5(uint32_t chanid, time_t recstartts); ProgramPtr GetRecorded6_0(uint32_t recordedid); bool DeleteRecording2_1(uint32_t chanid, time_t recstartts, bool forceDelete, bool allowRerecord); bool DeleteRecording6_0(uint32_t recordedid, bool forceDelete, bool allowRerecord); bool UnDeleteRecording2_1(uint32_t chanid, time_t recstartts); bool UnDeleteRecording6_0(uint32_t recordedid); bool UpdateRecordedWatchedStatus4_5(uint32_t chanid, time_t recstartts, bool watched); bool UpdateRecordedWatchedStatus6_0(uint32_t recordedid, bool watched); MarkListPtr GetRecordedCommBreak6_1(uint32_t recordedid, int unit); MarkListPtr GetRecordedCutList6_1(uint32_t recordedid, int unit); bool SetSavedBookmark6_2(uint32_t recordedid, int unit, int64_t value); int64_t GetSavedBookmark6_2(uint32_t recordedid, int unit); RecordScheduleListPtr GetRecordScheduleList1_5(); RecordSchedulePtr GetRecordSchedule1_5(uint32_t recordid); bool AddRecordSchedule1_5(RecordSchedule& record); bool AddRecordSchedule1_7(RecordSchedule& record); bool UpdateRecordSchedule1_7(RecordSchedule& record); bool DisableRecordSchedule1_5(uint32_t recordid); bool EnableRecordSchedule1_5(uint32_t recordid); bool RemoveRecordSchedule1_5(uint32_t recordid); ProgramListPtr GetUpcomingList1_5(); ProgramListPtr GetUpcomingList2_2(); ProgramListPtr GetConflictList1_5(); ProgramListPtr GetExpiringList1_5(); StringListPtr GetRecGroupList1_5(); WSStreamPtr GetFile1_32(const std::string& filename, const std::string& sgname); WSStreamPtr GetChannelIcon1_32(uint32_t chanid, unsigned width, unsigned height); std::string GetChannelIconUrl1_32(uint32_t chanid, unsigned width, unsigned height); WSStreamPtr GetPreviewImage1_32(uint32_t chanid, time_t recstartts, unsigned width, unsigned height); std::string GetPreviewImageUrl1_32(uint32_t chanid, time_t recstartts, unsigned width, unsigned height); WSStreamPtr GetRecordingArtwork1_32(const std::string& type, const std::string& inetref, uint16_t season, unsigned width, unsigned height); std::string GetRecordingArtworkUrl1_32(const std::string& type, const std::string& inetref, uint16_t season, unsigned width, unsigned height); ArtworkListPtr GetRecordingArtworkList1_32(uint32_t chanid, time_t recstartts); }; } #endif /* MYTHWSAPI_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/mythwsstream.cpp000066400000000000000000000034111360567320200231730ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "mythwsstream.h" #include "private/wsresponse.h" #include "private/cppdef.h" using namespace Myth; WSStream::WSStream() : m_response(NULL) , m_position(0) { } WSStream::WSStream(WSResponse *response) : m_response(response) , m_position(0) { } WSStream::~WSStream() { SAFE_DELETE(m_response); } int WSStream::Read(void* buffer, unsigned n) { if (m_response == NULL) return 0; size_t s = m_response->ReadContent((char *)buffer, n); m_position += s; return (int)s; } int64_t WSStream::GetSize() const { return (m_response != NULL ? (int64_t)(-1) : 0); } int64_t WSStream::GetPosition() const { return (m_response != NULL ? m_position : 0); } int64_t WSStream::Seek(int64_t offset, WHENCE_t whence) { (void)offset; (void)whence; return GetPosition(); } std::string WSStream::GetContentType() const { std::string val; if (m_response->GetHeaderValue("CONTENT-TYPE", val)) return val.substr(0, val.find(';')); return val; } pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/mythwsstream.h000066400000000000000000000027221360567320200226440ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHWSSTREAM_H #define MYTHWSSTREAM_H #include "mythtypes.h" #include "mythstream.h" namespace Myth { class WSStream; class WSResponse; typedef MYTH_SHARED_PTR WSStreamPtr; class WSStream : public Stream { public: WSStream(); WSStream(WSResponse *response); ~WSStream(); int Read(void* buffer, unsigned n); int64_t GetSize() const; // Always returns -1 for valid stream else 0 int64_t GetPosition() const; int64_t Seek(int64_t offset, WHENCE_t whence); std::string GetContentType() const; private: WSResponse *m_response; int64_t m_position; }; } #endif /* MYTHWSSTREAM_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/000077500000000000000000000000001360567320200213735ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/atomic.h000066400000000000000000000241001360567320200230150ustar00rootroot00000000000000/* * Copyright (C) 2014-2015 Jean-Luc Barriere * * 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 3, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef ATOMIC_H #define ATOMIC_H #include #ifdef __GNUC__ #if defined __arm__ && (!defined __thumb__ || defined __thumb2__) /* The __ARM_ARCH define is provided by gcc 4.8. Construct it otherwise. */ #ifndef __ARM_ARCH #ifdef __ARM_ARCH_2__ #define __ARM_ARCH 2 #elif defined (__ARM_ARCH_3__) || defined (__ARM_ARCH_3M__) #define __ARM_ARCH 3 #elif defined (__ARM_ARCH_4__) || defined (__ARM_ARCH_4T__) #define __ARM_ARCH 4 #elif defined (__ARM_ARCH_5__) || defined (__ARM_ARCH_5E__) \ || defined(__ARM_ARCH_5T__) || defined(__ARM_ARCH_5TE__) \ || defined(__ARM_ARCH_5TEJ__) #define __ARM_ARCH 5 #elif defined (__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \ || defined (__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) \ || defined (__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) #define __ARM_ARCH 6 #elif defined (__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \ || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \ || defined(__ARM_ARCH_7EM__) #define __ARM_ARCH 7 #endif #endif #endif namespace NSROOT { template class atomic { public: typedef volatile T atomic_t; atomic(T val) : m_val(val) {} atomic_t load() { return m_val; } private: atomic_t m_val; }; template<> class atomic { public: typedef volatile int atomic_t; atomic(int val) : m_val(val) {} int __attribute__((always_inline)) load() { return m_val; } int __attribute__((always_inline)) operator()() { return load(); } int __attribute__((always_inline)) add_fetch(int amount) { atomic_t __val; #if defined __mips__ int temp; __asm__ volatile ( " .set arch=r4000\n" "1: ll %0, %1\n" /* load old value */ " addu %2, %0, %3\n" /* calculate new value */ " sc %2, %1\n" /* attempt to store */ " beqzl %2, 1b\n" /* spin if failed */ " .set mips0\n" : "=&r" (__val), "=m" (m_val), "=&r" (temp) : "r" (amount), "m" (m_val)); /* __val is the old value, so normalize it. */ __val += amount; #elif defined __i386__ || defined __i486__ || defined __i586__ || defined __i686__ || defined __x86_64__ __asm__ volatile ( "lock xaddl %0, (%1);" : "=r" (__val) : "r" (&m_val), "0" (amount) : "cc", "memory" ); /* __val is the old value, so normalize it. */ __val += amount; #elif defined __powerpc__ || defined __ppc__ || defined __ppc64__ __asm__ volatile ( "1: lwarx %0,0,%1\n" " add %0,%2,%0\n" " dcbt %0,%1\n" " stwcx. %0,0,%1\n" " bne- 1b\n" " isync\n" : "=&r" (__val) : "r" (&m_val), "r" (amount) : "cc", "memory"); #elif defined __sparc__ || defined __sparc64__ atomic_t __old, __new = m_val; do { __old = __new; __new = __old + amount; /* compare and swap: if (*a == b) swap(*a, c) else c = *a */ __asm__ volatile ( "cas [%2], %3, %0" : "=&r" (__new) : "" (__new), "r" (&m_val), "r" (__old) : "memory"); } while (__new != __old); __val = __old + amount; #elif (defined __ARM_ARCH && __ARM_ARCH == 7) __asm__ volatile ( " dmb ish\n" /* Memory barrier */ "1: ldrex %0, [%1]\n" " add %0, %0, %2\n" " strex r1, %0, [%1]\n" " cmp r1, #0\n" " bne 1b\n" " dmb ish\n" /* Memory barrier */ : "=&r" (__val) : "r" (&m_val), "r" (amount) : "r1", "memory"); #elif (defined __ARM_ARCH && __ARM_ARCH == 6) __asm__ volatile ( "mcr p15, 0, %0, c7, c10, 5" /* Memory barrier */ : : "r" (0) : "memory"); __asm__ volatile ( "1: ldrex %0, [%1]\n" " add %0, %0, %2\n" " strex r1, %0, [%1]\n" " cmp r1, #0\n" " bne 1b\n" : "=&r" (__val) : "r" (&m_val), "r" (amount) : "r1"); __asm__ volatile ( "mcr p15, 0, %0, c7, c10, 5" /* Memory barrier */ : : "r" (0) : "memory"); #elif (defined __ARM_ARCH && __ARM_ARCH < 6) int tmp1, tmp2; __asm__ volatile ( "0: ldr %0, [%3]\n" " add %1, %0, %4\n" " swp %2, %1, [%3]\n" " cmp %0, %2\n" " swpne %0, %2, [%3]\n" " bne 0b\n" : "=&r" (tmp1), "=&r" (__val), "=&r" (tmp2) : "r" (&m_val), "r" (amount) : "cc", "memory"); #elif defined __aarch64__ unsigned long tmp; __asm__ volatile ( " dmb ish\n" /* Memory barrier */ "1: ldxr %w0, %2\n" " add %w0, %w0, %w3\n" " stlxr %w1, %w0, %2\n" " cbnz %w1, 1b\n" " dmb ish\n" /* Memory barrier */ : "=&r" (__val), "=&r" (tmp), "+Q" (m_val) : "Ir" (amount) : "memory"); #else /* warning unknown architecture, atomic increment is not... */ #ifndef ATOMIC_NOATOMIC #define ATOMIC_NOATOMIC #endif __val = m_val += amount; #endif return __val; } int __attribute__((always_inline)) operator++() { return add_fetch(1); } int __attribute__((always_inline)) sub_fetch(int amount) { atomic_t __val; #if defined __mips__ int temp; __asm__ volatile ( " .set arch=r4000\n" "1: ll %0, %1\n" /* load old value */ " subu %2, %0, %3\n" /* calculate new value */ " sc %2, %1\n" /* attempt to store */ " beqzl %2, 1b\n" /* spin if failed */ " .set mips0\n" : "=&r" (__val), "=m" (m_val), "=&r" (temp) : "r" (amount), "m" (m_val)); /* __val is the old value, so normalize it */ __val -= amount; #elif defined __i386__ || defined __i486__ || defined __i586__ || defined __i686__ || defined __x86_64__ __asm__ volatile ( "lock xaddl %0, (%1);" : "=r" (__val) : "r" (&m_val), "0" (-amount) : "cc", "memory" ); /* __val is the pre-decrement value, so normalize it */ __val -= amount; #elif defined __powerpc__ || defined __ppc__ || defined __ppc64__ __asm__ volatile ( "1: lwarx %0,0,%1\n" " subf %0,%2,%0\n" " dcbt %0,%1\n" " stwcx. %0,0,%1\n" " bne- 1b\n" " isync\n" : "=&r" (__val) : "r" (&m_val), "r" (amount) : "cc", "memory"); #elif defined __sparc__ || defined __sparc64__ atomic_t __old, __new = m_val; do { __old = __new; __new = __old - amount; /* compare and swap: if (*a == b) swap(*a, c) else c = *a */ __asm__ volatile ( "cas [%2], %3, %0" : "=&r" (__new) : "" (__new), "r" (&m_val), "r" (__old) : "memory"); } while (__new != __old); __val = __old - amount; #elif (defined __ARM_ARCH && __ARM_ARCH == 7) __asm__ volatile ( " dmb ish\n" /* Memory barrier */ "1: ldrex %0, [%1]\n" " sub %0, %0, %2\n" " strex r1, %0, [%1]\n" " cmp r1, #0\n" " bne 1b\n" " dmb ish\n" /* Memory barrier */ : "=&r" (__val) : "r" (&m_val), "r" (amount) : "r1", "memory"); #elif (defined __ARM_ARCH && __ARM_ARCH == 6) __asm__ volatile ( "mcr p15, 0, %0, c7, c10, 5" /* Memory barrier */ : : "r" (0) : "memory"); __asm__ volatile ( "1: ldrex %0, [%1]\n" " sub %0, %0, %2\n" " strex r1, %0, [%1]\n" " cmp r1, #0\n" " bne 1b\n" : "=&r" (__val) : "r" (&m_val), "r" (amount) : "r1"); __asm__ volatile ( "mcr p15, 0, %0, c7, c10, 5" /* Memory barrier */ : : "r" (0) : "memory"); #elif (defined __ARM_ARCH && __ARM_ARCH < 6) int tmp1, tmp2; __asm__ volatile ( "0: ldr %0, [%3]\n" " add %1, %0, %4\n" " swp %2, %1, [%3]\n" " cmp %0, %2\n" " swpne %0, %2, [%3]\n" " bne 0b\n" : "=&r" (tmp1), "=&r" (__val), "=&r" (tmp2) : "r" (&m_val), "r" (-amount) : "cc", "memory"); #elif defined __aarch64__ unsigned long tmp; __asm__ volatile ( " dmb ish\n" /* Memory barrier */ "1: ldxr %w0, %2\n" " sub %w0, %w0, %w3\n" " stlxr %w1, %w0, %2\n" " cbnz %w1, 1b\n" " dmb ish\n" /* Memory barrier */ : "=&r" (__val), "=&r" (tmp), "+Q" (m_val) : "Ir" (amount) : "memory"); #else /* warning unknown architecture, atomic deccrement is not... */ #ifndef ATOMIC_NOATOMIC #define ATOMIC_NOATOMIC #endif __val = m_val -= amount; #endif return __val; } int __attribute__((always_inline)) operator--() { return sub_fetch(1); } private: atomic_t m_val; }; } #else #ifndef ATOMIC_NOATOMIC #define ATOMIC_NOATOMIC #endif #endif #endif /* ATOMIC_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/builtin.c000066400000000000000000000207261360567320200232140ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "builtin.h" #include #include #include #include int string_to_int64(const char *str, int64_t *num) { uint64_t val = 0; int sign = 1; uint64_t limit = INT64_MAX; if (str == NULL) return -(EINVAL); while (isspace(*str)) { ++str; } if (*str && (*str == '-')) { ++str; sign = -1; } while (*str && !isspace(*str)) { if (!isdigit(*str)) return -(EINVAL); val *= 10; val += ((*str) - '0'); /* * Check and make sure we are still under the limit (this is * an absolute value limit, sign will be applied later). */ if (val > limit) return -(ERANGE); str++; } *num = (int64_t) (sign * val); return 0; } int string_to_int32(const char *str, int32_t *num) { uint64_t val = 0; int sign = 1; uint64_t limit = INT32_MAX; if (str == NULL) return -(EINVAL); while (isspace(*str)) { ++str; } if (*str && (*str == '-')) { ++str; sign = -1; } while (*str && !isspace(*str)) { if (!isdigit(*str)) return -(EINVAL); val *= 10; val += ((*str) - '0'); /* * Check and make sure we are still under the limit (this is * an absolute value limit, sign will be applied later). */ if (val > limit) return -(ERANGE); str++; } *num = (int32_t) (sign * val); return 0; } int string_to_int16(const char *str, int16_t *num) { int32_t val; int err; if ((err = string_to_int32(str, &val))) return err; if (val > 32767 || val < -32768) return -(ERANGE); *num = (int16_t) val; return 0; } int string_to_int8(const char *str, int8_t *num) { int32_t val; int err; if ((err = string_to_int32(str, &val))) return err; if (val > 127 || val < -128) return -(ERANGE); *num = (int8_t) val; return 0; } int string_to_uint32(const char *str, uint32_t *num) { uint64_t val = 0; uint64_t limit = UINT32_MAX; if (str == NULL) return -(EINVAL); while (isspace(*str)) { ++str; } while (*str && !isspace(*str)) { if (!isdigit(*str)) return -(EINVAL); val *= 10; val += ((*str) - '0'); /* * Check and make sure we are still under the limit (this is * an absolute value limit, sign will be applied later). */ if (val > limit) return -(ERANGE); str++; } *num = (uint32_t) val; return 0; } int string_to_uint16(const char *str, uint16_t *num) { uint32_t val; int err; if ((err = string_to_uint32(str, &val))) return err; if (val > 65535) return -(ERANGE); *num = (uint16_t) val; return 0; } int string_to_uint8(const char *str, uint8_t *num) { uint32_t val; int err; if ((err = string_to_uint32(str, &val))) return err; if (val > 255) return -(ERANGE); *num = (uint8_t) val; return 0; } time_t __timegm(struct tm *utctime_tm) { time_t time; struct tm adj_tm, chk_tm; adj_tm.tm_year = utctime_tm->tm_year; adj_tm.tm_mon = utctime_tm->tm_mon; adj_tm.tm_mday = utctime_tm->tm_mday; adj_tm.tm_hour = utctime_tm->tm_hour; adj_tm.tm_min = utctime_tm->tm_min; adj_tm.tm_sec = utctime_tm->tm_sec; adj_tm.tm_isdst = -1; for (;;) { time = mktime(&adj_tm); if (time == INVALID_TIME) return time; if (NULL == gmtime_r(&time, &chk_tm)) return INVALID_TIME; if (chk_tm.tm_min == utctime_tm->tm_min && chk_tm.tm_hour == utctime_tm->tm_hour && chk_tm.tm_mday == utctime_tm->tm_mday && chk_tm.tm_mon == utctime_tm->tm_mon && chk_tm.tm_year == utctime_tm->tm_year) break; adj_tm.tm_min += utctime_tm->tm_min - chk_tm.tm_min; adj_tm.tm_hour += utctime_tm->tm_hour - chk_tm.tm_hour; adj_tm.tm_mday += utctime_tm->tm_mday - chk_tm.tm_mday; adj_tm.tm_mon += utctime_tm->tm_mon - chk_tm.tm_mon; adj_tm.tm_year += utctime_tm->tm_year - chk_tm.tm_year; } return time; } int string_to_time(const char *str, time_t *time) { struct tm time_tm; int i, len, format, isutc; char *yyyy, *MM, *dd, *hh, *mm, *ss; char buf[TIMESTAMP_UTC_LEN + 1]; if (*str == '\0') { /* empty string */ *time = INVALID_TIME; return 0; } memset(buf, 0, sizeof(buf)); strncpy(buf, str, sizeof(buf) - 1); len = strlen(buf); switch (len) { case TIMESTAMP_UTC_LEN: if (((buf[4] != '-') || (buf[7] != '-') || (buf[10] != 'T') || (buf[13] != ':') || (buf[16] != ':') || (buf[19] != 'Z'))) { fprintf(stderr, "%s: string is badly formed '%s'\n", __FUNCTION__, buf); goto err; } format = 1; isutc = 1; break; case TIMESTAMP_LEN: if (((buf[4] != '-') || (buf[7] != '-') || (buf[10] != 'T') || (buf[13] != ':') || (buf[16] != ':'))) { fprintf(stderr, "%s: string is badly formed '%s'\n", __FUNCTION__, buf); goto err; } format = 2; isutc = 0; break; case DATESTAMP_LEN: if (((buf[4] != '-') || (buf[7] != '-'))) { fprintf(stderr, "%s: string is badly formed '%s'\n", __FUNCTION__, buf); goto err; } format = 3; isutc = 0; break; default: fprintf(stderr, "%s: string is not a timestamp '%s'\n", __FUNCTION__, buf); goto err; break; } yyyy = buf; MM = buf + 5; dd = buf + 8; hh = buf + 11; mm = buf + 14; ss = buf + 17; yyyy[4] = MM[2] = dd[2] = hh[2] = mm[2] = ss[2] = '\0'; for (i = 0; i < len; ++i) { if (buf[i] && !isdigit(buf[i])) { fprintf(stderr, "%s: expected numeral at '%s'[%d]\n", __FUNCTION__, str, i); goto err; } } time_tm.tm_isdst = -1; time_tm.tm_year = atoi(yyyy) - 1900; time_tm.tm_mon = atoi(MM) - 1; if (time_tm.tm_mon > 11) { fprintf(stderr, "%s: month value too big '%s'\n", __FUNCTION__, str); goto err; } time_tm.tm_mday = atoi(dd); if (time_tm.tm_mday > 31) { fprintf(stderr, "%s: day value too big '%s'\n", __FUNCTION__, str); goto err; } if (format == 3) { time_tm.tm_hour = time_tm.tm_min = time_tm.tm_sec = 0; *time = mktime(&time_tm); return 0; } time_tm.tm_hour = atoi(hh); if (time_tm.tm_hour > 23) { fprintf(stderr, "%s: hour value too big '%s'\n", __FUNCTION__, str); goto err; } time_tm.tm_min = atoi(mm); if (time_tm.tm_min > 59) { fprintf(stderr, "%s: minute value too big '%s'\n", __FUNCTION__, str); goto err; } time_tm.tm_sec = atoi(ss); if (time_tm.tm_sec > 59) { fprintf(stderr, "%s: second value too big '%s'\n", __FUNCTION__, str); goto err; } if (isutc) *time = timegm(&time_tm); else *time = mktime(&time_tm); return 0; err: *time = INVALID_TIME; return -(EINVAL); } void time_to_iso8601utc(time_t time, char *str) { struct tm time_tm; if (time == INVALID_TIME || NULL == gmtime_r(&time, &time_tm)) { str[0] = '\0'; return; } sprintf(str, "%4.4d-%2.2d-%2.2dT%2.2d:%2.2d:%2.2dZ", time_tm.tm_year + 1900, time_tm.tm_mon + 1, time_tm.tm_mday, time_tm.tm_hour, time_tm.tm_min, time_tm.tm_sec); } void time_to_iso8601(time_t time, char *str) { struct tm time_tm; if (time == INVALID_TIME || NULL == localtime_r(&time, &time_tm)) { str[0] = '\0'; return; } sprintf(str, "%4.4d-%2.2d-%2.2dT%2.2d:%2.2d:%2.2d", time_tm.tm_year + 1900, time_tm.tm_mon + 1, time_tm.tm_mday, time_tm.tm_hour, time_tm.tm_min, time_tm.tm_sec); } void time_to_isodate(time_t time, char *str) { struct tm time_tm; if (time == INVALID_TIME || NULL == localtime_r(&time, &time_tm)) { str[0] = '\0'; return; } sprintf(str, "%4.4d-%2.2d-%2.2d", time_tm.tm_year + 1900, time_tm.tm_mon + 1, time_tm.tm_mday); } pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/builtin.h000066400000000000000000000100201360567320200232030ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef BUILTIN_H #define BUILTIN_H #if defined __cplusplus #define __STDC_LIMIT_MACROS extern "C" { #endif #include #include #include #include #include #define string_to_int64 __str2int64 extern int string_to_int64(const char *str, int64_t *num); #define string_to_int32 __str2int32 extern int string_to_int32(const char *str, int32_t *num); #define string_to_int16 __str2int16 extern int string_to_int16(const char *str, int16_t *num); #define string_to_int8 __str2int8 extern int string_to_int8(const char *str, int8_t *num); #define string_to_uint32 __str2uint32 extern int string_to_uint32(const char *str, uint32_t *num); #define string_to_uint16 __str2uint16 extern int string_to_uint16(const char *str, uint16_t *num); #define string_to_uint8 __str2uint8 extern int string_to_uint8(const char *str, uint8_t *num); #define int64_to_string __int64str static CC_INLINE void int64_to_string(int64_t num, char *str) { sprintf(str, "%lld", (long long)num); } #define int32_to_string __int32str static CC_INLINE void int32_to_string(int32_t num, char *str) { sprintf(str, "%ld", (long)num); } #define int16_to_string __int16str static CC_INLINE void int16_to_string(int16_t num, char *str) { sprintf(str, "%d", num); } #define int8_to_string __int8str static CC_INLINE void int8_to_string(int8_t num, char *str) { sprintf(str, "%d", num); } #define uint32_to_string __uint32str static CC_INLINE void uint32_to_string(uint32_t num, char *str) { sprintf(str, "%lu", (unsigned long)num); } #define uint16_to_string __uint16str static CC_INLINE void uint16_to_string(uint16_t num, char *str) { sprintf(str, "%u", num); } #define uint8_to_string __uint8str static CC_INLINE void uint8_to_string(uint8_t num, char *str) { sprintf(str, "%u", num); } #define TIMESTAMP_UTC_LEN (sizeof("YYYY-MM-DDTHH:MM:SSZ") - 1) #define TIMESTAMP_LEN (sizeof("YYYY-MM-DDTHH:MM:SS") - 1) #define DATESTAMP_LEN (sizeof("YYYY-MM-DD") - 1) #define INVALID_TIME (time_t)(0) #if !HAVE_TIMEGM && !defined(timegm) #define timegm __timegm extern time_t timegm(struct tm *utctime_tm); #endif #if !HAVE_LOCALTIME_R && !defined(localtime_r) #define localtime_r __localtime_r static CC_INLINE struct tm *localtime_r(const time_t *clock, struct tm *result) { struct tm *data; if (!clock || !result) return NULL; data = localtime(clock); if (!data) return NULL; memcpy(result, data, sizeof(*result)); return result; } #endif #if !HAVE_GMTIME_R && !defined(gmtime_r) #define gmtime_r __gmtime_r static CC_INLINE struct tm *gmtime_r(const time_t *clock, struct tm *result) { struct tm *data; if (!clock || !result) return NULL; data = gmtime(clock); if (!data) return NULL; memcpy(result, data, sizeof(*result)); return result; } #endif #define string_to_time __str2time extern int string_to_time(const char *str, time_t *time); #define time_to_iso8601utc __time2iso8601utc extern void time_to_iso8601utc(time_t time, char *str); #define time_to_iso8601 __time2iso8601 extern void time_to_iso8601(time_t time, char *str); #define time_to_isodate __time2isodate extern void time_to_isodate(time_t time, char *str); #ifdef __cplusplus } #endif #endif /* BUILTIN_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/compressor.cpp000066400000000000000000000255231360567320200243020ustar00rootroot00000000000000/* * Copyright (C) 2016 Jean-Luc Barriere * * 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 3, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "compressor.h" #include "cppdef.h" #if HAVE_ZLIB #include #else #define Z_NO_FLUSH 0 #define Z_OK 0 #define Z_STREAM_END 1 #define Z_STREAM_ERROR (-2) #define Z_BUF_ERROR (-5) #endif #define GZIP_WINDOWS_BIT 15 + 16 #define GZIP_CHUNK_SIZE 16384 #define MIN(a,b) (a > b ? b : a) #define MAX(a,b) (a > b ? a : b) using namespace NSROOT; Compressor::Compressor(const char *input, size_t len, int level /*= -1*/) : m_status(Z_STREAM_ERROR) , m_flush(Z_NO_FLUSH) , m_stop(true) , m_chunk_size(GZIP_CHUNK_SIZE) , m_type_in(MEM_BUFFER) , m_input_len(len) , m_input(input) , m_rstream(0) , m_rstream_hdl(0) , m_rstream_buf(0) , m_output(0) , m_output_pos(0) , m_output_len(0) , _opaque(0) { #if HAVE_ZLIB m_output = new char[m_chunk_size]; _opaque = new z_stream; m_status = _init(_opaque, m_output, m_chunk_size, level); m_stop = (m_status != Z_OK); #endif } Compressor::Compressor(STREAM_READER reader, void *handle, int level /*= -1*/) : m_status(Z_STREAM_ERROR) , m_flush(Z_NO_FLUSH) , m_stop(true) , m_chunk_size(GZIP_CHUNK_SIZE) , m_type_in(FCB_READER) , m_input_len(0) , m_input(0) , m_rstream(reader) , m_rstream_hdl(handle) , m_rstream_buf(0) , m_output(0) , m_output_pos(0) , m_output_len(0) , _opaque(0) { #if HAVE_ZLIB m_rstream_buf = new char[m_chunk_size]; m_output = new char[m_chunk_size]; _opaque = new z_stream; m_status = _init(_opaque, m_output, m_chunk_size, level); m_stop = (m_status != Z_OK); #endif } Compressor::~Compressor() { #if HAVE_ZLIB z_stream *strm = static_cast(_opaque); deflateEnd(strm); SAFE_DELETE(strm); SAFE_DELETE_ARRAY(m_output); SAFE_DELETE_ARRAY(m_rstream_buf); #endif } bool Compressor::IsCompleted() { return (m_status == Z_STREAM_END); } bool Compressor::HasBufferError() { return (m_status == Z_BUF_ERROR); } bool Compressor::HasStreamError() { switch(m_status) { case Z_OK: case Z_STREAM_END: case Z_BUF_ERROR: return false; default: return true; } } size_t Compressor::ReadOutput(char *buf, size_t len) { size_t out = 0; #if HAVE_ZLIB while (len) { if (m_output_len) { size_t sz = MIN(m_output_len, len); memcpy(buf, m_output + m_output_pos, sz); out += sz; buf += sz; len -= sz; m_output_pos += sz; m_output_len -= sz; } else if (m_status != Z_STREAM_END) { z_stream *strm = static_cast(_opaque); if (!strm->avail_in) NextChunk(); if (!strm->avail_out) { strm->next_out = (unsigned char*)m_output; strm->avail_out = m_chunk_size; m_output_pos = 0; } // Try to deflate chunk m_status = deflate(strm, m_flush); if (m_status < 0) { m_stop = true; return 0; } m_output_len = m_chunk_size - m_output_pos - strm->avail_out; m_stop = false; } else { m_stop = true; break; } } #endif return out; } size_t Compressor::FetchOutput(const char **data) { *data = 0; #if HAVE_ZLIB size_t len = 0; while (!m_stop) { if (m_output_len) { *data = m_output + m_output_pos; len = m_output_len; m_output_pos += m_output_len; m_output_len = 0; return len; } else if (m_status != Z_STREAM_END) { z_stream *strm = static_cast(_opaque); if (!strm->avail_in) NextChunk(); if (!strm->avail_out) { strm->next_out = (unsigned char*)m_output; strm->avail_out = m_chunk_size; m_output_pos = 0; } // Try to inflate chunk m_status = deflate(strm, m_flush); if (m_status < 0) { m_stop = true; return 0; } m_output_len = m_chunk_size - m_output_pos - strm->avail_out; m_stop = false; } else { m_stop = true; break; } } #endif return 0; } int Compressor::_init(void *zp, void *out, size_t len, int level) { #if HAVE_ZLIB z_stream *strm = static_cast(zp); // Prepare inflater status strm->zalloc = Z_NULL; strm->zfree = Z_NULL; strm->opaque = Z_NULL; strm->avail_in = 0; strm->next_in = Z_NULL; strm->avail_out = len; strm->next_out = (unsigned char*)out; return deflateInit2(strm, MAX(-1, MIN(level, 9)), Z_DEFLATED, GZIP_WINDOWS_BIT, 8, Z_DEFAULT_STRATEGY); #else return Z_STREAM_ERROR; #endif } size_t Compressor::NextChunk() { size_t sz = 0; #if HAVE_ZLIB if (m_flush != Z_FINISH) { z_stream *strm = static_cast(_opaque); switch(m_type_in) { case MEM_BUFFER: // Determine current chunk size sz = MIN(m_chunk_size, m_input_len); // Check for end of data if (sz) { // Set stream strm->next_in = (unsigned char*)m_input; strm->avail_in = (unsigned)sz; // Update next chunk m_input += sz; m_input_len -= sz; // flush on last chunk m_flush = (m_input_len > 0 ? Z_NO_FLUSH : Z_FINISH); } break; case FCB_READER: { int ret = (*m_rstream)(m_rstream_hdl, (void*)m_rstream_buf, m_chunk_size); if (ret < 0) sz = 0; else { m_flush = (ret > 0 ? Z_NO_FLUSH : Z_FINISH); sz = ret; } // Set stream strm->next_in = (unsigned char*)m_rstream_buf; strm->avail_in = (unsigned)sz; } break; default: break; } } #endif return sz; } Decompressor::Decompressor(const char *input, size_t len) : m_status(Z_STREAM_ERROR) , m_stop(true) , m_chunk_size(GZIP_CHUNK_SIZE) , m_type_in(MEM_BUFFER) , m_input_len(len) , m_input(input) , m_rstream(0) , m_rstream_hdl(0) , m_rstream_buf(0) , m_output(0) , m_output_pos(0) , m_output_len(0) , _opaque(0) { #if HAVE_ZLIB m_output = new char[m_chunk_size]; _opaque = new z_stream; m_status = _init(_opaque, m_output, m_chunk_size); m_stop = (m_status != Z_OK); #endif } Decompressor::Decompressor(STREAM_READER reader, void *handle) : m_status(Z_STREAM_ERROR) , m_stop(true) , m_chunk_size(GZIP_CHUNK_SIZE) , m_type_in(FCB_READER) , m_input_len(0) , m_input(0) , m_rstream(reader) , m_rstream_hdl(handle) , m_rstream_buf(0) , m_output(0) , m_output_pos(0) , m_output_len(0) , _opaque(0) { #if HAVE_ZLIB m_rstream_buf = new char[m_chunk_size]; m_output = new char[m_chunk_size]; _opaque = new z_stream; m_status = _init(_opaque, m_output, m_chunk_size); m_stop = (m_status != Z_OK); #endif } Decompressor::~Decompressor() { #if HAVE_ZLIB z_stream *strm = static_cast(_opaque); inflateEnd(strm); SAFE_DELETE(strm); SAFE_DELETE_ARRAY(m_output); SAFE_DELETE_ARRAY(m_rstream_buf); #endif } bool Decompressor::IsCompleted() { return (m_status == Z_STREAM_END); } bool Decompressor::HasBufferError() { return (m_status == Z_BUF_ERROR); } bool Decompressor::HasStreamError() { switch(m_status) { case Z_OK: case Z_STREAM_END: case Z_BUF_ERROR: return false; default: return true; } } size_t Decompressor::ReadOutput(char *buf, size_t len) { size_t out = 0; #if HAVE_ZLIB while (len) { if (m_output_len) { size_t sz = MIN(m_output_len, len); memcpy(buf, m_output + m_output_pos, sz); out += sz; buf += sz; len -= sz; m_output_pos += sz; m_output_len -= sz; } else if (m_status != Z_STREAM_END) { z_stream *strm = static_cast(_opaque); if (!strm->avail_in) NextChunk(); if (!strm->avail_out) { strm->next_out = (unsigned char*)m_output; strm->avail_out = m_chunk_size; m_output_pos = 0; } // Try to inflate chunk m_status = inflate(strm, Z_NO_FLUSH); if (m_status < 0) { m_stop = true; return 0; } m_output_len = m_chunk_size - m_output_pos - strm->avail_out; m_stop = false; } else { m_stop = true; break; } } #endif return out; } size_t Decompressor::FetchOutput(const char **data) { *data = 0; #if HAVE_ZLIB size_t len = 0; do { if (m_output_len) { *data = m_output + m_output_pos; len = m_output_len; m_output_pos += m_output_len; m_output_len = 0; return len; } else if (m_status != Z_STREAM_END) { z_stream *strm = static_cast(_opaque); if (!strm->avail_in) NextChunk(); if (!strm->avail_out) { strm->next_out = (unsigned char*)m_output; strm->avail_out = m_chunk_size; m_output_pos = 0; } // Try to inflate chunk m_status = inflate(strm, Z_NO_FLUSH); if (m_status < 0) { m_stop = true; return 0; } m_output_len = m_chunk_size - m_output_pos - strm->avail_out; m_stop = false; } else { m_stop = true; break; } } while (!m_stop); #endif return 0; } int Decompressor::_init(void *zp, void *out, size_t len) { #if HAVE_ZLIB z_stream *strm = static_cast(zp); // Prepare inflater status strm->zalloc = Z_NULL; strm->zfree = Z_NULL; strm->opaque = Z_NULL; strm->avail_in = 0; strm->next_in = Z_NULL; strm->avail_out = len; strm->next_out = (unsigned char*)out; return inflateInit2(strm, GZIP_WINDOWS_BIT); #else return Z_STREAM_ERROR; #endif } size_t Decompressor::NextChunk() { size_t sz = 0; #if HAVE_ZLIB z_stream *strm = static_cast(_opaque); switch(m_type_in) { case MEM_BUFFER: // Determine current chunk size sz = MIN(m_chunk_size, m_input_len); // Check for end of data if (sz) { // Set stream strm->next_in = (unsigned char*)m_input; strm->avail_in = (unsigned)sz; // Update next chunk m_input += sz; m_input_len -= sz; } break; case FCB_READER: { int ret = (*m_rstream)(m_rstream_hdl, (void*)m_rstream_buf, m_chunk_size); if (ret > 0) sz = ret; else sz = 0; // Set stream strm->next_in = (unsigned char*)m_rstream_buf; strm->avail_in = (unsigned)sz; } break; default: break; } #endif return sz; } pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/compressor.h000066400000000000000000000110111360567320200237320ustar00rootroot00000000000000/* * Copyright (C) 2016 Jean-Luc Barriere * * 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 3, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef COMPRESSOR_H #define COMPRESSOR_H #include #include // for size_t #include // for memcpy namespace NSROOT { class Compressor { public: typedef int(*STREAM_READER)(void *handle, void *buf, int sz); Compressor(STREAM_READER reader, void *handle, int level = -1); Compressor(const char *input, size_t len, int level = -1); virtual ~Compressor(); /** * @brief More data can be read from output stream. * @return Output status */ bool HasOutputData() { return !m_stop; } /** * @brief Output stream is completed. * @return Output stream status */ bool IsCompleted(); /** * @brief Data cannot be read from input. * @return Input status */ bool HasBufferError(); /** * @brief Data error occurred from stream. * @return stream status */ bool HasStreamError(); /** * @brief Copy data from output stream to the given pointer until size limit. * @param buf pointer to copy data * @param len max length of data * @return lenght of copied data */ size_t ReadOutput(char *buf, size_t len); /** * @brief Fetch next chunk of data from output stream. * No copy of data is performed and result can be used as is. * @param data pointer to const data pointer * @return the byte count available from the pointer to const data */ size_t FetchOutput(const char **data); private: int m_status; int m_flush; bool m_stop; size_t m_chunk_size; const enum { MEM_BUFFER, FCB_READER } m_type_in; size_t m_input_len; const char *m_input; STREAM_READER m_rstream; void *m_rstream_hdl; char *m_rstream_buf; char *m_output; size_t m_output_pos; size_t m_output_len; void *_opaque; static int _init(void *zp, void *out, size_t len, int level); size_t NextChunk(); }; class Decompressor { public: typedef int(*STREAM_READER)(void *handle, void *buf, int sz); Decompressor(STREAM_READER reader, void *handle); Decompressor(const char *input, size_t len); virtual ~Decompressor(); /** * @brief More data can be read from output stream. * @return Output status */ bool HasOutputData() { return !m_stop; } /** * @brief Output stream is completed. * @return Output stream status */ bool IsCompleted(); /** * @brief Data cannot be read from input. * @return Input status */ bool HasBufferError(); /** * @brief Data error occurred from stream. * @return stream status */ bool HasStreamError(); /** * @brief Copy data from output stream to the given pointer until size limit. * @param buf pointer to copy data * @param len max length of data * @return lenght of copied data */ size_t ReadOutput(char *buf, size_t len); /** * @brief Fetch next chunk of data from output stream. * No copy of data is performed and result can be used as is. * @param data pointer to const data pointer * @return the byte count available from the pointer to const data */ size_t FetchOutput(const char **data); private: int m_status; bool m_stop; size_t m_chunk_size; const enum { MEM_BUFFER, FCB_READER } m_type_in; size_t m_input_len; const char *m_input; STREAM_READER m_rstream; void *m_rstream_hdl; char *m_rstream_buf; char *m_output; size_t m_output_pos; size_t m_output_len; void *_opaque; static int _init(void *zp, void *out, size_t len); size_t NextChunk(); }; } #endif /* COMPRESSOR_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/cppdef.h000066400000000000000000000002761360567320200230120ustar00rootroot00000000000000#pragma once #include #define SAFE_DELETE(p) if ((p) != NULL) { delete (p); (p) = NULL; } #define SAFE_DELETE_ARRAY(p) if ((p) != NULL) { delete[] (p); (p) = NULL; } pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/debug.cpp000066400000000000000000000052011360567320200231630ustar00rootroot00000000000000/* * Copyright (C) 2014-2015 Jean-Luc Barriere * * 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 3, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "debug.h" #include #include #include #include #include #if defined(_MSC_VER) && _MSC_VER < 1900 #define snprintf _snprintf #endif typedef struct { const char* name; int cur_level; void (*msg_callback)(int level, char* msg); } debug_ctx_t; static debug_ctx_t debug_ctx = {LIBTAG, DBG_NONE, NULL}; /** * Set the debug level to be used for the subsystem * \param ctx the subsystem debug context to use * \param level the debug level for the subsystem * \return an integer subsystem id used for future interaction */ static inline void __dbg_setlevel(debug_ctx_t* ctx, int level) { if (ctx != NULL) { ctx->cur_level = level; } } /** * Generate a debug message at a given debug level * \param ctx the subsystem debug context to use * \param level the debug level of the debug message * \param fmt a printf style format string for the message * \param ... arguments to the format */ static inline void __dbg(debug_ctx_t* ctx, int level, const char* fmt, va_list ap) { if (ctx != NULL && level <= ctx->cur_level) { char msg[4096]; int len = snprintf(msg, sizeof (msg), "(%s)", ctx->name); vsnprintf(msg + len, sizeof (msg) - len, fmt, ap); if (ctx->msg_callback) { ctx->msg_callback(level, msg); } else { fwrite(msg, strlen(msg), 1, stderr); } } } void NSROOT::DBGLevel(int l) { __dbg_setlevel(&debug_ctx, l); } void NSROOT::DBGAll() { __dbg_setlevel(&debug_ctx, DBG_ALL); } void NSROOT::DBGNone() { __dbg_setlevel(&debug_ctx, DBG_NONE); } void NSROOT::DBG(int level, const char* fmt, ...) { va_list ap; va_start(ap, fmt); __dbg(&debug_ctx, level, fmt, ap); va_end(ap); } void NSROOT::SetDBGMsgCallback(void (*msgcb)(int level, char*)) { debug_ctx.msg_callback = msgcb; } pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/debug.h000066400000000000000000000024031360567320200226310ustar00rootroot00000000000000/* * Copyright (C) 2014-2015 Jean-Luc Barriere * * 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 3, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef DEBUG_H #define DEBUG_H #include #define DBG_NONE -1 #define DBG_ERROR 0 #define DBG_WARN 1 #define DBG_INFO 2 #define DBG_DEBUG 3 #define DBG_PROTO 4 #define DBG_ALL 6 namespace NSROOT { void DBGLevel(int l); void DBGAll(void); void DBGNone(void); void DBG(int level, const char* fmt, ...); void SetDBGMsgCallback(void (*msgcb)(int level, char*)); } #endif /* DEBUG_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/jsonparser.cpp000066400000000000000000000130121360567320200242620ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "jsonparser.h" #include "debug.h" using namespace NSROOT; /////////////////////////////////////////////////////////////////////////////// //// //// Node //// JSON::Node::Node() : m_value(sajson::TYPE_NULL, 0, 0) { } JSON::Node::Node(const sajson::value& value) : m_value(value) { } bool JSON::Node::IsNull() const { return (m_value.get_type() == sajson::TYPE_NULL); } bool JSON::Node::IsObject() const { return (m_value.get_type() == sajson::TYPE_OBJECT); } bool JSON::Node::IsArray() const { return (m_value.get_type() == sajson::TYPE_ARRAY); } bool JSON::Node::IsString() const { return (m_value.get_type() == sajson::TYPE_STRING); } bool JSON::Node::IsDouble() const { return (m_value.get_type() == sajson::TYPE_DOUBLE); } bool JSON::Node::IsInt() const { return (m_value.get_type() == sajson::TYPE_INTEGER); } bool JSON::Node::IsTrue() const { return (m_value.get_type() == sajson::TYPE_TRUE); } bool JSON::Node::IsFalse() const { return (m_value.get_type() == sajson::TYPE_FALSE); } std::string JSON::Node::GetStringValue() const { if (m_value.get_type() == sajson::TYPE_STRING) return m_value.as_string(); DBG(DBG_ERROR, "%s: bad type (%d)\n", __FUNCTION__, (int) m_value.get_type()); return std::string(); } size_t JSON::Node::GetStringSize() const { if (m_value.get_type() == sajson::TYPE_STRING) return m_value.get_string_length(); DBG(DBG_ERROR, "%s: bad type (%d)\n", __FUNCTION__, (int) m_value.get_type()); return 0; } double JSON::Node::GetDoubleValue() const { if (m_value.get_type() == sajson::TYPE_DOUBLE) return m_value.get_double_value(); DBG(DBG_ERROR, "%s: bad type (%d)\n", __FUNCTION__, (int) m_value.get_type()); return 0.0; } int64_t JSON::Node::GetBigIntValue() const { if (m_value.get_type() == sajson::TYPE_DOUBLE || m_value.get_type() == sajson::TYPE_INTEGER) return (int64_t) m_value.get_number_value(); DBG(DBG_ERROR, "%s: bad type (%d)\n", __FUNCTION__, (int) m_value.get_type()); return 0; } int32_t JSON::Node::GetIntValue() const { if (m_value.get_type() == sajson::TYPE_INTEGER) return (int32_t) m_value.get_integer_value(); DBG(DBG_ERROR, "%s: bad type (%d)\n", __FUNCTION__, (int) m_value.get_type()); return 0; } size_t JSON::Node::Size() const { if (m_value.get_type() == sajson::TYPE_ARRAY || m_value.get_type() == sajson::TYPE_OBJECT) return m_value.get_length(); DBG(DBG_ERROR, "%s: bad type (%d)\n", __FUNCTION__, (int) m_value.get_type()); return 0; } JSON::Node JSON::Node::GetArrayElement(size_t index) const { if (m_value.get_type() == sajson::TYPE_ARRAY) return Node(m_value.get_array_element(index)); DBG(DBG_ERROR, "%s: bad type (%d)\n", __FUNCTION__, (int) m_value.get_type()); return Node(); } std::string JSON::Node::GetObjectKey(size_t index) const { if (m_value.get_type() == sajson::TYPE_OBJECT) return m_value.get_object_key(index).as_string(); DBG(DBG_ERROR, "%s: bad type (%d)\n", __FUNCTION__, (int) m_value.get_type()); return std::string(); } JSON::Node JSON::Node::GetObjectValue(size_t index) const { if (m_value.get_type() == sajson::TYPE_OBJECT) return Node(m_value.get_object_value(index)); DBG(DBG_ERROR, "%s: bad type (%d)\n", __FUNCTION__, (int) m_value.get_type()); return Node(); } JSON::Node JSON::Node::GetObjectValue(const char *key) const { if (m_value.get_type() == sajson::TYPE_OBJECT) { size_t idx = m_value.find_object_key(sajson::literal(key)); if (idx < m_value.get_length()) return Node(m_value.get_object_value(idx)); return Node(); } DBG(DBG_ERROR, "%s: bad type (%d)\n", __FUNCTION__, (int) m_value.get_type()); return Node(); } /////////////////////////////////////////////////////////////////////////////// //// //// Document //// JSON::Document::Document(NSROOT::WSResponse& resp) : m_isValid(false) , m_document(NULL) { std::string content; content.reserve(resp.GetContentLength()); // Read content response size_t s; char buf[4000]; while ((s = resp.ReadContent(buf, sizeof(buf)))) content.append(buf, s); if (!content.empty()) { DBG(DBG_PROTO, "%s: %s\n", __FUNCTION__, content.c_str()); // Parse JSON content m_document = new sajson::document(sajson::parse(sajson::string(content.c_str(), content.length()))); if (!m_document) DBG(DBG_ERROR, "%s: memory allocation failed\n", __FUNCTION__); else if (!m_document->is_valid()) DBG(DBG_ERROR, "%s: failed to parse: %d: %s\n", __FUNCTION__, (int)m_document->get_error_line(), m_document->get_error_message().c_str()); else m_isValid = true; } else { DBG(DBG_ERROR, "%s: read error\n", __FUNCTION__); } } JSON::Node JSON::Document::GetRoot() const { if (m_document) return Node(m_document->get_root()); return Node(); } pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/jsonparser.h000066400000000000000000000042421360567320200237340ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef JSONPARSER_H #define JSONPARSER_H #include #include "wsresponse.h" #include "sajson.h" #include "os/os.h" #include "cppdef.h" #include /** * @namespace NSROOT::JSON * @brief This namespace contains all operations to handle JSON content */ namespace NSROOT { namespace JSON { class Node { public: Node(); Node(const sajson::value& value); ~Node() { } bool IsNull() const; bool IsObject() const; bool IsArray() const; bool IsString() const; bool IsDouble() const; bool IsInt() const; bool IsTrue() const; bool IsFalse() const; std::string GetStringValue() const; size_t GetStringSize() const; double GetDoubleValue() const; int64_t GetBigIntValue() const; int32_t GetIntValue() const; size_t Size() const; Node GetArrayElement(size_t index) const; std::string GetObjectKey(size_t index) const; Node GetObjectValue(size_t index) const; Node GetObjectValue(const char *key) const; private: sajson::value m_value; }; class Document { public: Document(NSROOT::WSResponse& resp); ~Document() { SAFE_DELETE(m_document); } bool IsValid() const { return m_isValid; } Node GetRoot() const; private: bool m_isValid; sajson::document *m_document; }; } } #endif /* JSONPARSER_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/mythdto/000077500000000000000000000000001360567320200230635ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/mythdto/artwork.h000066400000000000000000000024431360567320200247300ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHDTO_ARTWORK_H #define MYTHDTO_ARTWORK_H #include "../../mythtypes.h" namespace MythDTO { void SetArtwork_URL(Myth::Artwork *obj, const char *val) { obj->url = val; } void SetArtwork_FileName(Myth::Artwork *obj, const char *val) { obj->fileName = val; } void SetArtwork_StorageGroup(Myth::Artwork *obj, const char *val) { obj->storageGroup = val; } void SetArtwork_Type(Myth::Artwork *obj, const char *val) { obj->type = val; } } #endif /* MYTHDTO_ARTWORK_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/mythdto/capturecard.h000066400000000000000000000023631360567320200255350ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHDTO_CAPTURECARD_H #define MYTHDTO_CAPTURECARD_H #include "../../mythtypes.h" namespace MythDTO { void SetCaptureCard_CardId(Myth::CaptureCard *obj, uint32_t *val) { obj->cardId = *val; } void SetCaptureCard_CardType(Myth::CaptureCard *obj, const char *val) { obj->cardType = val; } void SetCaptureCard_HostName(Myth::CaptureCard *obj, const char *val) { obj->hostName = val; } } #endif /* MYTHDTO_CAPTURECARD_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/mythdto/channel.h000066400000000000000000000036211360567320200246460ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHDTO_CHANNEL_H #define MYTHDTO_CHANNEL_H #include "../../mythtypes.h" namespace MythDTO { void SetChannel_ChanId(Myth::Channel *obj, uint32_t *val) { obj->chanId = *val; } void SetChannel_ChanNum(Myth::Channel *obj, const char *val) { obj->chanNum = val; } void SetChannel_CallSign(Myth::Channel *obj, const char *val) { obj->callSign = val; } void SetChannel_IconURL(Myth::Channel *obj, const char *val) { obj->iconURL = val; } void SetChannel_ChannelName(Myth::Channel *obj, const char *val) { obj->channelName = val; } void SetChannel_MplexId(Myth::Channel *obj, uint32_t *val) { obj->mplexId = *val; } void SetChannel_CommFree(Myth::Channel *obj, const char *val) { obj->commFree = val; } void SetChannel_ChanFilters(Myth::Channel *obj, const char *val) { obj->chanFilters = val; } void SetChannel_SourceId(Myth::Channel *obj, uint32_t *val) { obj->sourceId = *val; } void SetChannel_InputId(Myth::Channel *obj, uint32_t *val) { obj->inputId = *val; } void SetChannel_Visible(Myth::Channel *obj, bool *val) { obj->visible = *val; } } #endif /* MYTHDTO_CHANNEL_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/mythdto/cutting.h000066400000000000000000000022151360567320200247110ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHDTO_CUTTING_H #define MYTHDTO_CUTTING_H #include "../../mythtypes.h" namespace MythDTO { void SetCutting_MarkType(Myth::Mark *obj, int8_t *val) { obj->markType = static_cast(*val); } void SetCutting_MarkValue(Myth::Mark *obj, int64_t *val) { obj->markValue = *val; } } #endif /* MYTHDTO_CUTTING_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/mythdto/list.h000066400000000000000000000021561360567320200242130ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHDTO_LIST_H #define MYTHDTO_LIST_H #include "../../mythtypes.h" namespace MythDTO { void SetItemList_Count(Myth::ItemList *obj, uint32_t *val) { obj->count = *val; } void SetItemList_ProtoVer(Myth::ItemList *obj, uint32_t *val) { obj->protoVer = *val; } } #endif /* MYTHDTO_LIST_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/mythdto/mythdto.cpp000066400000000000000000000051061360567320200252610ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "mythdto.h" #include "mythdto75.h" // Base protocol version 75 #include "mythdto76.h" // Add protocol version 76 #include "mythdto82.h" // Add protocol version 82 #include "mythdto85.h" // Add protocol version 85 #include const bindings_t *MythDTO::getVersionBindArray(unsigned ranking) { (void)ranking; return &MythDTO75::VersionBindArray2_0; } const bindings_t *MythDTO::getListBindArray(unsigned proto) { (void)proto; return &MythDTO75::ListBindArray; } const bindings_t *MythDTO::getChannelBindArray(unsigned proto) { if (proto >= 75) return &MythDTO75::ChannelBindArray; return NULL; } const bindings_t *MythDTO::getRecordingBindArray(unsigned proto) { if (proto >= 82) return &MythDTO82::RecordingBindArray; if (proto >= 75) return &MythDTO75::RecordingBindArray; return NULL; } const bindings_t *MythDTO::getArtworkBindArray(unsigned proto) { if (proto >= 75) return &MythDTO75::ArtworkBindArray; return NULL; } const bindings_t *MythDTO::getProgramBindArray(unsigned proto) { if (proto >= 75) return &MythDTO75::ProgramBindArray; return NULL; } const bindings_t *MythDTO::getCaptureCardBindArray(unsigned proto) { if (proto >= 75) return &MythDTO75::CaptureCardBindArray; return NULL; } const bindings_t *MythDTO::getVideoSourceBindArray(unsigned proto) { if (proto >= 75) return &MythDTO75::VideoSourceBindArray; return NULL; } const bindings_t *MythDTO::getRecordScheduleBindArray(unsigned proto) { if (proto >= 76) return &MythDTO76::RecordScheduleBindArray; if (proto >= 75) return &MythDTO75::RecordScheduleBindArray; return NULL; } const bindings_t *MythDTO::getCuttingBindArray(unsigned proto) { if (proto >= 85) return &MythDTO85::CuttingBindArray; return NULL; } pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/mythdto/mythdto.h000066400000000000000000000060301360567320200247230ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHDTO_H #define MYTHDTO_H /** * @brief Enemerates field types known to be binded */ typedef enum { IS_STRING = 0, IS_INT8, IS_INT16, IS_INT32, IS_INT64, IS_UINT8, IS_UINT16, IS_UINT32, IS_DOUBLE, IS_TIME, IS_BOOLEAN, } FT_t; /** * @brief Definition of function setter * @param 1 pointer to object handle * @param 2 pointer to value */ typedef void(*setter_t)(void *, const void *); /** * @struct attr_bind_t * @brief Definition of binding from a source field to an object attribute */ typedef struct { const char *field; /**< name of source field */ FT_t type; /**< type of source field */ void(*set)(void *, const void *); /**< function setter */ } attr_bind_t; /** * @struct bindings_t * @brief Brings together all attribute bindings of an object */ typedef struct { int attr_count; /**< count binded attribute */ attr_bind_t *attr_bind; /**< pointer to the first element */ } bindings_t; /** * @namespace MythDTO * @brief This namespace contains all DTO definitions */ namespace MythDTO { /** @brief Returns bindings for Myth::Version */ const bindings_t *getVersionBindArray(unsigned ranking); /** @brief Returns bindings for Myth::List */ const bindings_t *getListBindArray(unsigned proto); /** @brief Returns bindings for Myth::Channel */ const bindings_t *getChannelBindArray(unsigned proto); /** @brief Returns bindings for Myth::Recording */ const bindings_t *getRecordingBindArray(unsigned proto); /** @brief Returns bindings for Myth::Artwork */ const bindings_t *getArtworkBindArray(unsigned proto); /** @brief Returns bindings for Myth::Program */ const bindings_t *getProgramBindArray(unsigned proto); /** @brief Returns bindings for Myth::CaptureCard */ const bindings_t *getCaptureCardBindArray(unsigned proto); /** @brief Returns bindings for Myth::VideoSource */ const bindings_t *getVideoSourceBindArray(unsigned proto); /** @brief Returns bindings for Myth::RecordSchedule */ const bindings_t *getRecordScheduleBindArray(unsigned proto); /** @brief Returns bindings for Myth::Mark */ const bindings_t *getCuttingBindArray(unsigned proto); } #endif /* MYTHDTO_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/mythdto/mythdto75.h000066400000000000000000000244401360567320200251040ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHDTO75_H #define MYTHDTO75_H #include "mythdto.h" #include "version.h" #include "list.h" #include "program.h" #include "channel.h" #include "recording.h" #include "artwork.h" #include "capturecard.h" #include "videosource.h" #include "recordschedule.h" namespace MythDTO75 { attr_bind_t version2_0[] = { { "Version", IS_STRING, (setter_t)MythDTO::SetVersion_Version }, { "Protocol", IS_UINT32, (setter_t)MythDTO::SetVersion_Protocol }, { "Schema", IS_UINT32, (setter_t)MythDTO::SetVersion_Schema }, }; bindings_t VersionBindArray2_0 = { sizeof(version2_0) / sizeof(attr_bind_t), version2_0 }; attr_bind_t list[] = { { "Count", IS_UINT32, (setter_t)MythDTO::SetItemList_Count }, { "ProtoVer", IS_UINT32, (setter_t)MythDTO::SetItemList_ProtoVer }, }; bindings_t ListBindArray = { sizeof(list) / sizeof(attr_bind_t), list }; attr_bind_t artwork[] = { { "URL", IS_STRING, (setter_t)MythDTO::SetArtwork_URL }, { "FileName", IS_STRING, (setter_t)MythDTO::SetArtwork_FileName }, { "StorageGroup", IS_STRING, (setter_t)MythDTO::SetArtwork_StorageGroup }, { "Type", IS_STRING, (setter_t)MythDTO::SetArtwork_Type }, }; bindings_t ArtworkBindArray = { sizeof(artwork) / sizeof(attr_bind_t), artwork }; attr_bind_t channel[] = { { "ChanId", IS_UINT32, (setter_t)MythDTO::SetChannel_ChanId }, { "ChanNum", IS_STRING, (setter_t)MythDTO::SetChannel_ChanNum }, { "CallSign", IS_STRING, (setter_t)MythDTO::SetChannel_CallSign }, { "IconURL", IS_STRING, (setter_t)MythDTO::SetChannel_IconURL }, { "ChannelName", IS_STRING, (setter_t)MythDTO::SetChannel_ChannelName }, { "MplexId", IS_UINT32, (setter_t)MythDTO::SetChannel_MplexId }, { "CommFree", IS_STRING, (setter_t)MythDTO::SetChannel_CommFree }, { "ChanFilters", IS_STRING, (setter_t)MythDTO::SetChannel_ChanFilters }, { "SourceId", IS_UINT32, (setter_t)MythDTO::SetChannel_SourceId }, { "InputId", IS_UINT32, (setter_t)MythDTO::SetChannel_InputId }, { "Visible", IS_BOOLEAN, (setter_t)MythDTO::SetChannel_Visible }, }; bindings_t ChannelBindArray = { sizeof(channel) / sizeof(attr_bind_t), channel }; attr_bind_t recording[] = { { "RecordId", IS_UINT32, (setter_t)MythDTO::SetRecording_RecordId }, { "Priority", IS_INT32, (setter_t)MythDTO::SetRecording_Priority }, { "Status", IS_INT8, (setter_t)MythDTO::SetRecording_Status }, { "EncoderId", IS_UINT32, (setter_t)MythDTO::SetRecording_EncoderId }, { "RecType", IS_UINT8, (setter_t)MythDTO::SetRecording_RecType }, { "DupInType", IS_UINT8, (setter_t)MythDTO::SetRecording_DupInType }, { "DupMethod", IS_UINT8, (setter_t)MythDTO::SetRecording_DupMethod }, { "StartTs", IS_TIME, (setter_t)MythDTO::SetRecording_StartTs }, { "EndTs", IS_TIME, (setter_t)MythDTO::SetRecording_EndTs }, { "Profile", IS_STRING, (setter_t)MythDTO::SetRecording_Profile }, { "RecGroup", IS_STRING, (setter_t)MythDTO::SetRecording_RecGroup }, { "StorageGroup", IS_STRING, (setter_t)MythDTO::SetRecording_StorageGroup }, { "PlayGroup", IS_STRING, (setter_t)MythDTO::SetRecording_PlayGroup }, }; bindings_t RecordingBindArray = { sizeof(recording) / sizeof(attr_bind_t), recording }; attr_bind_t program[] = { { "StartTime", IS_TIME, (setter_t)MythDTO::SetProgram_StartTime }, { "EndTime", IS_TIME, (setter_t)MythDTO::SetProgram_EndTime }, { "Title", IS_STRING, (setter_t)MythDTO::SetProgram_Title }, { "SubTitle", IS_STRING, (setter_t)MythDTO::SetProgram_SubTitle }, { "Description", IS_STRING, (setter_t)MythDTO::SetProgram_Description }, { "Season", IS_UINT16, (setter_t)MythDTO::SetProgram_Season }, { "Episode", IS_UINT16, (setter_t)MythDTO::SetProgram_Episode }, { "Category", IS_STRING, (setter_t)MythDTO::SetProgram_Category }, { "CatType", IS_STRING, (setter_t)MythDTO::SetProgram_CatType}, { "HostName", IS_STRING, (setter_t)MythDTO::SetProgram_HostName }, { "FileName", IS_STRING, (setter_t)MythDTO::SetProgram_FileName }, { "FileSize", IS_INT64, (setter_t)MythDTO::SetProgram_FileSize }, { "Repeat", IS_BOOLEAN, (setter_t)MythDTO::SetProgram_Repeat }, { "ProgramFlags", IS_INT32, (setter_t)MythDTO::SetProgram_ProgramFlags }, { "SeriesId", IS_STRING, (setter_t)MythDTO::SetProgram_SeriesId }, { "ProgramId", IS_STRING, (setter_t)MythDTO::SetProgram_ProgramId }, { "Inetref", IS_STRING, (setter_t)MythDTO::SetProgram_Inetref }, { "LastModified", IS_TIME, (setter_t)MythDTO::SetProgram_LastModified }, { "Stars", IS_STRING, (setter_t)MythDTO::SetProgram_Stars }, { "Airdate", IS_TIME, (setter_t)MythDTO::SetProgram_Airdate }, { "AudioProps", IS_UINT16, (setter_t)MythDTO::SetProgram_AudioProps }, { "VideoProps", IS_UINT16, (setter_t)MythDTO::SetProgram_VideoProps }, { "SubProps", IS_UINT16, (setter_t)MythDTO::SetProgram_SubProps }, }; bindings_t ProgramBindArray = { sizeof(program) / sizeof(attr_bind_t), program }; attr_bind_t capturecard[] = { { "CardId", IS_UINT32, (setter_t)MythDTO::SetCaptureCard_CardId }, { "CardType", IS_STRING, (setter_t)MythDTO::SetCaptureCard_CardType }, { "HostName", IS_STRING, (setter_t)MythDTO::SetCaptureCard_HostName }, }; bindings_t CaptureCardBindArray = { sizeof(capturecard) / sizeof(attr_bind_t), capturecard }; attr_bind_t videosource[] = { { "Id", IS_UINT32, (setter_t)MythDTO::SetVideoSource_Id }, { "SourceName", IS_STRING, (setter_t)MythDTO::SetVideoSource_SourceName }, }; bindings_t VideoSourceBindArray = { sizeof(videosource) / sizeof(attr_bind_t), videosource }; attr_bind_t recordschedule[] = { { "Id", IS_UINT32, (setter_t)MythDTO::SetSchedule_Id }, { "ParentId", IS_UINT32, (setter_t)MythDTO::SetSchedule_ParentId }, { "Inactive", IS_BOOLEAN, (setter_t)MythDTO::SetSchedule_Inactive }, { "Title", IS_STRING, (setter_t)MythDTO::SetSchedule_Title }, { "SubTitle", IS_STRING, (setter_t)MythDTO::SetSchedule_Subtitle }, { "Description", IS_STRING, (setter_t)MythDTO::SetSchedule_Description }, { "Season", IS_UINT16, (setter_t)MythDTO::SetSchedule_Season }, { "Episode", IS_UINT16, (setter_t)MythDTO::SetSchedule_Episode }, { "Category", IS_STRING, (setter_t)MythDTO::SetSchedule_Category }, { "StartTime", IS_TIME, (setter_t)MythDTO::SetSchedule_StartTime }, { "EndTime", IS_TIME, (setter_t)MythDTO::SetSchedule_EndTime }, { "SeriesId", IS_STRING, (setter_t)MythDTO::SetSchedule_SeriesId }, { "ProgramId", IS_STRING, (setter_t)MythDTO::SetSchedule_ProgramId }, { "Inetref", IS_STRING, (setter_t)MythDTO::SetSchedule_Inetref }, { "ChanId", IS_UINT32, (setter_t)MythDTO::SetSchedule_ChanId }, { "CallSign", IS_STRING, (setter_t)MythDTO::SetSchedule_CallSign }, { "Day", IS_INT8, (setter_t)MythDTO::SetSchedule_FindDay }, { "Time", IS_STRING, (setter_t)MythDTO::SetSchedule_FindTime }, { "Type", IS_STRING, (setter_t)MythDTO::SetSchedule_Type }, { "SearchType", IS_STRING, (setter_t)MythDTO::SetSchedule_SearchType }, { "RecPriority", IS_INT8, (setter_t)MythDTO::SetSchedule_RecPriority }, { "PreferredInput", IS_UINT32, (setter_t)MythDTO::SetSchedule_PreferredInput }, { "StartOffset", IS_UINT8, (setter_t)MythDTO::SetSchedule_StartOffset }, { "EndOffset", IS_UINT8, (setter_t)MythDTO::SetSchedule_EndOffset }, { "DupMethod", IS_STRING, (setter_t)MythDTO::SetSchedule_DupMethod }, { "DupIn", IS_STRING, (setter_t)MythDTO::SetSchedule_DupIn }, { "Filter", IS_UINT32, (setter_t)MythDTO::SetSchedule_Filter }, { "RecProfile", IS_STRING, (setter_t)MythDTO::SetSchedule_RecProfile }, { "RecGroup", IS_STRING, (setter_t)MythDTO::SetSchedule_RecGroup }, { "StorageGroup", IS_STRING, (setter_t)MythDTO::SetSchedule_StorageGroup }, { "PlayGroup", IS_STRING, (setter_t)MythDTO::SetSchedule_PlayGroup }, { "AutoExpire", IS_BOOLEAN, (setter_t)MythDTO::SetSchedule_AutoExpire }, { "MaxEpisodes", IS_UINT32, (setter_t)MythDTO::SetSchedule_MaxEpisodes }, { "MaxNewest", IS_BOOLEAN, (setter_t)MythDTO::SetSchedule_MaxNewest }, { "AutoCommflag", IS_BOOLEAN, (setter_t)MythDTO::SetSchedule_AutoCommflag }, { "AutoTranscode", IS_BOOLEAN, (setter_t)MythDTO::SetSchedule_AutoTranscode }, { "AutoMetaLookup", IS_BOOLEAN, (setter_t)MythDTO::SetSchedule_AutoMetaLookup }, { "AutoUserJob1", IS_BOOLEAN, (setter_t)MythDTO::SetSchedule_AutoUserJob1 }, { "AutoUserJob2", IS_BOOLEAN, (setter_t)MythDTO::SetSchedule_AutoUserJob2 }, { "AutoUserJob3", IS_BOOLEAN, (setter_t)MythDTO::SetSchedule_AutoUserJob3 }, { "AutoUserJob4", IS_BOOLEAN, (setter_t)MythDTO::SetSchedule_AutoUserJob4 }, { "Transcoder", IS_UINT32, (setter_t)MythDTO::SetSchedule_Transcoder }, }; bindings_t RecordScheduleBindArray = { sizeof(recordschedule) / sizeof(attr_bind_t), recordschedule }; } #endif /* MYTHDTO75_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/mythdto/mythdto76.h000066400000000000000000000117271360567320200251110ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHDTO76_H #define MYTHDTO76_H #include "mythdto.h" #include "version.h" #include "list.h" #include "program.h" #include "channel.h" #include "recording.h" #include "artwork.h" #include "capturecard.h" #include "videosource.h" #include "recordschedule.h" namespace MythDTO76 { attr_bind_t recordschedule[] = { { "Id", IS_UINT32, (setter_t)MythDTO::SetSchedule_Id }, { "ParentId", IS_UINT32, (setter_t)MythDTO::SetSchedule_ParentId }, { "Inactive", IS_BOOLEAN, (setter_t)MythDTO::SetSchedule_Inactive }, { "Title", IS_STRING, (setter_t)MythDTO::SetSchedule_Title }, { "SubTitle", IS_STRING, (setter_t)MythDTO::SetSchedule_Subtitle }, { "Description", IS_STRING, (setter_t)MythDTO::SetSchedule_Description }, { "Season", IS_UINT16, (setter_t)MythDTO::SetSchedule_Season }, { "Episode", IS_UINT16, (setter_t)MythDTO::SetSchedule_Episode }, { "Category", IS_STRING, (setter_t)MythDTO::SetSchedule_Category }, { "StartTime", IS_TIME, (setter_t)MythDTO::SetSchedule_StartTime }, { "EndTime", IS_TIME, (setter_t)MythDTO::SetSchedule_EndTime }, { "SeriesId", IS_STRING, (setter_t)MythDTO::SetSchedule_SeriesId }, { "ProgramId", IS_STRING, (setter_t)MythDTO::SetSchedule_ProgramId }, { "Inetref", IS_STRING, (setter_t)MythDTO::SetSchedule_Inetref }, { "ChanId", IS_UINT32, (setter_t)MythDTO::SetSchedule_ChanId }, { "CallSign", IS_STRING, (setter_t)MythDTO::SetSchedule_CallSign }, { "FindDay", IS_INT8, (setter_t)MythDTO::SetSchedule_FindDay }, { "FindTime", IS_STRING, (setter_t)MythDTO::SetSchedule_FindTime }, { "Type", IS_STRING, (setter_t)MythDTO::SetSchedule_Type }, { "SearchType", IS_STRING, (setter_t)MythDTO::SetSchedule_SearchType }, { "RecPriority", IS_INT8, (setter_t)MythDTO::SetSchedule_RecPriority }, { "PreferredInput", IS_UINT32, (setter_t)MythDTO::SetSchedule_PreferredInput }, { "StartOffset", IS_UINT8, (setter_t)MythDTO::SetSchedule_StartOffset }, { "EndOffset", IS_UINT8, (setter_t)MythDTO::SetSchedule_EndOffset }, { "DupMethod", IS_STRING, (setter_t)MythDTO::SetSchedule_DupMethod }, { "DupIn", IS_STRING, (setter_t)MythDTO::SetSchedule_DupIn }, { "Filter", IS_UINT32, (setter_t)MythDTO::SetSchedule_Filter }, { "RecProfile", IS_STRING, (setter_t)MythDTO::SetSchedule_RecProfile }, { "RecGroup", IS_STRING, (setter_t)MythDTO::SetSchedule_RecGroup }, { "StorageGroup", IS_STRING, (setter_t)MythDTO::SetSchedule_StorageGroup }, { "PlayGroup", IS_STRING, (setter_t)MythDTO::SetSchedule_PlayGroup }, { "AutoExpire", IS_BOOLEAN, (setter_t)MythDTO::SetSchedule_AutoExpire }, { "MaxEpisodes", IS_UINT32, (setter_t)MythDTO::SetSchedule_MaxEpisodes }, { "MaxNewest", IS_BOOLEAN, (setter_t)MythDTO::SetSchedule_MaxNewest }, { "AutoCommflag", IS_BOOLEAN, (setter_t)MythDTO::SetSchedule_AutoCommflag }, { "AutoTranscode", IS_BOOLEAN, (setter_t)MythDTO::SetSchedule_AutoTranscode }, { "AutoMetaLookup", IS_BOOLEAN, (setter_t)MythDTO::SetSchedule_AutoMetaLookup }, { "AutoUserJob1", IS_BOOLEAN, (setter_t)MythDTO::SetSchedule_AutoUserJob1 }, { "AutoUserJob2", IS_BOOLEAN, (setter_t)MythDTO::SetSchedule_AutoUserJob2 }, { "AutoUserJob3", IS_BOOLEAN, (setter_t)MythDTO::SetSchedule_AutoUserJob3 }, { "AutoUserJob4", IS_BOOLEAN, (setter_t)MythDTO::SetSchedule_AutoUserJob4 }, { "Transcoder", IS_UINT32, (setter_t)MythDTO::SetSchedule_Transcoder }, { "NextRecording", IS_TIME, (setter_t)MythDTO::SetSchedule_NextRecording }, { "LastRecorded", IS_TIME, (setter_t)MythDTO::SetSchedule_LastRecorded }, { "LastDeleted", IS_TIME, (setter_t)MythDTO::SetSchedule_LastDeleted }, { "AverageDelay", IS_UINT32, (setter_t)MythDTO::SetSchedule_AverageDelay }, }; bindings_t RecordScheduleBindArray = { sizeof(recordschedule) / sizeof(attr_bind_t), recordschedule }; } #endif /* MYTHDTO76_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/mythdto/mythdto82.h000066400000000000000000000045351360567320200251050ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHDTO82_H #define MYTHDTO82_H #include "mythdto.h" #include "version.h" #include "list.h" #include "program.h" #include "channel.h" #include "recording.h" #include "artwork.h" #include "capturecard.h" #include "videosource.h" #include "recordschedule.h" namespace MythDTO82 { attr_bind_t recording[] = { { "RecordId", IS_UINT32, (setter_t)MythDTO::SetRecording_RecordId }, { "Priority", IS_INT32, (setter_t)MythDTO::SetRecording_Priority }, { "Status", IS_INT8, (setter_t)MythDTO::SetRecording_Status }, { "EncoderId", IS_UINT32, (setter_t)MythDTO::SetRecording_EncoderId }, { "RecType", IS_UINT8, (setter_t)MythDTO::SetRecording_RecType }, { "DupInType", IS_UINT8, (setter_t)MythDTO::SetRecording_DupInType }, { "DupMethod", IS_UINT8, (setter_t)MythDTO::SetRecording_DupMethod }, { "StartTs", IS_TIME, (setter_t)MythDTO::SetRecording_StartTs }, { "EndTs", IS_TIME, (setter_t)MythDTO::SetRecording_EndTs }, { "Profile", IS_STRING, (setter_t)MythDTO::SetRecording_Profile }, { "RecGroup", IS_STRING, (setter_t)MythDTO::SetRecording_RecGroup }, { "StorageGroup", IS_STRING, (setter_t)MythDTO::SetRecording_StorageGroup }, { "PlayGroup", IS_STRING, (setter_t)MythDTO::SetRecording_PlayGroup }, { "RecordedId", IS_UINT32, (setter_t)MythDTO::SetRecording_RecordedId }, }; bindings_t RecordingBindArray = { sizeof(recording) / sizeof(attr_bind_t), recording }; } #endif /* MYTHDTO82_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/mythdto/mythdto85.h000066400000000000000000000026511360567320200251050ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHDTO85_H #define MYTHDTO85_H #include "mythdto.h" #include "version.h" #include "list.h" #include "program.h" #include "channel.h" #include "recording.h" #include "artwork.h" #include "capturecard.h" #include "videosource.h" #include "recordschedule.h" #include "cutting.h" namespace MythDTO85 { attr_bind_t cutting[] = { { "Mark", IS_INT8, (setter_t)MythDTO::SetCutting_MarkType }, { "Offset", IS_INT64, (setter_t)MythDTO::SetCutting_MarkValue }, }; bindings_t CuttingBindArray = { sizeof(cutting) / sizeof(attr_bind_t), cutting }; } #endif /* MYTHDTO85_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/mythdto/program.h000066400000000000000000000056631360567320200247150ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHDTO_PROGRAM_H #define MYTHDTO_PROGRAM_H #include "../../mythtypes.h" namespace MythDTO { void SetProgram_StartTime(Myth::Program *obj, time_t *val) { obj->startTime = *val; } void SetProgram_EndTime(Myth::Program *obj, time_t *val) { obj->endTime = *val; } void SetProgram_Title(Myth::Program *obj, const char *val) { obj->title = val; } void SetProgram_SubTitle(Myth::Program *obj, const char *val) { obj->subTitle = val; } void SetProgram_Description(Myth::Program *obj, const char *val) { obj->description = val; } void SetProgram_Season(Myth::Program *obj, uint16_t *val) { obj->season = *val; } void SetProgram_Episode(Myth::Program *obj, uint16_t *val) { obj->episode = *val; } void SetProgram_Category(Myth::Program *obj, const char *val) { obj->category = val; } void SetProgram_CatType(Myth::Program *obj, const char *val) { obj->catType = val; } void SetProgram_HostName(Myth::Program *obj, const char *val) { obj->hostName = val; } void SetProgram_FileName(Myth::Program *obj, const char *val) { obj->fileName = val; } void SetProgram_FileSize(Myth::Program *obj, int64_t *val) { obj->fileSize = *val; } void SetProgram_Repeat(Myth::Program *obj, bool *val) { obj->repeat = *val; } void SetProgram_ProgramFlags(Myth::Program *obj, uint32_t *val) { obj->programFlags = *val; } void SetProgram_SeriesId(Myth::Program *obj, const char *val) { obj->seriesId = val; } void SetProgram_ProgramId(Myth::Program *obj, const char *val) { obj->programId = val; } void SetProgram_Inetref(Myth::Program *obj, const char *val) { obj->inetref = val; } void SetProgram_LastModified(Myth::Program *obj, time_t *val) { obj->lastModified = *val; } void SetProgram_Stars(Myth::Program *obj, const char *val) { obj->stars = val; } void SetProgram_Airdate(Myth::Program *obj, time_t *val) { obj->airdate = *val; } void SetProgram_AudioProps(Myth::Program *obj, uint16_t *val) { obj->audioProps = *val; } void SetProgram_VideoProps(Myth::Program *obj, uint16_t *val) { obj->videoProps = *val; } void SetProgram_SubProps(Myth::Program *obj, uint16_t *val) { obj->subProps = *val; } } #endif /* MYTHDTO_PROGRAM_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/mythdto/recording.h000066400000000000000000000043251360567320200252140ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHDTO_RECORDING_H #define MYTHDTO_RECORDING_H #include "../../mythtypes.h" namespace MythDTO { void SetRecording_RecordId(Myth::Recording *obj, uint32_t *val) { obj->recordId = *val; } void SetRecording_Priority(Myth::Recording *obj, int32_t *val) { obj->priority = *val; } void SetRecording_Status(Myth::Recording *obj, int8_t *val) { obj->status = *val; } void SetRecording_EncoderId(Myth::Recording *obj, uint32_t *val) { obj->encoderId = *val; } void SetRecording_RecType(Myth::Recording *obj, uint8_t *val) { obj->recType = *val; } void SetRecording_DupInType(Myth::Recording *obj, uint8_t *val) { obj->dupInType = *val; } void SetRecording_DupMethod(Myth::Recording *obj, uint8_t *val) { obj->dupMethod = *val; } void SetRecording_StartTs(Myth::Recording *obj, time_t *val) { obj->startTs = *val; } void SetRecording_EndTs(Myth::Recording *obj, time_t *val) { obj->endTs = *val; } void SetRecording_Profile(Myth::Recording *obj, const char *val) { obj->profile = val; } void SetRecording_RecGroup(Myth::Recording *obj, const char *val) { obj->recGroup = val; } void SetRecording_StorageGroup(Myth::Recording *obj, const char *val) { obj->storageGroup = val; } void SetRecording_PlayGroup(Myth::Recording *obj, const char *val) { obj->playGroup = val; } void SetRecording_RecordedId(Myth::Recording *obj, uint32_t *val) { obj->recordedId = *val; } } #endif /* MYTHDTO_RECORDING_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/mythdto/recordschedule.h000066400000000000000000000125611360567320200262340ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHDTO_RECORDSCHEDULE_H #define MYTHDTO_RECORDSCHEDULE_H #include "../../mythtypes.h" namespace MythDTO { void SetSchedule_Id(Myth::RecordSchedule *obj, uint32_t *val) { obj->recordId = *val; } void SetSchedule_Title(Myth::RecordSchedule *obj, const char *val) { obj->title = val; } void SetSchedule_Subtitle(Myth::RecordSchedule *obj, const char *val) { obj->subtitle = val; } void SetSchedule_Description(Myth::RecordSchedule *obj, const char *val) { obj->description = val; } void SetSchedule_Category(Myth::RecordSchedule *obj, const char *val) { obj->category = val; } void SetSchedule_StartTime(Myth::RecordSchedule *obj, time_t *val) { obj->startTime = *val; } void SetSchedule_EndTime(Myth::RecordSchedule *obj, time_t *val) { obj->endTime = *val; } void SetSchedule_SeriesId(Myth::RecordSchedule *obj, const char *val) { obj->seriesId = val; } void SetSchedule_ProgramId(Myth::RecordSchedule *obj, const char *val) { obj->programId = val; } void SetSchedule_ChanId(Myth::RecordSchedule *obj, uint32_t *val) { obj->chanId = *val; } void SetSchedule_CallSign(Myth::RecordSchedule *obj, const char *val) { obj->callSign = val; } void SetSchedule_FindDay(Myth::RecordSchedule *obj, int8_t *val) { obj->findDay = *val; } void SetSchedule_FindTime(Myth::RecordSchedule *obj, const char *val) { obj->findTime = val; } void SetSchedule_ParentId(Myth::RecordSchedule *obj, uint32_t *val) { obj->parentId = *val; } void SetSchedule_Inactive(Myth::RecordSchedule *obj, bool *val) { obj->inactive = *val; } void SetSchedule_Season(Myth::RecordSchedule *obj, uint16_t *val) { obj->season = *val; } void SetSchedule_Episode(Myth::RecordSchedule *obj, uint16_t *val) { obj->episode = *val; } void SetSchedule_Inetref(Myth::RecordSchedule *obj, const char *val) { obj->inetref = val; } void SetSchedule_Type(Myth::RecordSchedule *obj, const char *val) { obj->type = val; } void SetSchedule_SearchType(Myth::RecordSchedule *obj, const char *val) { obj->searchType = val; } void SetSchedule_RecPriority(Myth::RecordSchedule *obj, int8_t *val) { obj->recPriority = *val; } void SetSchedule_PreferredInput(Myth::RecordSchedule *obj, uint32_t *val) { obj->preferredInput = *val; } void SetSchedule_StartOffset(Myth::RecordSchedule *obj, uint8_t *val) { obj->startOffset = *val; } void SetSchedule_EndOffset(Myth::RecordSchedule *obj, uint8_t *val) { obj->endOffset = *val; } void SetSchedule_DupMethod(Myth::RecordSchedule *obj, const char *val) { obj->dupMethod = val; } void SetSchedule_DupIn(Myth::RecordSchedule *obj, const char *val) { obj->dupIn = *val; } void SetSchedule_Filter(Myth::RecordSchedule *obj, uint32_t *val) { obj->filter = *val; } void SetSchedule_RecProfile(Myth::RecordSchedule *obj, const char *val) { obj->recProfile = val; } void SetSchedule_RecGroup(Myth::RecordSchedule *obj, const char *val) { obj->recGroup = val; } void SetSchedule_StorageGroup(Myth::RecordSchedule *obj, const char *val) { obj->storageGroup = val; } void SetSchedule_PlayGroup(Myth::RecordSchedule *obj, const char *val) { obj->playGroup = val; } void SetSchedule_AutoExpire(Myth::RecordSchedule *obj, bool *val) { obj->autoExpire = *val; } void SetSchedule_MaxEpisodes(Myth::RecordSchedule *obj, uint32_t *val) { obj->maxEpisodes = *val; } void SetSchedule_MaxNewest(Myth::RecordSchedule *obj, bool *val) { obj->maxNewest = *val; } void SetSchedule_AutoCommflag(Myth::RecordSchedule *obj, bool *val) { obj->autoCommflag = *val; } void SetSchedule_AutoTranscode(Myth::RecordSchedule *obj, bool *val) { obj->autoTranscode = *val; } void SetSchedule_AutoMetaLookup(Myth::RecordSchedule *obj, bool *val) { obj->autoMetaLookup = *val; } void SetSchedule_AutoUserJob1(Myth::RecordSchedule *obj, bool *val) { obj->autoUserJob1 = *val; } void SetSchedule_AutoUserJob2(Myth::RecordSchedule *obj, bool *val) { obj->autoUserJob2 = *val; } void SetSchedule_AutoUserJob3(Myth::RecordSchedule *obj, bool *val) { obj->autoUserJob3 = *val; } void SetSchedule_AutoUserJob4(Myth::RecordSchedule *obj, bool *val) { obj->autoUserJob4 = *val; } void SetSchedule_Transcoder(Myth::RecordSchedule *obj, uint32_t *val) { obj->transcoder = *val; } void SetSchedule_NextRecording(Myth::RecordSchedule *obj, time_t *val) { obj->nextRecording = *val; } void SetSchedule_LastRecorded(Myth::RecordSchedule *obj, time_t *val) { obj->lastRecorded = *val; } void SetSchedule_LastDeleted(Myth::RecordSchedule *obj, time_t *val) { obj->lastDeleted = *val; } void SetSchedule_AverageDelay(Myth::RecordSchedule *obj, uint32_t *val) { obj->averageDelay = *val; } } #endif /* MYTHDTO_RECORDSCHEDULE_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/mythdto/version.h000066400000000000000000000023041360567320200247200ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHDTO_VERSION_H #define MYTHDTO_VERSION_H #include "../../mythtypes.h" namespace MythDTO { void SetVersion_Version(Myth::Version *obj, const char *val) { obj->version = val; } void SetVersion_Protocol(Myth::Version *obj, uint32_t *val) { obj->protocol = *val; } void SetVersion_Schema(Myth::Version *obj, uint32_t *val) { obj->schema = *val; } } #endif /* VERSION_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/mythdto/videosource.h000066400000000000000000000022241360567320200255630ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHDTO_VIDEOSOURCE_H #define MYTHDTO_VIDEOSOURCE_H #include "../../mythtypes.h" namespace MythDTO { void SetVideoSource_Id(Myth::VideoSource *obj, uint32_t *val) { obj->sourceId = *val; } void SetVideoSource_SourceName(Myth::VideoSource *obj, const char *val) { obj->sourceName = val; } } #endif /* MYTHDTO_VIDEOSOURCE_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/mythjsonbinder.cpp000066400000000000000000000071701360567320200251430ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "mythjsonbinder.h" #include "builtin.h" #include "debug.h" #include // for atof #include // for strcmp #include #include using namespace Myth; void JSON::BindObject(const Node& node, void *obj, const bindings_t *bl) { int i, err; if (bl == NULL) return; for (i = 0; i < bl->attr_count; ++i) { const Node& field = node.GetObjectValue(bl->attr_bind[i].field); if (field.IsNull()) continue; if (field.IsString()) { std::string value(field.GetStringValue()); err = 0; switch (bl->attr_bind[i].type) { case IS_STRING: bl->attr_bind[i].set(obj, value.c_str()); break; case IS_INT8: { int8_t num = 0; err = string_to_int8(value.c_str(), &num); bl->attr_bind[i].set(obj, &num); break; } case IS_INT16: { int16_t num = 0; err = string_to_int16(value.c_str(), &num); bl->attr_bind[i].set(obj, &num); break; } case IS_INT32: { int32_t num = 0; err = string_to_int32(value.c_str(), &num); bl->attr_bind[i].set(obj, &num); break; } case IS_INT64: { int64_t num = 0; err = string_to_int64(value.c_str(), &num); bl->attr_bind[i].set(obj, &num); break; } case IS_UINT8: { uint8_t num = 0; err = string_to_uint8(value.c_str(), &num); bl->attr_bind[i].set(obj, &num); break; } case IS_UINT16: { uint16_t num = 0; err = string_to_uint16(value.c_str(), &num); bl->attr_bind[i].set(obj, &num); break; } case IS_UINT32: { uint32_t num = 0; err = string_to_uint32(value.c_str(), &num); bl->attr_bind[i].set(obj, &num); break; } case IS_DOUBLE: { double num = atof(value.c_str()); bl->attr_bind[i].set(obj, &num); break; } case IS_BOOLEAN: { bool b = (strcmp(value.c_str(), "true") == 0 ? true : false); bl->attr_bind[i].set(obj, &b); break; } case IS_TIME: { time_t time = 0; err = string_to_time(value.c_str(), &time); bl->attr_bind[i].set(obj, &time); break; } default: break; } if (err) Myth::DBG(DBG_ERROR, "%s: failed (%d) field \"%s\" type %d: %s\n", __FUNCTION__, err, bl->attr_bind[i].field, bl->attr_bind[i].type, value.c_str()); } else Myth::DBG(DBG_WARN, "%s: invalid value for field \"%s\" type %d\n", __FUNCTION__, bl->attr_bind[i].field, bl->attr_bind[i].type); } } pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/mythjsonbinder.h000066400000000000000000000020641360567320200246050ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHJSONBINDER_H #define MYTHJSONBINDER_H #include "mythdto/mythdto.h" #include "jsonparser.h" namespace Myth { namespace JSON { void BindObject(const Node& node, void *obj, const bindings_t *bl); } } #endif /* MYTHJSONBINDER_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/os/000077500000000000000000000000001360567320200220145ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/os/os.h000066400000000000000000000002501360567320200226030ustar00rootroot00000000000000#pragma once #ifndef NSROOT #define NSROOT Myth #endif #if (defined(_WIN32) || defined(_WIN64)) #include "windows/os-types.h" #else #include "unix/os-types.h" #endif pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/os/threads/000077500000000000000000000000001360567320200234465ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/os/threads/condition.h000066400000000000000000000042011360567320200256020ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2015 Jean-Luc Barriere * * 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 3, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "mutex.h" #include "timeout.h" #ifdef NSROOT namespace NSROOT { #endif namespace OS { template class CCondition { public: CCondition() { cond_init(&m_condition); } ~CCondition() { cond_destroy(&m_condition); } void Broadcast() { cond_broadcast(&m_condition); } void Signal() { cond_signal(&m_condition); } bool Wait(CMutex& mutex, P& predicate) { while(!predicate) cond_wait(&m_condition, mutex.NativeHandle()); return true; } bool Wait(CMutex& mutex, P& predicate, unsigned timeout) { CTimeout _timeout(timeout); while (!predicate) { // wait for time left timeout = _timeout.TimeLeft(); if (timeout == 0) return false; cond_timedwait(&m_condition, mutex.NativeHandle(), timeout); } return true; } bool Wait(CMutex& mutex, CTimeout& timeout) { cond_timedwait(&m_condition, mutex.NativeHandle(), timeout.TimeLeft()); return (timeout.TimeLeft() > 0 ? true : false); } private: condition_t m_condition; // Prevent copy CCondition(const CCondition

& other); CCondition

& operator=(const CCondition

& other); }; } #ifdef NSROOT } #endif pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/os/threads/event.h000066400000000000000000000047741360567320200247540ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2015 Jean-Luc Barriere * * 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 3, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "condition.h" #ifdef NSROOT namespace NSROOT { #endif namespace OS { class CEvent { public: CEvent(bool autoReset = true) : m_notified(false) , m_notifyOne(false) , m_waitingCount(0) , m_autoReset(autoReset) {} ~CEvent() {} void Broadcast() { CLockGuard lock(m_mutex); m_notifyOne = false; m_notified = true; m_condition.Broadcast(); } void Signal() { CLockGuard lock(m_mutex); m_notifyOne = true; m_notified = true; m_condition.Signal(); } bool Wait() { CLockGuard lock(m_mutex); ++m_waitingCount; bool notified = m_condition.Wait(m_mutex, m_notified); --m_waitingCount; if (m_autoReset && notified) __reset(m_notifyOne); return notified; } bool Wait(unsigned timeout) { CLockGuard lock(m_mutex); ++m_waitingCount; bool notified = m_condition.Wait(m_mutex, m_notified, timeout); --m_waitingCount; if (m_autoReset && notified) __reset(m_notifyOne); return notified; } void Reset() { CLockGuard lock(m_mutex); __reset(true); } private: volatile bool m_notified; volatile bool m_notifyOne; unsigned m_waitingCount; bool m_autoReset; CCondition m_condition; CMutex m_mutex; void __reset(bool force) { if (force || m_waitingCount == 0) m_notified = false; } // Prevent copy CEvent(const CEvent& other); CEvent& operator=(const CEvent& other); }; } #ifdef NSROOT } #endif pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/os/threads/mutex.h000066400000000000000000000060011360567320200247560ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2015 Jean-Luc Barriere * * 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 3, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "os-threads.h" #ifdef NSROOT namespace NSROOT { #endif namespace OS { class CMutex { public: CMutex() : m_lockCount(0) { mutex_init(&m_handle); } ~CMutex() { Clear(); mutex_destroy(&m_handle); } mutex_t* NativeHandle() { return &m_handle; } bool TryLock() { if (mutex_trylock(&m_handle)) { ++m_lockCount; return true; } return false; } void Lock() { mutex_lock(&m_handle); ++m_lockCount; } void Unlock() { if (mutex_trylock(&m_handle)) { if (m_lockCount > 0) { mutex_unlock(&m_handle); --m_lockCount; } mutex_unlock(&m_handle); } } void Clear() { if (mutex_trylock(&m_handle)) { for (unsigned i = m_lockCount; i > 0; --i) mutex_unlock(&m_handle); m_lockCount = 0; mutex_unlock(&m_handle); } } private: mutex_t m_handle; volatile unsigned m_lockCount; // Prevent copy CMutex(const CMutex& other); CMutex& operator=(const CMutex& other); }; class CLockGuard { public: CLockGuard(CMutex& mutex) : m_mutex(mutex) , m_lockCount(0) { Lock(); } ~CLockGuard() { Clear(); } bool TryLock() { if (m_mutex.TryLock()) { ++m_lockCount; return true; } return false; } void Lock() { m_mutex.Lock(); ++m_lockCount; } void Unlock() { if (m_mutex.TryLock()) { if (m_lockCount > 0) { m_mutex.Unlock(); --m_lockCount; } m_mutex.Unlock(); } } void Clear() { if (m_mutex.TryLock()) { for (unsigned i = m_lockCount; i > 0; --i) m_mutex.Unlock(); m_lockCount = 0; m_mutex.Unlock(); } } private: CMutex& m_mutex; volatile unsigned m_lockCount; // Prevent copy CLockGuard(const CLockGuard& other); CLockGuard& operator=(const CLockGuard& other); }; } #ifdef NSROOT } #endif pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/os/threads/os-threads.h000066400000000000000000000105601360567320200256720ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2015 Jean-Luc Barriere * * 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 3, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "../os.h" #if defined(_MSC_VER) #include "../windows/winpthreads.h" #else #include #endif #ifdef NSROOT namespace NSROOT { #endif namespace OS { #if defined (__WINDOWS__) #define gettimeofday __gettimeofday inline int __gettimeofday(struct timeval *pcur_time, struct timezone *tz) { if (pcur_time == NULL) { SetLastError(EFAULT); return -1; } struct _timeb current; _ftime(¤t); pcur_time->tv_sec = (long) current.time; pcur_time->tv_usec = current.millitm * 1000L; if (tz) { tz->tz_minuteswest = current.timezone; /* minutes west of Greenwich */ tz->tz_dsttime = current.dstflag; /* type of dst correction */ } return 0; } #endif typedef pthread_t thread_t; #define thread_create(a, b, c) __thread_create(a, b, c) inline bool __thread_create(thread_t* thread, void* (*func)(void*), void* arg) { static pthread_attr_t _attr; static bool _init = false; if (!_init) { pthread_attr_init(&_attr); pthread_attr_setdetachstate(&_attr, PTHREAD_CREATE_DETACHED); _init = true; } return pthread_create(thread, &_attr, func, arg) == 0; } typedef pthread_mutex_t mutex_t; #define mutex_init(a) __mutex_init(a) inline bool __mutex_init(mutex_t* mutex) { static pthread_mutexattr_t _attr; static bool _init = false; if (!_init) { pthread_mutexattr_init(&_attr); pthread_mutexattr_settype(&_attr, PTHREAD_MUTEX_RECURSIVE); _init = true; } return pthread_mutex_init(mutex, &_attr) == 0; } #define mutex_lock(a) __mutex_lock(a) inline bool __mutex_lock(mutex_t* mutex) { return pthread_mutex_lock(mutex) == 0; } #define mutex_trylock(a) __mutex_trylock(a) inline bool __mutex_trylock(mutex_t* mutex) { return pthread_mutex_trylock(mutex) == 0; } #define mutex_unlock(a) __mutex_unlock(a) inline void __mutex_unlock(mutex_t* mutex) { pthread_mutex_unlock(mutex); } #define mutex_destroy(a) __mutex_destroy(a) inline void __mutex_destroy(mutex_t* mutex) { pthread_mutex_destroy(mutex); } typedef pthread_cond_t condition_t; #define cond_init(a) __cond_init(a) inline bool __cond_init(condition_t* cond) { return pthread_cond_init(cond, NULL) == 0; } #define cond_signal(a) __cond_signal(a) inline void __cond_signal(condition_t* cond) { pthread_cond_signal(cond); } #define cond_broadcast(a) __cond_broadcast(a) inline void __cond_broadcast(condition_t* cond) { pthread_cond_broadcast(cond); } #define cond_wait(a, b) __cond_wait(a, b) inline bool __cond_wait(condition_t* cond, mutex_t* mutex) { return pthread_cond_wait(cond, mutex) == 0; } #define cond_timedwait(a, b, c) __cond_timedwait(a, b, c) inline bool __cond_timedwait(condition_t* cond, mutex_t* mutex, unsigned millisec) { if (millisec == 0) return cond_wait(cond, mutex); struct timespec time; #if defined(__APPLE__) || defined(__WINDOWS__) struct timeval tv; gettimeofday(&tv, NULL); tv.tv_usec += (millisec % 1000) * 1000; tv.tv_sec += millisec / 1000; time.tv_sec = tv.tv_sec + tv.tv_usec / 1000000; time.tv_nsec = (tv.tv_usec % 1000000) * 1000; #else clock_gettime(CLOCK_REALTIME, &time); time.tv_nsec += (millisec % 1000) * 1000000; time.tv_sec += millisec / 1000 + time.tv_nsec / 1000000000; time.tv_nsec %= 1000000000; #endif return (pthread_cond_timedwait(cond, mutex, &time) == 0); } #define cond_destroy(a) __cond_destroy(a) inline void __cond_destroy(condition_t* cond) { pthread_cond_destroy(cond); } } #ifdef NSROOT } #endif pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/os/threads/thread.h000066400000000000000000000112101360567320200250610ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2015 Jean-Luc Barriere * * 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 3, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "mutex.h" #include "condition.h" #ifdef NSROOT namespace NSROOT { #endif namespace OS { class CThread { public: CThread() : m_finalizeOnStop(false) , m_handle(new Handle()) { } virtual ~CThread() { delete m_handle; } CThread(const CThread& _thread) { this->m_handle = new Handle(); this->m_finalizeOnStop = _thread.m_finalizeOnStop; } CThread& operator=(const CThread& _thread) { if (this != &_thread) { delete this->m_handle; this->m_handle = new Handle(); this->m_finalizeOnStop = _thread.m_finalizeOnStop; } return *this; } thread_t* NativeHandle() { return &(m_handle->nativeHandle); } bool StartThread(bool wait = true) { CLockGuard lock(m_handle->mutex); if (!m_handle->running) { m_handle->notifiedStop = false; if (thread_create(&(m_handle->nativeHandle), CThread::ThreadHandler, ((void*)static_cast(this)))) { if (wait) m_handle->condition.Wait(m_handle->mutex, m_handle->running); return true; } } return false; } void StopThread(bool wait = true) { // First signal stop { CLockGuard lock(m_handle->mutex); m_handle->notifiedStop = true; m_handle->condition.Broadcast(); } // Waiting stopped if (wait) { CLockGuard lock(m_handle->mutex); m_handle->condition.Wait(m_handle->mutex, m_handle->stopped); } } bool WaitThread(unsigned timeout) { CLockGuard lock(m_handle->mutex); return m_handle->stopped ? true : m_handle->condition.Wait(m_handle->mutex, m_handle->stopped, timeout); } bool IsRunning() { CLockGuard lock(m_handle->mutex); return m_handle->running; } bool IsStopped() { CLockGuard lock(m_handle->mutex); return m_handle->notifiedStop || m_handle->stopped; } void Sleep(unsigned timeout) { CTimeout _timeout(timeout); CLockGuard lock(m_handle->mutex); while (!m_handle->notifiedStop && !m_handle->notifiedWake && m_handle->condition.Wait(m_handle->mutex, _timeout)); m_handle->notifiedWake = false; // Reset the wake flag } void WakeUp() { CLockGuard lock(m_handle->mutex); m_handle->notifiedWake = true; m_handle->condition.Broadcast(); } protected: virtual void* Process(void) = 0; virtual void Finalize(void) { }; bool m_finalizeOnStop; private: struct Handle { thread_t nativeHandle; volatile bool running; volatile bool stopped; volatile bool notifiedStop; volatile bool notifiedWake; CCondition condition; CMutex mutex; Handle() : nativeHandle(0) , running(false) , stopped(true) , notifiedStop(false) , notifiedWake(false) , condition() , mutex() { } }; Handle* m_handle; static void* ThreadHandler(void* _thread) { CThread* thread = static_cast(_thread); void* ret = NULL; if (thread) { bool finalize = thread->m_finalizeOnStop; { CLockGuard lock(thread->m_handle->mutex); thread->m_handle->running = true; thread->m_handle->stopped = false; thread->m_handle->condition.Broadcast(); lock.Unlock(); ret = thread->Process(); lock.Lock(); thread->m_handle->running = false; thread->m_handle->stopped = true; thread->m_handle->condition.Broadcast(); } // Thread without finalizer could be freed here if (finalize) thread->Finalize(); } return ret; } }; } #ifdef NSROOT } #endif pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/os/threads/threadpool.cpp000066400000000000000000000124771360567320200263260ustar00rootroot00000000000000/* * Copyright (C) 2015 Jean-Luc Barriere * * 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 3, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "threadpool.h" #include #define WTH_KEEPALIVE 5000 #ifdef NSROOT using namespace NSROOT::OS; #else using namespace OS; #endif CThreadPool::CThreadPool() : m_size(1) , m_keepAlive(WTH_KEEPALIVE) , m_poolSize(0) , m_waitingCount(0) , m_stopped(false) , m_suspended(false) , m_empty(false) { } CThreadPool::CThreadPool(unsigned size) : m_size(size) , m_keepAlive(WTH_KEEPALIVE) , m_poolSize(0) , m_waitingCount(0) , m_stopped(false) , m_suspended(false) , m_empty(false) { } CThreadPool::~CThreadPool() { m_mutex.Lock(); // Reject new runs m_stopped = true; // Destroy all queued workers while (!m_queue.empty()) { delete m_queue.front(); m_queue.pop(); } // Finalize all running if (!m_pool.empty()) { m_empty = false; // Signal stop for (std::set::iterator it = m_pool.begin(); it != m_pool.end(); ++it) (*it)->StopThread(false); // Wake sleeper m_queueFill.Broadcast(); // Waiting all finalized m_condition.Wait(m_mutex, m_empty); } } bool CThreadPool::Enqueue(CWorker* worker) { assert(worker->m_queued != true); CLockGuard lock(m_mutex); if (!m_stopped) { worker->m_queued = true; m_queue.push(worker); if (!m_suspended) { if (m_waitingCount) { // Wake a thread m_queueFill.Signal(); return true; } else { __resize(); return true; } } // Delayed work return true; } return false; } void CThreadPool::SetMaxSize(unsigned size) { CLockGuard lock(m_mutex); m_size = size; if (!m_suspended) __resize(); } void CThreadPool::SetKeepAlive(unsigned millisec) { CLockGuard lock(m_mutex); m_keepAlive = millisec; } unsigned CThreadPool::Size() const { CLockGuard lock(m_mutex); return m_poolSize; } unsigned CThreadPool::QueueSize() const { CLockGuard lock(m_mutex); return static_cast(m_queue.size()); } bool CThreadPool::IsQueueEmpty() const { CLockGuard lock(m_mutex); return m_queue.empty(); } bool CThreadPool::waitEmpty(unsigned millisec) { return IsQueueEmpty() || m_queueEmpty.Wait(millisec); } bool CThreadPool::waitEmpty() { return IsQueueEmpty() || m_queueEmpty.Wait(); } void CThreadPool::Suspend() { CLockGuard lock(m_mutex); m_suspended = true; } void CThreadPool::Resume() { CLockGuard lock(m_mutex); m_suspended = false; __resize(); } bool CThreadPool::IsSuspended() const { CLockGuard lock(m_mutex); return m_suspended; } void CThreadPool::Reset() { CLockGuard lock(m_mutex); m_stopped = true; // Destroy all queued workers while (!m_queue.empty()) { delete m_queue.front(); m_queue.pop(); } } void CThreadPool::Stop() { CLockGuard lock(m_mutex); m_stopped = true; } void CThreadPool::Start() { CLockGuard lock(m_mutex); m_stopped = false; } bool CThreadPool::IsStopped() const { CLockGuard lock(m_mutex); return m_stopped; } CWorker* CThreadPool::PopQueue(CWorkerThread* _thread) { (void)_thread; CLockGuard lock(m_mutex); if (!m_suspended) { m_queueEmpty.Signal(); if (!m_queue.empty()) { CWorker* worker = m_queue.front(); m_queue.pop(); return worker; } } return NULL; } void CThreadPool::WaitQueue(CWorkerThread* _thread) { (void)_thread; CLockGuard lock(m_mutex); ++m_waitingCount; unsigned millisec = m_keepAlive; lock.Unlock(); m_queueFill.Wait(millisec); lock.Lock(); --m_waitingCount; } void CThreadPool::StartThread(CWorkerThread* _thread) { ++m_poolSize; m_pool.insert(_thread); if (!_thread->StartThread(false)) FinalizeThread(_thread); } void CThreadPool::FinalizeThread(CWorkerThread* _thread) { CLockGuard lock(m_mutex); if (m_pool.erase(_thread)) { --m_poolSize; delete _thread; } if (m_pool.empty()) { m_empty = true; m_condition.Broadcast(); } } void CThreadPool::__resize() { if (m_poolSize < m_size && !m_queue.empty()) { for (unsigned i = m_queue.size(); i > 0; --i) { if (m_poolSize >= m_size) break; CWorkerThread* _thread = new CWorkerThread(*this); // The new thread will check the queue StartThread(_thread); } } else if (m_poolSize > m_size) { std::set::iterator it = m_pool.begin(); for (unsigned i = m_poolSize - m_size; i > 0; --i) { if (it == m_pool.end()) break; (*it)->StopThread(false); ++it; } // Wake up the waiting threads to stop if (m_waitingCount) m_queueFill.Broadcast(); } } pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/os/threads/threadpool.h000066400000000000000000000063301360567320200257620ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2015 Jean-Luc Barriere * * 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 3, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "thread.h" #include "event.h" #include #include #ifdef NSROOT namespace NSROOT { #endif namespace OS { class CWorker; class CWorkerThread; class CThreadPool { friend class CWorkerThread; public: CThreadPool(); CThreadPool(unsigned size); ~CThreadPool(); bool Enqueue(CWorker* worker); unsigned GetMaxSize() const { return m_size; } void SetMaxSize(unsigned size); void SetKeepAlive(unsigned millisec); unsigned Size() const; unsigned QueueSize() const; bool IsQueueEmpty() const; bool waitEmpty(unsigned millisec); bool waitEmpty(); void Suspend(); void Resume(); bool IsSuspended() const; void Reset(); void Stop(); void Start(); bool IsStopped() const; private: unsigned m_size; unsigned m_keepAlive; unsigned m_poolSize; unsigned m_waitingCount; volatile bool m_stopped; volatile bool m_suspended; volatile bool m_empty; std::queue m_queue; std::set m_pool; mutable CMutex m_mutex; CCondition m_condition; CEvent m_queueFill; CEvent m_queueEmpty; CWorker* PopQueue(CWorkerThread* _thread); void WaitQueue(CWorkerThread* _thread); void StartThread(CWorkerThread* _thread); void FinalizeThread(CWorkerThread* _thread); void __resize(); }; class CWorker { friend class CThreadPool; public: CWorker() : m_queued(false) { } virtual ~CWorker() { } virtual void Process() = 0; private: bool m_queued; }; class CWorkerThread : public CThread { public: CWorkerThread(CThreadPool& pool) : CThread() , m_threadPool(pool) { m_finalizeOnStop = true; } void* Process(void) { bool waiting = false; while (!IsStopped()) { CWorker* worker = m_threadPool.PopQueue(this); if (worker != NULL) { worker->Process(); delete worker; waiting = false; } else if (!waiting) { m_threadPool.WaitQueue(this); waiting = true; } else break; } return NULL; } void Finalize(void) { m_threadPool.FinalizeThread(this); } private: CThreadPool& m_threadPool; }; } #ifdef NSROOT } #endif pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/os/threads/timeout.h000066400000000000000000000057671360567320200253240ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2015 Jean-Luc Barriere * * 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 3, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "../os.h" #if defined(__APPLE__) #include #endif #ifdef NSROOT namespace NSROOT { #endif namespace OS { #define gettime_ms __gettime_ms inline int64_t __gettime_ms() { #if defined(__APPLE__) // Recommended by Apple's QA1398. int64_t ticks = 0; static mach_timebase_info_data_t timebase; // Get the timebase if this is the first time we run. if (timebase.denom == 0) (void)mach_timebase_info(&timebase); // Use timebase to convert absolute time tick units into nanoseconds. ticks = mach_absolute_time() * timebase.numer / timebase.denom; return ticks / 1000000; #elif defined(__WINDOWS__) LARGE_INTEGER tickPerSecond; LARGE_INTEGER tick; if (QueryPerformanceFrequency(&tickPerSecond)) { QueryPerformanceCounter(&tick); return (int64_t) (tick.QuadPart / (tickPerSecond.QuadPart / 1000.0)); } return -1; #else timespec time; clock_gettime(CLOCK_MONOTONIC, &time); return (int64_t)time.tv_sec * 1000 + time.tv_nsec / 1000000; #endif } class CTimeout { public: CTimeout() : m_time(0) { } CTimeout(unsigned millisec) : m_time(0) { Set(millisec); } void Set(unsigned millisec) { m_time = gettime_ms() + millisec; } bool IsSet() const { return (m_time > 0 ? true : false); } void Clear() { m_time = 0; } unsigned TimeLeft() const { int64_t time = gettime_ms(); return (time > m_time ? 0 : static_cast(m_time - time)); } bool operator==(const CTimeout& other) const { return m_time == other.m_time; } bool operator!=(const CTimeout& other) const { return m_time != other.m_time; } bool operator<(const CTimeout& other) const { return m_time < other.m_time; } bool operator>(const CTimeout& other) const { return m_time > other.m_time; } bool operator>=(const CTimeout& other) const { return !(m_time < other.m_time); } bool operator<=(const CTimeout& other) const { return !(m_time > other.m_time); } private: int64_t m_time; }; } #ifdef NSROOT } #endif pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/os/unix/000077500000000000000000000000001360567320200227775ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/os/unix/os-types.h000066400000000000000000000036011360567320200247330ustar00rootroot00000000000000#pragma once #include #include #include #include #include #include #include #ifndef __STDC_FORMAT_MACROS #define __STDC_FORMAT_MACROS #endif #include typedef int net_socket_t; #define INVALID_SOCKET_VALUE (-1) typedef long LONG; typedef LONG HRESULT; #define _FILE_OFFSET_BITS 64 #define FILE_BEGIN SEEK_SET #define FILE_CURRENT SEEK_CUR #define FILE_END SEEK_END // Success codes #define S_OK 0L #define S_FALSE 1L #define FAILED(hr) (((HRESULT)(hr)) < 0) #define SUCCEEDED(hr) (((HRESULT)(hr)) >= 0) // Error codes #define ERROR_FILENAME_EXCED_RANGE 206L #define ERROR_INVALID_NAME 123L #define E_OUTOFMEMORY 0x8007000EL #define E_FAIL 0x8004005EL #if defined(__linux__) #include #define MAX_PATH PATH_MAX #elif defined(__APPLE__) || defined(__FreeBSD__) #include #include #define MAX_PATH PATH_MAX #else #define MAX_PATH 256 #endif #if defined(__APPLE__) #include /* for fpos_t */ #include #include typedef int64_t off64_t; typedef off_t __off_t; typedef off64_t __off64_t; typedef fpos_t fpos64_t; #define __stat64 stat #define stat64 stat #define statfs64 statfs #define fstat64 fstat #elif defined(__FreeBSD__) #include /* for fpos_t */ typedef int64_t off64_t; typedef off_t __off_t; typedef off64_t __off64_t; typedef fpos_t fpos64_t; #define __stat64 stat #define stat64 stat #define statfs64 statfs #define fstat64 fstat #else #define __stat64 stat64 #endif #include #define strnicmp(X,Y,N) strncasecmp(X,Y,N) typedef unsigned char byte; /* OS dependent path separator */ #ifndef PATH_SEPARATOR_CHAR #define PATH_SEPARATOR_CHAR '/' #define PATH_SEPARATOR_STRING "/" #endif pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/os/windows/000077500000000000000000000000001360567320200235065ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/os/windows/msc_inttypes.h000066400000000000000000000175051360567320200264100ustar00rootroot00000000000000// ISO C9x compliant inttypes.h for Microsoft Visual Studio // Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 // // Copyright (c) 2006 Alexander Chemeris // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // 3. The name of the author may be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // /////////////////////////////////////////////////////////////////////////////// #ifndef _MSC_VER // [ #error "Use this header only with Microsoft Visual C++ compilers!" #endif // _MSC_VER ] #ifndef _MSC_INTTYPES_H_ // [ #define _MSC_INTTYPES_H_ #include "stdint.h" // 7.8 Format conversion of integer types typedef struct { intmax_t quot; intmax_t rem; } imaxdiv_t; // 7.8.1 Macros for format specifiers #if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198 // The fprintf macros for signed integers are: #define PRId8 "d" #define PRIi8 "i" #define PRIdLEAST8 "d" #define PRIiLEAST8 "i" #define PRIdFAST8 "d" #define PRIiFAST8 "i" #define PRId16 "hd" #define PRIi16 "hi" #define PRIdLEAST16 "hd" #define PRIiLEAST16 "hi" #define PRIdFAST16 "hd" #define PRIiFAST16 "hi" #define PRId32 "I32d" #define PRIi32 "I32i" #define PRIdLEAST32 "I32d" #define PRIiLEAST32 "I32i" #define PRIdFAST32 "I32d" #define PRIiFAST32 "I32i" #define PRId64 "I64d" #define PRIi64 "I64i" #define PRIdLEAST64 "I64d" #define PRIiLEAST64 "I64i" #define PRIdFAST64 "I64d" #define PRIiFAST64 "I64i" #define PRIdMAX "I64d" #define PRIiMAX "I64i" #define PRIdPTR "Id" #define PRIiPTR "Ii" // The fprintf macros for unsigned integers are: #define PRIo8 "o" #define PRIu8 "u" #define PRIx8 "x" #define PRIX8 "X" #define PRIoLEAST8 "o" #define PRIuLEAST8 "u" #define PRIxLEAST8 "x" #define PRIXLEAST8 "X" #define PRIoFAST8 "o" #define PRIuFAST8 "u" #define PRIxFAST8 "x" #define PRIXFAST8 "X" #define PRIo16 "ho" #define PRIu16 "hu" #define PRIx16 "hx" #define PRIX16 "hX" #define PRIoLEAST16 "ho" #define PRIuLEAST16 "hu" #define PRIxLEAST16 "hx" #define PRIXLEAST16 "hX" #define PRIoFAST16 "ho" #define PRIuFAST16 "hu" #define PRIxFAST16 "hx" #define PRIXFAST16 "hX" #define PRIo32 "I32o" #define PRIu32 "I32u" #define PRIx32 "I32x" #define PRIX32 "I32X" #define PRIoLEAST32 "I32o" #define PRIuLEAST32 "I32u" #define PRIxLEAST32 "I32x" #define PRIXLEAST32 "I32X" #define PRIoFAST32 "I32o" #define PRIuFAST32 "I32u" #define PRIxFAST32 "I32x" #define PRIXFAST32 "I32X" #define PRIo64 "I64o" #define PRIu64 "I64u" #define PRIx64 "I64x" #define PRIX64 "I64X" #define PRIoLEAST64 "I64o" #define PRIuLEAST64 "I64u" #define PRIxLEAST64 "I64x" #define PRIXLEAST64 "I64X" #define PRIoFAST64 "I64o" #define PRIuFAST64 "I64u" #define PRIxFAST64 "I64x" #define PRIXFAST64 "I64X" #define PRIoMAX "I64o" #define PRIuMAX "I64u" #define PRIxMAX "I64x" #define PRIXMAX "I64X" #define PRIoPTR "Io" #define PRIuPTR "Iu" #define PRIxPTR "Ix" #define PRIXPTR "IX" #define PRIdS "Id" #define PRIuS "Iu" // The fscanf macros for signed integers are: #define SCNd8 "d" #define SCNi8 "i" #define SCNdLEAST8 "d" #define SCNiLEAST8 "i" #define SCNdFAST8 "d" #define SCNiFAST8 "i" #define SCNd16 "hd" #define SCNi16 "hi" #define SCNdLEAST16 "hd" #define SCNiLEAST16 "hi" #define SCNdFAST16 "hd" #define SCNiFAST16 "hi" #define SCNd32 "ld" #define SCNi32 "li" #define SCNdLEAST32 "ld" #define SCNiLEAST32 "li" #define SCNdFAST32 "ld" #define SCNiFAST32 "li" #define SCNd64 "I64d" #define SCNi64 "I64i" #define SCNdLEAST64 "I64d" #define SCNiLEAST64 "I64i" #define SCNdFAST64 "I64d" #define SCNiFAST64 "I64i" #define SCNdMAX "I64d" #define SCNiMAX "I64i" #ifdef _WIN64 // [ # define SCNdPTR "I64d" # define SCNiPTR "I64i" #else // _WIN64 ][ # define SCNdPTR "ld" # define SCNiPTR "li" #endif // _WIN64 ] // The fscanf macros for unsigned integers are: #define SCNo8 "o" #define SCNu8 "u" #define SCNx8 "x" #define SCNX8 "X" #define SCNoLEAST8 "o" #define SCNuLEAST8 "u" #define SCNxLEAST8 "x" #define SCNXLEAST8 "X" #define SCNoFAST8 "o" #define SCNuFAST8 "u" #define SCNxFAST8 "x" #define SCNXFAST8 "X" #define SCNo16 "ho" #define SCNu16 "hu" #define SCNx16 "hx" #define SCNX16 "hX" #define SCNoLEAST16 "ho" #define SCNuLEAST16 "hu" #define SCNxLEAST16 "hx" #define SCNXLEAST16 "hX" #define SCNoFAST16 "ho" #define SCNuFAST16 "hu" #define SCNxFAST16 "hx" #define SCNXFAST16 "hX" #define SCNo32 "lo" #define SCNu32 "lu" #define SCNx32 "lx" #define SCNX32 "lX" #define SCNoLEAST32 "lo" #define SCNuLEAST32 "lu" #define SCNxLEAST32 "lx" #define SCNXLEAST32 "lX" #define SCNoFAST32 "lo" #define SCNuFAST32 "lu" #define SCNxFAST32 "lx" #define SCNXFAST32 "lX" #define SCNo64 "I64o" #define SCNu64 "I64u" #define SCNx64 "I64x" #define SCNX64 "I64X" #define SCNoLEAST64 "I64o" #define SCNuLEAST64 "I64u" #define SCNxLEAST64 "I64x" #define SCNXLEAST64 "I64X" #define SCNoFAST64 "I64o" #define SCNuFAST64 "I64u" #define SCNxFAST64 "I64x" #define SCNXFAST64 "I64X" #define SCNoMAX "I64o" #define SCNuMAX "I64u" #define SCNxMAX "I64x" #define SCNXMAX "I64X" #ifdef _WIN64 // [ # define SCNoPTR "I64o" # define SCNuPTR "I64u" # define SCNxPTR "I64x" # define SCNXPTR "I64X" #else // _WIN64 ][ # define SCNoPTR "lo" # define SCNuPTR "lu" # define SCNxPTR "lx" # define SCNXPTR "lX" #endif // _WIN64 ] #endif // __STDC_FORMAT_MACROS ] // 7.8.2 Functions for greatest-width integer types // 7.8.2.1 The imaxabs function #define imaxabs _abs64 // 7.8.2.2 The imaxdiv function // This is modified version of div() function from Microsoft's div.c found // in %MSVC.NET%\crt\src\div.c #ifdef STATIC_IMAXDIV // [ static #else // STATIC_IMAXDIV ][ _inline #endif // STATIC_IMAXDIV ] imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) { imaxdiv_t result; result.quot = numer / denom; result.rem = numer % denom; if (numer < 0 && result.rem > 0) { // did division wrong; must fix up ++result.quot; result.rem -= denom; } return result; } // 7.8.2.3 The strtoimax and strtoumax functions #define strtoimax _strtoi64 #define strtoumax _strtoui64 // 7.8.2.4 The wcstoimax and wcstoumax functions #define wcstoimax _wcstoi64 #define wcstoumax _wcstoui64 #endif // _MSC_INTTYPES_H_ ] pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/os/windows/os-types.h000066400000000000000000000032421360567320200254430ustar00rootroot00000000000000#pragma once #if !defined(__WINDOWS__) #define __WINDOWS__ #endif /* Enable LEAN_AND_MEAN support */ #define WIN32_LEAN_AND_MEAN /* Don't define min() and max() to prevent a clash with std::min() and std::max */ #ifndef NOMINMAX #define NOMINMAX #endif /* Disable warning C4005: '_WINSOCKAPI_' : macro redefinition */ #pragma warning(disable:4005) #include #pragma warning(default:4005) #include #include #include #include #include #include #include #include #include #ifndef __STDC_FORMAT_MACROS #define __STDC_FORMAT_MACROS #endif /* prevent inclusion of wingdi.h */ #define NOGDI typedef SOCKET net_socket_t; #define INVALID_SOCKET_VALUE INVALID_SOCKET /* OS dependent path separator */ #ifndef PATH_SEPARATOR_CHAR #define PATH_SEPARATOR_CHAR '\\' #define PATH_SEPARATOR_STRING "\\" #endif #ifndef _SSIZE_T_DEFINED #ifdef _WIN64 typedef __int64 ssize_t; #else typedef _W64 int ssize_t; #endif #define _SSIZE_T_DEFINED #endif __inline int usleep(unsigned int usec) { Sleep((DWORD)(usec / 1000)); return 0; } __inline unsigned int sleep(unsigned int sec) { Sleep((DWORD)(sec * 1000)); return 0; } /* Using MS Visual C++ compilers */ #if defined(_MSC_VER) #if (_MSC_VER < 1800) #include "msc_inttypes.h" #else #include #endif struct timezone { int tz_minuteswest; int tz_dsttime; }; /* String to 64-bit int */ #if (_MSC_VER < 1800) #define atoll(S) _atoi64(S) #endif /* Prevent deprecation warnings */ #if (_MSC_VER < 1900) #define snprintf _snprintf #endif #define strnicmp _strnicmp #else #include #endif /* _MSC_VER */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/os/windows/winpthreads.c000066400000000000000000000577031360567320200262160ustar00rootroot00000000000000/* * Posix Threads library for Microsoft Windows * * Use at own risk, there is no implied warranty to this code. * It uses undocumented features of Microsoft Windows that can change * at any time in the future. * * (C) 2010 Lockless Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Lockless Inc. nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AN * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Version 1.0.1 Released 2 Feb 2012 * Fixes pthread_barrier_destroy() to wait for threads to exit the barrier. */ #include "winpthreads.h" #include #include #include #include typedef struct _pthread_cleanup _pthread_cleanup; struct _pthread_cleanup { void (*func)(void *); void *arg; _pthread_cleanup *next; }; struct _pthread_v { void *ret_arg; void *(* func)(void *); _pthread_cleanup *clean; HANDLE h; int cancelled; unsigned p_state; unsigned keymax; void **keyval; jmp_buf jb; }; volatile long _pthread_cancelling; int _pthread_concur; /* Will default to zero as needed */ pthread_once_t _pthread_tls_once; DWORD _pthread_tls; /* Note initializer is zero, so this works */ pthread_rwlock_t _pthread_key_lock; unsigned _pthread_key_max; unsigned _pthread_key_sch; void (**_pthread_key_dest)(void *); #define pthread_cleanup_push(F, A)\ {\ const _pthread_cleanup _pthread_cup = {(F), (A), pthread_self()->clean};\ _ReadWriteBarrier();\ pthread_self()->clean = (_pthread_cleanup *) &_pthread_cup;\ _ReadWriteBarrier() /* Note that if async cancelling is used, then there is a race here */ #define pthread_cleanup_pop(E)\ (pthread_self()->clean = _pthread_cup.next, (E ? _pthread_cup.func(_pthread_cup.arg) : 0));} static void _pthread_once_cleanup(pthread_once_t *o) { *o = 0; } int pthread_once(pthread_once_t *o, void (*func)(void)) { long state = *o; _ReadWriteBarrier(); while (state != 1) { if (!state) { if (!_InterlockedCompareExchange(o, 2, 0)) { /* Success */ pthread_cleanup_push((void(*)(void*))_pthread_once_cleanup, o); func(); pthread_cleanup_pop(0); /* Mark as done */ *o = 1; return 0; } } YieldProcessor(); _ReadWriteBarrier(); state = *o; } /* Done */ return 0; } static int _pthread_once_raw(pthread_once_t *o, void (*func)(void)) { long state = *o; _ReadWriteBarrier(); while (state != 1) { if (!state) { if (!_InterlockedCompareExchange(o, 2, 0)) { /* Success */ func(); /* Mark as done */ *o = 1; return 0; } } YieldProcessor(); _ReadWriteBarrier(); state = *o; } /* Done */ return 0; } int pthread_mutex_lock(pthread_mutex_t *m) { EnterCriticalSection(m); return 0; } int pthread_mutex_unlock(pthread_mutex_t *m) { LeaveCriticalSection(m); return 0; } int pthread_mutex_trylock(pthread_mutex_t *m) { return TryEnterCriticalSection(m) ? 0 : EBUSY; } int pthread_mutex_init(pthread_mutex_t *m, pthread_mutexattr_t *a) { (void) a; InitializeCriticalSection(m); return 0; } int pthread_mutex_destroy(pthread_mutex_t *m) { DeleteCriticalSection(m); return 0; } int pthread_equal(pthread_t t1, pthread_t t2) { return t1 == t2; } int pthread_rwlock_init(pthread_rwlock_t *l, pthread_rwlockattr_t *a) { (void) a; InitializeSRWLock(l); return 0; } int pthread_rwlock_destroy(pthread_rwlock_t *l) { (void) *l; return 0; } int pthread_rwlock_rdlock(pthread_rwlock_t *l) { pthread_testcancel(); AcquireSRWLockShared(l); return 0; } int pthread_rwlock_wrlock(pthread_rwlock_t *l) { pthread_testcancel(); AcquireSRWLockExclusive(l); return 0; } int pthread_rwlock_unlock(pthread_rwlock_t *l) { void *state = *(void **)l; if (state == (void *)1) { /* Known to be an exclusive lock */ ReleaseSRWLockExclusive(l); } else { /* A shared unlock will work */ ReleaseSRWLockShared(l); } return 0; } int pthread_rwlock_tryrdlock(pthread_rwlock_t *l) { /* Get the current state of the lock */ void *state = *(void **)l; if (!state) { /* Unlocked to locked */ if (!_InterlockedCompareExchangePointer((void *volatile *)l, (void *)0x11, NULL)) return 0; return EBUSY; } /* A single writer exists */ if (state == (void *)1) return EBUSY; /* Multiple writers exist? */ if ((uintptr_t)state & 14) return EBUSY; if (_InterlockedCompareExchangePointer((void *volatile *)l, (void *)((uintptr_t)state + 16), state) == state) return 0; return EBUSY; } int pthread_rwlock_trywrlock(pthread_rwlock_t *l) { /* Try to grab lock if it has no users */ if (!_InterlockedCompareExchangePointer((void *volatile *)l, (void *)1, NULL)) return 0; return EBUSY; } void pthread_tls_init(void) { _pthread_tls = TlsAlloc(); /* Cannot continue if out of indexes */ if (_pthread_tls == TLS_OUT_OF_INDEXES) abort(); } static void _pthread_cleanup_dest(pthread_t t) { unsigned i, j; for (j = 0; j < PTHREAD_DESTRUCTOR_ITERATIONS; j++) { int flag = 0; for (i = 0; i < t->keymax; i++) { void *val = t->keyval[i]; if (val) { pthread_rwlock_rdlock(&_pthread_key_lock); if ((uintptr_t) _pthread_key_dest[i] > 1) { /* Call destructor */ t->keyval[i] = NULL; _pthread_key_dest[i](val); flag = 1; } pthread_rwlock_unlock(&_pthread_key_lock); } } /* Nothing to do? */ if (!flag) return; } } pthread_t pthread_self(void) { pthread_t t; _pthread_once_raw(&_pthread_tls_once, pthread_tls_init); t = (struct _pthread_v*)TlsGetValue(_pthread_tls); /* Main thread? */ if (!t) { t = (struct _pthread_v*)malloc(sizeof(struct _pthread_v)); /* If cannot initialize main thread, then the only thing we can do is abort */ if (!t) abort(); t->ret_arg = NULL; t->func = NULL; t->clean = NULL; t->cancelled = 0; t->p_state = PTHREAD_DEFAULT_ATTR; t->keymax = 0; t->keyval = NULL; t->h = GetCurrentThread(); /* Save for later */ TlsSetValue(_pthread_tls, t); if (setjmp(t->jb)) { /* Make sure we free ourselves if we are detached */ if (!t->h) free(t); /* Time to die */ _endthreadex(0); } } return t; } static unsigned long long _pthread_time_in_ms(void) { struct __timeb64 tb; _ftime64(&tb); return tb.time * 1000 + tb.millitm; } static unsigned long long _pthread_time_in_ms_from_timespec(const struct timespec *ts) { unsigned long long t = ts->tv_sec * 1000; t += ts->tv_nsec / 1000000; return t; } static unsigned long long _pthread_rel_time_in_ms(const struct timespec *ts) { unsigned long long t1 = _pthread_time_in_ms_from_timespec(ts); unsigned long long t2 = _pthread_time_in_ms(); /* Prevent underflow */ if (t1 < t2) return 0; return t1 - t2; } int pthread_rwlock_timedrdlock(pthread_rwlock_t *l, const struct timespec *ts) { unsigned long long ct = _pthread_time_in_ms(); unsigned long long t = _pthread_time_in_ms_from_timespec(ts); pthread_testcancel(); /* Use a busy-loop */ while (1) { /* Try to grab lock */ if (!pthread_rwlock_tryrdlock(l)) return 0; /* Get current time */ ct = _pthread_time_in_ms(); /* Have we waited long enough? */ if (ct > t) return ETIMEDOUT; } } int pthread_rwlock_timedwrlock(pthread_rwlock_t *l, const struct timespec *ts) { unsigned long long ct = _pthread_time_in_ms(); unsigned long long t = _pthread_time_in_ms_from_timespec(ts); pthread_testcancel(); /* Use a busy-loop */ while (1) { /* Try to grab lock */ if (!pthread_rwlock_trywrlock(l)) return 0; /* Get current time */ ct = _pthread_time_in_ms(); /* Have we waited long enough? */ if (ct > t) return ETIMEDOUT; } } int pthread_get_concurrency(int *val) { *val = _pthread_concur; return 0; } int pthread_set_concurrency(int val) { _pthread_concur = val; return 0; } int pthread_exit(void *res) { pthread_t t = pthread_self(); t->ret_arg = res; _pthread_cleanup_dest(t); longjmp(t->jb, 1); } static void _pthread_invoke_cancel(void) { _pthread_cleanup *pcup; _InterlockedDecrement(&_pthread_cancelling); /* Call cancel queue */ for (pcup = pthread_self()->clean; pcup; pcup = pcup->next) { pcup->func(pcup->arg); } pthread_exit(PTHREAD_CANCELED); } void pthread_testcancel(void) { if (_pthread_cancelling) { pthread_t t = pthread_self(); if (t->cancelled && (t->p_state & PTHREAD_CANCEL_ENABLE)) { _pthread_invoke_cancel(); } } } int pthread_cancel(pthread_t t) { #if !defined(WINAPI_FAMILY) || (WINAPI_FAMILY != WINAPI_FAMILY_APP) if (t->p_state & PTHREAD_CANCEL_ASYNCHRONOUS) { /* Dangerous asynchronous cancelling */ CONTEXT ctxt; /* Already done? */ if (t->cancelled) return ESRCH; ctxt.ContextFlags = CONTEXT_CONTROL; SuspendThread(t->h); GetThreadContext(t->h, &ctxt); #ifdef _M_X64 ctxt.Rip = (uintptr_t) _pthread_invoke_cancel; #else ctxt.Eip = (uintptr_t) _pthread_invoke_cancel; #endif SetThreadContext(t->h, &ctxt); /* Also try deferred Cancelling */ t->cancelled = 1; /* Notify everyone to look */ _InterlockedIncrement(&_pthread_cancelling); ResumeThread(t->h); } else #endif { /* Safe deferred Cancelling */ t->cancelled = 1; /* Notify everyone to look */ _InterlockedIncrement(&_pthread_cancelling); } return 0; } static unsigned _pthread_get_state(pthread_attr_t *attr, unsigned flag) { return attr->p_state & flag; } static int _pthread_set_state(pthread_attr_t *attr, unsigned flag, unsigned val) { if (~flag & val) return EINVAL; attr->p_state &= ~flag; attr->p_state |= val; return 0; } int pthread_attr_init(pthread_attr_t *attr) { attr->p_state = PTHREAD_DEFAULT_ATTR; attr->stack = NULL; attr->s_size = 0; return 0; } int pthread_attr_destroy(pthread_attr_t *attr) { /* No need to do anything */ return 0; } int pthread_attr_setdetachstate(pthread_attr_t *a, int flag) { return _pthread_set_state(a, PTHREAD_CREATE_DETACHED, flag); } int pthread_attr_getdetachstate(pthread_attr_t *a, int *flag) { *flag = _pthread_get_state(a, PTHREAD_CREATE_DETACHED); return 0; } int pthread_attr_setinheritsched(pthread_attr_t *a, int flag) { return _pthread_set_state(a, PTHREAD_INHERIT_SCHED, flag); } int pthread_attr_getinheritsched(pthread_attr_t *a, int *flag) { *flag = _pthread_get_state(a, PTHREAD_INHERIT_SCHED); return 0; } int pthread_attr_setscope(pthread_attr_t *a, int flag) { return _pthread_set_state(a, PTHREAD_SCOPE_SYSTEM, flag); } int pthread_attr_getscope(pthread_attr_t *a, int *flag) { *flag = _pthread_get_state(a, PTHREAD_SCOPE_SYSTEM); return 0; } int pthread_attr_getstackaddr(pthread_attr_t *attr, void **stack) { *stack = attr->stack; return 0; } int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stack) { attr->stack = stack; return 0; } int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *size) { *size = attr->s_size; return 0; } int pthread_attr_setstacksize(pthread_attr_t *attr, size_t size) { attr->s_size = size; return 0; } #define pthread_attr_getguardsize(A, S) ENOTSUP #define pthread_attr_setgaurdsize(A, S) ENOTSUP #define pthread_attr_getschedparam(A, S) ENOTSUP #define pthread_attr_setschedparam(A, S) ENOTSUP #define pthread_attr_getschedpolicy(A, S) ENOTSUP #define pthread_attr_setschedpolicy(A, S) ENOTSUP int pthread_setcancelstate(int state, int *oldstate) { pthread_t t = pthread_self(); if ((state & PTHREAD_CANCEL_ENABLE) != state) return EINVAL; if (oldstate) *oldstate = t->p_state & PTHREAD_CANCEL_ENABLE; t->p_state &= ~PTHREAD_CANCEL_ENABLE; t->p_state |= state; return 0; } int pthread_setcanceltype(int type, int *oldtype) { pthread_t t = pthread_self(); if ((type & PTHREAD_CANCEL_ASYNCHRONOUS) != type) return EINVAL; if (oldtype) *oldtype = t->p_state & PTHREAD_CANCEL_ASYNCHRONOUS; t->p_state &= ~PTHREAD_CANCEL_ASYNCHRONOUS; t->p_state |= type; return 0; } unsigned __stdcall pthread_create_wrapper(void *args) { struct _pthread_v *tv = (struct _pthread_v*)args; _pthread_once_raw(&_pthread_tls_once, pthread_tls_init); TlsSetValue(_pthread_tls, tv); if (!setjmp(tv->jb)) { /* Call function and save return value */ tv->ret_arg = tv->func(tv->ret_arg); /* Clean up destructors */ _pthread_cleanup_dest(tv); } /* If we exit too early, then we can race with create */ while (tv->h == (HANDLE) -1) { YieldProcessor(); _ReadWriteBarrier(); } /* Make sure we free ourselves if we are detached */ if (!tv->h) free(tv); return 0; } int pthread_create(pthread_t *th, pthread_attr_t *attr, void *(* func)(void *), void *arg) { struct _pthread_v *tv = (struct _pthread_v*)malloc(sizeof(struct _pthread_v)); unsigned ssize = 0; if (!tv) return 1; *th = tv; /* Save data in pthread_t */ tv->ret_arg = arg; tv->func = func; tv->clean = NULL; tv->cancelled = 0; tv->p_state = PTHREAD_DEFAULT_ATTR; tv->keymax = 0; tv->keyval = NULL; tv->h = (HANDLE) -1; if (attr) { tv->p_state = attr->p_state; ssize = (unsigned) attr->s_size; } /* Make sure tv->h has value of -1 */ _ReadWriteBarrier(); tv->h = (HANDLE) _beginthreadex(NULL, ssize, pthread_create_wrapper, tv, 0, NULL); /* Failed */ if (!tv->h) return 1; if (tv->p_state & PTHREAD_CREATE_DETACHED) { CloseHandle(tv->h); _ReadWriteBarrier(); tv->h = 0; } return 0; } int pthread_join(pthread_t t, void **res) { struct _pthread_v *tv = t; pthread_testcancel(); WaitForSingleObject(tv->h, INFINITE); CloseHandle(tv->h); /* Obtain return value */ if (res) *res = tv->ret_arg; free(tv); return 0; } int pthread_detach(pthread_t t) { struct _pthread_v *tv = t; /* * This can't race with thread exit because * our call would be undefined if called on a dead thread. */ CloseHandle(tv->h); _ReadWriteBarrier(); tv->h = 0; return 0; } int pthread_mutexattr_init(pthread_mutexattr_t *a) { *a = 0; return 0; } int pthread_mutexattr_destroy(pthread_mutexattr_t *a) { (void) a; return 0; } int pthread_mutexattr_gettype(pthread_mutexattr_t *a, int *type) { *type = *a & 3; return 0; } int pthread_mutexattr_settype(pthread_mutexattr_t *a, int type) { if ((unsigned) type > 3) return EINVAL; *a &= ~3; *a |= type; return 0; } int pthread_mutexattr_getpshared(pthread_mutexattr_t *a, int *type) { *type = *a & 4; return 0; } int pthread_mutexattr_setpshared(pthread_mutexattr_t * a, int type) { if ((type & 4) != type) return EINVAL; *a &= ~4; *a |= type; return 0; } int pthread_mutexattr_getprotocol(pthread_mutexattr_t *a, int *type) { *type = *a & (8 + 16); return 0; } int pthread_mutexattr_setprotocol(pthread_mutexattr_t *a, int type) { if ((type & (8 + 16)) != 8 + 16) return EINVAL; *a &= ~(8 + 16); *a |= type; return 0; } int pthread_mutexattr_getprioceiling(pthread_mutexattr_t *a, int * prio) { *prio = *a / PTHREAD_PRIO_MULT; return 0; } int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *a, int prio) { *a &= (PTHREAD_PRIO_MULT - 1); *a += prio * PTHREAD_PRIO_MULT; return 0; } int pthread_mutex_timedlock(pthread_mutex_t *m, struct timespec *ts) { unsigned long long t, ct; struct _pthread_crit_t { void *debug; LONG count; LONG r_count; HANDLE owner; HANDLE sem; ULONG_PTR spin; }; /* Try to lock it without waiting */ if (!pthread_mutex_trylock(m)) return 0; ct = _pthread_time_in_ms(); t = _pthread_time_in_ms_from_timespec(ts); while (1) { /* Have we waited long enough? */ if (ct > t) return ETIMEDOUT; /* Wait on semaphore within critical section */ WaitForSingleObject(((struct _pthread_crit_t *)m)->sem, (DWORD)(t - ct)); /* Try to grab lock */ if (!pthread_mutex_trylock(m)) return 0; /* Get current time */ ct = _pthread_time_in_ms(); } } #define _PTHREAD_BARRIER_FLAG (1<<30) int pthread_barrier_destroy(pthread_barrier_t *b) { EnterCriticalSection(&b->m); while (b->total > _PTHREAD_BARRIER_FLAG) { /* Wait until everyone exits the barrier */ SleepConditionVariableCS(&b->cv, &b->m, INFINITE); } LeaveCriticalSection(&b->m); DeleteCriticalSection(&b->m); return 0; } int pthread_barrier_init(pthread_barrier_t *b, void *attr, int count) { /* Ignore attr */ (void) attr; b->count = count; b->total = 0; InitializeCriticalSection(&b->m); InitializeConditionVariable(&b->cv); return 0; } int pthread_barrier_wait(pthread_barrier_t *b) { EnterCriticalSection(&b->m); while (b->total > _PTHREAD_BARRIER_FLAG) { /* Wait until everyone exits the barrier */ SleepConditionVariableCS(&b->cv, &b->m, INFINITE); } /* Are we the first to enter? */ if (b->total == _PTHREAD_BARRIER_FLAG) b->total = 0; b->total++; if (b->total == b->count) { b->total += _PTHREAD_BARRIER_FLAG - 1; WakeAllConditionVariable(&b->cv); LeaveCriticalSection(&b->m); return 1; } else { while (b->total < _PTHREAD_BARRIER_FLAG) { /* Wait until enough threads enter the barrier */ SleepConditionVariableCS(&b->cv, &b->m, INFINITE); } b->total--; /* Get entering threads to wake up */ if (b->total == _PTHREAD_BARRIER_FLAG) WakeAllConditionVariable(&b->cv); LeaveCriticalSection(&b->m); return 0; } } int pthread_barrierattr_init(void **attr) { *attr = NULL; return 0; } int pthread_barrierattr_destroy(void **attr) { /* Ignore attr */ (void) attr; return 0; } int pthread_barrierattr_setpshared(void **attr, int s) { *attr = (void *) s; return 0; } int pthread_barrierattr_getpshared(void **attr, int *s) { *s = (int) (size_t) *attr; return 0; } int pthread_key_create(pthread_key_t *key, void (* dest)(void *)) { unsigned i; unsigned nmax; void (**d)(void *); if (!key) return EINVAL; pthread_rwlock_wrlock(&_pthread_key_lock); for (i = _pthread_key_sch; i < _pthread_key_max; i++) { if (!_pthread_key_dest[i]) { *key = i; if (dest) { _pthread_key_dest[i] = dest; } else { _pthread_key_dest[i] = (void(*)(void *))1; } pthread_rwlock_unlock(&_pthread_key_lock); return 0; } } for (i = 0; i < _pthread_key_sch; i++) { if (!_pthread_key_dest[i]) { *key = i; if (dest) { _pthread_key_dest[i] = dest; } else { _pthread_key_dest[i] = (void(*)(void *))1; } pthread_rwlock_unlock(&_pthread_key_lock); return 0; } } if (!_pthread_key_max) _pthread_key_max = 1; if (_pthread_key_max == PTHREAD_KEYS_MAX) { pthread_rwlock_unlock(&_pthread_key_lock); return ENOMEM; } nmax = _pthread_key_max * 2; if (nmax > PTHREAD_KEYS_MAX) nmax = PTHREAD_KEYS_MAX; /* No spare room anywhere */ d = (void (**)(void*))realloc(_pthread_key_dest, nmax * sizeof(*d)); if (!d) { pthread_rwlock_unlock(&_pthread_key_lock); return ENOMEM; } /* Clear new region */ memset((void *) &d[_pthread_key_max], 0, (nmax-_pthread_key_max)*sizeof(void *)); /* Use new region */ _pthread_key_dest = d; _pthread_key_sch = _pthread_key_max + 1; *key = _pthread_key_max; _pthread_key_max = nmax; if (dest) { _pthread_key_dest[*key] = dest; } else { _pthread_key_dest[*key] = (void(*)(void *))1; } pthread_rwlock_unlock(&_pthread_key_lock); return 0; } int pthread_key_delete(pthread_key_t key) { if (key > _pthread_key_max) return EINVAL; if (!_pthread_key_dest) return EINVAL; pthread_rwlock_wrlock(&_pthread_key_lock); _pthread_key_dest[key] = NULL; /* Start next search from our location */ if (_pthread_key_sch > key) _pthread_key_sch = key; pthread_rwlock_unlock(&_pthread_key_lock); return 0; } void *pthread_getspecific(pthread_key_t key) { pthread_t t = pthread_self(); if (key >= t->keymax) return NULL; return t->keyval[key]; } int pthread_setspecific(pthread_key_t key, const void *value) { pthread_t t = pthread_self(); if (key > t->keymax) { int keymax = (key + 1) * 2; void **kv = (void**)realloc(t->keyval, keymax * sizeof(void *)); if (!kv) return ENOMEM; /* Clear new region */ memset(&kv[t->keymax], 0, (keymax - t->keymax)*sizeof(void*)); t->keyval = kv; t->keymax = keymax; } t->keyval[key] = (void *) value; return 0; } int pthread_spin_init(pthread_spinlock_t *l, int pshared) { (void) pshared; *l = 0; return 0; } int pthread_spin_destroy(pthread_spinlock_t *l) { (void) l; return 0; } /* No-fair spinlock due to lack of knowledge of thread number */ int pthread_spin_lock(pthread_spinlock_t *l) { while (_InterlockedExchange(l, EBUSY)) { /* Don't lock the bus whilst waiting */ while (*l) { YieldProcessor(); /* Compiler barrier. Prevent caching of *l */ _ReadWriteBarrier(); } } return 0; } int pthread_spin_trylock(pthread_spinlock_t *l) { return _InterlockedExchange(l, EBUSY); } int pthread_spin_unlock(pthread_spinlock_t *l) { /* Compiler barrier. The store below acts with release symmantics */ _ReadWriteBarrier(); *l = 0; return 0; } int pthread_cond_init(pthread_cond_t *c, pthread_condattr_t *a) { (void) a; InitializeConditionVariable(c); return 0; } int pthread_cond_signal(pthread_cond_t *c) { WakeConditionVariable(c); return 0; } int pthread_cond_broadcast(pthread_cond_t *c) { WakeAllConditionVariable(c); return 0; } int pthread_cond_wait(pthread_cond_t *c, pthread_mutex_t *m) { pthread_testcancel(); SleepConditionVariableCS(c, m, INFINITE); return 0; } int pthread_cond_destroy(pthread_cond_t *c) { (void) c; return 0; } int pthread_cond_timedwait(pthread_cond_t *c, pthread_mutex_t *m, struct timespec *t) { unsigned long long tm = _pthread_rel_time_in_ms(t); pthread_testcancel(); if (!SleepConditionVariableCS(c, m, (DWORD)tm)) return ETIMEDOUT; /* We can have a spurious wakeup after the timeout */ if (!_pthread_rel_time_in_ms(t)) return ETIMEDOUT; return 0; } int pthread_condattr_destroy(pthread_condattr_t *a) { (void) a; return 0; } int pthread_condattr_init(pthread_condattr_t *a) { *a = 0; return 0; } int pthread_condattr_getpshared(pthread_condattr_t *a, int *s) { *s = *a; return 0; } int pthread_condattr_setpshared(pthread_condattr_t *a, int s) { *a = s; return 0; } int pthread_rwlockattr_destroy(pthread_rwlockattr_t *a) { (void) a; return 0; } int pthread_rwlockattr_init(pthread_rwlockattr_t *a) { *a = 0; return 0; } int pthread_rwlockattr_getpshared(pthread_rwlockattr_t *a, int *s) { *s = *a; return 0; } int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *a, int s) { *a = s; return 0; } pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/os/windows/winpthreads.h000066400000000000000000000240501360567320200262100ustar00rootroot00000000000000/* * Posix Threads library for Microsoft Windows * * Use at own risk, there is no implied warranty to this code. * It uses undocumented features of Microsoft Windows that can change * at any time in the future. * * (C) 2010 Lockless Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Lockless Inc. nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AN * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef WIN_PTHREADS #define WIN_PTHREADS #include #include #ifdef __cplusplus extern "C" { #endif #ifndef ETIMEDOUT #define ETIMEDOUT 110 #endif #ifndef ENOTSUP #define ENOTSUP 134 #endif #define PTHREAD_CANCEL_DISABLE 0 #define PTHREAD_CANCEL_ENABLE 0x01 #define PTHREAD_CANCEL_DEFERRED 0 #define PTHREAD_CANCEL_ASYNCHRONOUS 0x02 #define PTHREAD_CREATE_JOINABLE 0 #define PTHREAD_CREATE_DETACHED 0x04 #define PTHREAD_EXPLICT_SCHED 0 #define PTHREAD_INHERIT_SCHED 0x08 #define PTHREAD_SCOPE_PROCESS 0 #define PTHREAD_SCOPE_SYSTEM 0x10 #define PTHREAD_DEFAULT_ATTR (PTHREAD_CANCEL_ENABLE) #define PTHREAD_CANCELED ((void *) 0xDEADBEEF) #define PTHREAD_ONCE_INIT 0 #define PTHREAD_MUTEX_INITIALIZER {(void*)-1,-1,0,0,0,0} #define PTHREAD_RWLOCK_INITIALIZER {0} #define PTHREAD_COND_INITIALIZER {0} #define PTHREAD_BARRIER_INITIALIZER \ {0,0,PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER} #define PTHREAD_SPINLOCK_INITIALIZER 0 #define PTHREAD_DESTRUCTOR_ITERATIONS 256 #define PTHREAD_KEYS_MAX (1<<20) #define PTHREAD_MUTEX_NORMAL 0 #define PTHREAD_MUTEX_ERRORCHECK 1 #define PTHREAD_MUTEX_RECURSIVE 2 #define PTHREAD_MUTEX_DEFAULT 3 #define PTHREAD_MUTEX_SHARED 4 #define PTHREAD_MUTEX_PRIVATE 0 #define PTHREAD_PRIO_NONE 0 #define PTHREAD_PRIO_INHERIT 8 #define PTHREAD_PRIO_PROTECT 16 #define PTHREAD_PRIO_MULT 32 #define PTHREAD_PROCESS_SHARED 0 #define PTHREAD_PROCESS_PRIVATE 1 #define PTHREAD_BARRIER_SERIAL_THREAD 1 /* Windows doesn't have this, so declare it ourselves. */ #if (_MSC_VER < 1900) struct timespec { /* long long in windows is the same as long in unix for 64bit */ long long tv_sec; long long tv_nsec; }; #else #include #endif struct _pthread_v; typedef struct _pthread_v *pthread_t; struct pthread_barrier_t { int count; int total; CRITICAL_SECTION m; CONDITION_VARIABLE cv; }; typedef struct pthread_barrier_t pthread_barrier_t; struct pthread_attr_t { unsigned p_state; void *stack; size_t s_size; }; typedef struct pthread_attr_t pthread_attr_t; typedef long pthread_once_t; typedef unsigned pthread_mutexattr_t; typedef SRWLOCK pthread_rwlock_t; typedef CRITICAL_SECTION pthread_mutex_t; typedef unsigned pthread_key_t; typedef void *pthread_barrierattr_t; typedef long pthread_spinlock_t; typedef int pthread_condattr_t; typedef CONDITION_VARIABLE pthread_cond_t; typedef int pthread_rwlockattr_t; extern pthread_t pthread_self(void); extern int pthread_once(pthread_once_t *o, void(*func)(void)); extern int pthread_mutex_lock(pthread_mutex_t *m); extern int pthread_mutex_unlock(pthread_mutex_t *m); extern int pthread_mutex_trylock(pthread_mutex_t *m); extern int pthread_mutex_init(pthread_mutex_t *m, pthread_mutexattr_t *a); extern int pthread_mutex_destroy(pthread_mutex_t *m); #define pthread_mutex_getprioceiling(M, P) ENOTSUP #define pthread_mutex_setprioceiling(M, P) ENOTSUP extern int pthread_equal(pthread_t t1, pthread_t t2); extern int pthread_rwlock_init(pthread_rwlock_t *l, pthread_rwlockattr_t *a); extern int pthread_rwlock_destroy(pthread_rwlock_t *l); extern int pthread_rwlock_rdlock(pthread_rwlock_t *l); extern int pthread_rwlock_wrlock(pthread_rwlock_t *l); extern int pthread_rwlock_unlock(pthread_rwlock_t *l); extern int pthread_rwlock_tryrdlock(pthread_rwlock_t *l); extern int pthread_rwlock_trywrlock(pthread_rwlock_t *l); extern void pthread_tls_init(void); extern int pthread_rwlock_timedrdlock(pthread_rwlock_t *l, const struct timespec *ts); extern int pthread_rwlock_timedwrlock(pthread_rwlock_t *l, const struct timespec *ts); extern int pthread_get_concurrency(int *val); extern int pthread_set_concurrency(int val); #define pthread_getschedparam(T, P, S) ENOTSUP #define pthread_setschedparam(T, P, S) ENOTSUP #define pthread_getcpuclockid(T, C) ENOTSUP extern int pthread_exit(void *res); extern void pthread_testcancel(void); extern int pthread_cancel(pthread_t t); extern int pthread_attr_init(pthread_attr_t *attr); extern int pthread_attr_destroy(pthread_attr_t *attr); extern int pthread_attr_setdetachstate(pthread_attr_t *a, int flag); extern int pthread_attr_getdetachstate(pthread_attr_t *a, int *flag); extern int pthread_attr_setinheritsched(pthread_attr_t *a, int flag); extern int pthread_attr_getinheritsched(pthread_attr_t *a, int *flag); extern int pthread_attr_setscope(pthread_attr_t *a, int flag); extern int pthread_attr_getscope(pthread_attr_t *a, int *flag); extern int pthread_attr_getstackaddr(pthread_attr_t *attr, void **stack); extern int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stack); extern int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *size); extern int pthread_attr_setstacksize(pthread_attr_t *attr, size_t size); #define pthread_attr_getguardsize(A, S) ENOTSUP #define pthread_attr_setgaurdsize(A, S) ENOTSUP #define pthread_attr_getschedparam(A, S) ENOTSUP #define pthread_attr_setschedparam(A, S) ENOTSUP #define pthread_attr_getschedpolicy(A, S) ENOTSUP #define pthread_attr_setschedpolicy(A, S) ENOTSUP extern int pthread_setcancelstate(int state, int *oldstate); extern int pthread_setcanceltype(int type, int *oldtype); extern unsigned __stdcall pthread_create_wrapper(void *args); extern int pthread_create(pthread_t *th, pthread_attr_t *attr, void *(*func)(void *), void *arg); extern int pthread_join(pthread_t t, void **res); extern int pthread_detach(pthread_t t); extern int pthread_mutexattr_init(pthread_mutexattr_t *a); extern int pthread_mutexattr_destroy(pthread_mutexattr_t *a); extern int pthread_mutexattr_gettype(pthread_mutexattr_t *a, int *type); extern int pthread_mutexattr_settype(pthread_mutexattr_t *a, int type); extern int pthread_mutexattr_getpshared(pthread_mutexattr_t *a, int *type); extern int pthread_mutexattr_setpshared(pthread_mutexattr_t * a, int type); extern int pthread_mutexattr_getprotocol(pthread_mutexattr_t *a, int *type); extern int pthread_mutexattr_setprotocol(pthread_mutexattr_t *a, int type); extern int pthread_mutexattr_getprioceiling(pthread_mutexattr_t *a, int * prio); extern int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *a, int prio); extern int pthread_mutex_timedlock(pthread_mutex_t *m, struct timespec *ts); extern int pthread_barrier_destroy(pthread_barrier_t *b); extern int pthread_barrier_init(pthread_barrier_t *b, void *attr, int count); extern int pthread_barrier_wait(pthread_barrier_t *b); extern int pthread_barrierattr_init(void **attr); extern int pthread_barrierattr_destroy(void **attr); extern int pthread_barrierattr_setpshared(void **attr, int s); extern int pthread_barrierattr_getpshared(void **attr, int *s); extern int pthread_key_create(pthread_key_t *key, void(*dest)(void *)); extern int pthread_key_delete(pthread_key_t key); extern void *pthread_getspecific(pthread_key_t key); extern int pthread_setspecific(pthread_key_t key, const void *value); extern int pthread_spin_init(pthread_spinlock_t *l, int pshared); extern int pthread_spin_destroy(pthread_spinlock_t *l); extern int pthread_spin_lock(pthread_spinlock_t *l); extern int pthread_spin_trylock(pthread_spinlock_t *l); extern int pthread_spin_unlock(pthread_spinlock_t *l); extern int pthread_cond_init(pthread_cond_t *c, pthread_condattr_t *a); extern int pthread_cond_signal(pthread_cond_t *c); extern int pthread_cond_broadcast(pthread_cond_t *c); extern int pthread_cond_wait(pthread_cond_t *c, pthread_mutex_t *m); extern int pthread_cond_destroy(pthread_cond_t *c); extern int pthread_cond_timedwait(pthread_cond_t *c, pthread_mutex_t *m, struct timespec *t); extern int pthread_condattr_destroy(pthread_condattr_t *a); #define pthread_condattr_getclock(A, C) ENOTSUP #define pthread_condattr_setclock(A, C) ENOTSUP extern int pthread_condattr_init(pthread_condattr_t *a); extern int pthread_condattr_getpshared(pthread_condattr_t *a, int *s); extern int pthread_condattr_setpshared(pthread_condattr_t *a, int s); extern int pthread_rwlockattr_destroy(pthread_rwlockattr_t *a); extern int pthread_rwlockattr_init(pthread_rwlockattr_t *a); extern int pthread_rwlockattr_getpshared(pthread_rwlockattr_t *a, int *s); extern int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *a, int s); /* No fork() in windows - so ignore this */ #define pthread_atfork(F1,F2,F3) 0 /* Windows has rudimentary signals support */ #define pthread_kill(T, S) 0 #define pthread_sigmask(H, S1, S2) 0 #ifdef __cplusplus } #endif #endif /* WIN_PTHREADS */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/sajson.h000066400000000000000000001211421360567320200230420ustar00rootroot00000000000000/* * Copyright (c) 2012, 2013, 2014 Chad Austin * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, copy, * modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #pragma once #include #include #include #include #include #include #include #include #include #include #include // for error messages. kill someday? #if defined(__GNUC__) || defined(__clang__) #define SAJSON_LIKELY(x) __builtin_expect(!!(x), 1) #define SAJSON_UNLIKELY(x) __builtin_expect(!!(x), 0) #else #define SAJSON_LIKELY(x) x #define SAJSON_UNLIKELY(x) x #endif namespace sajson { enum type { TYPE_INTEGER = 0, TYPE_DOUBLE = 1, TYPE_NULL = 2, TYPE_FALSE = 3, TYPE_TRUE = 4, TYPE_STRING = 5, TYPE_ARRAY = 6, TYPE_OBJECT = 7, }; inline std::ostream& operator<<(std::ostream& os, type t) { switch (t) { case TYPE_INTEGER: return os << ""; case TYPE_DOUBLE: return os << ""; case TYPE_NULL: return os << ""; case TYPE_FALSE: return os << ""; case TYPE_TRUE: return os << ""; case TYPE_STRING: return os << ""; case TYPE_ARRAY: return os << ""; case TYPE_OBJECT: return os << ""; default: return os << "> TYPE_BITS; static const size_t ROOT_MARKER = size_t(-1) & VALUE_MASK; inline type get_element_type(size_t s) { return static_cast((s >> TYPE_SHIFT) & TYPE_MASK); } inline size_t get_element_value(size_t s) { return s & VALUE_MASK; } inline size_t make_element(type t, size_t value) { //assert(value & VALUE_MASK == 0); //value &= VALUE_MASK; return value | (static_cast(t) << TYPE_SHIFT); } class string { public: string(const char* text, size_t length) : text(text) , _length(length) {} const char* data() const { return text; } size_t length() const { return _length; } std::string as_string() const { return std::string(text, text + _length); } private: const char* const text; const size_t _length; string(); /*=delete*/ }; class literal : public string { public: explicit literal(const char* text) : string(text, strlen(text)) {} }; struct object_key_record { size_t key_start; size_t key_end; size_t value; }; struct object_key_comparator { object_key_comparator(const char* object_data) : data(object_data) { } bool operator()(const object_key_record& lhs, const string& rhs) const { const size_t lhs_length = lhs.key_end - lhs.key_start; const size_t rhs_length = rhs.length(); if (lhs_length < rhs_length) { return true; } else if (lhs_length > rhs_length) { return false; } return memcmp(data + lhs.key_start, rhs.data(), lhs_length) < 0; } bool operator()(const string& lhs, const object_key_record& rhs) const { return !(*this)(rhs, lhs); } bool operator()(const object_key_record& lhs, const object_key_record& rhs) { const size_t lhs_length = lhs.key_end - lhs.key_start; const size_t rhs_length = rhs.key_end - rhs.key_start; if (lhs_length < rhs_length) { return true; } else if (lhs_length > rhs_length) { return false; } return memcmp(data + lhs.key_start, data + rhs.key_start, lhs_length) < 0; } const char* data; }; class refcount { public: refcount() : pn(new size_t(1)) {} refcount(const refcount& rc) : pn(rc.pn) { ++*pn; } ~refcount() { if (--*pn == 0) { delete pn; } } size_t count() const { return *pn; } private: size_t* pn; refcount& operator=(const refcount&); }; class mutable_string_view { public: mutable_string_view() : length(0) , data(0) {} mutable_string_view(const literal& s) : length(s.length()) { data = new char[length]; memcpy(data, s.data(), length); } mutable_string_view(const string& s) : length(s.length()) { data = new char[length]; memcpy(data, s.data(), length); } ~mutable_string_view() { if (uses.count() == 1) { delete[] data; } } size_t get_length() const { return length; } char* get_data() const { return data; } private: refcount uses; size_t length; char* data; }; union integer_storage { int i; size_t u; }; // TODO: reinstate with c++03 implementation //static_assert(sizeof(integer_storage) == sizeof(size_t), "integer_storage must have same size as one structure slot"); union double_storage { enum { word_length = sizeof(double) / sizeof(size_t) }; #if defined(_M_IX86) || defined(__i386__) || defined(_X86_) static double load(const size_t* location) { return *reinterpret_cast(location); } static void store(size_t* location, double value) { *reinterpret_cast(location) = value; } #else static double load(const size_t* location) { double_storage s; for (unsigned i = 0; i < double_storage::word_length; ++i) { s.u[i] = location[i]; } return s.d; } static void store(size_t* location, double value) { double_storage ns; ns.d = value; for (int i = 0; i < ns.word_length; ++i) { location[i] = ns.u[i]; } } double d; size_t u[word_length]; #endif }; // TODO: reinstate with c++03 implementation //static_assert(sizeof(double_storage) == sizeof(double), "double_storage should have same size as double"); class value { public: explicit value(type value_type, const size_t* payload, const char* text) : value_type(value_type) , payload(payload) , text(text) {} type get_type() const { return value_type; } // valid iff get_type() is TYPE_ARRAY or TYPE_OBJECT size_t get_length() const { assert_type_2(TYPE_ARRAY, TYPE_OBJECT); return payload[0]; } // valid iff get_type() is TYPE_ARRAY value get_array_element(size_t index) const { assert_type(TYPE_ARRAY); size_t element = payload[1 + index]; return value(get_element_type(element), payload + get_element_value(element), text); } // valid iff get_type() is TYPE_OBJECT string get_object_key(size_t index) const { assert_type(TYPE_OBJECT); const size_t* s = payload + 1 + index * 3; return string(text + s[0], s[1] - s[0]); } // valid iff get_type() is TYPE_OBJECT value get_object_value(size_t index) const { assert_type(TYPE_OBJECT); size_t element = payload[3 + index * 3]; return value(get_element_type(element), payload + get_element_value(element), text); } // valid iff get_type() is TYPE_OBJECT value get_value_of_key(const string& key) const { assert_type(TYPE_OBJECT); size_t i = find_object_key(key); assert_in_bounds(i); return get_object_value(i); } // valid iff get_type() is TYPE_OBJECT // return get_length() if there is no such key size_t find_object_key(const string& key) const { assert_type(TYPE_OBJECT); const object_key_record* start = reinterpret_cast(payload + 1); const object_key_record* end = start + get_length(); const object_key_record* i = std::lower_bound(start, end, key, object_key_comparator(text)); return (i != end && (i->key_end - i->key_start) == key.length() && memcmp(key.data(), text + i->key_start, key.length()) == 0)? i - start : get_length(); } // valid iff get_type() is TYPE_INTEGER int get_integer_value() const { assert_type(TYPE_INTEGER); integer_storage s; s.u = payload[0]; return s.i; } // valid iff get_type() is TYPE_DOUBLE double get_double_value() const { assert_type(TYPE_DOUBLE); return double_storage::load(payload); } // valid iff get_type() is TYPE_INTEGER or TYPE_DOUBLE double get_number_value() const { assert_type_2(TYPE_INTEGER, TYPE_DOUBLE); if (get_type() == TYPE_INTEGER) { return get_integer_value(); } else { return get_double_value(); } } // valid iff get_type() is TYPE_STRING size_t get_string_length() const { assert_type(TYPE_STRING); return payload[1] - payload[0]; } // valid iff get_type() is TYPE_STRING std::string as_string() const { assert_type(TYPE_STRING); return std::string(text + payload[0], text + payload[1]); } private: void assert_type(type expected) const { assert(expected == get_type()); } void assert_type_2(type e1, type e2) const { assert(e1 == get_type() || e2 == get_type()); } void assert_in_bounds(size_t i) const { assert(i < get_length()); } const type value_type; const size_t* const payload; const char* const text; }; class document { public: explicit document(mutable_string_view& input, const size_t* structure, type root_type, const size_t* root, size_t error_line, size_t error_column, const std::string& error_message) : input(input) , structure(structure) , root_type(root_type) , root(root) , error_line(error_line) , error_column(error_column) , error_message(error_message) {} #if __cplusplus >= 201103L document(const document&) = delete; void operator=(const document&) = delete; document(document&& rhs) : uses(rhs.uses) , input(rhs.input) , structure(rhs.structure) , root_type(rhs.root_type) , root(rhs.root) , error_line(rhs.error_line) , error_column(rhs.error_column) , error_message(rhs.error_message) {} #else private: void operator=(const document& rhs); public: document(const document& rhs) : uses(rhs.uses) , input(rhs.input) , structure(rhs.structure) , root_type(rhs.root_type) , root(rhs.root) , error_line(rhs.error_line) , error_column(rhs.error_column) , error_message(rhs.error_message) {} #endif ~document() { if (uses.count() == 1) { delete[] structure; } } bool is_valid() const { return !!structure; } value get_root() const { return value(root_type, root, input.get_data()); } size_t get_error_line() const { return error_line; } size_t get_error_column() const { return error_column; } std::string get_error_message() const { return error_message; } private: refcount uses; mutable_string_view input; const size_t* const structure; const type root_type; const size_t* const root; const size_t error_line; const size_t error_column; const std::string error_message; }; class parser { public: parser(const mutable_string_view& msv, size_t* structure) : input(msv) , input_end(input.get_data() + input.get_length()) , structure(structure) , p(input.get_data()) , temp(structure) , root_type(TYPE_NULL) , out(structure + input.get_length()) , error_line(0) , error_column(0) {} document get_document() { if (parse()) { return document(input, structure, root_type, out, 0, 0, std::string()); } else { delete[] structure; return document(input, 0, TYPE_NULL, 0, error_line, error_column, error_message); } } private: struct error_result { operator bool() const { return false; } }; struct parse_result { parse_result(error_result) : success(false) , value_type(TYPE_NULL) {} parse_result(type t) : success(true) , value_type(t) {} bool operator!() const { return !success; } bool success; type value_type; }; bool at_eof() { return p == input_end; } char peek_structure() { for (;;) { if (p == input_end) { // 0 is never legal as a structural character in json text so treat it as eof return 0; } switch (*p) { case 0x20: case 0x09: case 0x0A: case 0x0D: ++p; continue; default: return *p; } } } error_result error(const char* format, ...) { error_line = 1; error_column = 1; char* c = input.get_data(); while (c < p) { if (*c == '\r') { if (c + 1 < p && c[1] == '\n') { ++error_line; error_column = 1; ++c; } else { ++error_line; error_column = 1; } } else if (*c == '\n') { ++error_line; error_column = 1; } else { // TODO: count UTF-8 characters ++error_column; } ++c; } char buf[1024]; buf[1023] = 0; va_list ap; va_start(ap, format); vsnprintf(buf, 1023, format, ap); va_end(ap); error_message = buf; return error_result(); } bool parse() { char c = peek_structure(); if (c == 0) { return error("no root element"); } type current_structure_type; if (c == '[') { current_structure_type = TYPE_ARRAY; } else if (c == '{') { current_structure_type = TYPE_OBJECT; } else { return error("document root must be object or array"); } ++p; size_t* current_base = temp; *temp++ = make_element(current_structure_type, ROOT_MARKER); parse_result result = error_result(); for (;;) { const char closing_bracket = (current_structure_type == TYPE_OBJECT ? '}' : ']'); const bool is_first_element = temp == current_base + 1; bool had_comma = false; c = peek_structure(); if (is_first_element) { if (c == ',') { return error("unexpected comma"); } } else { if (c == ',') { ++p; c = peek_structure(); had_comma = true; } else if (c != closing_bracket) { return error("expected ,"); } } if (current_structure_type == TYPE_OBJECT && c != '}') { if (c != '"') { return error("object key must be quoted"); } result = parse_string(temp); if (!result) { return error("invalid object key"); } if (peek_structure() != ':') { return error("expected :"); } ++p; temp += 2; } switch (peek_structure()) { type next_type; parse_result (parser::*structure_installer)(size_t* base); case 0: return error("unexpected end of input"); case 'n': result = parse_null(); break; case 'f': result = parse_false(); break; case 't': result = parse_true(); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '-': result = parse_number(); break; case '"': result = parse_string(); break; case '[': next_type = TYPE_ARRAY; goto push; case '{': next_type = TYPE_OBJECT; goto push; push: { ++p; size_t* previous_base = current_base; current_base = temp; *temp++ = make_element(current_structure_type, previous_base - structure); current_structure_type = next_type; continue; } case ']': if (current_structure_type == TYPE_ARRAY) { structure_installer = &parser::install_array; goto pop; } else { return error("expected }"); } case '}': if (current_structure_type == TYPE_OBJECT) { structure_installer = &parser::install_object; goto pop; } else { return error("expected ]"); } pop: { if (had_comma) { return error("trailing commas not allowed"); } ++p; size_t element = *current_base; result = (this->*structure_installer)(current_base + 1); size_t parent = get_element_value(element); if (parent == ROOT_MARKER) { root_type = result.value_type; goto done; } temp = current_base; current_base = structure + parent; current_structure_type = get_element_type(element); break; } case ',': return error("unexpected comma"); default: return error("cannot parse unknown value"); } if (!result) { return result.success; } *temp++ = make_element(result.value_type, out - current_base - 1); } done: if (0 == peek_structure()) { return true; } else { return error("expected end of input"); } } bool has_remaining_characters(ptrdiff_t remaining) { return input_end - p >= remaining; } parse_result parse_null() { if (SAJSON_UNLIKELY(!has_remaining_characters(4))) { return error("unexpected end of input"); } char p1 = p[1]; char p2 = p[2]; char p3 = p[3]; if (SAJSON_UNLIKELY(p1 != 'u' || p2 != 'l' || p3 != 'l')) { return error("expected 'null'"); } p += 4; return TYPE_NULL; } parse_result parse_false() { if (SAJSON_UNLIKELY(!has_remaining_characters(5))) { return error("unexpected end of input"); } char p1 = p[1]; char p2 = p[2]; char p3 = p[3]; char p4 = p[4]; if (SAJSON_UNLIKELY(p1 != 'a' || p2 != 'l' || p3 != 's' || p4 != 'e')) { return error("expected 'false'"); } p += 5; return TYPE_FALSE; } parse_result parse_true() { if (SAJSON_UNLIKELY(!has_remaining_characters(4))) { return error("unexpected end of input"); } char p1 = p[1]; char p2 = p[2]; char p3 = p[3]; if (SAJSON_UNLIKELY(p1 != 'r' || p2 != 'u' || p3 != 'e')) { return error("expected 'true'"); } p += 4; return TYPE_TRUE; } static double pow10(int exponent) { if (exponent > 308) { return std::numeric_limits::infinity(); } else if (exponent < -323) { return 0.0; } static const double constants[] = { 1e-323,1e-322,1e-321,1e-320,1e-319,1e-318,1e-317,1e-316,1e-315,1e-314, 1e-313,1e-312,1e-311,1e-310,1e-309,1e-308,1e-307,1e-306,1e-305,1e-304, 1e-303,1e-302,1e-301,1e-300,1e-299,1e-298,1e-297,1e-296,1e-295,1e-294, 1e-293,1e-292,1e-291,1e-290,1e-289,1e-288,1e-287,1e-286,1e-285,1e-284, 1e-283,1e-282,1e-281,1e-280,1e-279,1e-278,1e-277,1e-276,1e-275,1e-274, 1e-273,1e-272,1e-271,1e-270,1e-269,1e-268,1e-267,1e-266,1e-265,1e-264, 1e-263,1e-262,1e-261,1e-260,1e-259,1e-258,1e-257,1e-256,1e-255,1e-254, 1e-253,1e-252,1e-251,1e-250,1e-249,1e-248,1e-247,1e-246,1e-245,1e-244, 1e-243,1e-242,1e-241,1e-240,1e-239,1e-238,1e-237,1e-236,1e-235,1e-234, 1e-233,1e-232,1e-231,1e-230,1e-229,1e-228,1e-227,1e-226,1e-225,1e-224, 1e-223,1e-222,1e-221,1e-220,1e-219,1e-218,1e-217,1e-216,1e-215,1e-214, 1e-213,1e-212,1e-211,1e-210,1e-209,1e-208,1e-207,1e-206,1e-205,1e-204, 1e-203,1e-202,1e-201,1e-200,1e-199,1e-198,1e-197,1e-196,1e-195,1e-194, 1e-193,1e-192,1e-191,1e-190,1e-189,1e-188,1e-187,1e-186,1e-185,1e-184, 1e-183,1e-182,1e-181,1e-180,1e-179,1e-178,1e-177,1e-176,1e-175,1e-174, 1e-173,1e-172,1e-171,1e-170,1e-169,1e-168,1e-167,1e-166,1e-165,1e-164, 1e-163,1e-162,1e-161,1e-160,1e-159,1e-158,1e-157,1e-156,1e-155,1e-154, 1e-153,1e-152,1e-151,1e-150,1e-149,1e-148,1e-147,1e-146,1e-145,1e-144, 1e-143,1e-142,1e-141,1e-140,1e-139,1e-138,1e-137,1e-136,1e-135,1e-134, 1e-133,1e-132,1e-131,1e-130,1e-129,1e-128,1e-127,1e-126,1e-125,1e-124, 1e-123,1e-122,1e-121,1e-120,1e-119,1e-118,1e-117,1e-116,1e-115,1e-114, 1e-113,1e-112,1e-111,1e-110,1e-109,1e-108,1e-107,1e-106,1e-105,1e-104, 1e-103,1e-102,1e-101,1e-100,1e-99,1e-98,1e-97,1e-96,1e-95,1e-94,1e-93, 1e-92,1e-91,1e-90,1e-89,1e-88,1e-87,1e-86,1e-85,1e-84,1e-83,1e-82,1e-81, 1e-80,1e-79,1e-78,1e-77,1e-76,1e-75,1e-74,1e-73,1e-72,1e-71,1e-70,1e-69, 1e-68,1e-67,1e-66,1e-65,1e-64,1e-63,1e-62,1e-61,1e-60,1e-59,1e-58,1e-57, 1e-56,1e-55,1e-54,1e-53,1e-52,1e-51,1e-50,1e-49,1e-48,1e-47,1e-46,1e-45, 1e-44,1e-43,1e-42,1e-41,1e-40,1e-39,1e-38,1e-37,1e-36,1e-35,1e-34,1e-33, 1e-32,1e-31,1e-30,1e-29,1e-28,1e-27,1e-26,1e-25,1e-24,1e-23,1e-22,1e-21, 1e-20,1e-19,1e-18,1e-17,1e-16,1e-15,1e-14,1e-13,1e-12,1e-11,1e-10,1e-9, 1e-8,1e-7,1e-6,1e-5,1e-4,1e-3,1e-2,1e-1,1e0,1e1,1e2,1e3,1e4,1e5,1e6,1e7, 1e8,1e9,1e10,1e11,1e12,1e13,1e14,1e15,1e16,1e17,1e18,1e19,1e20,1e21, 1e22,1e23,1e24,1e25,1e26,1e27,1e28,1e29,1e30,1e31,1e32,1e33,1e34,1e35, 1e36,1e37,1e38,1e39,1e40,1e41,1e42,1e43,1e44,1e45,1e46,1e47,1e48,1e49, 1e50,1e51,1e52,1e53,1e54,1e55,1e56,1e57,1e58,1e59,1e60,1e61,1e62,1e63, 1e64,1e65,1e66,1e67,1e68,1e69,1e70,1e71,1e72,1e73,1e74,1e75,1e76,1e77, 1e78,1e79,1e80,1e81,1e82,1e83,1e84,1e85,1e86,1e87,1e88,1e89,1e90,1e91, 1e92,1e93,1e94,1e95,1e96,1e97,1e98,1e99,1e100,1e101,1e102,1e103,1e104, 1e105,1e106,1e107,1e108,1e109,1e110,1e111,1e112,1e113,1e114,1e115,1e116, 1e117,1e118,1e119,1e120,1e121,1e122,1e123,1e124,1e125,1e126,1e127,1e128, 1e129,1e130,1e131,1e132,1e133,1e134,1e135,1e136,1e137,1e138,1e139,1e140, 1e141,1e142,1e143,1e144,1e145,1e146,1e147,1e148,1e149,1e150,1e151,1e152, 1e153,1e154,1e155,1e156,1e157,1e158,1e159,1e160,1e161,1e162,1e163,1e164, 1e165,1e166,1e167,1e168,1e169,1e170,1e171,1e172,1e173,1e174,1e175,1e176, 1e177,1e178,1e179,1e180,1e181,1e182,1e183,1e184,1e185,1e186,1e187,1e188, 1e189,1e190,1e191,1e192,1e193,1e194,1e195,1e196,1e197,1e198,1e199,1e200, 1e201,1e202,1e203,1e204,1e205,1e206,1e207,1e208,1e209,1e210,1e211,1e212, 1e213,1e214,1e215,1e216,1e217,1e218,1e219,1e220,1e221,1e222,1e223,1e224, 1e225,1e226,1e227,1e228,1e229,1e230,1e231,1e232,1e233,1e234,1e235,1e236, 1e237,1e238,1e239,1e240,1e241,1e242,1e243,1e244,1e245,1e246,1e247,1e248, 1e249,1e250,1e251,1e252,1e253,1e254,1e255,1e256,1e257,1e258,1e259,1e260, 1e261,1e262,1e263,1e264,1e265,1e266,1e267,1e268,1e269,1e270,1e271,1e272, 1e273,1e274,1e275,1e276,1e277,1e278,1e279,1e280,1e281,1e282,1e283,1e284, 1e285,1e286,1e287,1e288,1e289,1e290,1e291,1e292,1e293,1e294,1e295,1e296, 1e297,1e298,1e299,1e300,1e301,1e302,1e303,1e304,1e305,1e306,1e307,1e308 }; return constants[exponent + 323]; } parse_result parse_number() { bool negative = false; if ('-' == *p) { ++p; negative = true; if (at_eof()) { return error("unexpected end of input"); } } bool try_double = false; int i = 0; double d = 0.0; // gcc complains that d might be used uninitialized which isn't true. appease the warning anyway. if (*p == '0') { ++p; } else for (;;) { char c = *p; if (c < '0' || c > '9') { break; } ++p; if (SAJSON_UNLIKELY(at_eof())) { return error("unexpected end of input"); } char digit = c - '0'; if (SAJSON_UNLIKELY(!try_double && i > INT_MAX / 10 - 9)) { // TODO: could split this into two loops try_double = true; d = i; } if (SAJSON_UNLIKELY(try_double)) { d = 10.0 * d + digit; } else { i = 10 * i + digit; } } int exponent = 0; if ('.' == *p) { if (!try_double) { try_double = true; d = i; } ++p; if (at_eof()) { return error("unexpected end of input"); } for (;;) { char c = *p; if (c < '0' || c > '9') { break; } ++p; if (at_eof()) { return error("unexpected end of input"); } d = d * 10 + (c - '0'); --exponent; } } char e = *p; if ('e' == e || 'E' == e) { if (!try_double) { try_double = true; d = i; } ++p; if (at_eof()) { return error("unexpected end of input"); } bool negativeExponent = false; if ('-' == *p) { negativeExponent = true; ++p; if (at_eof()) { return error("unexpected end of input"); } } else if ('+' == *p) { ++p; if (at_eof()) { return error("unexpected end of input"); } } int exp = 0; char c = *p; if (SAJSON_UNLIKELY(c < '0' || c > '9')) { return error("missing exponent"); } for (;;) { exp = 10 * exp + (c - '0'); ++p; if (at_eof()) { return error("unexpected end of input"); } c = *p; if (c < '0' || c > '9') { break; } } exponent += (negativeExponent ? -exp : exp); } if (exponent) { assert(try_double); d *= pow10(exponent); } if (negative) { if (try_double) { d = -d; } else { i = -i; } } if (try_double) { out -= double_storage::word_length; double_storage::store(out, d); return TYPE_DOUBLE; } else { integer_storage is; is.i = i; *--out = is.u; return TYPE_INTEGER; } } parse_result install_array(size_t* array_base) { const size_t length = temp - array_base; size_t* const new_base = out - length - 1; while (temp > array_base) { // I think this addition is legal because the tag bits are at the top? *(--out) = *(--temp) + (array_base - new_base); } *(--out) = length; return TYPE_ARRAY; } parse_result install_object(size_t* object_base) { const size_t length = (temp - object_base) / 3; object_key_record* oir = reinterpret_cast(object_base); std::sort( oir, oir + length, object_key_comparator(input.get_data())); size_t* const new_base = out - length * 3 - 1; size_t i = length; while (i--) { // I think this addition is legal because the tag bits are at the top? *(--out) = *(--temp) + (object_base - new_base); *(--out) = *(--temp); *(--out) = *(--temp); } *(--out) = length; return TYPE_OBJECT; } parse_result parse_string(size_t* tag = 0) { if (!tag) { out -= 2; tag = out; } ++p; // " size_t start = p - input.get_data(); for (;;) { if (SAJSON_UNLIKELY(p >= input_end)) { return error("unexpected end of input"); } if (SAJSON_UNLIKELY(*p >= 0 && *p < 0x20)) { *p = 0x20; } switch (*p) { case '"': tag[0] = start; tag[1] = p - input.get_data(); ++p; return TYPE_STRING; case '\\': return parse_string_slow(tag, start); default: ++p; break; } } } parse_result read_hex(unsigned& u) { unsigned v = 0; int i = 4; while (i--) { unsigned char c = *p++; if (c >= '0' && c <= '9') { c -= '0'; } else if (c >= 'a' && c <= 'f') { c = c - 'a' + 10; } else if (c >= 'A' && c <= 'F') { c = c - 'A' + 10; } else { return error("invalid character in unicode escape"); } v = (v << 4) + c; } u = v; return TYPE_NULL; // ??? } void write_utf8(unsigned codepoint, char*& end) { if (codepoint < 0x80) { *end++ = codepoint; } else if (codepoint < 0x800) { *end++ = 0xC0 | (codepoint >> 6); *end++ = 0x80 | (codepoint & 0x3F); } else if (codepoint < 0x10000) { *end++ = 0xE0 | (codepoint >> 12); *end++ = 0x80 | ((codepoint >> 6) & 0x3F); *end++ = 0x80 | (codepoint & 0x3F); } else { assert(codepoint < 0x200000); *end++ = 0xF0 | (codepoint >> 18); *end++ = 0x80 | ((codepoint >> 12) & 0x3F); *end++ = 0x80 | ((codepoint >> 6) & 0x3F); *end++ = 0x80 | (codepoint & 0x3F); } } parse_result parse_string_slow(size_t* tag, size_t start) { char* end = p; for (;;) { if (SAJSON_UNLIKELY(p >= input_end)) { return error("unexpected end of input"); } if (SAJSON_UNLIKELY(*p >= 0 && *p < 0x20)) { *p = 0x20; } switch (*p) { case '"': tag[0] = start; tag[1] = end - input.get_data(); ++p; return TYPE_STRING; case '\\': ++p; if (SAJSON_UNLIKELY(p >= input_end)) { return error("unexpected end of input"); } char replacement; switch (*p) { case '"': replacement = '"'; goto replace; case '\\': replacement = '\\'; goto replace; case '/': replacement = '/'; goto replace; case 'b': replacement = '\b'; goto replace; case 'f': replacement = '\f'; goto replace; case 'n': replacement = '\n'; goto replace; case 'r': replacement = '\r'; goto replace; case 't': replacement = '\t'; goto replace; replace: *end++ = replacement; ++p; break; case 'u': { ++p; if (SAJSON_UNLIKELY(!has_remaining_characters(4))) { return error("unexpected end of input"); } unsigned u = 0; // gcc's complaining that this could be used uninitialized. wrong. parse_result result = read_hex(u); if (!result) { return result; } if (u >= 0xD800 && u <= 0xDBFF) { if (SAJSON_UNLIKELY(!has_remaining_characters(6))) { return error("unexpected end of input during UTF-16 surrogate pair"); } char p0 = p[0]; char p1 = p[1]; if (p0 != '\\' || p1 != 'u') { return error("expected \\u"); } p += 2; unsigned v = 0; // gcc's complaining that this could be used uninitialized. wrong. result = read_hex(v); if (!result) { return result; } if (v < 0xDC00 || v > 0xDFFF) { return error("invalid UTF-16 trail surrogate"); } u = 0x10000 + (((u - 0xD800) << 10) | (v - 0xDC00)); } write_utf8(u, end); break; } default: return error("unknown escape"); } break; default: *end++ = *p++; break; } } } mutable_string_view input; char* const input_end; size_t* const structure; char* p; size_t* temp; type root_type; size_t* out; size_t error_line; size_t error_column; std::string error_message; }; template document parse(const StringType& string) { mutable_string_view ms(string); size_t length = string.length(); size_t* structure = new size_t[length]; return parser(ms, structure).get_document(); } } pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/securesocket.cpp000066400000000000000000000233231360567320200246010ustar00rootroot00000000000000/* * Copyright (C) 2016 Jean-Luc Barriere * * 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 3, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "securesocket.h" #include "debug.h" #include "cppdef.h" #include #ifdef __WINDOWS__ #include #define LASTERROR WSAGetLastError() #define ERRNO_INTR WSAEINTR #else #define LASTERROR errno #define ERRNO_INTR EINTR #endif /* __WINDOWS__ */ using namespace NSROOT; SSLSessionFactory* SSLSessionFactory::m_instance = 0; SSLSessionFactory& SSLSessionFactory::Instance() { if (!m_instance) m_instance = new SSLSessionFactory(); return *m_instance; } void SSLSessionFactory::Destroy() { SAFE_DELETE(m_instance); } #if HAVE_OPENSSL #include #include #include #include #include /* Cipher suites, https://www.openssl.org/docs/apps/ciphers.html */ const char* const PREFERRED_CIPHERS = "HIGH:!aNULL:!kRSA:!SRP:!PSK:!CAMELLIA:!RC4:!MD5:!DSS"; SSLSessionFactory::SSLSessionFactory() : m_enabled(false) , m_ctx(NULL) { if (SSL_library_init() < 0) DBG(DBG_ERROR, "%s: could not initialize the SSL library\n", __FUNCTION__); else { SSL_load_error_strings(); /* SSL_load_error_strings loads both libssl and libcrypto strings */ /* ERR_load_crypto_strings(); */ #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) m_ctx = SSL_CTX_new(TLS_client_method()); #else m_ctx = SSL_CTX_new(SSLv23_client_method()); #endif if (m_ctx == NULL) DBG(DBG_ERROR, "%s: could not create the SSL context\n", __FUNCTION__); else { SSL_CTX_set_verify(static_cast(m_ctx), SSL_VERIFY_NONE, 0); /* Remove the most egregious. Because SSLv2 and SSLv3 have been removed, * a TLSv1.0 handshake is used. The client accepts TLSv1.0 and above. * An added benefit of TLS 1.0 and above are TLS extensions like Server * Name Indicatior (SNI). */ const long flags = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION; (void)SSL_CTX_set_options(static_cast(m_ctx), flags); /* Each cipher suite takes 2 bytes in the ClientHello, so advertising every * cipher suite available at the client is going to cause a big ClientHello * (or bigger then needed to get the job done). * When using SSL_CTX_set_cipher_list or SSL_set_cipher_list with the string * below you'll cut the number of cipher suites down to about 45. */ if (SSL_CTX_set_cipher_list(static_cast(m_ctx), PREFERRED_CIPHERS) != 1) DBG(DBG_ERROR, "%s: Set cipher list failed\n", __FUNCTION__); /* The SSL trace callback is only used for verbose logging */ /* SSL_CTX_set_msg_callback(static_cast(m_ctx), ssl_trace); */ DBG(DBG_INFO, "%s: SSL engine initialized\n", __FUNCTION__); m_enabled = true; } } } SSLSessionFactory::~SSLSessionFactory() { if (m_ctx) SSL_CTX_free(static_cast(m_ctx)); ERR_free_strings(); EVP_cleanup(); DBG(DBG_INFO, "%s: SSL resources destroyed\n", __FUNCTION__); } SecureSocket* SSLSessionFactory::NewSocket() { if (m_enabled) { SSL* ssl = SSL_new(static_cast(m_ctx)); /* SSL_MODE_AUTO_RETRY * With this option set, if the server suddenly wants a new handshake, * OpenSSL handles it in the background. Without this option, any read * or write operation will return an error if the server wants a new * handshake, setting the retry flag in the process. */ SSL_set_mode(static_cast(ssl), SSL_MODE_AUTO_RETRY); return new SecureSocket(ssl); } return NULL; } SecureSocket::SecureSocket(void* ssl) : TcpSocket() , m_ssl(ssl) , m_cert(NULL) , m_connected(false) , m_ssl_error(0) { } SecureSocket::~SecureSocket() { Disconnect(); SSL_free(static_cast(m_ssl)); } bool SecureSocket::Connect(const char* server, unsigned port, int rcvbuf) { m_ssl_error = 0; if (m_connected) Disconnect(); /* Connect the tcp socket to the server */ if (!TcpSocket::Connect(server, port, rcvbuf)) return false; /* setup SSL */ SSL_set_fd(static_cast(m_ssl), m_socket); SSL_set_tlsext_host_name(static_cast(m_ssl), server); /* fix SNI */ /* do SSL handshake */ for (;;) { int r = SSL_connect(static_cast(m_ssl)); if (r > 0) break; if (r < 0) { int err = SSL_get_error(static_cast(m_ssl), r); if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) { DBG(DBG_DEBUG, "%s: SSL retry (%d)\n", __FUNCTION__, err); continue; } } const char* errmsg = ERR_error_string(ERR_get_error(), NULL); DBG(DBG_ERROR, "%s: SSL connect failed: %s\n", __FUNCTION__, errmsg); TcpSocket::Disconnect(); return false; } DBG(DBG_PROTO, "%s: SSL handshake initialized\n", __FUNCTION__); m_connected = true; /* check for a valid certificate */ std::string str(""); if (!IsCertificateValid(str)) { DBG(DBG_ERROR, "%s: could not get a valid certificate from the server\n", __FUNCTION__); Disconnect(); } DBG(DBG_PROTO, "%s: %s\n", __FUNCTION__, str.c_str()); return true; } size_t SecureSocket::ReceiveData(void* buf, size_t n) { if (m_connected && n > 0) { m_ssl_error = SSL_ERROR_NONE; for (;;) { if (SSL_pending(static_cast(m_ssl)) == 0) { int hangcount = 0; for (;;) { int s = TcpSocket::Listen(&m_timeout); if (s > 0) break; else if (s == 0) { DBG(DBG_WARN, "%s: socket(%p) timed out (%d)\n", __FUNCTION__, &m_socket, hangcount); m_errno = ETIMEDOUT; if (++hangcount >= m_attempt) return 0; } else if (m_errno != ERRNO_INTR) return 0; } } int r = SSL_read(static_cast(m_ssl), buf, (int) n); if (r >= 0) return (size_t) r; int err = SSL_get_error(static_cast(m_ssl), r); if (err == SSL_ERROR_WANT_READ) { DBG(DBG_DEBUG, "%s: SSL retry\n", __FUNCTION__); continue; } if (err == SSL_ERROR_WANT_WRITE) { DBG(DBG_DEBUG, "%s: SSL wants write\n", __FUNCTION__); m_ssl_error = err; break; } const char* errmsg = ERR_error_string(ERR_get_error(), NULL); DBG(DBG_ERROR, "%s: SSL read failed: %s\n", __FUNCTION__, errmsg); m_ssl_error = err; break; } } return 0; } bool SecureSocket::SendData(const char* buf, size_t size) { if (m_connected && size > 0) { m_ssl_error = SSL_ERROR_NONE; for (;;) { int r = SSL_write(static_cast(m_ssl), buf, (int) size); if (r > 0 && size == (size_t) r) return true; int err = SSL_get_error(static_cast(m_ssl), r); if (err == SSL_ERROR_WANT_WRITE) { DBG(DBG_DEBUG, "%s: SSL retry\n", __FUNCTION__); continue; } if (err == SSL_ERROR_WANT_READ) { DBG(DBG_DEBUG, "%s: SSL wants read\n", __FUNCTION__); m_ssl_error = err; break; } const char* errmsg = ERR_error_string(ERR_get_error(), NULL); DBG(DBG_ERROR, "%s: SSL write failed: %s\n", __FUNCTION__, errmsg); m_ssl_error = err; break; } } return false; } void SecureSocket::Disconnect() { if (m_connected) { SSL_shutdown(static_cast(m_ssl)); m_connected = false; } TcpSocket::Disconnect(); if (m_cert) { X509_free(static_cast(m_cert)); m_cert = NULL; } } bool SecureSocket::IsValid() const { return m_connected; } bool SecureSocket::IsCertificateValid(std::string& str) { if (m_cert) X509_free(static_cast(m_cert)); m_cert = SSL_get_peer_certificate(static_cast(m_ssl)); if (m_cert) { char buf[80]; // X509_get_subject_name() returns the subject name of certificate x. // The returned value is an internal pointer which MUST NOT be freed. X509_NAME* name = X509_get_subject_name(static_cast(m_cert)); str.assign(X509_NAME_oneline(name, buf, sizeof(buf) - 1)); return true; } return false; } #else SSLSessionFactory::SSLSessionFactory() : m_enabled(false) , m_ctx(NULL) { DBG(DBG_INFO, "%s: SSL feature is disabled\n", __FUNCTION__); } SSLSessionFactory::~SSLSessionFactory() { } SecureSocket* SSLSessionFactory::NewSocket() { return new SecureSocket(NULL); } SecureSocket::SecureSocket(void* ssl) : TcpSocket() , m_ssl(ssl) , m_cert(NULL) , m_connected(false) , m_ssl_error(0) { } SecureSocket::~SecureSocket() { } bool SecureSocket::Connect(const char* server, unsigned port, int rcvbuf) { (void)server; (void)port; (void)rcvbuf; return false; } size_t SecureSocket::ReceiveData(void* buf, size_t n) { (void)buf; (void)n; return 0; } bool SecureSocket::SendData(const char* buf, size_t size) { (void)buf; (void)size; return false; } void SecureSocket::Disconnect() { } bool SecureSocket::IsValid() const { return m_connected; } bool SecureSocket::IsCertificateValid(std::string& str) { (void)str; return false; } #endif pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/securesocket.h000066400000000000000000000041561360567320200242510ustar00rootroot00000000000000/* * Copyright (C) 2016 Jean-Luc Barriere * * 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 3, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef SECURESOCKET_H #define SECURESOCKET_H #include "socket.h" #include namespace NSROOT { class SecureSocket; class SSLSessionFactory { public: static SSLSessionFactory& Instance(); static void Destroy(); bool isEnabled() const { return m_enabled; } SecureSocket* NewSocket(); private: SSLSessionFactory(); ~SSLSessionFactory(); SSLSessionFactory(const SSLSessionFactory&); SSLSessionFactory& operator=(const SSLSessionFactory&); static SSLSessionFactory* m_instance; bool m_enabled; ///< SSL feature status void* m_ctx; ///< SSL default context for the application }; class SecureSocket : public TcpSocket { friend class SSLSessionFactory; public: virtual ~SecureSocket(); // Overrides TcpSocket bool Connect(const char *server, unsigned port, int rcvbuf); bool SendData(const char* buf, size_t size); size_t ReceiveData(void* buf, size_t n); void Disconnect(); bool IsValid() const; bool IsCertificateValid(std::string& info); private: SecureSocket(void* ssl); void* m_ssl; ///< SSL handle void* m_cert; ///< X509 certificate bool m_connected; ///< SSL session state int m_ssl_error; ///< SSL error code }; } #endif /* SECURESOCKET_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/socket.cpp000066400000000000000000000702061360567320200233740ustar00rootroot00000000000000/* * Copyright (C) 2014-2019 Jean-Luc Barriere * * 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 3, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "socket.h" #include "debug.h" #include #include #include #ifdef __WINDOWS__ #include #define SHUT_RDWR SD_BOTH #define SHUT_WR SD_SEND #define LASTERROR WSAGetLastError() #define ERRNO_INTR WSAEINTR typedef int socklen_t; typedef IN_ADDR in_addr_t; #else #include #include #include #include #include #include #include #define closesocket(a) close(a) #define LASTERROR errno #define ERRNO_INTR EINTR #endif /* __WINDOWS__ */ #include using namespace NSROOT; static int __addressFamily(SOCKET_AF_t saf) { switch(saf) { case SOCKET_AF_INET4: return AF_INET; case SOCKET_AF_INET6: return AF_INET6; default: return AF_UNSPEC; } } namespace NSROOT { struct SocketAddress { sockaddr_storage data; socklen_t sa_len; SocketAddress() { Clear(AF_UNSPEC); } SocketAddress(int family) { Clear(family); } inline sockaddr* sa() { return (sockaddr*)&data; } inline int sa_family() { return data.ss_family; } void Clear(int family) { memset(&data, 0, sizeof(data)); data.ss_family = family; sa_len = (family == AF_INET ? sizeof(sockaddr_in) : sizeof(sockaddr_in6)); } }; } /////////////////////////////////////////////////////////////////////////////// //// //// TCP socket //// static char my_hostname[SOCKET_HOSTNAME_MAXSIZE]; static volatile net_socket_t my_socket; static void __sigHandler(int sig) { closesocket(my_socket); my_socket = INVALID_SOCKET_VALUE; (void)sig; } TcpSocket::TcpSocket() : NetSocket() , m_socket(INVALID_SOCKET_VALUE) , m_rcvbuf(SOCKET_RCVBUF_MINSIZE) , m_errno(0) , m_attempt(SOCKET_READ_ATTEMPT) , m_buffer(NULL) , m_bufptr(NULL) , m_buflen(SOCKET_BUFFER_SIZE) , m_rcvlen(0) { } TcpSocket::~TcpSocket() { if (IsValid()) Disconnect(); if (m_buffer) delete[] m_buffer; } static int __connectAddr(struct addrinfo *addr, net_socket_t *s, int rcvbuf) { #ifndef __WINDOWS__ void (*old_sighandler)(int); int old_alarm; #endif socklen_t size; int err = 0, opt_rcvbuf; if ((my_hostname[0] == '\0') && (gethostname(my_hostname, sizeof (my_hostname)) < 0)) { err = LASTERROR; DBG(DBG_ERROR, "%s: gethostname failed (%d)\n", __FUNCTION__, err); return err; } *s = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); if (*s == INVALID_SOCKET_VALUE) { err = LASTERROR; DBG(DBG_ERROR, "%s: invalid socket (%d)\n", __FUNCTION__, err); return err; } opt_rcvbuf = (rcvbuf < SOCKET_RCVBUF_MINSIZE ? SOCKET_RCVBUF_MINSIZE : rcvbuf); size = sizeof (opt_rcvbuf); if (setsockopt(*s, SOL_SOCKET, SO_RCVBUF, (char *)&opt_rcvbuf, size)) DBG(DBG_WARN, "%s: could not set rcvbuf from socket (%d)\n", __FUNCTION__, LASTERROR); if (getsockopt(*s, SOL_SOCKET, SO_RCVBUF, (char *)&opt_rcvbuf, &size)) DBG(DBG_WARN, "%s: could not get rcvbuf from socket (%d)\n", __FUNCTION__, LASTERROR); #ifdef SO_NOSIGPIPE int opt_set = 1; if (setsockopt(*s, SOL_SOCKET, SO_NOSIGPIPE, (void *)&opt_set, sizeof(int))) DBG(DBG_WARN, "%s: could not set nosigpipe from socket (%d)\n", __FUNCTION__, LASTERROR); #endif #ifndef __WINDOWS__ old_sighandler = signal(SIGALRM, __sigHandler); old_alarm = alarm(5); my_socket = *s; #endif if (connect(*s, addr->ai_addr, addr->ai_addrlen) < 0) { err = LASTERROR; DBG(DBG_ERROR, "%s: failed to connect (%d)\n", __FUNCTION__, err); closesocket(*s); *s = INVALID_SOCKET_VALUE; #ifndef __WINDOWS__ signal(SIGALRM, old_sighandler); alarm(old_alarm); #endif return err; } #ifndef __WINDOWS__ my_socket = INVALID_SOCKET_VALUE; signal(SIGALRM, old_sighandler); alarm(old_alarm); #endif DBG(DBG_PROTO, "%s: connected to socket(%p)\n", __FUNCTION__, s); return err; } bool TcpSocket::Connect(const char *server, unsigned port, int rcvbuf) { struct addrinfo hints; struct addrinfo *result, *addr; char service[33]; int err; if (IsValid()) Disconnect(); if (rcvbuf > SOCKET_RCVBUF_MINSIZE) m_rcvbuf = rcvbuf; memset(&hints, 0, sizeof (hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; snprintf(service, sizeof(service), "%u", port); err = getaddrinfo(server, service, &hints, &result); if (err) { switch (err) { case EAI_NONAME: DBG(DBG_ERROR, "%s: the specified host is unknown\n", __FUNCTION__); break; case EAI_FAIL: DBG(DBG_ERROR, "%s: a non-recoverable failure in name resolution occurred\n", __FUNCTION__); break; case EAI_MEMORY: DBG(DBG_ERROR, "%s: a memory allocation failure occurred\n", __FUNCTION__); break; case EAI_AGAIN: DBG(DBG_ERROR, "%s: a temporary error occurred on an authoritative name server\n", __FUNCTION__); break; default: DBG(DBG_ERROR, "%s: unknown error %d\n", __FUNCTION__, err); break; } m_errno = err; return false; } for (addr = result; addr; addr = addr->ai_next) { err = __connectAddr(addr, &m_socket, m_rcvbuf); if (!err) break; } freeaddrinfo(result); m_errno = err; return (err ? false : true); } bool TcpSocket::SendData(const char *msg, size_t size) { if (IsValid()) { #if defined(__WINDOWS__) || defined(SO_NOSIGPIPE) size_t s = send(m_socket, msg, size, 0); if (s != size) { m_errno = LASTERROR; return false; } #elif defined(MSG_NOSIGNAL) size_t s = send(m_socket, msg, size, MSG_NOSIGNAL); if (s != size) { m_errno = LASTERROR; return false; } #else sigset_t sig_block, sig_restore, sig_pending; sigemptyset(&sig_block); sigaddset(&sig_block, SIGPIPE); /* * Block SIGPIPE for this thread. * This works since kernel sends SIGPIPE to the thread that called write(), * not to the whole process. */ if (pthread_sigmask(SIG_BLOCK, &sig_block, &sig_restore) != 0) return false; /* * Check if SIGPIPE is already pending. */ int sigpipe_pending = -1; if (sigpending(&sig_pending) != -1) sigpipe_pending = sigismember(&sig_pending, SIGPIPE); if (sigpipe_pending == -1) { pthread_sigmask(SIG_SETMASK, &sig_restore, NULL); return false; } size_t s = send(m_socket, msg, size, 0); if (s != size) { m_errno = LASTERROR; /* * Fetch generated SIGPIPE if write() failed with EPIPE. * However, if SIGPIPE was already pending before calling write(), it was * also generated and blocked by caller, and caller may expect that it can * fetch it later. Since signals are not queued, we don't fetch it in this * case. */ if (m_errno == EPIPE && sigpipe_pending == 0) { struct timespec ts; ts.tv_sec = 0; ts.tv_nsec = 0; int sig; while ((sig = sigtimedwait(&sig_block, 0, &ts)) == -1 && LASTERROR == EINTR); } pthread_sigmask(SIG_SETMASK, &sig_restore, NULL); return false; } pthread_sigmask(SIG_SETMASK, &sig_restore, NULL); #endif m_errno = 0; return true; } m_errno = ENOTCONN; return false; } size_t TcpSocket::ReceiveData(void *buf, size_t n) { if (IsValid()) { m_errno = 0; size_t rcvlen = 0; char *p = (char*)buf; // Check for data remaining in buffer if (m_buffer) { if (m_bufptr < m_buffer + m_rcvlen) { rcvlen = m_rcvlen - (m_bufptr - m_buffer); if (rcvlen > n) rcvlen = n; memcpy(p, m_bufptr, rcvlen); m_bufptr += rcvlen; p += rcvlen; n -= rcvlen; if (n == 0) return rcvlen; } } else if ((m_buffer = new char[m_buflen]) == NULL) { m_errno = ENOMEM; DBG(DBG_ERROR, "%s: cannot allocate %u bytes for buffer\n", __FUNCTION__, m_buflen); return 0; } // Reset buffer m_bufptr = m_buffer; m_rcvlen = 0; struct timeval tv; fd_set fds; int r = 0, hangcount = 0; while (n > 0) { tv = m_timeout; FD_ZERO(&fds); FD_SET(m_socket, &fds); r = select(m_socket + 1, &fds, NULL, NULL, &tv); if (r > 0) { // Under threshold use buffering if (n < m_buflen) { if ((r = recv(m_socket, m_buffer, m_buflen, 0)) > 0) { m_rcvlen = r; size_t s = r; if (s > n) s = n; memcpy(p, m_buffer, s); m_bufptr = m_buffer + s; p += s; n -= s; rcvlen += s; } } // No buffering else { if ((r = recv(m_socket, p, n, 0)) > 0) { p += r; n -= r; rcvlen += r; } } } if (r == 0) { DBG(DBG_WARN, "%s: socket(%p) timed out (%d)\n", __FUNCTION__, &m_socket, hangcount); m_errno = ETIMEDOUT; if (++hangcount >= m_attempt) break; } if (r < 0) { m_errno = LASTERROR; if (m_errno != ERRNO_INTR) break; } } return rcvlen; } m_errno = ENOTCONN; return 0; } void TcpSocket::Disconnect() { if (IsValid()) { char buf[256]; struct timeval tv; fd_set fds; int r = 0; shutdown(m_socket, SHUT_RDWR); tv.tv_sec = 5; tv.tv_usec = 0; do { FD_ZERO(&fds); FD_SET(m_socket, &fds); r = select(m_socket + 1, &fds, NULL, NULL, &tv); if (r > 0) r = recv(m_socket, buf, sizeof(buf), 0); } while (r > 0); closesocket(m_socket); m_socket = INVALID_SOCKET_VALUE; m_rcvlen = 0; } } bool TcpSocket::IsValid() const { return (m_socket == INVALID_SOCKET_VALUE ? false : true); } int TcpSocket::Listen(timeval *timeout) { if (IsValid()) { fd_set fds; int r; FD_ZERO(&fds); FD_SET(m_socket, &fds); r = select(m_socket + 1, &fds, NULL, NULL, timeout); if (r < 0) m_errno = LASTERROR; return r; } m_errno = ENOTCONN; return -1; } std::string TcpSocket::GetHostAddrInfo() { char host[INET6_ADDRSTRLEN]; memset(host, 0, INET6_ADDRSTRLEN); if (!IsValid()) return host; char addr[sizeof(sockaddr_in6)]; socklen_t addr_len = sizeof(addr); if (getsockname(m_socket, (sockaddr*)&addr, &addr_len) == 0) getnameinfo((sockaddr*)&addr, addr_len, host, sizeof(host), NULL, 0, NI_NUMERICHOST); else m_errno = LASTERROR; return host; } const char* TcpSocket::GetMyHostName() { return my_hostname; } /////////////////////////////////////////////////////////////////////////////// //// //// TCP server socket //// TcpServerSocket::TcpServerSocket() : m_socket(INVALID_SOCKET_VALUE) , m_errno(0) , m_requestQueueSize(0) { m_addr = new(SocketAddress); } TcpServerSocket::~TcpServerSocket() { Close(); if (m_addr) { delete(m_addr); m_addr = NULL; } } bool TcpServerSocket::Create(SOCKET_AF_t af) { if (IsValid()) return false; m_addr->Clear(__addressFamily(af)); m_socket = socket(m_addr->sa_family(), SOCK_STREAM, 0); if (!IsValid()) { m_errno = LASTERROR; DBG(DBG_ERROR, "%s: invalid socket (%d)\n", __FUNCTION__, m_errno); return false; } #ifdef __WINDOWS__ // The bind will succeed even an other socket is currently listening on the // same address. So enable the option SO_EXCLUSIVEADDRUSE will fix the issue. int opt_exclusive = 1; if (setsockopt(m_socket, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char*)&opt_exclusive, sizeof(opt_exclusive))) { m_errno = LASTERROR; DBG(DBG_ERROR, "%s: could not set exclusiveaddruse from socket (%d)\n", __FUNCTION__, m_errno); return false; } #else // Reuse address. The bind will fail only if an other socket is currently // listening on the same address. int opt_reuseaddr = 1; if (setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&opt_reuseaddr, sizeof(opt_reuseaddr))) { m_errno = LASTERROR; DBG(DBG_ERROR, "%s: could not set reuseaddr from socket (%d)\n", __FUNCTION__, m_errno); return false; } #endif return true; } bool TcpServerSocket::IsValid() const { return (m_socket == INVALID_SOCKET_VALUE ? false : true); } bool TcpServerSocket::Bind(unsigned port) { if (!IsValid()) return false; int r = 0; m_addr->Clear(m_addr->sa_family()); switch (m_addr->sa_family()) { case AF_INET: { sockaddr_in* sa = (sockaddr_in*)m_addr->sa(); sa->sin_addr.s_addr = htonl(INADDR_ANY); sa->sin_port = htons(port); r = bind(m_socket, m_addr->sa(), m_addr->sa_len); break; } case AF_INET6: { sockaddr_in6* sa = (sockaddr_in6*)m_addr->sa(); sa->sin6_addr = in6addr_any; sa->sin6_port = htons(port); r = bind(m_socket, m_addr->sa(), m_addr->sa_len); break; } } if (r) { m_errno = LASTERROR; DBG(DBG_ERROR, "%s: could not bind to address (%d)\n", __FUNCTION__, m_errno); return false; } return true; } bool TcpServerSocket::ListenConnection(int queueSize /*= SOCKET_CONNECTION_REQUESTS*/) { if (!IsValid()) return false; if (listen(m_socket, queueSize)) { m_errno = LASTERROR; DBG(DBG_ERROR, "%s: listen failed (%d)\n", __FUNCTION__, m_errno); return false; } m_requestQueueSize = queueSize; return true; } bool TcpServerSocket::AcceptConnection(TcpSocket& socket) { socket.m_socket = accept(m_socket, m_addr->sa(), &m_addr->sa_len); if (!socket.IsValid()) { m_errno = LASTERROR; DBG(DBG_ERROR, "%s: accept failed (%d)\n", __FUNCTION__, m_errno); return false; } #ifdef SO_NOSIGPIPE int opt_set = 1; if (setsockopt(socket.m_socket, SOL_SOCKET, SO_NOSIGPIPE, (void *)&opt_set, sizeof(int))) DBG(DBG_WARN, "%s: could not set nosigpipe from socket (%d)\n", __FUNCTION__, LASTERROR); #endif socket.SetReadAttempt(0); return true; } void TcpServerSocket::Close() { if (IsValid()) { closesocket(m_socket); m_socket = INVALID_SOCKET_VALUE; } } /////////////////////////////////////////////////////////////////////////////// //// //// UDP socket //// UdpSocket::UdpSocket() : m_socket(INVALID_SOCKET_VALUE) , m_errno(0) , m_buffer(NULL) , m_bufptr(NULL) , m_buflen(SOCKET_BUFFER_SIZE) , m_rcvlen(0) { m_addr = new SocketAddress; m_from = new SocketAddress; } UdpSocket::UdpSocket(size_t bufferSize) : m_socket(INVALID_SOCKET_VALUE) , m_errno(0) , m_buffer(NULL) , m_bufptr(NULL) , m_buflen(bufferSize) , m_rcvlen(0) { m_addr = new SocketAddress; m_from = new SocketAddress; } UdpSocket::~UdpSocket() { if (IsValid()) { closesocket(m_socket); m_socket = INVALID_SOCKET_VALUE; } if (m_addr) { delete m_addr; m_addr = NULL; } if (m_from) { delete m_from; m_from = NULL; } if (m_buffer) { delete[] m_buffer; m_buffer = m_bufptr = NULL; } } bool UdpSocket::Open(SOCKET_AF_t af, const char* target, unsigned port) { return Open(af) && SetAddress(target, port); } bool UdpSocket::Open(SOCKET_AF_t af, bool broadcast /*= false*/) { if (IsValid() && m_addr->sa_family() != __addressFamily(af)) { closesocket(m_socket); m_socket = INVALID_SOCKET_VALUE; } if (m_socket == INVALID_SOCKET_VALUE) { m_addr->Clear(__addressFamily(af)); m_from->Clear(AF_UNSPEC); if ((m_socket = socket(m_addr->sa_family(), SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET_VALUE) { m_errno = LASTERROR; DBG(DBG_ERROR, "%s: create socket failed (%d)\n", __FUNCTION__, m_errno); return false; } if (broadcast && af == SOCKET_AF_INET4) { // set broadcast permission int _broadcast = 1; if (setsockopt(m_socket, SOL_SOCKET, SO_BROADCAST, (char*)&_broadcast, sizeof(_broadcast))) { m_errno = LASTERROR; DBG(DBG_ERROR, "%s: could not set SO_BROADCAST from socket (%d)\n", __FUNCTION__, m_errno); return false; } } } m_errno = 0; return true; } bool UdpSocket::SetAddress(const char* target, unsigned port) { if (!IsValid()) { DBG(DBG_ERROR, "%s: invalid socket\n", __FUNCTION__); return false; } unsigned char _addr[sizeof(struct in6_addr)]; if (inet_pton(m_addr->sa_family(), target, &_addr) == 0) { m_errno = LASTERROR; DBG(DBG_ERROR, "%s: invalid address (%s)\n", __FUNCTION__, target); return false; } m_addr->Clear(m_addr->sa_family()); switch(m_addr->sa_family()) { case AF_INET: { sockaddr_in* sa = (sockaddr_in*)m_addr->sa(); memcpy(&(sa->sin_addr.s_addr), _addr, sizeof(in_addr_t)); sa->sin_port = htons(port); break; } case AF_INET6: { sockaddr_in6* sa = (sockaddr_in6*)m_addr->sa(); memcpy(&(sa->sin6_addr), _addr, sizeof(struct in6_addr)); sa->sin6_port = htons(port); break; } default: m_errno = EINVAL; DBG(DBG_ERROR, "%s: address familly unknown (%d)\n", __FUNCTION__, m_addr->sa_family()); return false; } m_errno = 0; return true; } bool UdpSocket::SetMulticastTTL(int multicastTTL) { if (!IsValid()) return false; switch(m_addr->sa_family()) { case AF_INET: { // The v4 multicast TTL socket option requires that the value be passed in an unsigned char unsigned char _ttl = (unsigned char) multicastTTL; if (setsockopt(m_socket, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&_ttl, sizeof(_ttl))) { m_errno = LASTERROR; DBG(DBG_ERROR, "%s: could not set IP_MULTICAST_TTL from socket (%d)\n", __FUNCTION__, m_errno); return false; } break; } case AF_INET6: { // The v6 multicast TTL socket option requires that the value be passed in as an integer if (setsockopt(m_socket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char*)&multicastTTL, sizeof(multicastTTL))) { m_errno = LASTERROR; DBG(DBG_ERROR, "%s: could not set IPV6_MULTICAST_HOPS from socket (%d)\n", __FUNCTION__, m_errno); return false; } break; } default: m_errno = EINVAL; DBG(DBG_ERROR, "%s: address familly unknown (%d)\n", __FUNCTION__, m_addr->sa_family()); return false; } m_errno = 0; return true; } bool UdpSocket::SendData(const char* buf, size_t size) { if (IsValid()) { size_t s = sendto(m_socket, buf, size, 0, m_addr->sa(), m_addr->sa_len); if (s != size) { m_errno = LASTERROR; return false; } m_errno = 0; return true; } m_errno = ENOTSOCK; return false; } size_t UdpSocket::ReceiveData(void* buf, size_t n) { if (IsValid()) { m_errno = 0; size_t len = 0; // fill rest of data from buffer if (m_buffer) { if (m_bufptr < m_buffer + m_rcvlen) { len = m_rcvlen - (m_bufptr - m_buffer); if (len > n) len = n; memcpy(buf, m_bufptr, len); m_bufptr += len; return len; } } else if ((m_buffer = new char[m_buflen]) == NULL) { m_errno = ENOMEM; DBG(DBG_ERROR, "%s: cannot allocate %u bytes for buffer\n", __FUNCTION__, m_buflen); return 0; } // fill buffer with the next incoming datagram m_bufptr = m_buffer; m_rcvlen = 0; struct timeval tv; fd_set fds; int r = 0; tv = m_timeout; FD_ZERO(&fds); FD_SET(m_socket, &fds); r = select(m_socket + 1, &fds, NULL, NULL, &tv); if (r > 0) { if ((r = recvfrom(m_socket, m_buffer, m_buflen, 0, m_from->sa(), &m_from->sa_len)) > 0) { m_rcvlen = len = r; if (m_rcvlen == m_buflen) DBG(DBG_WARN, "%s: datagram have been truncated (%d)\n", __FUNCTION__, r); if (len > n) len = n; memcpy(buf, m_buffer, len); m_bufptr += len; } } if (r == 0) { m_errno = ETIMEDOUT; DBG(DBG_DEBUG, "%s: socket(%p) timed out\n", __FUNCTION__, &m_socket); } if (r < 0) { m_errno = LASTERROR; DBG(DBG_ERROR, "%s: socket(%p) read error (%d)\n", __FUNCTION__, &m_socket, m_errno); } return len; } m_errno = ENOTSOCK; return 0; } bool UdpSocket::IsValid() const { return (m_socket == INVALID_SOCKET_VALUE ? false : true); } std::string UdpSocket::GetRemoteAddrInfo() const { char host[INET6_ADDRSTRLEN]; memset(host, 0, INET6_ADDRSTRLEN); getnameinfo(m_from->sa(), m_from->sa_len, host, sizeof(host), NULL, 0, NI_NUMERICHOST); return host; } /////////////////////////////////////////////////////////////////////////////// //// //// UDP server socket //// UdpServerSocket::UdpServerSocket() : m_socket(INVALID_SOCKET_VALUE) , m_errno(0) , m_buffer(NULL) , m_bufptr(NULL) , m_buflen(SOCKET_BUFFER_SIZE) , m_rcvlen(0) { m_addr = new SocketAddress; m_from = new SocketAddress; m_timeout.tv_sec = SOCKET_READ_TIMEOUT_SEC; m_timeout.tv_usec = SOCKET_READ_TIMEOUT_USEC; } UdpServerSocket::UdpServerSocket(size_t bufferSize) : m_socket(INVALID_SOCKET_VALUE) , m_errno(0) , m_buffer(NULL) , m_bufptr(NULL) , m_buflen(bufferSize) , m_rcvlen(0) { m_addr = new SocketAddress; m_from = new SocketAddress; m_timeout.tv_sec = SOCKET_READ_TIMEOUT_SEC; m_timeout.tv_usec = SOCKET_READ_TIMEOUT_USEC; } UdpServerSocket::~UdpServerSocket() { if (IsValid()) { closesocket(m_socket); m_socket = INVALID_SOCKET_VALUE; } if (m_addr) { delete m_addr; m_addr = NULL; } if (m_from) { delete m_from; m_from = NULL; } if (m_buffer) { delete[] m_buffer; m_buffer = m_bufptr = NULL; } } bool UdpServerSocket::Create(SOCKET_AF_t af) { if (IsValid()) return false; m_addr->Clear(__addressFamily(af)); m_socket = socket(m_addr->sa_family(), SOCK_DGRAM, 0); if (!IsValid()) { m_errno = LASTERROR; DBG(DBG_ERROR, "%s: invalid socket (%d)\n", __FUNCTION__, m_errno); return false; } int opt_reuseaddr = 1; if (setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&opt_reuseaddr, sizeof(opt_reuseaddr))) { m_errno = LASTERROR; DBG(DBG_ERROR, "%s: could not set reuseaddr from socket (%d)\n", __FUNCTION__, m_errno); return false; } return true; } bool UdpServerSocket::IsValid() const { return (m_socket == INVALID_SOCKET_VALUE ? false : true); } bool UdpServerSocket::Bind(unsigned port) { if (!IsValid()) return false; m_addr->Clear(m_addr->sa_family()); switch (m_addr->sa_family()) { case AF_INET: { sockaddr_in* sa = (sockaddr_in*)m_addr->sa(); sa->sin_addr.s_addr = htonl(INADDR_ANY); sa->sin_port = htons(port); break; } case AF_INET6: { sockaddr_in6* sa = (sockaddr_in6*)m_addr->sa(); sa->sin6_addr = in6addr_any; sa->sin6_port = htons(port); break; } default: m_errno = EINVAL; DBG(DBG_ERROR, "%s: address familly unknown (%d)\n", __FUNCTION__, m_addr->sa_family()); return false; } if (bind(m_socket, m_addr->sa(), m_addr->sa_len) != 0) { m_errno = LASTERROR; DBG(DBG_ERROR, "%s: could not bind to address (%d)\n", __FUNCTION__, m_errno); return false; } m_errno = 0; return true; } bool UdpServerSocket::SetMulticastTTL(int multicastTTL) { if (!IsValid()) return false; switch(m_addr->sa_family()) { case AF_INET: { // The v4 multicast TTL socket option requires that the value be passed in an unsigned char unsigned char _ttl = (unsigned char) multicastTTL; if (setsockopt(m_socket, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&_ttl, sizeof(_ttl))) { m_errno = LASTERROR; DBG(DBG_ERROR, "%s: could not set IP_MULTICAST_TTL from socket (%d)\n", __FUNCTION__, m_errno); return false; } break; } case AF_INET6: { // The v6 multicast TTL socket option requires that the value be passed in as an integer if (setsockopt(m_socket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char*)&multicastTTL, sizeof(multicastTTL))) { m_errno = LASTERROR; DBG(DBG_ERROR, "%s: could not set IPV6_MULTICAST_HOPS from socket (%d)\n", __FUNCTION__, m_errno); return false; } break; } default: m_errno = EINVAL; DBG(DBG_ERROR, "%s: address familly unknown (%d)\n", __FUNCTION__, m_addr->sa_family()); return false; } m_errno = 0; return true; } bool UdpServerSocket::SetMulticastMembership(const char* group, bool join) { if (!IsValid()) return false; switch(m_addr->sa_family()) { case AF_INET: { struct ip_mreq mreq; if (inet_pton(AF_INET, group, &mreq.imr_multiaddr) == 0) { m_errno = LASTERROR; DBG(DBG_ERROR, "%s: invalid address (%d)\n", __FUNCTION__, m_errno); return false; } mreq.imr_interface.s_addr = htonl(INADDR_ANY); if (setsockopt(m_socket, IPPROTO_IP, join ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP, reinterpret_cast(&mreq), sizeof(mreq))) { m_errno = LASTERROR; DBG(DBG_ERROR, "%s: could not set multicast membership from socket (%d)\n", __FUNCTION__, m_errno); return false; } break; } case AF_INET6: { struct ipv6_mreq mreq; if (inet_pton(AF_INET6, group, &mreq.ipv6mr_multiaddr) == 0) { m_errno = LASTERROR; DBG(DBG_ERROR, "%s: invalid address (%d)\n", __FUNCTION__, m_errno); return false; } mreq.ipv6mr_interface = 0; if (setsockopt(m_socket, IPPROTO_IPV6, join ? IPV6_JOIN_GROUP : IPV6_LEAVE_GROUP, reinterpret_cast(&mreq), sizeof(mreq))) { m_errno = LASTERROR; DBG(DBG_ERROR, "%s: could not set multicast membership from socket (%d)\n", __FUNCTION__, m_errno); return false; } break; } default: m_errno = EINVAL; DBG(DBG_ERROR, "%s: address familly unknown (%d)\n", __FUNCTION__, m_addr->sa_family()); return false; } m_errno = 0; return true; } size_t UdpServerSocket::AwaitIncoming(timeval timeout) { if (IsValid()) { m_errno = 0; if (!m_buffer && (m_buffer = new char[m_buflen]) == NULL) { m_errno = ENOMEM; DBG(DBG_ERROR, "%s: cannot allocate %u bytes for buffer\n", __FUNCTION__, m_buflen); return 0; } // reset buffer m_bufptr = m_buffer; m_rcvlen = 0; struct timeval tv = timeout; fd_set fds; int r = 0; FD_ZERO(&fds); FD_SET(m_socket, &fds); r = select(m_socket + 1, &fds, NULL, NULL, &tv); if (r > 0) { if ((r = recvfrom(m_socket, m_buffer, m_buflen, 0, m_from->sa(), &m_from->sa_len)) > 0) { m_rcvlen = r; if (m_rcvlen == m_buflen) DBG(DBG_WARN, "%s: datagram have been truncated (%d)\n", __FUNCTION__, r); } } if (r == 0) { m_errno = ETIMEDOUT; DBG(DBG_DEBUG, "%s: socket(%p) timed out\n", __FUNCTION__, &m_socket); } if (r < 0) { m_errno = LASTERROR; DBG(DBG_ERROR, "%s: socket(%p) read error (%d)\n", __FUNCTION__, &m_socket, m_errno); } return m_rcvlen; } m_errno = ENOTSOCK; return 0; } size_t UdpServerSocket::AwaitIncoming() { return AwaitIncoming(m_timeout); } std::string UdpServerSocket::GetRemoteAddrInfo() const { char host[INET6_ADDRSTRLEN]; memset(host, 0, INET6_ADDRSTRLEN); getnameinfo(m_from->sa(), m_from->sa_len, host, sizeof(host), NULL, 0, NI_NUMERICHOST); return host; } size_t UdpServerSocket::ReadData(void* buf, size_t n) { if (IsValid()) { m_errno = 0; size_t len = 0; if (m_buffer && m_bufptr < m_buffer + m_rcvlen) { len = m_rcvlen - (m_bufptr - m_buffer); if (len > n) len = n; memcpy(buf, m_bufptr, len); m_bufptr += len; } return len; } m_errno = ENOTSOCK; return 0; } pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/socket.h000066400000000000000000000247141360567320200230440ustar00rootroot00000000000000/* * Copyright (C) 2014-2015 Jean-Luc Barriere * * 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 3, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef SOCKET_H #define SOCKET_H #include #include "os/os.h" #include // for size_t #include #define SOCKET_HOSTNAME_MAXSIZE 256 #define SOCKET_RCVBUF_MINSIZE 16384 #define SOCKET_READ_TIMEOUT_SEC 10 #define SOCKET_READ_TIMEOUT_USEC 0 #define SOCKET_READ_ATTEMPT 3 #define SOCKET_BUFFER_SIZE 1472 #define SOCKET_CONNECTION_REQUESTS 5 namespace NSROOT { typedef enum { SOCKET_AF_INET4, SOCKET_AF_INET6, } SOCKET_AF_t; struct SocketAddress; class NetSocket { public: NetSocket() { m_timeout.tv_sec = SOCKET_READ_TIMEOUT_SEC; m_timeout.tv_usec = SOCKET_READ_TIMEOUT_USEC; } virtual ~NetSocket() { } virtual bool SendData(const char* buf, size_t size) = 0; virtual size_t ReceiveData(void* buf, size_t n) = 0; void SetTimeout(timeval timeout) { m_timeout = timeout; } protected: struct timeval m_timeout; }; class TcpSocket : public NetSocket { friend class TcpServerSocket; public: TcpSocket(); virtual ~TcpSocket(); /** * @return the last error occuring on call */ int GetErrNo() const { return m_errno; } /** * Configure the number of timed out attempt reading the socket before * returning. * @param n the number of attempt */ void SetReadAttempt(int n) { m_attempt = n; } /** * Try to connect the socket to an address name, port. * @param server the destination address name * @param port the destination port * @param rcvbuf the size of read buffer, else 0 for SOCKET_RCVBUF_MINSIZE * @return true on success, else false */ virtual bool Connect(const char *server, unsigned port, int rcvbuf); /** * Send data into the socket. * @param buf the pointer to data * @param size the number of byte to send * @return true when succeeded, else false */ virtual bool SendData(const char* buf, size_t size); /** * Read data from the socket. * @param buf the pointer to write received data * @param n the number of byte to read * @return the number of received byte */ virtual size_t ReceiveData(void* buf, size_t n); /** * Gracefully disconnect the socket. */ virtual void Disconnect(); /** * @return true when socket is connected, else false */ virtual bool IsValid() const; /** * Check for read readiness. It returns -1 for errors, 0 for occurred * timeout, and >0 when incoming data are ready to read. * @param timeout * @return an int for status */ int Listen(timeval *timeout); /** * @return the socket handle */ net_socket_t GetHandle() const { return m_socket; } /** * @return the address string of this host */ std::string GetHostAddrInfo(); /** * @return this host name */ static const char* GetMyHostName(); protected: net_socket_t m_socket; int m_rcvbuf; int m_errno; int m_attempt; private: char* m_buffer; char* m_bufptr; size_t m_buflen; size_t m_rcvlen; // prevent copy TcpSocket(const TcpSocket&); TcpSocket& operator=(const TcpSocket&); }; class TcpServerSocket { public: TcpServerSocket(); ~TcpServerSocket(); /** * @return the last error occuring on call */ int GetErrNo() const { return m_errno; } /** * Initialize the socket for the given protocol. * @return true on success, else false */ bool Create(SOCKET_AF_t af); /** * @return true when socket is created, else false */ bool IsValid() const; /** * Bind the socket to the given port on any local addresses. * @param port * @return true on success, else false */ bool Bind(unsigned port); /** * Prepare to accept connections on the socket. * @param queueSize the maximum length for the queue of pending connections * @return true on success, else false */ bool ListenConnection(int queueSize = SOCKET_CONNECTION_REQUESTS); /** * Await a connection. * @param socket the tcp socket to connect on new request * @return true on success, else false */ bool AcceptConnection(TcpSocket& socket); /** * Close the socket. */ void Close(); /** * @return the socket handle */ net_socket_t GetHandle() const { return m_socket; } private: SocketAddress* m_addr; net_socket_t m_socket; int m_errno; unsigned m_requestQueueSize; // prevent copy TcpServerSocket(const TcpServerSocket&); TcpServerSocket& operator=(const TcpServerSocket&); }; class UdpSocket : public NetSocket { public: UdpSocket(); UdpSocket(size_t bufferSize); virtual ~UdpSocket(); /** * @return the last error occuring on call */ int GetErrNo() const { return m_errno; } /** * Send data into the socket. * @param buf the pointer to data * @param size the number of byte to send * @return true when succeeded, else false */ bool SendData(const char* buf, size_t size); /** * Read data from the socket. * @param buf the pointer to write received data * @param n the number of byte to read * @return the number of received byte */ size_t ReceiveData(void* buf, size_t n); /** * @return true when socket is opened, else false */ bool IsValid() const; /** * Open the socket and configure the given destination. * @param af the protocol * @param target the address name of destination * @param port * @return true on success, else false */ bool Open(SOCKET_AF_t af, const char* target, unsigned port); /** * Open the socket. * @param af the protocol * @param broadcast enable broadcast permission * @return true on success, else false */ bool Open(SOCKET_AF_t af, bool broadcast = false); /** * Configure the destination. * @param target the address name of destination * @param port * @return true on success, else false */ bool SetAddress(const char* target, unsigned port); /** * Configure hop limit value to be used for multicast packets on the opened * socket. * @param multicastTTL * @return true on success, else false */ bool SetMulticastTTL(int multicastTTL); /** * @return the address string of the remote host */ std::string GetRemoteAddrInfo() const; /** * @return the socket handle */ net_socket_t GetHandle() const { return m_socket; } private: SocketAddress* m_addr; SocketAddress* m_from; net_socket_t m_socket; int m_errno; char* m_buffer; char* m_bufptr; size_t m_buflen; size_t m_rcvlen; // prevent copy UdpSocket(const UdpSocket&); UdpSocket& operator=(const UdpSocket&); }; class UdpServerSocket { public: UdpServerSocket(); UdpServerSocket(size_t bufferSize); ~UdpServerSocket(); /** * @return the last error occuring on call */ int GetErrNo() const { return m_errno; } /** * Initialize the socket for the given protocol. * @return true on success, else false */ bool Create(SOCKET_AF_t af); /** * @return true when socket is created, else false */ bool IsValid() const; /** * Bind the socket to the given port on any local addresses. * @param port * @return true on success, else false */ bool Bind(unsigned port); /** * Configure hop limit value to be used for multicast packets on the opened * socket. * @param multicastTTL * @return true on success, else false */ bool SetMulticastTTL(int multicastTTL); /** * Configure socket to join/leave the given multicast group. * @param group address name of the group * @param join add/drop membership * @return true on success, else false */ bool SetMulticastMembership(const char *group, bool join); /** * Wait for incoming data. * @return the size of datagram else 0 when timeout occurred */ size_t AwaitIncoming(timeval timeout); size_t AwaitIncoming(); /** * @return the address string of the remote host that provided the incoming * datagram */ std::string GetRemoteAddrInfo() const; /** * Read remaining data from the datagram buffer. * @param buf the pointer to write received data * @param n the number of byte to read * @return the number of received byte */ size_t ReadData(void* buf, size_t n); /** * @return the socket handle */ net_socket_t GetHandle() const { return m_socket; } private: SocketAddress* m_addr; SocketAddress* m_from; net_socket_t m_socket; int m_errno; char* m_buffer; char* m_bufptr; size_t m_buflen; size_t m_rcvlen; struct timeval m_timeout; // prevent copy UdpServerSocket(const UdpServerSocket&); UdpServerSocket& operator=(const UdpServerSocket&); }; class UdpMessageReader : public NetSocket { public: UdpMessageReader(UdpServerSocket& boundSocket) : NetSocket() , m_bound(boundSocket) { } bool SendData(const char* buf, size_t size) { (void)buf; (void)size; return false; }; size_t ReceiveData(void* buf, size_t n) { size_t r = 0; if (m_bound.IsValid()) { if ((r = m_bound.ReadData(buf, n)) > 0) return r; if (m_bound.AwaitIncoming(m_timeout) > 0) return m_bound.ReadData(buf, n); } return r; } private: UdpServerSocket& m_bound; }; } #endif /* SOCKET_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/uriparser.cpp000066400000000000000000000071531360567320200241210ustar00rootroot00000000000000/* * Copyright (C) 2014-2015 Jean-Luc Barriere * * 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 3, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "uriparser.h" #include "cppdef.h" #include // for toupper #include // for strchr #include // for atoi using namespace NSROOT; URIParser::URIParser(const std::string& location) { size_t len = location.length(); m_buffer = new char[len + 1]; strncpy(m_buffer, location.c_str(), len); m_buffer[len] = '\0'; URIScan(m_buffer, &m_parts); } URIParser::~URIParser() { SAFE_DELETE_ARRAY(m_buffer); } void URIParser::URIScan(char *uri, URI_t *parts) { char *p; char *after_scheme = uri; memset(parts, '\0', sizeof(URI_t)); /* look for fragment identifier */ if ((p = strchr(uri, '#')) != NULL) { *p = '\0'; parts->fragment = ++p; } if ((p = strchr(uri, ' ')) != NULL) *p = '\0'; for (p = after_scheme; *p; p++) { if (*p == '/' || *p == '#' || *p == '?') break; if (*p == ':') { /* terminate scheme */ *p = '\0'; /* scheme has been specified */ if (toupper(after_scheme[0]) == 'U' && toupper(after_scheme[1]) == 'R' && toupper(after_scheme[2]) == 'L') { /* ignore IETF's URL: pre-prefix */ parts->scheme = NULL; } else { parts->scheme = after_scheme; } after_scheme = p + 1; break; } } p = after_scheme; if (*p == '/') { if (p[1] == '/') { /* host has been specified */ parts->host = p + 2; /* terminate scheme */ *p = '\0'; /* look for end of host:port if any */ if ((p = strchr(parts->host, '/')) != NULL) { /* terminate host:port */ *p = '\0'; /* root has been found */ parts->absolute = p + 1; } /* look for user:pass from host */ if ((p = strchr(parts->host, '@')) != NULL) { /* terminate user:pass */ *p = '\0'; parts->user = parts->host; parts->host = p + 1; /* look for pass from user */ if ((p = strchr(parts->user, ':')) != NULL) { /* terminate user */ *p = '\0'; parts->pass = p + 1; } } /* look for port from [host] */ if ((p = strchr(parts->host, ']')) != NULL) { /* terminate host */ *p = '\0'; ++(parts->host); if (p[1] == ':') parts->port = (unsigned) atoi(p + 2); } else { /* look for port from host */ if ((p = strchr(parts->host, ':')) != NULL) if (p) { /* terminate host */ *p = '\0'; parts->port = (unsigned) atoi(p + 1); } } } else { /* root found but no host */ parts->absolute = p + 1; } } else { /* NULL for "" */ parts->relative = (*after_scheme) ? after_scheme : NULL; } } pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/uriparser.h000066400000000000000000000037541360567320200235710ustar00rootroot00000000000000/* * Copyright (C) 2014-2015 Jean-Luc Barriere * * 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 3, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef URIPARSER_H #define URIPARSER_H #include #include namespace NSROOT { class URIParser { public: URIParser(const std::string& location); ~URIParser(); const char *Scheme() const { return m_parts.scheme; } const char *Host() const { return m_parts.host; } unsigned Port() const { return m_parts.port; } const char *User() const { return m_parts.user; } const char *Pass() const { return m_parts.pass; } bool IsRelative() const { return m_parts.relative ? true : false; } const char *Path() const { return IsRelative() ? m_parts.relative : m_parts.absolute; } const char *Fragment() const { return m_parts.fragment; } private: // prevent copy URIParser(const URIParser&); URIParser& operator=(const URIParser&); typedef struct { char *scheme; char *host; unsigned port; char *user; char *pass; char *absolute; char *relative; char *fragment; } URI_t; URI_t m_parts; char *m_buffer; static void URIScan(char *uri, URI_t *parts); }; } #endif /* URIPARSER_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/urlencoder.h000066400000000000000000000036521360567320200237140ustar00rootroot00000000000000/* * Copyright (C) 2017 Jean-Luc Barriere * * 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 3, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef URLENCODER_H #define URLENCODER_H #include #include #include #define urlencode __urlencode inline std::string __urlencode(const std::string& str) { std::string out; out.reserve(2 * str.length()); const char* cstr = str.c_str(); while (*cstr) { if (isalnum(*cstr) || *cstr == '-' || *cstr == '_' || *cstr == '.' || *cstr == '~') out.push_back(*cstr); else { char buf[4]; sprintf(buf, "%%%.2x", static_cast(*cstr)); out.append(buf); } ++cstr; } return out; } #define urldecode __urldecode inline std::string __urldecode(const std::string& str) { std::string out; out.reserve(str.length()); const char* cstr = str.c_str(); while (*cstr) { char c = *cstr; if (c == '%') { int v; char buf[3]; strncpy(buf, cstr + 1, 3); buf[2] = '\0'; if (sscanf(buf, "%x", &v) == 1 || sscanf(buf, "%X", &v) == 1) { c = static_cast(v); cstr += 2; } } out.push_back(c); ++cstr; } return out; } #endif /* URLENCODER_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/wscontent.cpp000066400000000000000000000040531360567320200241250ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * 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 3, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "wscontent.h" #include // for strcmp using namespace NSROOT; struct mimetype { const char *content_type; const char *extn; }; static struct mimetype mimetypes[] = { { "", "" }, { "application/x-www-form-urlencoded", "" }, { "application/soap+xml", "xml" }, { "application/json", "txt" }, { "text/xml", "xml" }, { "text/plain", "txt" }, { "image/gif", "gif" }, { "image/png", "png" }, { "image/jpeg", "jpg" }, { "application/octet-stream", "" } }; CT_t NSROOT::ContentTypeFromMime(const char *mime) { int i; for (i = 0; i < CT_UNKNOWN; ++i) { if (0 == strcmp(mimetypes[i].content_type, mime)) return (CT_t)i; } return CT_UNKNOWN; } const char* NSROOT::MimeFromContentType(CT_t ct) { if (ct >= 0 && ct < CT_UNKNOWN) return mimetypes[ct].content_type; return mimetypes[CT_UNKNOWN].content_type; } const char* NSROOT::ExtnFromContentType(CT_t ct) { if (ct >= 0 && ct < CT_UNKNOWN) return mimetypes[ct].extn; return mimetypes[CT_UNKNOWN].extn; } pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/wscontent.h000066400000000000000000000025741360567320200236000ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * 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 3, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef WSCONTENT_H #define WSCONTENT_H #include namespace NSROOT { typedef enum { CT_NONE = 0, CT_FORM = 1, CT_SOAP, CT_JSON, CT_XML, CT_TXT, CT_GIF, CT_PNG, CT_JPG, CT_UNKNOWN // Keep at last } CT_t; CT_t ContentTypeFromMime(const char* mime); const char* MimeFromContentType(CT_t ct); const char* ExtnFromContentType(CT_t ct); typedef enum { CE_NONE = 0, CE_DEFLATE = 1, CE_GZIP, CE_UNKNOWN // Keep at last } CE_t; } #endif /* WSCONTENT_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/wsrequest.cpp000066400000000000000000000162721360567320200241510ustar00rootroot00000000000000/* * Copyright (C) 2014-2015 Jean-Luc Barriere * * 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 3, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "wsrequest.h" #include "urlencoder.h" #include "debug.h" #include #include // for strlen using namespace NSROOT; WSRequest::WSRequest(const std::string& server, unsigned port) : m_server(server) , m_port(port) , m_secure_uri(false) , m_service_url() , m_service_method(HRM_GET) , m_charset(REQUEST_STD_CHARSET) , m_accept(CT_NONE) , m_contentType(CT_FORM) , m_contentData() { if (port == 443) m_secure_uri = true; // by default allow content encoding if possible RequestAcceptEncoding(true); } WSRequest::WSRequest(const std::string& server, unsigned port, bool secureURI) : m_server(server) , m_port(port) , m_secure_uri(secureURI) , m_service_url() , m_service_method(HRM_GET) , m_charset(REQUEST_STD_CHARSET) , m_accept(CT_NONE) , m_contentType(CT_FORM) , m_contentData() { // by default allow content encoding if possible RequestAcceptEncoding(true); } WSRequest::WSRequest(const URIParser& uri, HRM_t method) : m_port(0) , m_secure_uri(false) , m_service_method(method) , m_charset(REQUEST_STD_CHARSET) , m_accept(CT_NONE) , m_contentType(CT_FORM) , m_contentData() { if (uri.Host()) m_server.assign(uri.Host()); if (uri.Scheme() && strncmp(uri.Scheme(), "https", 5) == 0) { m_secure_uri = true; m_port = uri.Port() ? uri.Port() : 443; } else m_port = uri.Port() ? uri.Port() : 80; m_service_url = "/"; if (uri.Path()) m_service_url.append(uri.Path()); // by default allow content encoding if possible RequestAcceptEncoding(true); } WSRequest::~WSRequest() { } void WSRequest::RequestService(const std::string& url, HRM_t method) { m_service_url = url; m_service_method = method; } void WSRequest::RequestAccept(CT_t contentType) { m_accept = contentType; } void WSRequest::RequestAcceptEncoding(bool yesno) { #if HAVE_ZLIB if (yesno) SetHeader("Accept-Encoding", "gzip, deflate"); else SetHeader("Accept-Encoding", ""); #else (void)yesno; SetHeader("Accept-Encoding", ""); #endif } void WSRequest::SetUserAgent(const std::string& value) { m_userAgent = value; } void WSRequest::SetContentParam(const std::string& param, const std::string& value) { if (m_contentType != CT_FORM) return; if (!m_contentData.empty()) m_contentData.append("&"); m_contentData.append(param).append("=").append(urlencode(value)); } void WSRequest::SetContentCustom(CT_t contentType, const char *content) { m_contentType = contentType; m_contentData = content; } void WSRequest::SetHeader(const std::string& field, const std::string& value) { m_headers[field] = value; } void WSRequest::ClearContent() { m_contentData.clear(); m_contentType = CT_FORM; } void WSRequest::MakeMessage(std::string& msg) const { switch (m_service_method) { case HRM_GET: MakeMessageGET(msg); break; case HRM_POST: MakeMessagePOST(msg); break; case HRM_HEAD: MakeMessageHEAD(msg); break; case HRM_SUBSCRIBE: MakeMessageHEAD(msg, "SUBSCRIBE"); break; case HRM_UNSUBSCRIBE: MakeMessageHEAD(msg, "UNSUBSCRIBE"); break; case HRM_NOTIFY: MakeMessagePOST(msg, "NOTIFY"); break; default: break; } } void WSRequest::MakeMessageGET(std::string& msg, const char* method) const { char buf[32]; msg.clear(); msg.reserve(256); msg.append(method).append(" ").append(m_service_url); if (!m_contentData.empty()) msg.append("?").append(m_contentData); msg.append(" " REQUEST_PROTOCOL "\r\n"); sprintf(buf, "%u", m_port); msg.append("Host: ").append(m_server).append(":").append(buf).append("\r\n"); if (m_userAgent.empty()) msg.append("User-Agent: " REQUEST_USER_AGENT "\r\n"); else msg.append("User-Agent: ").append(m_userAgent).append("\r\n"); msg.append("Connection: " REQUEST_CONNECTION "\r\n"); if (m_accept != CT_NONE) msg.append("Accept: ").append(MimeFromContentType(m_accept)).append("\r\n"); msg.append("Accept-Charset: ").append(m_charset).append("\r\n"); for (std::map::const_iterator it = m_headers.begin(); it != m_headers.end(); ++it) msg.append(it->first).append(": ").append(it->second).append("\r\n"); msg.append("\r\n"); } void WSRequest::MakeMessagePOST(std::string& msg, const char* method) const { char buf[32]; size_t content_len = m_contentData.size(); msg.clear(); msg.reserve(256); msg.append(method).append(" ").append(m_service_url).append(" " REQUEST_PROTOCOL "\r\n"); sprintf(buf, "%u", m_port); msg.append("Host: ").append(m_server).append(":").append(buf).append("\r\n"); if (m_userAgent.empty()) msg.append("User-Agent: " REQUEST_USER_AGENT "\r\n"); else msg.append("User-Agent: ").append(m_userAgent).append("\r\n"); msg.append("Connection: " REQUEST_CONNECTION "\r\n"); if (m_accept != CT_NONE) msg.append("Accept: ").append(MimeFromContentType(m_accept)).append("\r\n"); msg.append("Accept-Charset: ").append(m_charset).append("\r\n"); if (content_len) { sprintf(buf, "%lu", (unsigned long)content_len); msg.append("Content-Type: ").append(MimeFromContentType(m_contentType)); msg.append("; charset=" REQUEST_STD_CHARSET "\r\n"); msg.append("Content-Length: ").append(buf).append("\r\n"); } for (std::map::const_iterator it = m_headers.begin(); it != m_headers.end(); ++it) msg.append(it->first).append(": ").append(it->second).append("\r\n"); msg.append("\r\n"); if (content_len) msg.append(m_contentData); } void WSRequest::MakeMessageHEAD(std::string& msg, const char* method) const { char buf[32]; msg.clear(); msg.reserve(256); msg.append(method).append(" ").append(m_service_url); if (!m_contentData.empty()) msg.append("?").append(m_contentData); msg.append(" " REQUEST_PROTOCOL "\r\n"); sprintf(buf, "%u", m_port); msg.append("Host: ").append(m_server).append(":").append(buf).append("\r\n"); if (m_userAgent.empty()) msg.append("User-Agent: " REQUEST_USER_AGENT "\r\n"); else msg.append("User-Agent: ").append(m_userAgent).append("\r\n"); msg.append("Connection: " REQUEST_CONNECTION "\r\n"); if (m_accept != CT_NONE) msg.append("Accept: ").append(MimeFromContentType(m_accept)).append("\r\n"); msg.append("Accept-Charset: ").append(m_charset).append("\r\n"); for (std::map::const_iterator it = m_headers.begin(); it != m_headers.end(); ++it) msg.append(it->first).append(": ").append(it->second).append("\r\n"); msg.append("\r\n"); } pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/wsrequest.h000066400000000000000000000055651360567320200236210ustar00rootroot00000000000000/* * Copyright (C) 2014-2015 Jean-Luc Barriere * * 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 3, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef WSREQUEST_H #define WSREQUEST_H #include #include "wscontent.h" #include "uriparser.h" #include // for size_t #include #include #define REQUEST_PROTOCOL "HTTP/1.1" #define REQUEST_USER_AGENT "libcppmyth/2.0" #define REQUEST_CONNECTION "close" // "keep-alive" #define REQUEST_STD_CHARSET "utf-8" namespace NSROOT { typedef enum { HRM_GET, HRM_POST, HRM_HEAD, HRM_SUBSCRIBE, HRM_UNSUBSCRIBE, HRM_NOTIFY, } HRM_t; class WSRequest { public: WSRequest(const std::string& server, unsigned port); WSRequest(const std::string& server, unsigned port, bool secureURI); WSRequest(const URIParser& uri, HRM_t method = HRM_GET); ~WSRequest(); void RequestService(const std::string& url, HRM_t method = HRM_GET); void RequestAccept(CT_t contentType); void RequestAcceptEncoding(bool yesno); void SetUserAgent(const std::string& value); void SetContentParam(const std::string& param, const std::string& value); void SetContentCustom(CT_t contentType, const char *content); void SetHeader(const std::string& field, const std::string& value); const std::string& GetContent() const { return m_contentData; } void ClearContent(); void MakeMessage(std::string& msg) const; const std::string& GetServer() const { return m_server; } unsigned GetPort() const { return m_port; } bool IsSecureURI() const { return m_secure_uri; } private: std::string m_server; unsigned m_port; bool m_secure_uri; std::string m_service_url; HRM_t m_service_method; std::string m_charset; CT_t m_accept; CT_t m_contentType; std::string m_contentData; std::map m_headers; std::string m_userAgent; void MakeMessageGET(std::string& msg, const char* method = "GET") const; void MakeMessagePOST(std::string& msg, const char* method = "POST") const; void MakeMessageHEAD(std::string& msg, const char* method = "HEAD") const; }; } #endif /* WSREQUEST_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/wsresponse.cpp000066400000000000000000000270271360567320200243170ustar00rootroot00000000000000/* * Copyright (C) 2014-2015 Jean-Luc Barriere * * 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 3, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "wsresponse.h" #include "securesocket.h" #include "debug.h" #include "cppdef.h" #include "compressor.h" #include // for atol #include #include #define HTTP_TOKEN_MAXSIZE 20 #define HTTP_HEADER_MAXSIZE 4000 #define RESPONSE_BUFFER_SIZE 4000 using namespace NSROOT; bool WSResponse::ReadHeaderLine(NetSocket *socket, const char *eol, std::string& line, size_t *len) { char buf[RESPONSE_BUFFER_SIZE]; const char *s_eol; int p = 0, p_eol = 0, l_eol; size_t l = 0; if (eol != NULL) s_eol = eol; else s_eol = "\n"; l_eol = strlen(s_eol); line.clear(); do { if (socket->ReceiveData(&buf[p], 1) > 0) { if (buf[p++] == s_eol[p_eol]) { if (++p_eol >= l_eol) { buf[p - l_eol] = '\0'; line.append(buf); l += p - l_eol; break; } } else { p_eol = 0; if (p > (RESPONSE_BUFFER_SIZE - 2 - l_eol)) { buf[p] = '\0'; line.append(buf); l += p; p = 0; } } } else { /* No EOL found until end of data */ *len = l; return false; } } while (l < HTTP_HEADER_MAXSIZE); *len = l; return true; } WSResponse::WSResponse(const WSRequest &request) : m_socket(NULL) , m_successful(false) , m_statusCode(0) , m_serverInfo() , m_etag() , m_location() , m_contentType(CT_NONE) , m_contentEncoding(CE_NONE) , m_contentChunked(false) , m_contentLength(0) , m_consumed(0) , m_chunkBuffer(NULL) , m_chunkPtr(NULL) , m_chunkEOR(NULL) , m_chunkEnd(NULL) , m_decoder(NULL) { if (request.IsSecureURI()) m_socket = SSLSessionFactory::Instance().NewSocket(); else m_socket = new TcpSocket(); if (!m_socket) DBG(DBG_ERROR, "%s: create socket failed\n", __FUNCTION__); else if (m_socket->Connect(request.GetServer().c_str(), request.GetPort(), SOCKET_RCVBUF_MINSIZE)) { m_socket->SetReadAttempt(6); // 60 sec to hang up if (SendRequest(request) && GetResponse()) { if (m_statusCode < 200) DBG(DBG_WARN, "%s: status %d\n", __FUNCTION__, m_statusCode); else if (m_statusCode < 300) m_successful = true; else if (m_statusCode < 400) m_successful = false; else if (m_statusCode < 500) DBG(DBG_ERROR, "%s: bad request (%d)\n", __FUNCTION__, m_statusCode); else DBG(DBG_ERROR, "%s: server error (%d)\n", __FUNCTION__, m_statusCode); } else DBG(DBG_ERROR, "%s: invalid response\n", __FUNCTION__); } } WSResponse::~WSResponse() { SAFE_DELETE(m_decoder); SAFE_DELETE_ARRAY(m_chunkBuffer); SAFE_DELETE(m_socket); } bool WSResponse::SendRequest(const WSRequest &request) { std::string msg; request.MakeMessage(msg); DBG(DBG_PROTO, "%s: %s\n", __FUNCTION__, msg.c_str()); if (!m_socket->SendData(msg.c_str(), msg.size())) { DBG(DBG_ERROR, "%s: failed (%d)\n", __FUNCTION__, m_socket->GetErrNo()); return false; } return true; } bool WSResponse::GetResponse() { size_t len; std::string strread; char token[HTTP_TOKEN_MAXSIZE + 1]; int n = 0, token_len = 0; bool ret = false; token[0] = 0; while (ReadHeaderLine(m_socket, "\r\n", strread, &len)) { const char *line = strread.c_str(), *val = NULL; int value_len = 0; DBG(DBG_PROTO, "%s: %s\n", __FUNCTION__, line); /* * The first line of a Response message is the Status-Line, consisting of * the protocol version followed by a numeric status code and its associated * textual phrase, with each element separated by SP characters. */ if (++n == 1) { int status; if (len > 5 && 0 == memcmp(line, "HTTP", 4) && 1 == sscanf(line, "%*s %d", &status)) { /* We have received a valid feedback */ m_statusCode = status; ret = true; } else { /* Not a response header */ return false; } } if (len == 0) { /* End of header */ break; } /* * Header fields can be extended over multiple lines by preceding each * extra line with at least one SP or HT. */ if ((line[0] == ' ' || line[0] == '\t') && token_len) { /* Append value of previous token */ val = line; } /* * Each header field consists of a name followed by a colon (":") and the * field value. Field names are case-insensitive. The field value MAY be * preceded by any amount of LWS, though a single SP is preferred. */ else if ((val = strchr(line, ':'))) { int p; if ((token_len = val - line) > HTTP_TOKEN_MAXSIZE) token_len = HTTP_TOKEN_MAXSIZE; for (p = 0; p < token_len; ++p) token[p] = toupper(line[p]); token[token_len] = 0; value_len = len - (val - line + 1); while (*(++val) == ' ' && value_len > 0) --value_len; m_headers.push_front(std::make_pair(token, "")); } else { /* Unknown syntax! Close previous token */ token_len = 0; token[token_len] = 0; } if (token_len) { m_headers.front().second.append(val); switch (token_len) { case 4: if (memcmp(token, "ETAG", token_len) == 0) m_etag.append(val); break; case 6: if (memcmp(token, "SERVER", token_len) == 0) m_serverInfo.append(val); break; case 8: if (memcmp(token, "LOCATION", token_len) == 0) m_location.append(val); break; case 12: if (memcmp(token, "CONTENT-TYPE", token_len) == 0) m_contentType = ContentTypeFromMime(val); break; case 14: if (memcmp(token, "CONTENT-LENGTH", token_len) == 0) m_contentLength = atol(val); break; case 16: if (memcmp(token, "CONTENT-ENCODING", token_len) == 0) { if (value_len > 6 && memcmp(val, "deflate", 7) == 0) m_contentEncoding = CE_DEFLATE; else if (value_len > 3 && memcmp(val, "gzip", 4) == 0) m_contentEncoding = CE_GZIP; else { m_contentEncoding = CE_UNKNOWN; DBG(DBG_ERROR, "%s: unsupported content encoding (%s) %d\n", __FUNCTION__, val, value_len); } } break; case 17: if (memcmp(token, "TRANSFER-ENCODING", token_len) == 0) { if (value_len > 6 && memcmp(val, "chunked", 7) == 0) m_contentChunked = true; } break; default: break; } } } return ret; } size_t WSResponse::ReadChunk(void *buf, size_t buflen) { size_t s = 0; if (m_contentChunked) { // no more pending byte in chunk buffer if (m_chunkPtr >= m_chunkEnd) { // process next chunk SAFE_DELETE_ARRAY(m_chunkBuffer); m_chunkBuffer = m_chunkPtr = m_chunkEOR = m_chunkEnd = NULL; std::string strread; size_t len = 0; while (ReadHeaderLine(m_socket, "\r\n", strread, &len) && len == 0); DBG(DBG_PROTO, "%s: chunked data (%s)\n", __FUNCTION__, strread.c_str()); std::string chunkStr("0x0"); uint32_t chunkSize; if (!strread.empty() && sscanf(chunkStr.append(strread).c_str(), "%x", &chunkSize) == 1 && chunkSize > 0) { if (!(m_chunkBuffer = new char[chunkSize])) return 0; m_chunkPtr = m_chunkEOR = m_chunkBuffer; m_chunkEnd = m_chunkBuffer + chunkSize; } else return 0; // that's the end of chunks } // fill chunk buffer if (m_chunkPtr >= m_chunkEOR) { // ask for new data to fill in the chunk buffer // fill at last read position and until to the end m_chunkEOR += m_socket->ReceiveData(m_chunkEOR, m_chunkEnd - m_chunkEOR); } if ((s = m_chunkEOR - m_chunkPtr) > buflen) s = buflen; memcpy(buf, m_chunkPtr, s); m_chunkPtr += s; m_consumed += s; } return s; } int WSResponse::SocketStreamReader(void *hdl, void *buf, int sz) { WSResponse *resp = static_cast(hdl); if (resp == NULL) return 0; size_t s = 0; // let read on unknown length if (!resp->m_contentLength) s = resp->m_socket->ReceiveData(buf, sz); else if (resp->m_contentLength > resp->m_consumed) { size_t len = resp->m_contentLength - resp->m_consumed; s = resp->m_socket->ReceiveData(buf, len > (size_t)sz ? (size_t)sz : len); } resp->m_consumed += s; return s; } int WSResponse::ChunkStreamReader(void *hdl, void *buf, int sz) { WSResponse *resp = static_cast(hdl); return (resp == NULL ? 0 : resp->ReadChunk(buf, sz)); } size_t WSResponse::ReadContent(char* buf, size_t buflen) { size_t s = 0; if (!m_contentChunked) { if (m_contentEncoding == CE_NONE) { // let read on unknown length if (!m_contentLength) s = m_socket->ReceiveData(buf, buflen); else if (m_contentLength > m_consumed) { size_t len = m_contentLength - m_consumed; s = m_socket->ReceiveData(buf, len > buflen ? buflen : len); } m_consumed += s; } else if (m_contentEncoding == CE_GZIP || m_contentEncoding == CE_DEFLATE) { if (m_decoder == NULL) m_decoder = new Decompressor(&SocketStreamReader, this); if (m_decoder->HasOutputData()) s = m_decoder->ReadOutput(buf, buflen); if (s == 0 && !m_decoder->IsCompleted()) { if (m_decoder->HasStreamError()) DBG(DBG_ERROR, "%s: decoding failed: stream error\n", __FUNCTION__); else if (m_decoder->HasBufferError()) DBG(DBG_ERROR, "%s: decoding failed: buffer error\n", __FUNCTION__); else DBG(DBG_ERROR, "%s: decoding failed\n", __FUNCTION__); } } } else { if (m_contentEncoding == CE_NONE) { s = ReadChunk(buf, buflen); } else if (m_contentEncoding == CE_GZIP || m_contentEncoding == CE_DEFLATE) { if (m_decoder == NULL) m_decoder = new Decompressor(&ChunkStreamReader, this); if (m_decoder->HasOutputData()) s = m_decoder->ReadOutput(buf, buflen); if (s == 0 && !m_decoder->IsCompleted()) { if (m_decoder->HasStreamError()) DBG(DBG_ERROR, "%s: decoding failed: stream error\n", __FUNCTION__); else if (m_decoder->HasBufferError()) DBG(DBG_ERROR, "%s: decoding failed: buffer error\n", __FUNCTION__); else DBG(DBG_ERROR, "%s: decoding failed\n", __FUNCTION__); } } } return s; } bool WSResponse::GetHeaderValue(const std::string& header, std::string& value) { for (HeaderList::const_iterator it = m_headers.begin(); it != m_headers.end(); ++it) { if (it->first != header) continue; value.assign(it->second); return true; } return false; } pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/private/wsresponse.h000066400000000000000000000055061360567320200237620ustar00rootroot00000000000000/* * Copyright (C) 2014-2015 Jean-Luc Barriere * * 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 3, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef WSRESPONSE_H #define WSRESPONSE_H #include #include "wscontent.h" #include "wsrequest.h" #include // for size_t #include #include namespace NSROOT { class NetSocket; class TcpSocket; class Decompressor; class WSResponse { public: WSResponse(const WSRequest& request); ~WSResponse(); bool IsSuccessful() const { return m_successful; } bool IsChunkedTransfer() const { return m_contentChunked; } size_t GetContentLength() const { return m_contentLength; } size_t ReadContent(char *buf, size_t buflen); size_t GetConsumed() const { return m_consumed; } int GetStatusCode() const { return m_statusCode; } const std::string& Redirection() const { return m_location; } bool GetHeaderValue(const std::string& header, std::string& value); static bool ReadHeaderLine(NetSocket *socket, const char *eol, std::string& line, size_t *len); private: TcpSocket *m_socket; bool m_successful; int m_statusCode; std::string m_serverInfo; std::string m_etag; std::string m_location; CT_t m_contentType; CE_t m_contentEncoding; bool m_contentChunked; size_t m_contentLength; size_t m_consumed; char* m_chunkBuffer; ///< The chunk data buffer char* m_chunkPtr; ///< The next position to read data from the chunk char* m_chunkEOR; ///< The end of received data in the chunk char* m_chunkEnd; ///< The end of the chunk buffer Decompressor *m_decoder; typedef std::list > HeaderList; HeaderList m_headers; // prevent copy WSResponse(const WSResponse&); WSResponse& operator=(const WSResponse&); bool SendRequest(const WSRequest& request); bool GetResponse(); size_t ReadChunk(void *buf, size_t buflen); static int SocketStreamReader(void *hdl, void *buf, int sz); static int ChunkStreamReader(void *hdl, void *buf, int sz); }; } #endif /* WSRESPONSE_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/proto/000077500000000000000000000000001360567320200210645ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/proto/mythprotobase.cpp000066400000000000000000001436751360567320200245100ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "mythprotobase.h" #include "../private/debug.h" #include "../private/socket.h" #include "../private/os/threads/mutex.h" #include "../private/cppdef.h" #include "../private/builtin.h" #include #include using namespace Myth; typedef struct { unsigned version; char token[44]; // up to 43 chars used in v87 + the terminating NULL character } myth_protomap_t; static myth_protomap_t protomap[] = { {91, "BuzzOff"}, {90, "BuzzCut"}, {89, "BuzzKill"}, {88, "XmasGift"}, {87, "(ノಠ益ಠ)ノ彡┻â”â”»_No_entiendo!)"}, {86, "(ノಠ益ಠ)ノ彡┻â”â”»"}, {85, "BluePool"}, {84, "CanaryCoalmine"}, {83, "BreakingGlass"}, {82, "IdIdO"}, {81, "MultiRecDos"}, {80, "TaDah!"}, {79, "BasaltGiant"}, {77, "WindMark"}, {76, "FireWilde"}, {75, "SweetRock"}, {0, ""} }; ProtoBase::ProtoBase(const std::string& server, unsigned port) : m_mutex(new OS::CMutex) , m_socket(new TcpSocket()) , m_protoVersion(0) , m_server(server) , m_port(port) , m_hang(false) , m_tainted(false) , m_msgLength(0) , m_msgConsumed(0) , m_isOpen(false) , m_protoError(ERROR_NO_ERROR) { m_socket->SetReadAttempt(6); // 60 sec to hang up } ProtoBase::~ProtoBase() { this->Close(); SAFE_DELETE(m_socket); SAFE_DELETE(m_mutex); } void ProtoBase::HangException() { DBG(DBG_ERROR, "%s: protocol connection hang with error %d\n", __FUNCTION__, m_socket->GetErrNo()); m_tainted = m_hang = true; ProtoBase::Close(); // Note: Opening connection successfully will reset m_hang } bool ProtoBase::SendCommand(const char *cmd, bool feedback) { size_t l = strlen(cmd); if (m_msgConsumed != m_msgLength) { DBG(DBG_ERROR, "%s: did not consume everything\n", __FUNCTION__); FlushMessage(); } if (l > 0 && l < PROTO_SENDMSG_MAXSIZE) { char buf[9]; std::string msg; msg.reserve(l + 8); sprintf(buf, "%-8u", (unsigned)l); msg.append(buf).append(cmd); DBG(DBG_PROTO, "%s: %s\n", __FUNCTION__, cmd); if (m_socket->SendData(msg.c_str(), msg.size())) { if (feedback) return RcvMessageLength(); return true; } DBG(DBG_ERROR, "%s: failed (%d)\n", __FUNCTION__, m_socket->GetErrNo()); HangException(); return false; } DBG(DBG_ERROR, "%s: message size out of bound (%d)\n", __FUNCTION__, (int)l); return false; } size_t ProtoBase::GetMessageLength() const { return m_msgLength; } /** * Read one field from the backend response * @param field * @return true : false */ bool ProtoBase::ReadField(std::string& field) { const char *str_sep = PROTO_STR_SEPARATOR; size_t str_sep_len = PROTO_STR_SEPARATOR_LEN; char buf[PROTO_BUFFER_SIZE]; size_t p = 0, p_ss = 0, l = m_msgLength, c = m_msgConsumed; field.clear(); if ( c >= l) return false; for (;;) { if (l > c) { if (m_socket->ReceiveData(&buf[p], 1) < 1) { HangException(); return false; } ++c; if (buf[p++] == str_sep[p_ss]) { if (++p_ss >= str_sep_len) { // Append data until separator before exit buf[p - str_sep_len] = '\0'; field.append(buf); break; } } else { p_ss = 0; if (p > (PROTO_BUFFER_SIZE - 2 - str_sep_len)) { // Append data before flushing to refill the following buf[p] = '\0'; field.append(buf); p = 0; } } } else { // All is consumed. Append rest of data before exit buf[p] = '\0'; field.append(buf); break; } } // Renew consumed or reset when no more data if (l > c) m_msgConsumed = c; else m_msgConsumed = m_msgLength = 0; return true; } bool ProtoBase::IsMessageOK(const std::string& field) const { if (field.size() == 2) { if ((field[0] == 'O' || field[0] == 'o') && (field[1] == 'K' || field[1] == 'k')) return true; } return false; } size_t ProtoBase::FlushMessage() { char buf[PROTO_BUFFER_SIZE]; size_t r, n = 0, f = m_msgLength - m_msgConsumed; while (f > 0) { r = (f > PROTO_BUFFER_SIZE ? PROTO_BUFFER_SIZE : f); if (m_socket->ReceiveData(buf, r) != r) { HangException(); break; } f -= r; n += r; } m_msgLength = m_msgConsumed = 0; return n; } bool ProtoBase::RcvMessageLength() { char buf[9]; uint32_t val = 0; // If not placed on head of new response then break if (m_msgLength > 0) return false; if (m_socket->ReceiveData(buf, 8) == 8) { if (0 == string_to_uint32(buf, &val)) { DBG(DBG_PROTO, "%s: %" PRIu32 "\n", __FUNCTION__, val); m_msgLength = (size_t)val; m_msgConsumed = 0; return true; } DBG(DBG_ERROR, "%s: failed ('%s')\n", __FUNCTION__, buf); } HangException(); return false; } /** * Parse feedback of command MYTH_PROTO_VERSION and return protocol version * of backend * @param version * @return true : false */ bool ProtoBase::RcvVersion(unsigned *version) { std::string field; uint32_t val = 0; /* * The string we just consumed was either "ACCEPT" or "REJECT". In * either case, the number following it is the correct version, and * we use it as an unsigned. */ if (!ReadField(field)) goto out; if (!ReadField(field)) goto out; if (FlushMessage()) { DBG(DBG_ERROR, "%s: did not consume everything\n", __FUNCTION__); return false; } if (0 != string_to_uint32(field.c_str(), &val)) goto out; *version = (unsigned)val; return true; out: DBG(DBG_ERROR, "%s: failed ('%s')\n", __FUNCTION__, field.c_str()); FlushMessage(); return false; } bool ProtoBase::OpenConnection(int rcvbuf) { static unsigned my_version = 0; char cmd[256]; myth_protomap_t *map; unsigned tmp_ver; OS::CLockGuard lock(*m_mutex); if (!my_version) // try first version of the map tmp_ver = protomap->version; else // try previously agreed version tmp_ver = my_version; if (m_isOpen) ProtoBase::Close(); // Reset error status m_protoError = ERROR_NO_ERROR; for (;;) { // Reset to allow downgrade/upgrade map = protomap; while (map->version != 0 && map->version != tmp_ver) ++map; if (map->version == 0) { m_protoError = ERROR_UNKNOWN_VERSION; DBG(DBG_ERROR, "%s: failed to connect with any version\n", __FUNCTION__); break; } if (!m_socket->Connect(m_server.c_str(), m_port, rcvbuf)) { // hang will remain up allowing retry m_hang = true; m_protoError = ERROR_SERVER_UNREACHABLE; break; } // Now socket is connected: Reset hang m_hang = false; sprintf(cmd, "MYTH_PROTO_VERSION %" PRIu32 " %s", map->version, map->token); if (!SendCommand(cmd) || !RcvVersion(&tmp_ver)) { m_protoError = ERROR_SOCKET_ERROR; break; } DBG(DBG_DEBUG, "%s: asked for version %" PRIu32 ", got version %" PRIu32 "\n", __FUNCTION__, map->version, tmp_ver); if (map->version == tmp_ver) { DBG(DBG_DEBUG, "%s: agreed on version %u\n", __FUNCTION__, tmp_ver); if (tmp_ver != my_version) my_version = tmp_ver; // Store agreed version for next time m_isOpen = true; m_protoVersion = tmp_ver; return true; } // Retry with the returned version m_socket->Disconnect(); } m_socket->Disconnect(); m_isOpen = false; m_protoVersion = 0; return false; } void ProtoBase::Close() { OS::CLockGuard lock(*m_mutex); if (m_socket->IsValid()) { // Close gracefully by sending DONE message before disconnect if (m_isOpen && !m_hang) { const char *cmd = "DONE"; if (SendCommand(cmd, false)) DBG(DBG_PROTO, "%s: done\n", __FUNCTION__); else DBG(DBG_WARN, "%s: gracefully failed (%d)\n", __FUNCTION__, m_socket->GetErrNo()); } m_socket->Disconnect(); } m_isOpen = false; m_msgLength = m_msgConsumed = 0; } unsigned ProtoBase::GetProtoVersion() const { if (m_isOpen) return m_protoVersion; return 0; } std::string ProtoBase::GetServer() const { return m_server; } unsigned ProtoBase::GetPort() const { return m_port; } int ProtoBase::GetSocketErrNo() const { return m_socket->GetErrNo(); } int ProtoBase::GetSocket() const { return (int)(m_socket->GetHandle()); } bool ProtoBase::HasHanging() const { return m_tainted; } void ProtoBase::CleanHanging() { m_tainted = false; } ProtoBase::ERROR_t ProtoBase::GetProtoError() const { return m_protoError; } ProgramPtr ProtoBase::RcvProgramInfo75() { int64_t tmpi; std::string field; ProgramPtr program(new Program()); int i = 0; ++i; if (!ReadField(program->title)) goto out; ++i; if (!ReadField(program->subTitle)) goto out; ++i; if (!ReadField(program->description)) goto out; ++i; if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->season))) goto out; ++i; if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->episode))) goto out; ++i; if (!ReadField(program->category)) goto out; ++i; if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->channel.chanId))) goto out; ++i; if (!ReadField(program->channel.chanNum)) goto out; ++i; if (!ReadField(program->channel.callSign)) goto out; ++i; if (!ReadField(program->channel.channelName)) goto out; ++i; if (!ReadField(program->fileName)) goto out; ++i; if (!ReadField(field) || string_to_int64(field.c_str(), &(program->fileSize))) goto out; ++i; if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi)) goto out; program->startTime = (time_t)tmpi; ++i; if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi)) goto out; program->endTime = (time_t)tmpi; ++i; if (!ReadField(field)) // findid goto out; ++i; if (!ReadField(program->hostName)) goto out; ++i; if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->channel.sourceId))) goto out; ++i; if (!ReadField(field)) // cardid goto out; ++i; if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->channel.inputId))) goto out; ++i; if (!ReadField(field) || string_to_int32(field.c_str(), &(program->recording.priority))) goto out; ++i; if (!ReadField(field) || string_to_int8(field.c_str(), &(program->recording.status))) goto out; ++i; if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->recording.recordId))) goto out; ++i; if (!ReadField(field) || string_to_uint8(field.c_str(), &(program->recording.recType))) goto out; ++i; if (!ReadField(field) || string_to_uint8(field.c_str(), &(program->recording.dupInType))) goto out; ++i; if (!ReadField(field) || string_to_uint8(field.c_str(), &(program->recording.dupMethod))) goto out; ++i; if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi)) goto out; program->recording.startTs = (time_t)tmpi; ++i; if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi)) goto out; program->recording.endTs = (time_t)tmpi; ++i; if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->programFlags))) goto out; ++i; if (!ReadField(program->recording.recGroup)) goto out; ++i; if (!ReadField(program->channel.chanFilters)) goto out; ++i; if (!ReadField(program->seriesId)) goto out; ++i; if (!ReadField(program->programId)) goto out; ++i; if (!ReadField(program->inetref)) goto out; ++i; if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi)) goto out; program->lastModified = (time_t)tmpi; ++i; if (!ReadField(program->stars)) goto out; ++i; if (!ReadField(field) || string_to_time(field.c_str(), &(program->airdate))) goto out; ++i; if (!ReadField(program->recording.playGroup)) goto out; ++i; if (!ReadField(field)) // recpriority2 goto out; ++i; if (!ReadField(field)) // parentid goto out; ++i; if (!ReadField(program->recording.storageGroup)) goto out; ++i; if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->audioProps))) goto out; ++i; if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->videoProps))) goto out; return program; out: DBG(DBG_ERROR, "%s: failed (%d) buf='%s'\n", __FUNCTION__, i, field.c_str()); program.reset(); return program; } ProgramPtr ProtoBase::RcvProgramInfo76() { int64_t tmpi; std::string field; ProgramPtr program(new Program()); int i = 0; ++i; if (!ReadField(program->title)) goto out; ++i; if (!ReadField(program->subTitle)) goto out; ++i; if (!ReadField(program->description)) goto out; ++i; if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->season))) goto out; ++i; if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->episode))) goto out; ++i; if (!ReadField(field)) // syndicated episode goto out; ++i; if (!ReadField(program->category)) goto out; ++i; if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->channel.chanId))) goto out; ++i; if (!ReadField(program->channel.chanNum)) goto out; ++i; if (!ReadField(program->channel.callSign)) goto out; ++i; if (!ReadField(program->channel.channelName)) goto out; ++i; if (!ReadField(program->fileName)) goto out; ++i; if (!ReadField(field) || string_to_int64(field.c_str(), &(program->fileSize))) goto out; ++i; if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi)) goto out; program->startTime = (time_t)tmpi; ++i; if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi)) goto out; program->endTime = (time_t)tmpi; ++i; if (!ReadField(field)) // findid goto out; ++i; if (!ReadField(program->hostName)) goto out; ++i; if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->channel.sourceId))) goto out; ++i; if (!ReadField(field)) // cardid goto out; ++i; if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->channel.inputId))) goto out; ++i; if (!ReadField(field) || string_to_int32(field.c_str(), &(program->recording.priority))) goto out; ++i; if (!ReadField(field) || string_to_int8(field.c_str(), &(program->recording.status))) goto out; ++i; if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->recording.recordId))) goto out; ++i; if (!ReadField(field) || string_to_uint8(field.c_str(), &(program->recording.recType))) goto out; ++i; if (!ReadField(field) || string_to_uint8(field.c_str(), &(program->recording.dupInType))) goto out; ++i; if (!ReadField(field) || string_to_uint8(field.c_str(), &(program->recording.dupMethod))) goto out; ++i; if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi)) goto out; program->recording.startTs = (time_t)tmpi; ++i; if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi)) goto out; program->recording.endTs = (time_t)tmpi; ++i; if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->programFlags))) goto out; ++i; if (!ReadField(program->recording.recGroup)) goto out; ++i; if (!ReadField(program->channel.chanFilters)) goto out; ++i; if (!ReadField(program->seriesId)) goto out; ++i; if (!ReadField(program->programId)) goto out; ++i; if (!ReadField(program->inetref)) goto out; ++i; if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi)) goto out; program->lastModified = (time_t)tmpi; ++i; if (!ReadField(program->stars)) goto out; ++i; if (!ReadField(field) || string_to_time(field.c_str(), &(program->airdate))) goto out; ++i; if (!ReadField(program->recording.playGroup)) goto out; ++i; if (!ReadField(field)) // recpriority2 goto out; ++i; if (!ReadField(field)) // parentid goto out; ++i; if (!ReadField(program->recording.storageGroup)) goto out; ++i; if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->audioProps))) goto out; ++i; if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->videoProps))) goto out; ++i; if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->subProps))) goto out; ++i; if (!ReadField(field)) // year goto out; ++i; if (!ReadField(field)) // part number goto out; ++i; if (!ReadField(field)) // part total goto out; return program; out: DBG(DBG_ERROR, "%s: failed (%d) buf='%s'\n", __FUNCTION__, i, field.c_str()); program.reset(); return program; } ProgramPtr ProtoBase::RcvProgramInfo79() { int64_t tmpi; std::string field; ProgramPtr program(new Program()); int i = 0; ++i; if (!ReadField(program->title)) goto out; ++i; if (!ReadField(program->subTitle)) goto out; ++i; if (!ReadField(program->description)) goto out; ++i; if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->season))) goto out; ++i; if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->episode))) goto out; ++i; if (!ReadField(field)) // total episodes goto out; ++i; if (!ReadField(field)) // syndicated episode goto out; ++i; if (!ReadField(program->category)) goto out; ++i; if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->channel.chanId))) goto out; ++i; if (!ReadField(program->channel.chanNum)) goto out; ++i; if (!ReadField(program->channel.callSign)) goto out; ++i; if (!ReadField(program->channel.channelName)) goto out; ++i; if (!ReadField(program->fileName)) goto out; ++i; if (!ReadField(field) || string_to_int64(field.c_str(), &(program->fileSize))) goto out; ++i; if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi)) goto out; program->startTime = (time_t)tmpi; ++i; if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi)) goto out; program->endTime = (time_t)tmpi; ++i; if (!ReadField(field)) // findid goto out; ++i; if (!ReadField(program->hostName)) goto out; ++i; if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->channel.sourceId))) goto out; ++i; if (!ReadField(field)) // cardid goto out; ++i; if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->channel.inputId))) goto out; ++i; if (!ReadField(field) || string_to_int32(field.c_str(), &(program->recording.priority))) goto out; ++i; if (!ReadField(field) || string_to_int8(field.c_str(), &(program->recording.status))) goto out; ++i; if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->recording.recordId))) goto out; ++i; if (!ReadField(field) || string_to_uint8(field.c_str(), &(program->recording.recType))) goto out; ++i; if (!ReadField(field) || string_to_uint8(field.c_str(), &(program->recording.dupInType))) goto out; ++i; if (!ReadField(field) || string_to_uint8(field.c_str(), &(program->recording.dupMethod))) goto out; ++i; if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi)) goto out; program->recording.startTs = (time_t)tmpi; ++i; if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi)) goto out; program->recording.endTs = (time_t)tmpi; ++i; if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->programFlags))) goto out; ++i; if (!ReadField(program->recording.recGroup)) goto out; ++i; if (!ReadField(program->channel.chanFilters)) goto out; ++i; if (!ReadField(program->seriesId)) goto out; ++i; if (!ReadField(program->programId)) goto out; ++i; if (!ReadField(program->inetref)) goto out; ++i; if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi)) goto out; program->lastModified = (time_t)tmpi; ++i; if (!ReadField(program->stars)) goto out; ++i; if (!ReadField(field) || string_to_time(field.c_str(), &(program->airdate))) goto out; ++i; if (!ReadField(program->recording.playGroup)) goto out; ++i; if (!ReadField(field)) // recpriority2 goto out; ++i; if (!ReadField(field)) // parentid goto out; ++i; if (!ReadField(program->recording.storageGroup)) goto out; ++i; if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->audioProps))) goto out; ++i; if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->videoProps))) goto out; ++i; if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->subProps))) goto out; ++i; if (!ReadField(field)) // year goto out; ++i; if (!ReadField(field)) // part number goto out; ++i; if (!ReadField(field)) // part total goto out; ++i; if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi)) goto out; program->catType = CategoryTypeToString(m_protoVersion, CategoryTypeFromNum(m_protoVersion, (int)tmpi)); return program; out: DBG(DBG_ERROR, "%s: failed (%d) buf='%s'\n", __FUNCTION__, i, field.c_str()); program.reset(); return program; } ProgramPtr ProtoBase::RcvProgramInfo82() { int64_t tmpi; std::string field; ProgramPtr program(new Program()); int i = 0; ++i; if (!ReadField(program->title)) goto out; ++i; if (!ReadField(program->subTitle)) goto out; ++i; if (!ReadField(program->description)) goto out; ++i; if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->season))) goto out; ++i; if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->episode))) goto out; ++i; if (!ReadField(field)) // total episodes goto out; ++i; if (!ReadField(field)) // syndicated episode goto out; ++i; if (!ReadField(program->category)) goto out; ++i; if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->channel.chanId))) goto out; ++i; if (!ReadField(program->channel.chanNum)) goto out; ++i; if (!ReadField(program->channel.callSign)) goto out; ++i; if (!ReadField(program->channel.channelName)) goto out; ++i; if (!ReadField(program->fileName)) goto out; ++i; if (!ReadField(field) || string_to_int64(field.c_str(), &(program->fileSize))) goto out; ++i; if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi)) goto out; program->startTime = (time_t)tmpi; ++i; if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi)) goto out; program->endTime = (time_t)tmpi; ++i; if (!ReadField(field)) // findid goto out; ++i; if (!ReadField(program->hostName)) goto out; ++i; if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->channel.sourceId))) goto out; ++i; if (!ReadField(field)) // cardid goto out; ++i; if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->channel.inputId))) goto out; ++i; if (!ReadField(field) || string_to_int32(field.c_str(), &(program->recording.priority))) goto out; ++i; if (!ReadField(field) || string_to_int8(field.c_str(), &(program->recording.status))) goto out; ++i; if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->recording.recordId))) goto out; ++i; if (!ReadField(field) || string_to_uint8(field.c_str(), &(program->recording.recType))) goto out; ++i; if (!ReadField(field) || string_to_uint8(field.c_str(), &(program->recording.dupInType))) goto out; ++i; if (!ReadField(field) || string_to_uint8(field.c_str(), &(program->recording.dupMethod))) goto out; ++i; if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi)) goto out; program->recording.startTs = (time_t)tmpi; ++i; if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi)) goto out; program->recording.endTs = (time_t)tmpi; ++i; if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->programFlags))) goto out; ++i; if (!ReadField(program->recording.recGroup)) goto out; ++i; if (!ReadField(program->channel.chanFilters)) goto out; ++i; if (!ReadField(program->seriesId)) goto out; ++i; if (!ReadField(program->programId)) goto out; ++i; if (!ReadField(program->inetref)) goto out; ++i; if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi)) goto out; program->lastModified = (time_t)tmpi; ++i; if (!ReadField(program->stars)) goto out; ++i; if (!ReadField(field) || string_to_time(field.c_str(), &(program->airdate))) goto out; ++i; if (!ReadField(program->recording.playGroup)) goto out; ++i; if (!ReadField(field)) // recpriority2 goto out; ++i; if (!ReadField(field)) // parentid goto out; ++i; if (!ReadField(program->recording.storageGroup)) goto out; ++i; if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->audioProps))) goto out; ++i; if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->videoProps))) goto out; ++i; if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->subProps))) goto out; ++i; if (!ReadField(field)) // year goto out; ++i; if (!ReadField(field)) // part number goto out; ++i; if (!ReadField(field)) // part total goto out; ++i; if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi)) goto out; program->catType = CategoryTypeToString(m_protoVersion, CategoryTypeFromNum(m_protoVersion, (int)tmpi)); ++i; if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->recording.recordedId))) goto out; return program; out: DBG(DBG_ERROR, "%s: failed (%d) buf='%s'\n", __FUNCTION__, i, field.c_str()); program.reset(); return program; } ProgramPtr ProtoBase::RcvProgramInfo86() { int64_t tmpi; std::string field; ProgramPtr program(new Program()); int i = 0; ++i; if (!ReadField(program->title)) goto out; ++i; if (!ReadField(program->subTitle)) goto out; ++i; if (!ReadField(program->description)) goto out; ++i; if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->season))) goto out; ++i; if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->episode))) goto out; ++i; if (!ReadField(field)) // total episodes goto out; ++i; if (!ReadField(field)) // syndicated episode goto out; ++i; if (!ReadField(program->category)) goto out; ++i; if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->channel.chanId))) goto out; ++i; if (!ReadField(program->channel.chanNum)) goto out; ++i; if (!ReadField(program->channel.callSign)) goto out; ++i; if (!ReadField(program->channel.channelName)) goto out; ++i; if (!ReadField(program->fileName)) goto out; ++i; if (!ReadField(field) || string_to_int64(field.c_str(), &(program->fileSize))) goto out; ++i; if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi)) goto out; program->startTime = (time_t)tmpi; ++i; if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi)) goto out; program->endTime = (time_t)tmpi; ++i; if (!ReadField(field)) // findid goto out; ++i; if (!ReadField(program->hostName)) goto out; ++i; if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->channel.sourceId))) goto out; ++i; if (!ReadField(field)) // cardid goto out; ++i; if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->channel.inputId))) goto out; ++i; if (!ReadField(field) || string_to_int32(field.c_str(), &(program->recording.priority))) goto out; ++i; if (!ReadField(field) || string_to_int8(field.c_str(), &(program->recording.status))) goto out; ++i; if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->recording.recordId))) goto out; ++i; if (!ReadField(field) || string_to_uint8(field.c_str(), &(program->recording.recType))) goto out; ++i; if (!ReadField(field) || string_to_uint8(field.c_str(), &(program->recording.dupInType))) goto out; ++i; if (!ReadField(field) || string_to_uint8(field.c_str(), &(program->recording.dupMethod))) goto out; ++i; if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi)) goto out; program->recording.startTs = (time_t)tmpi; ++i; if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi)) goto out; program->recording.endTs = (time_t)tmpi; ++i; if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->programFlags))) goto out; ++i; if (!ReadField(program->recording.recGroup)) goto out; ++i; if (!ReadField(program->channel.chanFilters)) goto out; ++i; if (!ReadField(program->seriesId)) goto out; ++i; if (!ReadField(program->programId)) goto out; ++i; if (!ReadField(program->inetref)) goto out; ++i; if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi)) goto out; program->lastModified = (time_t)tmpi; ++i; if (!ReadField(program->stars)) goto out; ++i; if (!ReadField(field) || string_to_time(field.c_str(), &(program->airdate))) goto out; ++i; if (!ReadField(program->recording.playGroup)) goto out; ++i; if (!ReadField(field)) // recpriority2 goto out; ++i; if (!ReadField(field)) // parentid goto out; ++i; if (!ReadField(program->recording.storageGroup)) goto out; ++i; if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->audioProps))) goto out; ++i; if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->videoProps))) goto out; ++i; if (!ReadField(field) || string_to_uint16(field.c_str(), &(program->subProps))) goto out; ++i; if (!ReadField(field)) // year goto out; ++i; if (!ReadField(field)) // part number goto out; ++i; if (!ReadField(field)) // part total goto out; ++i; if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi)) goto out; program->catType = CategoryTypeToString(m_protoVersion, CategoryTypeFromNum(m_protoVersion, (int)tmpi)); ++i; if (!ReadField(field) || string_to_uint32(field.c_str(), &(program->recording.recordedId))) goto out; ++i; if (!ReadField(field)) // inputname goto out; ++i; if (!ReadField(field)) // bookmarkupdate goto out; return program; out: DBG(DBG_ERROR, "%s: failed (%d) buf='%s'\n", __FUNCTION__, i, field.c_str()); program.reset(); return program; } void ProtoBase::MakeProgramInfo75(const Program& program, std::string& msg) { char buf[32]; msg.clear(); msg.append(program.title).append(PROTO_STR_SEPARATOR); msg.append(program.subTitle).append(PROTO_STR_SEPARATOR); msg.append(program.description).append(PROTO_STR_SEPARATOR); uint16_to_string(program.season, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint16_to_string(program.episode, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append(program.category).append(PROTO_STR_SEPARATOR); uint32_to_string(program.channel.chanId, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append(program.channel.chanNum).append(PROTO_STR_SEPARATOR); msg.append(program.channel.callSign).append(PROTO_STR_SEPARATOR); msg.append(program.channel.channelName).append(PROTO_STR_SEPARATOR); msg.append(program.fileName).append(PROTO_STR_SEPARATOR); int64_to_string(program.fileSize, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); int64_to_string((int64_t)program.startTime, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); int64_to_string((int64_t)program.endTime, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append("0").append(PROTO_STR_SEPARATOR); // findid msg.append(program.hostName).append(PROTO_STR_SEPARATOR); uint32_to_string(program.channel.sourceId, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append("0").append(PROTO_STR_SEPARATOR); // cardid uint32_to_string(program.channel.inputId, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); int32_to_string(program.recording.priority, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); int8_to_string(program.recording.status, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint32_to_string(program.recording.recordId, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint8_to_string(program.recording.recType, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint8_to_string(program.recording.dupInType, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint8_to_string(program.recording.dupMethod, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); int64_to_string((int64_t)program.recording.startTs, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); int64_to_string((int64_t)program.recording.endTs, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint32_to_string(program.programFlags, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append(program.recording.recGroup).append(PROTO_STR_SEPARATOR); msg.append(program.channel.chanFilters).append(PROTO_STR_SEPARATOR); msg.append(program.seriesId).append(PROTO_STR_SEPARATOR); msg.append(program.programId).append(PROTO_STR_SEPARATOR); msg.append(program.inetref).append(PROTO_STR_SEPARATOR); int64_to_string((int64_t)program.lastModified, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append(program.stars).append(PROTO_STR_SEPARATOR); time_to_isodate(program.airdate, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append(program.recording.playGroup).append(PROTO_STR_SEPARATOR); msg.append("0").append(PROTO_STR_SEPARATOR); // recpriority2 msg.append("0").append(PROTO_STR_SEPARATOR); // parentid msg.append(program.recording.storageGroup).append(PROTO_STR_SEPARATOR); uint16_to_string(program.audioProps, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint16_to_string(program.videoProps, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint16_to_string(program.subProps, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append("0"); // year } void ProtoBase::MakeProgramInfo76(const Program& program, std::string& msg) { char buf[32]; msg.clear(); msg.append(program.title).append(PROTO_STR_SEPARATOR); msg.append(program.subTitle).append(PROTO_STR_SEPARATOR); msg.append(program.description).append(PROTO_STR_SEPARATOR); uint16_to_string(program.season, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint16_to_string(program.episode, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append(PROTO_STR_SEPARATOR); // syndicated episode msg.append(program.category).append(PROTO_STR_SEPARATOR); uint32_to_string(program.channel.chanId, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append(program.channel.chanNum).append(PROTO_STR_SEPARATOR); msg.append(program.channel.callSign).append(PROTO_STR_SEPARATOR); msg.append(program.channel.channelName).append(PROTO_STR_SEPARATOR); msg.append(program.fileName).append(PROTO_STR_SEPARATOR); int64_to_string(program.fileSize, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); int64_to_string((int64_t)program.startTime, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); int64_to_string((int64_t)program.endTime, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append("0").append(PROTO_STR_SEPARATOR); // findid msg.append(program.hostName).append(PROTO_STR_SEPARATOR); uint32_to_string(program.channel.sourceId, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append("0").append(PROTO_STR_SEPARATOR); // cardid uint32_to_string(program.channel.inputId, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); int32_to_string(program.recording.priority, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); int8_to_string(program.recording.status, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint32_to_string(program.recording.recordId, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint8_to_string(program.recording.recType, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint8_to_string(program.recording.dupInType, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint8_to_string(program.recording.dupMethod, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); int64_to_string((int64_t)program.recording.startTs, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); int64_to_string((int64_t)program.recording.endTs, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint32_to_string(program.programFlags, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append(program.recording.recGroup).append(PROTO_STR_SEPARATOR); msg.append(program.channel.chanFilters).append(PROTO_STR_SEPARATOR); msg.append(program.seriesId).append(PROTO_STR_SEPARATOR); msg.append(program.programId).append(PROTO_STR_SEPARATOR); msg.append(program.inetref).append(PROTO_STR_SEPARATOR); int64_to_string((int64_t)program.lastModified, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append(program.stars).append(PROTO_STR_SEPARATOR); time_to_isodate(program.airdate, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append(program.recording.playGroup).append(PROTO_STR_SEPARATOR); msg.append("0").append(PROTO_STR_SEPARATOR); // recpriority2 msg.append("0").append(PROTO_STR_SEPARATOR); // parentid msg.append(program.recording.storageGroup).append(PROTO_STR_SEPARATOR); uint16_to_string(program.audioProps, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint16_to_string(program.videoProps, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint16_to_string(program.subProps, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append("0").append(PROTO_STR_SEPARATOR); // year msg.append("0").append(PROTO_STR_SEPARATOR); // part number msg.append("0"); // part total } void ProtoBase::MakeProgramInfo79(const Program& program, std::string& msg) { char buf[32]; msg.clear(); msg.append(program.title).append(PROTO_STR_SEPARATOR); msg.append(program.subTitle).append(PROTO_STR_SEPARATOR); msg.append(program.description).append(PROTO_STR_SEPARATOR); uint16_to_string(program.season, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint16_to_string(program.episode, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append("0").append(PROTO_STR_SEPARATOR); // total episodes msg.append(PROTO_STR_SEPARATOR); // syndicated episode msg.append(program.category).append(PROTO_STR_SEPARATOR); uint32_to_string(program.channel.chanId, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append(program.channel.chanNum).append(PROTO_STR_SEPARATOR); msg.append(program.channel.callSign).append(PROTO_STR_SEPARATOR); msg.append(program.channel.channelName).append(PROTO_STR_SEPARATOR); msg.append(program.fileName).append(PROTO_STR_SEPARATOR); int64_to_string(program.fileSize, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); int64_to_string((int64_t)program.startTime, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); int64_to_string((int64_t)program.endTime, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append("0").append(PROTO_STR_SEPARATOR); // findid msg.append(program.hostName).append(PROTO_STR_SEPARATOR); uint32_to_string(program.channel.sourceId, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append("0").append(PROTO_STR_SEPARATOR); // cardid uint32_to_string(program.channel.inputId, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); int32_to_string(program.recording.priority, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); int8_to_string(program.recording.status, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint32_to_string(program.recording.recordId, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint8_to_string(program.recording.recType, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint8_to_string(program.recording.dupInType, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint8_to_string(program.recording.dupMethod, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); int64_to_string((int64_t)program.recording.startTs, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); int64_to_string((int64_t)program.recording.endTs, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint32_to_string(program.programFlags, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append(program.recording.recGroup).append(PROTO_STR_SEPARATOR); msg.append(program.channel.chanFilters).append(PROTO_STR_SEPARATOR); msg.append(program.seriesId).append(PROTO_STR_SEPARATOR); msg.append(program.programId).append(PROTO_STR_SEPARATOR); msg.append(program.inetref).append(PROTO_STR_SEPARATOR); int64_to_string((int64_t)program.lastModified, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append(program.stars).append(PROTO_STR_SEPARATOR); time_to_isodate(program.airdate, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append(program.recording.playGroup).append(PROTO_STR_SEPARATOR); msg.append("0").append(PROTO_STR_SEPARATOR); // recpriority2 msg.append("0").append(PROTO_STR_SEPARATOR); // parentid msg.append(program.recording.storageGroup).append(PROTO_STR_SEPARATOR); uint16_to_string(program.audioProps, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint16_to_string(program.videoProps, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint16_to_string(program.subProps, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append("0").append(PROTO_STR_SEPARATOR); // year msg.append("0").append(PROTO_STR_SEPARATOR); // part number msg.append("0").append(PROTO_STR_SEPARATOR); // part total uint8_to_string((uint8_t)CategoryTypeToNum(m_protoVersion, CategoryTypeFromString(m_protoVersion, program.catType)), buf); msg.append(buf); } void ProtoBase::MakeProgramInfo82(const Program& program, std::string& msg) { char buf[32]; msg.clear(); msg.append(program.title).append(PROTO_STR_SEPARATOR); msg.append(program.subTitle).append(PROTO_STR_SEPARATOR); msg.append(program.description).append(PROTO_STR_SEPARATOR); uint16_to_string(program.season, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint16_to_string(program.episode, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append("0").append(PROTO_STR_SEPARATOR); // total episodes msg.append(PROTO_STR_SEPARATOR); // syndicated episode msg.append(program.category).append(PROTO_STR_SEPARATOR); uint32_to_string(program.channel.chanId, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append(program.channel.chanNum).append(PROTO_STR_SEPARATOR); msg.append(program.channel.callSign).append(PROTO_STR_SEPARATOR); msg.append(program.channel.channelName).append(PROTO_STR_SEPARATOR); msg.append(program.fileName).append(PROTO_STR_SEPARATOR); int64_to_string(program.fileSize, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); int64_to_string((int64_t)program.startTime, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); int64_to_string((int64_t)program.endTime, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append("0").append(PROTO_STR_SEPARATOR); // findid msg.append(program.hostName).append(PROTO_STR_SEPARATOR); uint32_to_string(program.channel.sourceId, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append("0").append(PROTO_STR_SEPARATOR); // cardid uint32_to_string(program.channel.inputId, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); int32_to_string(program.recording.priority, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); int8_to_string(program.recording.status, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint32_to_string(program.recording.recordId, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint8_to_string(program.recording.recType, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint8_to_string(program.recording.dupInType, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint8_to_string(program.recording.dupMethod, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); int64_to_string((int64_t)program.recording.startTs, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); int64_to_string((int64_t)program.recording.endTs, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint32_to_string(program.programFlags, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append(program.recording.recGroup).append(PROTO_STR_SEPARATOR); msg.append(program.channel.chanFilters).append(PROTO_STR_SEPARATOR); msg.append(program.seriesId).append(PROTO_STR_SEPARATOR); msg.append(program.programId).append(PROTO_STR_SEPARATOR); msg.append(program.inetref).append(PROTO_STR_SEPARATOR); int64_to_string((int64_t)program.lastModified, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append(program.stars).append(PROTO_STR_SEPARATOR); time_to_isodate(program.airdate, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append(program.recording.playGroup).append(PROTO_STR_SEPARATOR); msg.append("0").append(PROTO_STR_SEPARATOR); // recpriority2 msg.append("0").append(PROTO_STR_SEPARATOR); // parentid msg.append(program.recording.storageGroup).append(PROTO_STR_SEPARATOR); uint16_to_string(program.audioProps, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint16_to_string(program.videoProps, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint16_to_string(program.subProps, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append("0").append(PROTO_STR_SEPARATOR); // year msg.append("0").append(PROTO_STR_SEPARATOR); // part number msg.append("0").append(PROTO_STR_SEPARATOR); // part total uint8_to_string((uint8_t)CategoryTypeToNum(m_protoVersion, CategoryTypeFromString(m_protoVersion, program.catType)), buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint32_to_string(program.recording.recordedId, buf); msg.append(buf); } void ProtoBase::MakeProgramInfo86(const Program& program, std::string& msg) { char buf[32]; msg.clear(); msg.append(program.title).append(PROTO_STR_SEPARATOR); msg.append(program.subTitle).append(PROTO_STR_SEPARATOR); msg.append(program.description).append(PROTO_STR_SEPARATOR); uint16_to_string(program.season, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint16_to_string(program.episode, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append("0").append(PROTO_STR_SEPARATOR); // total episodes msg.append(PROTO_STR_SEPARATOR); // syndicated episode msg.append(program.category).append(PROTO_STR_SEPARATOR); uint32_to_string(program.channel.chanId, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append(program.channel.chanNum).append(PROTO_STR_SEPARATOR); msg.append(program.channel.callSign).append(PROTO_STR_SEPARATOR); msg.append(program.channel.channelName).append(PROTO_STR_SEPARATOR); msg.append(program.fileName).append(PROTO_STR_SEPARATOR); int64_to_string(program.fileSize, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); int64_to_string((int64_t)program.startTime, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); int64_to_string((int64_t)program.endTime, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append("0").append(PROTO_STR_SEPARATOR); // findid msg.append(program.hostName).append(PROTO_STR_SEPARATOR); uint32_to_string(program.channel.sourceId, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append("0").append(PROTO_STR_SEPARATOR); // cardid uint32_to_string(program.channel.inputId, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); int32_to_string(program.recording.priority, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); int8_to_string(program.recording.status, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint32_to_string(program.recording.recordId, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint8_to_string(program.recording.recType, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint8_to_string(program.recording.dupInType, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint8_to_string(program.recording.dupMethod, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); int64_to_string((int64_t)program.recording.startTs, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); int64_to_string((int64_t)program.recording.endTs, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint32_to_string(program.programFlags, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append(program.recording.recGroup).append(PROTO_STR_SEPARATOR); msg.append(program.channel.chanFilters).append(PROTO_STR_SEPARATOR); msg.append(program.seriesId).append(PROTO_STR_SEPARATOR); msg.append(program.programId).append(PROTO_STR_SEPARATOR); msg.append(program.inetref).append(PROTO_STR_SEPARATOR); int64_to_string((int64_t)program.lastModified, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append(program.stars).append(PROTO_STR_SEPARATOR); time_to_isodate(program.airdate, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append(program.recording.playGroup).append(PROTO_STR_SEPARATOR); msg.append("0").append(PROTO_STR_SEPARATOR); // recpriority2 msg.append("0").append(PROTO_STR_SEPARATOR); // parentid msg.append(program.recording.storageGroup).append(PROTO_STR_SEPARATOR); uint16_to_string(program.audioProps, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint16_to_string(program.videoProps, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint16_to_string(program.subProps, buf); msg.append(buf).append(PROTO_STR_SEPARATOR); msg.append("0").append(PROTO_STR_SEPARATOR); // year msg.append("0").append(PROTO_STR_SEPARATOR); // part number msg.append("0").append(PROTO_STR_SEPARATOR); // part total uint8_to_string((uint8_t)CategoryTypeToNum(m_protoVersion, CategoryTypeFromString(m_protoVersion, program.catType)), buf); msg.append(buf).append(PROTO_STR_SEPARATOR); uint32_to_string(program.recording.recordedId, buf); msg.append(buf); msg.append(PROTO_STR_SEPARATOR); // inputname msg.append(PROTO_STR_SEPARATOR); // bookmarkupdate } pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/proto/mythprotobase.h000066400000000000000000000075131360567320200241430ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHPROTOBASE_H #define MYTHPROTOBASE_H #include "../mythtypes.h" #include #define PROTO_BUFFER_SIZE 4000 #define PROTO_SENDMSG_MAXSIZE 64000 #define PROTO_STR_SEPARATOR "[]:[]" #define PROTO_STR_SEPARATOR_LEN (sizeof(PROTO_STR_SEPARATOR) - 1) namespace Myth { namespace OS { class CMutex; } class TcpSocket; class ProtoBase { public: ProtoBase(const std::string& server, unsigned port); virtual ~ProtoBase(); typedef enum { ERROR_NO_ERROR = 0, ERROR_SERVER_UNREACHABLE, ERROR_SOCKET_ERROR, ERROR_UNKNOWN_VERSION, } ERROR_t; virtual bool Open() = 0; virtual void Close(); virtual bool IsOpen() { return m_isOpen; } virtual unsigned GetProtoVersion() const; virtual std::string GetServer() const; virtual unsigned GetPort() const; virtual int GetSocketErrNo() const; virtual int GetSocket() const; virtual bool HasHanging() const; virtual void CleanHanging(); virtual ERROR_t GetProtoError() const; protected: OS::CMutex *m_mutex; TcpSocket *m_socket; unsigned m_protoVersion; std::string m_server; unsigned m_port; bool m_hang; ///< Connection hang: while true allow retry bool m_tainted; ///< Connection has hung since last reset size_t m_msgLength; size_t m_msgConsumed; bool OpenConnection(int rcvbuf); void HangException(); bool SendCommand(const char *cmd, bool feedback = true); size_t GetMessageLength() const; bool ReadField(std::string& field); bool IsMessageOK(const std::string& field) const; size_t FlushMessage(); bool RcvMessageLength(); ProgramPtr RcvProgramInfo() { if (m_protoVersion >= 86) return RcvProgramInfo86(); if (m_protoVersion >= 82) return RcvProgramInfo82(); if (m_protoVersion >= 79) return RcvProgramInfo79(); if (m_protoVersion >= 76) return RcvProgramInfo76(); return RcvProgramInfo75(); } void MakeProgramInfo(const Program& program, std::string& msg) { if (m_protoVersion >= 86) MakeProgramInfo86(program, msg); else if (m_protoVersion >= 82) MakeProgramInfo82(program, msg); else if (m_protoVersion >= 79) MakeProgramInfo79(program, msg); else if (m_protoVersion >= 76) MakeProgramInfo76(program, msg); else MakeProgramInfo75(program, msg); } private: bool m_isOpen; ERROR_t m_protoError; bool RcvVersion(unsigned *version); ProgramPtr RcvProgramInfo75(); ProgramPtr RcvProgramInfo76(); ProgramPtr RcvProgramInfo79(); ProgramPtr RcvProgramInfo82(); ProgramPtr RcvProgramInfo86(); void MakeProgramInfo75(const Program& program, std::string& msg); void MakeProgramInfo76(const Program& program, std::string& msg); void MakeProgramInfo79(const Program& program, std::string& msg); void MakeProgramInfo82(const Program& program, std::string& msg); void MakeProgramInfo86(const Program& program, std::string& msg); }; } #endif /* MYTHPROTOBASE_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/proto/mythprotoevent.cpp000066400000000000000000000133131360567320200247000ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "mythprotoevent.h" #include "../private/debug.h" #include "../private/socket.h" #include "../private/os/threads/mutex.h" #include "../private/builtin.h" #include #include #include using namespace Myth; void __tokenize(const std::string& str, const char *delimiters, std::vector& tokens, bool trimnull = false) { std::string::size_type pa = 0, pb = 0; unsigned n = 0; // Counter n will break infinite loop. Max count is 255 tokens while ((pb = str.find_first_of(delimiters, pb)) != std::string::npos && ++n < 255) { tokens.push_back(str.substr(pa, pb - pa)); do { pa = ++pb; } while (trimnull && str.find_first_of(delimiters, pb) == pb); } tokens.push_back(str.substr(pa)); } /////////////////////////////////////////////////////////////////////////////// //// //// Protocol connection to listen event //// ProtoEvent::ProtoEvent(const std::string& server, unsigned port) : ProtoBase(server, port) { } bool ProtoEvent::Open() { bool ok = false; if (!OpenConnection(PROTO_EVENT_RCVBUF)) return false; if (m_protoVersion >= 75) ok = Announce75(); if (ok) return true; Close(); return false; } void ProtoEvent::Close() { ProtoBase::Close(); // Clean hanging and disable retry m_tainted = m_hang = false; } bool ProtoEvent::Announce75() { OS::CLockGuard lock(*m_mutex); std::string cmd("ANN Monitor "); cmd.append(m_socket->GetMyHostName()).append(" 1"); if (!SendCommand(cmd.c_str())) return false; std::string field; if (!ReadField(field) || !IsMessageOK(field)) goto out; return true; out: FlushMessage(); return false; } SignalStatusPtr ProtoEvent::RcvSignalStatus() { SignalStatusPtr signal(new SignalStatus()); // Using default constructor std::string field; while (ReadField(field)) { std::vector tokens; // Tokenize the content __tokenize(field, " ", tokens, false); // Fill my signal if (tokens.size() > 1) { int64_t tmpi; if (tokens[0] == "slock") signal->lock = (tokens[1] == "1" ? true : false); else if (tokens[0] == "signal") signal->signal = (0 == string_to_int64(tokens[1].c_str(), &tmpi) ? (int)tmpi : 0); else if (tokens[0] == "snr") signal->snr = (0 == string_to_int64(tokens[1].c_str(), &tmpi) ? (int)tmpi : 0); else if (tokens[0] == "ber") signal->ber = (0 == string_to_int64(tokens[1].c_str(), &tmpi) ? (long)tmpi : 0); else if (tokens[0] == "ucb") signal->ucb = (0 == string_to_int64(tokens[1].c_str(), &tmpi) ? (long)tmpi : 0); } } return signal; } int ProtoEvent::RcvBackendMessage(unsigned timeout, EventMessage **msg) { OS::CLockGuard lock(*m_mutex); struct timeval tv; tv.tv_sec = timeout; tv.tv_usec = 0; int r = m_socket->Listen(&tv); if (r > 0) { std::string field; EventMessage *pmsg = new EventMessage(); pmsg->event = EVENT_UNKNOWN; pmsg->subject.clear(); pmsg->program.reset(); pmsg->signal.reset(); if (RcvMessageLength() && ReadField(field) && field == "BACKEND_MESSAGE") { unsigned n = 0; ReadField(field); // Tokenize the subject __tokenize(field, " ", pmsg->subject, false); n = (unsigned)pmsg->subject.size(); DBG(DBG_DEBUG, "%s: %s (%u)\n", __FUNCTION__, field.c_str(), n); if (pmsg->subject[0] == "UPDATE_FILE_SIZE") pmsg->event = EVENT_UPDATE_FILE_SIZE; else if (pmsg->subject[0] == "DONE_RECORDING") pmsg->event = EVENT_DONE_RECORDING; else if (pmsg->subject[0] == "QUIT_LIVETV") pmsg->event = EVENT_QUIT_LIVETV; else if (pmsg->subject[0] == "LIVETV_WATCH") pmsg->event = EVENT_LIVETV_WATCH; else if (pmsg->subject[0] == "LIVETV_CHAIN") pmsg->event = EVENT_LIVETV_CHAIN; else if (pmsg->subject[0] == "SIGNAL") { pmsg->event = EVENT_SIGNAL; pmsg->signal = RcvSignalStatus(); } else if (pmsg->subject[0] == "RECORDING_LIST_CHANGE") { pmsg->event = EVENT_RECORDING_LIST_CHANGE; if (n > 1 && pmsg->subject[1] == "UPDATE") pmsg->program = RcvProgramInfo(); } else if (pmsg->subject[0] == "SCHEDULE_CHANGE") pmsg->event = EVENT_SCHEDULE_CHANGE; else if (pmsg->subject[0] == "ASK_RECORDING") { pmsg->event = EVENT_ASK_RECORDING; pmsg->program = RcvProgramInfo(); } else if (pmsg->subject[0] == "CLEAR_SETTINGS_CACHE") pmsg->event = EVENT_CLEAR_SETTINGS_CACHE; else if (pmsg->subject[0] == "GENERATED_PIXMAP") pmsg->event = EVENT_GENERATED_PIXMAP; else if (pmsg->subject[0] == "SYSTEM_EVENT") pmsg->event = EVENT_SYSTEM_EVENT; else pmsg->event = EVENT_UNKNOWN; } FlushMessage(); *msg = pmsg; return (m_hang ? -(ENOTCONN) : 1); } else if (r < 0) return r; return ((ProtoBase::IsOpen() && !m_hang) ? 0 : -(ENOTCONN)); } pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/proto/mythprotoevent.h000066400000000000000000000030441360567320200243450ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHPROTOEVENT_H #define MYTHPROTOEVENT_H #include "mythprotobase.h" #define PROTO_EVENT_RCVBUF 64000 namespace Myth { class ProtoEvent : public ProtoBase { public: ProtoEvent(const std::string& server, unsigned port); virtual bool Open(); virtual void Close(); /** * @brief Wait for new backend message from event connection * @param timeout Number of seconds * @param msg Handle MythEventMessage * @return success: 0 = No message, 1 = New message received * @return failure: -(errno) */ int RcvBackendMessage(unsigned timeout, EventMessage **msg); private: bool Announce75(); SignalStatusPtr RcvSignalStatus(); }; } #endif /* MYTHPROTOEVENT_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/proto/mythprotomonitor.cpp000066400000000000000000000557351360567320200252640ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "mythprotomonitor.h" #include "mythprotorecorder.h" #include "../private/debug.h" #include "../private/socket.h" #include "../private/os/threads/mutex.h" #include "../private/builtin.h" #include #include using namespace Myth; /////////////////////////////////////////////////////////////////////////////// //// //// Protocol connection to monitor DVR //// ProtoMonitor::ProtoMonitor(const std::string& server, unsigned port) : ProtoBase(server, port) , m_frontend(false) { } ProtoMonitor::ProtoMonitor(const std::string& server, unsigned port, bool frontend) : ProtoBase(server, port) , m_frontend(frontend) { } bool ProtoMonitor::Open() { bool ok = false; if (!OpenConnection(PROTO_MONITOR_RCVBUF)) return false; if (m_protoVersion >= 88) ok = Announce88(); else ok = Announce75(); if (ok) { return true; } Close(); return false; } void ProtoMonitor::Close() { ProtoBase::Close(); // Clean hanging and disable retry m_tainted = m_hang = false; } bool ProtoMonitor::IsOpen() { // Try reconnect if (m_hang) return ProtoMonitor::Open(); return ProtoBase::IsOpen(); } bool ProtoMonitor::Announce75() { OS::CLockGuard lock(*m_mutex); std::string cmd("ANN Monitor "); cmd.append(m_socket->GetMyHostName()).append(" 0"); if (!SendCommand(cmd.c_str())) return false; std::string field; if (!ReadField(field) || !IsMessageOK(field)) goto out; return true; out: FlushMessage(); return false; } bool ProtoMonitor::Announce88() { OS::CLockGuard lock(*m_mutex); std::string cmd((m_frontend ? "ANN Frontend " : "ANN Monitor ")); cmd.append(m_socket->GetMyHostName()).append(" 0"); if (!SendCommand(cmd.c_str())) return false; std::string field; if (!ReadField(field) || !IsMessageOK(field)) goto out; return true; out: FlushMessage(); return false; } ProtoRecorderPtr ProtoMonitor::GetRecorderFromNum75(int rnum) { char buf[32]; std::string field; ProtoRecorderPtr recorder; std::string hostname; uint16_t port; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) return recorder; std::string cmd("GET_RECORDER_FROM_NUM"); cmd.append(PROTO_STR_SEPARATOR); int32_to_string((int32_t)rnum, buf); cmd.append(buf); if (!SendCommand(cmd.c_str())) return recorder; if (!ReadField(hostname) || hostname == "nohost") goto out; if (!ReadField(field) || string_to_uint16(field.c_str(), &port)) goto out; FlushMessage(); DBG(DBG_DEBUG, "%s: open recorder %d (%s:%u)\n", __FUNCTION__, (int)rnum, hostname.c_str(), (unsigned)port); recorder.reset(new ProtoRecorder(rnum, hostname, port)); return recorder; out: DBG(DBG_ERROR, "%s: failed\n", __FUNCTION__); FlushMessage(); return recorder; } bool ProtoMonitor::QueryFreeSpaceSummary75(int64_t *total, int64_t *used) { std::string field; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) return false; std::string cmd("QUERY_FREE_SPACE_SUMMARY"); if (!SendCommand(cmd.c_str())) return false; if (!ReadField(field) || string_to_int64(field.c_str(), total)) goto out; if (!ReadField(field) || string_to_int64(field.c_str(), used)) goto out; FlushMessage(); return true; out: DBG(DBG_ERROR, "%s: failed\n", __FUNCTION__); FlushMessage(); return false; } std::string ProtoMonitor::GetSetting75(const std::string& hostname, const std::string& setting) { std::string field; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) return field; std::string cmd("QUERY_SETTING "); cmd.append(hostname).append(" ").append(setting); if (!SendCommand(cmd.c_str())) return field; if (!ReadField(field)) goto out; FlushMessage(); return field; out: DBG(DBG_ERROR, "%s: failed\n", __FUNCTION__); FlushMessage(); field.clear(); return field; } bool ProtoMonitor::SetSetting75(const std::string& hostname, const std::string& setting, const std::string& value) { std::string field; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) return false; std::string cmd("SET_SETTING "); cmd.append(hostname).append(" ").append(setting).append(" ").append(value); if (!SendCommand(cmd.c_str())) return false; if (!ReadField(field) || !IsMessageOK(field)) goto out; FlushMessage(); return true; out: DBG(DBG_ERROR, "%s: failed\n", __FUNCTION__); FlushMessage(); return false; } bool ProtoMonitor::QueryGenpixmap75(const Program& program) { std::string field; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) return false; std::string cmd("QUERY_GENPIXMAP2"); cmd.append(PROTO_STR_SEPARATOR).append("do_not_care").append(PROTO_STR_SEPARATOR); MakeProgramInfo(program, field); cmd.append(field); if (!SendCommand(cmd.c_str())) return false; if (!ReadField(field) || !IsMessageOK(field)) goto out; FlushMessage(); return true; out: DBG(DBG_ERROR, "%s: failed\n", __FUNCTION__); FlushMessage(); return false; } bool ProtoMonitor::DeleteRecording75(const Program& program, bool force, bool forget) { char buf[32]; std::string field; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) return false; std::string cmd("DELETE_RECORDING "); uint32_to_string(program.channel.chanId, buf); cmd.append(buf).append(" "); time_to_iso8601utc(program.recording.startTs, buf); cmd.append(buf).append(" "); if (force) cmd.append("FORCE "); else cmd.append("NO_FORCE "); if (forget) cmd.append("FORGET"); else cmd.append("NO_FORGET"); if (!SendCommand(cmd.c_str())) return false; if (!ReadField(field)) goto out; DBG(DBG_DEBUG, "%s: succeeded (%s)\n", __FUNCTION__, program.fileName.c_str()); return true; out: DBG(DBG_ERROR, "%s: failed\n", __FUNCTION__); FlushMessage(); return false; } bool ProtoMonitor::UndeleteRecording75(const Program& program) { std::string field; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) return false; std::string cmd("UNDELETE_RECORDING"); cmd.append(PROTO_STR_SEPARATOR); MakeProgramInfo(program, field); cmd.append(field); if (!SendCommand(cmd.c_str())) return false; if (!ReadField(field) || field != "0") goto out; DBG(DBG_DEBUG, "%s: succeeded (%s)\n", __FUNCTION__, program.fileName.c_str()); return true; out: DBG(DBG_ERROR, "%s: failed\n", __FUNCTION__); FlushMessage(); return false; } bool ProtoMonitor::StopRecording75(const Program& program) { std::string field; int32_t num; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) return false; std::string cmd("STOP_RECORDING"); cmd.append(PROTO_STR_SEPARATOR); MakeProgramInfo(program, field); cmd.append(field); if (!SendCommand(cmd.c_str())) return false; if (!ReadField(field) || string_to_int32(field.c_str(), &num) || num < 0) goto out; DBG(DBG_DEBUG, "%s: succeeded (%s)\n", __FUNCTION__, program.fileName.c_str()); return true; out: DBG(DBG_ERROR, "%s: failed\n", __FUNCTION__); FlushMessage(); return false; } bool ProtoMonitor::CancelNextRecording75(int rnum, bool cancel) { char buf[32]; std::string field; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) return false; std::string cmd("QUERY_RECORDER "); int32_to_string(rnum, buf); cmd.append(buf).append(PROTO_STR_SEPARATOR); cmd.append("CANCEL_NEXT_RECORDING").append(PROTO_STR_SEPARATOR); cmd.append((cancel ? "1" : "0")); if (!SendCommand(cmd.c_str())) return false; if (!ReadField(field) || !IsMessageOK(field)) goto out; DBG(DBG_DEBUG, "%s: succeeded\n", __FUNCTION__); return true; out: DBG(DBG_ERROR, "%s: failed\n", __FUNCTION__); FlushMessage(); return false; } StorageGroupFilePtr ProtoMonitor::QuerySGFile75(const std::string& hostname, const std::string& sgname, const std::string& filename) { std::string field; int64_t tmpi; StorageGroupFilePtr sgfile; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) return sgfile; std::string cmd("QUERY_SG_FILEQUERY"); cmd.append(PROTO_STR_SEPARATOR); cmd.append(hostname).append(PROTO_STR_SEPARATOR); cmd.append(sgname).append(PROTO_STR_SEPARATOR); cmd.append(filename); if (!SendCommand(cmd.c_str())) return sgfile; sgfile.reset(new StorageGroupFile()); if (!ReadField(sgfile->fileName)) goto out; if (!ReadField(field) || string_to_int64(field.c_str(), &tmpi)) goto out; sgfile->lastModified = (time_t)tmpi; if (!ReadField(field) || string_to_int64(field.c_str(), &(sgfile->size))) goto out; sgfile->hostName = hostname; sgfile->storageGroup = sgname; DBG(DBG_DEBUG, "%s: succeeded (%s)\n", __FUNCTION__, sgfile->fileName.c_str()); return sgfile; out: DBG(DBG_ERROR, "%s: failed\n", __FUNCTION__); FlushMessage(); sgfile.reset(); return sgfile; } MarkListPtr ProtoMonitor::GetCutList75(const Program& program) { char buf[32]; std::string field; int32_t nb; MarkListPtr list(new MarkList); OS::CLockGuard lock(*m_mutex); if (!IsOpen()) return list; std::string cmd("QUERY_CUTLIST "); uint32_to_string(program.channel.chanId, buf); cmd.append(buf).append(" "); int64_to_string(program.recording.startTs, buf); cmd.append(buf); if (!SendCommand(cmd.c_str())) return list; if (!ReadField(field) || string_to_int32(field.c_str(), &nb)) goto out; if (nb > 0) { list->reserve(nb); do { MarkPtr mark = MarkPtr(new Mark()); if (!ReadField(field) || string_to_int8(field.c_str(), (int8_t*)&(mark->markType))) break; if (!ReadField(field) || string_to_int64(field.c_str(), &(mark->markValue))) break; list->push_back(mark); } while (--nb > 0); } DBG(DBG_DEBUG, "%s: succeeded (%s)\n", __FUNCTION__, program.fileName.c_str()); return list; out: DBG(DBG_ERROR, "%s: failed\n", __FUNCTION__); FlushMessage(); return list; } MarkListPtr ProtoMonitor::GetCommBreakList75(const Program& program) { char buf[32]; std::string field; int32_t nb; MarkListPtr list(new MarkList); OS::CLockGuard lock(*m_mutex); if (!IsOpen()) return list; std::string cmd("QUERY_COMMBREAK "); uint32_to_string(program.channel.chanId, buf); cmd.append(buf).append(" "); int64_to_string(program.recording.startTs, buf); cmd.append(buf); if (!SendCommand(cmd.c_str())) return list; if (!ReadField(field) || string_to_int32(field.c_str(), &nb)) goto out; if (nb > 0) { list->reserve(nb); do { MarkPtr mark = MarkPtr(new Mark()); if (!ReadField(field) || string_to_int8(field.c_str(), (int8_t*)&(mark->markType))) break; if (!ReadField(field) || string_to_int64(field.c_str(), &(mark->markValue))) break; list->push_back(mark); } while (--nb > 0); } DBG(DBG_DEBUG, "%s: succeeded (%s)\n", __FUNCTION__, program.fileName.c_str()); return list; out: DBG(DBG_ERROR, "%s: failed\n", __FUNCTION__); FlushMessage(); return list; } bool ProtoMonitor::BlockShutdown75() { std::string field; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) return false; std::string cmd("BLOCK_SHUTDOWN"); if (!SendCommand(cmd.c_str())) return false; if (!ReadField(field) || !IsMessageOK(field)) goto out; DBG(DBG_DEBUG, "%s: succeeded\n", __FUNCTION__); return true; out: DBG(DBG_ERROR, "%s: failed\n", __FUNCTION__); FlushMessage(); return false; } bool ProtoMonitor::AllowShutdown75() { std::string field; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) return false; std::string cmd("ALLOW_SHUTDOWN"); if (!SendCommand(cmd.c_str())) return false; if (!ReadField(field) || !IsMessageOK(field)) goto out; DBG(DBG_DEBUG, "%s: succeeded\n", __FUNCTION__); return true; out: DBG(DBG_ERROR, "%s: failed\n", __FUNCTION__); FlushMessage(); return false; } std::vector ProtoMonitor::GetFreeCardIdList75() { std::string field; std::vector ids; int32_t rnum; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) return ids; std::string cmd("GET_FREE_RECORDER_LIST"); if (!SendCommand(cmd.c_str())) return ids; while (m_msgConsumed < m_msgLength) { if (!ReadField(field) || string_to_int32(field.c_str(), &rnum)) { DBG(DBG_ERROR, "%s: failed\n", __FUNCTION__); FlushMessage(); ids.clear(); return ids; } if (rnum > 0) ids.push_back(rnum); } DBG(DBG_DEBUG, "%s: succeeded (%u)\n", __FUNCTION__, (unsigned)ids.size()); return ids; } CardInputListPtr ProtoMonitor::GetFreeInputs75() { CardInputListPtr list = CardInputListPtr(new CardInputList()); std::vector cardList = GetFreeCardIdList75(); for (std::vector::const_iterator cardIt = cardList.begin(); cardIt != cardList.end(); ++cardIt) { bool succeeded = false; char buf[32]; std::string field; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) break; std::string cmd("QUERY_RECORDER "); int32_to_string((int32_t)(*cardIt), buf); cmd.append(buf); cmd.append(PROTO_STR_SEPARATOR); cmd.append("GET_FREE_INPUTS"); if (!SendCommand(cmd.c_str())) break; while (m_msgConsumed < m_msgLength) { CardInputPtr input(new CardInput()); if (!ReadField(input->inputName)) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->sourceId))) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->inputId))) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->cardId))) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->mplexId))) break; if (!ReadField(field) || string_to_uint8(field.c_str(), &(input->liveTVOrder))) break; list->push_back(input); succeeded = true; } FlushMessage(); if (!succeeded) break; } return list; } CardInputListPtr ProtoMonitor::GetFreeInputs79() { CardInputListPtr list = CardInputListPtr(new CardInputList()); std::vector cardList = GetFreeCardIdList75(); for (std::vector::const_iterator cardIt = cardList.begin(); cardIt != cardList.end(); ++cardIt) { bool succeeded = false; char buf[32]; std::string field; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) break; std::string cmd("QUERY_RECORDER "); int32_to_string((int32_t)(*cardIt), buf); cmd.append(buf); cmd.append(PROTO_STR_SEPARATOR); cmd.append("GET_FREE_INPUTS"); if (!SendCommand(cmd.c_str())) break; while (m_msgConsumed < m_msgLength) { CardInputPtr input(new CardInput()); if (!ReadField(input->inputName)) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->sourceId))) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->inputId))) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->cardId))) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->mplexId))) break; if (!ReadField(field) || string_to_uint8(field.c_str(), &(input->liveTVOrder))) break; if (!ReadField(field)) // displayName break; if (!ReadField(field)) // recPriority break; if (!ReadField(field)) // schedOrder break; if (!ReadField(field)) // quickTune break; list->push_back(input); succeeded = true; } FlushMessage(); if (!succeeded) break; } return list; } CardInputListPtr ProtoMonitor::GetFreeInputs81() { CardInputListPtr list = CardInputListPtr(new CardInputList()); std::vector cardList = GetFreeCardIdList75(); for (std::vector::const_iterator cardIt = cardList.begin(); cardIt != cardList.end(); ++cardIt) { bool succeeded = false; char buf[32]; std::string field; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) break; std::string cmd("QUERY_RECORDER "); int32_to_string((int32_t)(*cardIt), buf); cmd.append(buf); cmd.append(PROTO_STR_SEPARATOR); cmd.append("GET_FREE_INPUTS"); if (!SendCommand(cmd.c_str())) break; while (m_msgConsumed < m_msgLength) { CardInputPtr input(new CardInput()); if (!ReadField(input->inputName)) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->sourceId))) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->inputId))) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->cardId))) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->mplexId))) break; if (!ReadField(field) || string_to_uint8(field.c_str(), &(input->liveTVOrder))) break; if (!ReadField(field)) // displayName break; if (!ReadField(field)) // recPriority break; if (!ReadField(field)) // schedOrder break; if (!ReadField(field)) // quickTune break; if (!ReadField(field)) // chanid break; list->push_back(input); succeeded = true; } FlushMessage(); if (!succeeded) break; } return list; } CardInputListPtr ProtoMonitor::GetFreeInputs87(int rnum) { CardInputListPtr list = CardInputListPtr(new CardInputList()); char buf[32]; std::string field; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) return list; std::string cmd("GET_FREE_INPUT_INFO "); int32_to_string((int32_t)rnum, buf); cmd.append(buf); if (!SendCommand(cmd.c_str())) return list; while (m_msgConsumed < m_msgLength) { CardInputPtr input(new CardInput()); if (!ReadField(input->inputName)) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->sourceId))) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->inputId))) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->cardId))) // obsolete: same as inputId break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->mplexId))) break; if (!ReadField(field) || string_to_uint8(field.c_str(), &(input->liveTVOrder))) break; if (!ReadField(field)) // displayName break; if (!ReadField(field)) // recPriority break; if (!ReadField(field)) // schedOrder break; if (!ReadField(field)) // quickTune break; if (!ReadField(field)) // chanid break; list->push_back(input); } FlushMessage(); return list; } CardInputListPtr ProtoMonitor::GetFreeInputs89(int rnum) { CardInputListPtr list = CardInputListPtr(new CardInputList()); char buf[32]; std::string field; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) return list; std::string cmd("GET_FREE_INPUT_INFO "); int32_to_string((int32_t)rnum, buf); cmd.append(buf); if (!SendCommand(cmd.c_str())) return list; while (m_msgConsumed < m_msgLength) { CardInputPtr input(new CardInput()); if (!ReadField(input->inputName)) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->sourceId))) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->inputId))) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->cardId))) // obsolete: same as inputId break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->mplexId))) break; if (!ReadField(field) || string_to_uint8(field.c_str(), &(input->liveTVOrder))) break; if (!ReadField(field)) // displayName break; if (!ReadField(field)) // recPriority break; if (!ReadField(field)) // schedOrder break; if (!ReadField(field)) // quickTune break; if (!ReadField(field)) // chanid break; if (!ReadField(field)) // reclimit break; list->push_back(input); } FlushMessage(); return list; } CardInputListPtr ProtoMonitor::GetFreeInputs90(int rnum) { CardInputListPtr list = CardInputListPtr(new CardInputList()); char buf[32]; std::string field; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) return list; std::string cmd("GET_FREE_INPUT_INFO "); int32_to_string((int32_t)rnum, buf); cmd.append(buf); if (!SendCommand(cmd.c_str())) return list; while (m_msgConsumed < m_msgLength) { CardInputPtr input(new CardInput()); if (!ReadField(input->inputName)) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->sourceId))) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->inputId))) break; input->cardId = input->inputId; // @FIXME: since protocol 90 if (!ReadField(field)) // reccount break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->mplexId))) break; if (!ReadField(field) || string_to_uint8(field.c_str(), &(input->liveTVOrder))) break; if (!ReadField(field)) // displayName break; if (!ReadField(field)) // recPriority break; if (!ReadField(field)) // schedOrder break; if (!ReadField(field)) // quickTune break; if (!ReadField(field)) // chanid break; if (!ReadField(field)) // reclimit break; list->push_back(input); } FlushMessage(); return list; } CardInputListPtr ProtoMonitor::GetFreeInputs91(int rnum) { CardInputListPtr list = CardInputListPtr(new CardInputList()); char buf[32]; std::string field; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) return list; std::string cmd("GET_FREE_INPUT_INFO "); int32_to_string((int32_t)rnum, buf); cmd.append(buf); if (!SendCommand(cmd.c_str())) return list; while (m_msgConsumed < m_msgLength) { CardInputPtr input(new CardInput()); if (!ReadField(input->inputName)) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->sourceId))) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->inputId))) break; input->cardId = input->inputId; // @FIXME: since protocol 90 if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->mplexId))) break; if (!ReadField(field) || string_to_uint8(field.c_str(), &(input->liveTVOrder))) break; if (!ReadField(field)) // displayName break; if (!ReadField(field)) // recPriority break; if (!ReadField(field)) // schedOrder break; if (!ReadField(field)) // quickTune break; if (!ReadField(field)) // chanid break; list->push_back(input); } FlushMessage(); return list; } pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/proto/mythprotomonitor.h000066400000000000000000000122261360567320200247150ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHPROTOMONITOR_H #define MYTHPROTOMONITOR_H #include "mythprotobase.h" #include "mythprotorecorder.h" #include #define PROTO_MONITOR_RCVBUF 64000 namespace Myth { class ProtoMonitor : public ProtoBase { public: ProtoMonitor(const std::string& server, unsigned port); ProtoMonitor(const std::string& server, unsigned port, bool frontend); virtual bool Open(); virtual void Close(); virtual bool IsOpen(); ProtoRecorderPtr GetRecorderFromNum(int rnum) { return GetRecorderFromNum75(rnum); } bool QueryFreeSpaceSummary(int64_t *total, int64_t *used) { return QueryFreeSpaceSummary75(total, used); } std::string GetSetting(const std::string& hostname, const std::string& setting) { return GetSetting75(hostname, setting); } bool SetSetting(const std::string& hostname, const std::string& setting, const std::string& value) { return SetSetting75(hostname, setting, value); } bool QueryGenpixmap(const Program& program) { return QueryGenpixmap75(program); } bool DeleteRecording(const Program& program, bool force = false, bool forget = false) { return DeleteRecording75(program, force, forget); } bool UndeleteRecording(const Program& program) { return UndeleteRecording75(program); } bool StopRecording(const Program& program) { return StopRecording75(program); } bool CancelNextRecording(int rnum, bool cancel) { return CancelNextRecording75(rnum, cancel); } StorageGroupFilePtr QuerySGFile(const std::string& hostname, const std::string& sgname, const std::string& filename) { return QuerySGFile75(hostname, sgname, filename); } MarkListPtr GetCutList(const Program& program) { return GetCutList75(program); } MarkListPtr GetCommBreakList(const Program& program) { return GetCommBreakList75(program); } bool BlockShutdown() { return BlockShutdown75(); } bool AllowShutdown() { return AllowShutdown75(); } /** * @brief Asks the backend for a list of free inputs. A free input is one that is connected but not busy, not in a busy input group or is locked. * @param rnum Since protocol 87: Input to exclude (not counted as busy). Defaulted with 0 for none. * @return */ CardInputListPtr GetFreeInputs(int rnum = 0) { if (m_protoVersion >= 91) return GetFreeInputs91(rnum); if (m_protoVersion >= 90) return GetFreeInputs90(rnum); if (m_protoVersion >= 89) return GetFreeInputs89(rnum); if (m_protoVersion >= 87) return GetFreeInputs87(rnum); if (m_protoVersion >= 81) return GetFreeInputs81(); if (m_protoVersion >= 79) return GetFreeInputs79(); return GetFreeInputs75(); } private: bool m_frontend; bool Announce75(); bool Announce88(); ProtoRecorderPtr GetRecorderFromNum75(int rnum); bool QueryFreeSpaceSummary75(int64_t *total, int64_t *used); std::string GetSetting75(const std::string& hostname, const std::string& setting); bool SetSetting75(const std::string& hostname, const std::string& setting, const std::string& value); bool QueryGenpixmap75(const Program& program); bool DeleteRecording75(const Program& program, bool force, bool forget); bool UndeleteRecording75(const Program& program); bool StopRecording75(const Program& program); bool CancelNextRecording75(int rnum, bool cancel); StorageGroupFilePtr QuerySGFile75(const std::string& hostname, const std::string& sgname, const std::string& filename); MarkListPtr GetCutList75(const Program& program); MarkListPtr GetCommBreakList75(const Program& program); bool BlockShutdown75(); bool AllowShutdown75(); std::vector GetFreeCardIdList75(); CardInputListPtr GetFreeInputs75(); CardInputListPtr GetFreeInputs79(); CardInputListPtr GetFreeInputs81(); CardInputListPtr GetFreeInputs87(int rnum); CardInputListPtr GetFreeInputs89(int rnum); CardInputListPtr GetFreeInputs90(int rnum); CardInputListPtr GetFreeInputs91(int rnum); // Not implemented //int64_t GetBookmark75(Program& program); //bool SetBookmark75(Program& program, int64_t bookmark); //bool UpdateSchedules75(); //bool UpdateSchedules75(uint32_t recordid); }; } #endif /* MYTHPROTOMONITOR_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/proto/mythprotoplayback.cpp000066400000000000000000000207731360567320200253550ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "mythprotoplayback.h" #include "../private/debug.h" #include "../private/socket.h" #include "../private/os/threads/mutex.h" #include "../private/builtin.h" #include #include #ifdef __WINDOWS__ #include #else #include // for recv #include // for select #endif /* __WINDOWS__ */ using namespace Myth; /////////////////////////////////////////////////////////////////////////////// //// //// Protocol connection to control playback //// ProtoPlayback::ProtoPlayback(const std::string& server, unsigned port) : ProtoBase(server, port) { } bool ProtoPlayback::Open() { bool ok = false; if (!OpenConnection(PROTO_PLAYBACK_RCVBUF)) return false; if (m_protoVersion >= 75) ok = Announce75(); if (ok) return true; Close(); return false; } void ProtoPlayback::Close() { ProtoBase::Close(); // Clean hanging and disable retry m_tainted = m_hang = false; } bool ProtoPlayback::IsOpen() { // Try reconnect if (m_hang) return ProtoPlayback::Open(); return ProtoBase::IsOpen(); } bool ProtoPlayback::Announce75() { OS::CLockGuard lock(*m_mutex); std::string cmd("ANN Playback "); cmd.append(m_socket->GetMyHostName()).append(" 0"); if (!SendCommand(cmd.c_str())) return false; std::string field; if (!ReadField(field) || !IsMessageOK(field)) goto out; return true; out: FlushMessage(); return false; } void ProtoPlayback::TransferDone75(ProtoTransfer& transfer) { char buf[32]; OS::CLockGuard lock(*m_mutex); if (!transfer.IsOpen()) return; std::string cmd("QUERY_FILETRANSFER "); uint32_to_string(transfer.GetFileId(), buf); cmd.append(buf).append(PROTO_STR_SEPARATOR).append("DONE"); if (SendCommand(cmd.c_str())) { std::string field; if (!ReadField(field) || !IsMessageOK(field)) FlushMessage(); } } bool ProtoPlayback::TransferIsOpen75(ProtoTransfer& transfer) { char buf[32]; std::string field; int8_t status = 0; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) return false; std::string cmd("QUERY_FILETRANSFER "); uint32_to_string(transfer.GetFileId(), buf); cmd.append(buf); cmd.append(PROTO_STR_SEPARATOR); cmd.append("IS_OPEN"); if (!SendCommand(cmd.c_str())) return false; if (!ReadField(field) || 0 != string_to_int8(field.c_str(), &status)) { FlushMessage(); return false; } if (status == 0) return false; return true; } int ProtoPlayback::TransferRequestBlock(ProtoTransfer& transfer, void *buffer, unsigned n) { bool request = false, data = false; int r = 0, nfds = 0, fdc, fdd; char *p = (char*)buffer; struct timeval tv; fd_set fds; unsigned s = 0; int64_t filePosition = transfer.GetPosition(); int64_t fileRequest = transfer.GetRequested(); if (n == 0) return n; fdc = GetSocket(); if (INVALID_SOCKET_VALUE == (net_socket_t)fdc) return -1; fdd = transfer.GetSocket(); if (INVALID_SOCKET_VALUE == (net_socket_t)fdd) return -1; // Max size is RCVBUF size if (n > PROTO_TRANSFER_RCVBUF) n = PROTO_TRANSFER_RCVBUF; if ((filePosition + n) > fileRequest) { // Begin critical section m_mutex->Lock(); bool ok = TransferRequestBlock75(transfer, n); if (!ok) { m_mutex->Unlock(); goto err; } request = true; } do { FD_ZERO(&fds); if (request) { FD_SET((net_socket_t)fdc, &fds); if (nfds < fdc) nfds = fdc; } FD_SET((net_socket_t)fdd, &fds); if (nfds < fdd) nfds = fdd; if (data) { // Read directly to get all queued packets tv.tv_sec = 0; tv.tv_usec = 0; } else { // Wait and read for new packet tv.tv_sec = 10; tv.tv_usec = 0; } r = select (nfds + 1, &fds, NULL, NULL, &tv); if (r < 0) { DBG(DBG_ERROR, "%s: select error (%d)\n", __FUNCTION__, r); goto err; } if (r == 0 && !data) { DBG(DBG_ERROR, "%s: select timeout\n", __FUNCTION__); goto err; } // Check for data data = false; if (FD_ISSET((net_socket_t)fdd, &fds)) { r = recv((net_socket_t)fdd, p, (size_t)(n - s), 0); if (r < 0) { DBG(DBG_ERROR, "%s: recv data error (%d)\n", __FUNCTION__, r); goto err; } if (r > 0) { data = true; s += r; p += r; filePosition += r; transfer.SetPosition(filePosition); } } // Check for response of request if (request && FD_ISSET((net_socket_t)fdc, &fds)) { int32_t rlen = TransferRequestBlockFeedback75(); request = false; // request is completed m_mutex->Unlock(); if (rlen < 0) goto err; DBG(DBG_DEBUG, "%s: receive block size (%u)\n", __FUNCTION__, (unsigned)rlen); if (rlen == 0 && !data) break; // no more data fileRequest += rlen; transfer.SetRequested(fileRequest); } } while (request || data || !s); DBG(DBG_DEBUG, "%s: data read (%u)\n", __FUNCTION__, s); return (int)s; err: if (request) { if (RcvMessageLength()) FlushMessage(); m_mutex->Unlock(); } // Recover the file position or die if (TransferSeek(transfer, filePosition, WHENCE_SET) < 0) HangException(); return -1; } bool ProtoPlayback::TransferRequestBlock75(ProtoTransfer& transfer, unsigned n) { // Note: Caller has to hold mutex until feedback or cancel point char buf[32]; if (!transfer.IsOpen()) return false; std::string cmd("QUERY_FILETRANSFER "); uint32_to_string(transfer.GetFileId(), buf); cmd.append(buf); cmd.append(PROTO_STR_SEPARATOR); cmd.append("REQUEST_BLOCK"); cmd.append(PROTO_STR_SEPARATOR); uint32_to_string(n, buf); cmd.append(buf); // No wait for feedback if (!SendCommand(cmd.c_str(), false)) return false; return true; } int32_t ProtoPlayback::TransferRequestBlockFeedback75() { int32_t rlen = 0; std::string field; if (!RcvMessageLength() || !ReadField(field) || 0 != string_to_int32(field.c_str(), &rlen) || rlen < 0) { DBG(DBG_ERROR, "%s: invalid response for request block (%s)\n", __FUNCTION__, field.c_str()); FlushMessage(); return -1; } return rlen; } int64_t ProtoPlayback::TransferSeek75(ProtoTransfer& transfer, int64_t offset, WHENCE_t whence) { char buf[32]; int64_t position = 0; std::string field; int64_t filePosition = transfer.GetPosition(); int64_t fileSize = transfer.GetSize(); // Check offset switch (whence) { case WHENCE_CUR: if (offset == 0) return filePosition; position = filePosition + offset; if (position < 0 || position > fileSize) return -1; break; case WHENCE_SET: if (offset == filePosition) return filePosition; if (offset < 0 || offset > fileSize) return -1; break; case WHENCE_END: position = fileSize - offset; if (position < 0 || position > fileSize) return -1; break; default: return -1; } OS::CLockGuard lock(*m_mutex); if (!transfer.IsOpen()) return -1; std::string cmd("QUERY_FILETRANSFER "); uint32_to_string(transfer.GetFileId(), buf); cmd.append(buf); cmd.append(PROTO_STR_SEPARATOR); cmd.append("SEEK"); cmd.append(PROTO_STR_SEPARATOR); int64_to_string(offset, buf); cmd.append(buf); cmd.append(PROTO_STR_SEPARATOR); int8_to_string(whence, buf); cmd.append(buf); cmd.append(PROTO_STR_SEPARATOR); int64_to_string(filePosition, buf); cmd.append(buf); if (!SendCommand(cmd.c_str())) return -1; if (!ReadField(field) || 0 != string_to_int64(field.c_str(), &position)) { FlushMessage(); return -1; } // Reset transfer transfer.Flush(); transfer.SetRequested(position); transfer.SetPosition(position); return position; } pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/proto/mythprotoplayback.h000066400000000000000000000037311360567320200250150ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHPROTOPLAYBACK_H #define MYTHPROTOPLAYBACK_H #include "mythprotobase.h" #include "mythprototransfer.h" #define PROTO_PLAYBACK_RCVBUF 64000 namespace Myth { class ProtoPlayback : public ProtoBase { public: ProtoPlayback(const std::string& server, unsigned port); virtual bool Open(); virtual void Close(); virtual bool IsOpen(); void TransferDone(ProtoTransfer& transfer) { TransferDone75(transfer); } bool TransferIsOpen(ProtoTransfer& transfer) { return TransferIsOpen75(transfer); } int TransferRequestBlock(ProtoTransfer& transfer, void *buffer, unsigned n); int64_t TransferSeek(ProtoTransfer& transfer, int64_t offset, WHENCE_t whence) { return TransferSeek75(transfer, offset, whence); } private: bool Announce75(); void TransferDone75(ProtoTransfer& transfer); bool TransferIsOpen75(ProtoTransfer& transfer); bool TransferRequestBlock75(ProtoTransfer& transfer, unsigned n); int32_t TransferRequestBlockFeedback75(); int64_t TransferSeek75(ProtoTransfer& transfer, int64_t offset, WHENCE_t whence); }; } #endif /* MYTHPROTOPLAYBACK_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/proto/mythprotorecorder.cpp000066400000000000000000000377171360567320200254020ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "mythprotorecorder.h" #include "../private/debug.h" #include "../private/os/threads/mutex.h" #include "../private/builtin.h" #include #include using namespace Myth; ProtoRecorder::ProtoRecorder(int num, const std::string& server, unsigned port) : ProtoPlayback(server, port) , m_num(num) , m_playing(false) , m_liveRecording(false) { ProtoPlayback::Open(); } ProtoRecorder::~ProtoRecorder() { if (m_playing) StopLiveTV(); ProtoPlayback::Close(); } int ProtoRecorder::GetNum() const { return m_num; } bool ProtoRecorder::IsPlaying() const { return m_playing; } bool ProtoRecorder::IsTunable(const Channel& channel) { bool ok = false; CardInputListPtr inputlist = GetFreeInputs(); for (CardInputList::const_iterator it = inputlist->begin(); it != inputlist->end(); ++it) { const CardInput *input = (*it).get(); if (input->sourceId != channel.sourceId) { DBG(DBG_DEBUG, "%s: skip input, source id differs (channel: %" PRIu32 ", input: %" PRIu32 ")\n", __FUNCTION__, channel.sourceId, input->sourceId); continue; } if (input->mplexId && input->mplexId != channel.mplexId) { DBG(DBG_DEBUG, "%s: skip input, multiplex id differs (channel: %" PRIu32 ", input: %" PRIu32 ")\n", __FUNCTION__, channel.mplexId, input->mplexId); continue; } DBG(DBG_DEBUG,"%s: using recorder, input is tunable: source id: %" PRIu32 ", multiplex id: %" PRIu32 ", channel: %" PRIu32 ", input: %" PRIu32 ")\n", __FUNCTION__, channel.sourceId, channel.mplexId, channel.chanId, input->inputId); ok = true; break; } if (!ok) { DBG(DBG_INFO,"%s: recorder is not tunable\n", __FUNCTION__); } return ok; } void ProtoRecorder::DoneRecordingCallback() { OS::CLockGuard lock(*m_mutex); m_liveRecording = false; DBG(DBG_DEBUG, "%s: completed\n", __FUNCTION__); } bool ProtoRecorder::SpawnLiveTV75(const std::string& chainid, const std::string& channum) { char buf[32]; std::string field; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) return false; std::string cmd("QUERY_RECORDER "); int32_to_string((int32_t)m_num, buf); cmd.append(buf); cmd.append(PROTO_STR_SEPARATOR); cmd.append("SPAWN_LIVETV"); cmd.append(PROTO_STR_SEPARATOR); cmd.append(chainid); cmd.append(PROTO_STR_SEPARATOR).append("0").append(PROTO_STR_SEPARATOR); cmd.append(channum); DBG(DBG_DEBUG, "%s: starting ...\n", __FUNCTION__); m_playing = true; if (!SendCommand(cmd.c_str())) { m_playing = false; } else if (!ReadField(field) || !IsMessageOK(field)) { m_playing = false; FlushMessage(); } DBG(DBG_DEBUG, "%s: %s\n", __FUNCTION__, (m_playing ? "succeeded" : "failed")); return m_playing; } bool ProtoRecorder::StopLiveTV75() { char buf[32]; std::string field; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) return false; std::string cmd("QUERY_RECORDER "); int32_to_string((int32_t)m_num, buf); cmd.append(buf); cmd.append(PROTO_STR_SEPARATOR); cmd.append("STOP_LIVETV"); if (!SendCommand(cmd.c_str())) return false; if (!ReadField(field) || !IsMessageOK(field)) { FlushMessage(); return false; } m_playing = false; return true; } bool ProtoRecorder::CheckChannel75(const std::string& channum) { char buf[32]; std::string field; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) return false; std::string cmd("QUERY_RECORDER "); int32_to_string((int32_t)m_num, buf); cmd.append(buf); cmd.append(PROTO_STR_SEPARATOR); cmd.append("CHECK_CHANNEL"); cmd.append(PROTO_STR_SEPARATOR); cmd.append(channum); if (!SendCommand(cmd.c_str())) return false; if (!ReadField(field) || field != "1") { DBG(DBG_DEBUG, "%s: %s\n", __FUNCTION__, field.c_str()); FlushMessage(); return false; } return true; } ProgramPtr ProtoRecorder::GetCurrentRecording75() { char buf[32]; ProgramPtr program; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) return program; std::string cmd("QUERY_RECORDER "); int32_to_string((int32_t)m_num, buf); cmd.append(buf); cmd.append(PROTO_STR_SEPARATOR); cmd.append("GET_CURRENT_RECORDING"); if (!SendCommand(cmd.c_str())) return program; if (!(program = RcvProgramInfo())) goto out; FlushMessage(); return program; out: DBG(DBG_ERROR, "%s: failed\n", __FUNCTION__); FlushMessage(); return program; } int64_t ProtoRecorder::GetFilePosition75() { char buf[32]; int64_t pos; std::string field; OS::CLockGuard lock(*m_mutex); if (!IsOpen() || !IsPlaying()) return -1; std::string cmd("QUERY_RECORDER "); int32_to_string((int32_t)m_num, buf); cmd.append(buf); cmd.append(PROTO_STR_SEPARATOR); cmd.append("GET_FILE_POSITION"); if (!SendCommand(cmd.c_str())) return -1; if (!ReadField(field) || string_to_int64(field.c_str(), &pos)) goto out; FlushMessage(); return pos; out: FlushMessage(); return -1; } CardInputListPtr ProtoRecorder::GetFreeInputs75() { CardInputListPtr list = CardInputListPtr(new CardInputList()); char buf[32]; std::string field; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) return list; std::string cmd("QUERY_RECORDER "); int32_to_string((int32_t)m_num, buf); cmd.append(buf); cmd.append(PROTO_STR_SEPARATOR); cmd.append("GET_FREE_INPUTS"); if (!SendCommand(cmd.c_str())) return list; while (m_msgConsumed < m_msgLength) { CardInputPtr input(new CardInput()); if (!ReadField(input->inputName)) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->sourceId))) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->inputId))) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->cardId))) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->mplexId))) break; if (!ReadField(field) || string_to_uint8(field.c_str(), &(input->liveTVOrder))) break; list->push_back(input); } FlushMessage(); return list; } CardInputListPtr ProtoRecorder::GetFreeInputs79() { CardInputListPtr list = CardInputListPtr(new CardInputList()); char buf[32]; std::string field; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) return list; std::string cmd("QUERY_RECORDER "); int32_to_string((int32_t)m_num, buf); cmd.append(buf); cmd.append(PROTO_STR_SEPARATOR); cmd.append("GET_FREE_INPUTS"); if (!SendCommand(cmd.c_str())) return list; while (m_msgConsumed < m_msgLength) { CardInputPtr input(new CardInput()); if (!ReadField(input->inputName)) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->sourceId))) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->inputId))) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->cardId))) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->mplexId))) break; if (!ReadField(field) || string_to_uint8(field.c_str(), &(input->liveTVOrder))) break; if (!ReadField(field)) // displayName break; if (!ReadField(field)) // recPriority break; if (!ReadField(field)) // schedOrder break; if (!ReadField(field)) // quickTune break; list->push_back(input); } FlushMessage(); return list; } CardInputListPtr ProtoRecorder::GetFreeInputs81() { CardInputListPtr list = CardInputListPtr(new CardInputList()); char buf[32]; std::string field; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) return list; std::string cmd("QUERY_RECORDER "); int32_to_string((int32_t)m_num, buf); cmd.append(buf); cmd.append(PROTO_STR_SEPARATOR); cmd.append("GET_FREE_INPUTS"); if (!SendCommand(cmd.c_str())) return list; while (m_msgConsumed < m_msgLength) { CardInputPtr input(new CardInput()); if (!ReadField(input->inputName)) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->sourceId))) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->inputId))) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->cardId))) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->mplexId))) break; if (!ReadField(field) || string_to_uint8(field.c_str(), &(input->liveTVOrder))) break; if (!ReadField(field)) // displayName break; if (!ReadField(field)) // recPriority break; if (!ReadField(field)) // schedOrder break; if (!ReadField(field)) // quickTune break; if (!ReadField(field)) // chanid break; list->push_back(input); } FlushMessage(); return list; } CardInputListPtr ProtoRecorder::GetFreeInputs87() { CardInputListPtr list = CardInputListPtr(new CardInputList()); std::string field; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) return list; std::string cmd("GET_FREE_INPUT_INFO 0"); if (!SendCommand(cmd.c_str())) return list; while (m_msgConsumed < m_msgLength) { CardInputPtr input(new CardInput()); if (!ReadField(input->inputName)) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->sourceId))) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->inputId))) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->cardId))) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->mplexId))) break; if (!ReadField(field) || string_to_uint8(field.c_str(), &(input->liveTVOrder))) break; if (!ReadField(field)) // displayName break; if (!ReadField(field)) // recPriority break; if (!ReadField(field)) // schedOrder break; if (!ReadField(field)) // quickTune break; if (!ReadField(field)) // chanid break; if (input->cardId == static_cast(m_num)) list->push_back(input); } FlushMessage(); return list; } CardInputListPtr ProtoRecorder::GetFreeInputs89() { CardInputListPtr list = CardInputListPtr(new CardInputList()); std::string field; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) return list; std::string cmd("GET_FREE_INPUT_INFO 0"); if (!SendCommand(cmd.c_str())) return list; while (m_msgConsumed < m_msgLength) { CardInputPtr input(new CardInput()); if (!ReadField(input->inputName)) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->sourceId))) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->inputId))) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->cardId))) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->mplexId))) break; if (!ReadField(field) || string_to_uint8(field.c_str(), &(input->liveTVOrder))) break; if (!ReadField(field)) // displayName break; if (!ReadField(field)) // recPriority break; if (!ReadField(field)) // schedOrder break; if (!ReadField(field)) // quickTune break; if (!ReadField(field)) // chanid break; if (!ReadField(field)) // reclimit break; if (input->cardId == static_cast(m_num)) list->push_back(input); } FlushMessage(); return list; } CardInputListPtr ProtoRecorder::GetFreeInputs90() { CardInputListPtr list = CardInputListPtr(new CardInputList()); std::string field; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) return list; std::string cmd("GET_FREE_INPUT_INFO 0"); if (!SendCommand(cmd.c_str())) return list; while (m_msgConsumed < m_msgLength) { CardInputPtr input(new CardInput()); if (!ReadField(input->inputName)) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->sourceId))) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->inputId))) break; input->cardId = input->inputId; // @FIXME: since protocol 90 if (!ReadField(field)) // reccount break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->mplexId))) break; if (!ReadField(field) || string_to_uint8(field.c_str(), &(input->liveTVOrder))) break; if (!ReadField(field)) // displayName break; if (!ReadField(field)) // recPriority break; if (!ReadField(field)) // schedOrder break; if (!ReadField(field)) // quickTune break; if (!ReadField(field)) // chanid break; if (!ReadField(field)) // reclimit break; if (input->cardId == static_cast(m_num)) list->push_back(input); } FlushMessage(); return list; } CardInputListPtr ProtoRecorder::GetFreeInputs91() { CardInputListPtr list = CardInputListPtr(new CardInputList()); std::string field; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) return list; std::string cmd("GET_FREE_INPUT_INFO 0"); if (!SendCommand(cmd.c_str())) return list; while (m_msgConsumed < m_msgLength) { CardInputPtr input(new CardInput()); if (!ReadField(input->inputName)) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->sourceId))) break; if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->inputId))) break; input->cardId = input->inputId; // @FIXME: since protocol 90 if (!ReadField(field) || string_to_uint32(field.c_str(), &(input->mplexId))) break; if (!ReadField(field) || string_to_uint8(field.c_str(), &(input->liveTVOrder))) break; if (!ReadField(field)) // displayName break; if (!ReadField(field)) // recPriority break; if (!ReadField(field)) // schedOrder break; if (!ReadField(field)) // quickTune break; if (!ReadField(field)) // chanid break; if (input->cardId == static_cast(m_num)) list->push_back(input); } FlushMessage(); return list; } bool ProtoRecorder::IsLiveRecording() { OS::CLockGuard lock(*m_mutex); return m_liveRecording; } bool ProtoRecorder::SetLiveRecording75(bool keep) { char buf[32]; std::string field; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) return false; std::string cmd("QUERY_RECORDER "); int32_to_string((int32_t)m_num, buf); cmd.append(buf); cmd.append(PROTO_STR_SEPARATOR); cmd.append("SET_LIVE_RECORDING").append(PROTO_STR_SEPARATOR); if (keep) cmd.append("1"); else cmd.append("0"); if (!SendCommand(cmd.c_str())) return false; if (!ReadField(field) || !IsMessageOK(field)) goto out; DBG(DBG_DEBUG, "%s: succeeded (%d)\n", __FUNCTION__, keep); return true; out: DBG(DBG_ERROR, "%s: failed\n", __FUNCTION__); FlushMessage(); return false; } bool ProtoRecorder::FinishRecording75() { char buf[32]; std::string field; OS::CLockGuard lock(*m_mutex); if (!IsOpen()) return false; std::string cmd("QUERY_RECORDER "); int32_to_string((int32_t)m_num, buf); cmd.append(buf); cmd.append(PROTO_STR_SEPARATOR); cmd.append("FINISH_RECORDING"); if (!SendCommand(cmd.c_str())) return false; if (!ReadField(field) || !IsMessageOK(field)) goto out; DBG(DBG_DEBUG, "%s: succeeded\n", __FUNCTION__); return true; out: DBG(DBG_ERROR, "%s: failed\n", __FUNCTION__); FlushMessage(); return false; } pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/proto/mythprotorecorder.h000066400000000000000000000062221360567320200250320ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHPROTORECORDER_H #define MYTHPROTORECORDER_H #include "mythprotoplayback.h" namespace Myth { class ProtoRecorder; typedef MYTH_SHARED_PTR ProtoRecorderPtr; class ProtoRecorder : public ProtoPlayback { public: ProtoRecorder(int num, const std::string& server, unsigned port); virtual ~ProtoRecorder(); int GetNum() const; bool IsPlaying() const; bool IsTunable(const Channel& channel); void DoneRecordingCallback(); bool SpawnLiveTV(const std::string& chainid, const std::string& channum) { return SpawnLiveTV75(chainid, channum); } bool StopLiveTV() { return StopLiveTV75(); } bool CheckChannel(const std::string& channum) { return CheckChannel75(channum); } ProgramPtr GetCurrentRecording() { return GetCurrentRecording75(); } int64_t GetFilePosition() { return GetFilePosition75(); } CardInputListPtr GetFreeInputs() { if (m_protoVersion >= 91) return GetFreeInputs91(); if (m_protoVersion >= 90) return GetFreeInputs90(); if (m_protoVersion >= 89) return GetFreeInputs89(); if (m_protoVersion >= 87) return GetFreeInputs87(); if (m_protoVersion >= 81) return GetFreeInputs81(); if (m_protoVersion >= 79) return GetFreeInputs79(); return GetFreeInputs75(); } bool IsLiveRecording(); bool SetLiveRecording(bool keep) { bool ret = SetLiveRecording75(keep); if (keep && ret) m_liveRecording = keep; // Hold status for this showing return ret; } bool FinishRecording() { return FinishRecording75(); } private: int m_num; volatile bool m_playing; volatile bool m_liveRecording; bool SpawnLiveTV75(const std::string& chainid, const std::string& channum); bool StopLiveTV75(); bool CheckChannel75(const std::string& channum); ProgramPtr GetCurrentRecording75(); int64_t GetFilePosition75(); CardInputListPtr GetFreeInputs75(); CardInputListPtr GetFreeInputs79(); CardInputListPtr GetFreeInputs81(); CardInputListPtr GetFreeInputs87(); CardInputListPtr GetFreeInputs89(); CardInputListPtr GetFreeInputs90(); CardInputListPtr GetFreeInputs91(); bool SetLiveRecording75(bool keep); bool FinishRecording75(); }; } #endif /* MYTHPROTORECORDER_H */ pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/proto/mythprototransfer.cpp000066400000000000000000000105151360567320200254040ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "mythprototransfer.h" #include "../private/debug.h" #include "../private/socket.h" #include "../private/os/threads/mutex.h" #include "../private/builtin.h" #include #include using namespace Myth; /////////////////////////////////////////////////////////////////////////////// //// //// Protocol connection to transfer file //// ProtoTransfer::ProtoTransfer(const std::string& server, unsigned port, const std::string& pathname, const std::string& sgname) : ProtoBase(server, port) , m_fileSize(0) , m_filePosition(0) , m_fileRequest(0) , m_fileId(0) , m_pathName(pathname) , m_storageGroupName(sgname) { } bool ProtoTransfer::Open() { bool ok = false; if (IsOpen()) return true; if (!OpenConnection(PROTO_TRANSFER_RCVBUF)) return false; if (m_protoVersion >= 75) ok = Announce75(); if (!ok) { m_hang = true; // set hang to close without notice Close(); return false; } return true; } void ProtoTransfer::Close() { OS::CLockGuard lock(*m_mutex); ProtoBase::Close(); // Clean hanging and disable retry m_tainted = m_hang = false; // Reset transfer m_filePosition = m_fileRequest = 0; m_fileId = 0; } void ProtoTransfer::Lock() { m_mutex->Lock(); } void ProtoTransfer::Unlock() { m_mutex->Unlock(); } bool ProtoTransfer::TryLock() { return m_mutex->TryLock(); } void ProtoTransfer::Flush() { OS::CLockGuard lock(*m_mutex); int64_t unread = m_fileRequest - m_filePosition; if (unread > 0) { char buf[PROTO_BUFFER_SIZE]; size_t n = (size_t)unread; while (n > 0) { size_t s = (n > PROTO_BUFFER_SIZE ? PROTO_BUFFER_SIZE : n); if(m_socket->ReceiveData(buf, s) != s) break; n -= s; } DBG(DBG_DEBUG, "%s: unreaded bytes (%u)\n", __FUNCTION__, (unsigned)n); // Reset position regardless bytes read m_filePosition = m_fileRequest; } } bool ProtoTransfer::Announce75() { OS::CLockGuard lock(*m_mutex); m_filePosition = m_fileSize = m_fileRequest = 0; std::string cmd("ANN FileTransfer "); cmd.append(m_socket->GetMyHostName()); cmd.append(" 0 0 1000" PROTO_STR_SEPARATOR); cmd.append(m_pathName).append(PROTO_STR_SEPARATOR); cmd.append(m_storageGroupName); if (!SendCommand(cmd.c_str())) return false; std::string field; if (!ReadField(field) || !IsMessageOK(field)) goto out; if (!ReadField(field) || 0 != string_to_uint32(field.c_str(), &m_fileId)) goto out; if (!ReadField(field) || 0 != string_to_int64(field.c_str(), &m_fileSize)) goto out; return true; out: FlushMessage(); return false; } uint32_t ProtoTransfer::GetFileId() const { return m_fileId; } std::string ProtoTransfer::GetPathName() const { return m_pathName; } std::string ProtoTransfer::GetStorageGroupName() const { return m_storageGroupName; } int64_t ProtoTransfer::GetSize() const { OS::CLockGuard lock(*m_mutex); return m_fileSize; } int64_t ProtoTransfer::GetPosition() const { OS::CLockGuard lock(*m_mutex); return m_filePosition; } int64_t ProtoTransfer::GetRequested() const { OS::CLockGuard lock(*m_mutex); return m_fileRequest; } int64_t ProtoTransfer::GetRemaining() const { OS::CLockGuard lock(*m_mutex); return (m_fileSize - m_filePosition); } void ProtoTransfer::SetSize(int64_t size) { OS::CLockGuard lock(*m_mutex); m_fileSize = size; } void ProtoTransfer::SetPosition(int64_t position) { OS::CLockGuard lock(*m_mutex); m_filePosition = position; } void ProtoTransfer::SetRequested(int64_t requested) { OS::CLockGuard lock(*m_mutex); m_fileRequest = requested; } pvr.mythtv-5.10.15-Leia/lib/cppmyth/src/proto/mythprototransfer.h000066400000000000000000000041751360567320200250560ustar00rootroot00000000000000/* * Copyright (C) 2014 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef MYTHPROTOTRANSFER_H #define MYTHPROTOTRANSFER_H #include "mythprotobase.h" #define PROTO_TRANSFER_RCVBUF 64000 namespace Myth { class ProtoTransfer; typedef MYTH_SHARED_PTR ProtoTransferPtr; class ProtoTransfer : public ProtoBase { public: ProtoTransfer(const std::string& server, unsigned port, const std::string& pathname, const std::string& sgname); virtual bool Open(); virtual void Close(); void Lock(); void Unlock(); bool TryLock(); /** * @brief Flushing unread data previously requested * @return void */ void Flush(); uint32_t GetFileId() const; std::string GetPathName() const; std::string GetStorageGroupName() const; int64_t GetSize() const; int64_t GetPosition() const; int64_t GetRequested() const; int64_t GetRemaining() const; void SetSize(int64_t size); void SetPosition(int64_t position); void SetRequested(int64_t requested); private: int64_t m_fileSize; ///< Size of file int64_t m_filePosition; ///< Current read position int64_t m_fileRequest; ///< Current requested position uint32_t m_fileId; std::string m_pathName; std::string m_storageGroupName; bool Announce75(); }; } #endif /* MYTHPROTOTRANSFER_H */ pvr.mythtv-5.10.15-Leia/pvr.mythtv/000077500000000000000000000000001360567320200170415ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/addon.xml.in000066400000000000000000000611111360567320200212550ustar00rootroot00000000000000 @ADDON_DEPENDS@ Kodi voorprogram vir MythTV Kodi frontend for MythTV Kodi клиент за MythTV Frontal de Kodi per a MythTV Rozhraní Kodi pro MythTV Blaen Kodi ar gyfer MythTV Kodi frontend til MythTV Kodi's Zugang zu MythTV Frontend του Kodi για το MythTV Kodi frontend for MythTV Kodi frontend for MythTV Kodi frontend for MythTV Kodi frontend for MythTV Front-end de Kodi para MythTV Front-end de Kodi para MythTV Kodi frontend para MythTV Kodi liides MythTV'le Kodin MythTV-asiakasohjelma Frontal Kodi pour MythTV Interface logicielle pour MythTV Interface de Kodi para MythTV לקוח טלוויזיה ×—×™×” עבור MythTV Kodi suÄelje za MythTV Kodi elÅ‘tét a MythTV-hez Antarmuka Kodi untuk MythTV Kodi framendi fyrir MythTV Frontend di Kodi per MythTV MythTV 用 Kodi フロントエンド MythTV Kodi 프론트엔드 Kodi sÄ…saja į MythTV Kodi galasistÄ“ma MythTV Kodi Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÑ˜Ñ Ð·Ð° MythTV Bahagian hadapan Kodi untuk MythTV Kodi-klient for MythTV Kodi frontend voor MythTV Klient telewizji dla MythTV Kodi frontend para MythTV Interface Kodi para MythTV InterfaÈ›a Kodi pentru MythTV ФронтÑнд Kodi Ð´Ð»Ñ MythTV Kodi rozhranie pre MythTV Kodijev vmesnik za MythTV Kodi Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÑ˜Ñ Ð·Ð° MythTV Kodi interfejs za MythTV Kodi-gränssnitt för MythTV Klijynt telewizyjny dlÅ MythTV MythTV için Kodi ön ucu Kodi çš„ MythTV å‰ç«¯ MythTVçš„Kodiå‰ç«¯ä»‹é¢ MythTV voorprogram (tot MythTV 30). Ondersteun stroom van Lewendige TV & Opnames, luister na Radio kanale, EPG en Tydhouers. MythTV frontend (up to MythTV 30). Supports streaming of Live TV & Recordings, listening to Radio channels, EPG and Timers. Клиент за MythTV (до верÑÐ¸Ñ Ð½Ð° MythTV 30). Поддържа Ñ‚ÐµÐ»ÐµÐ²Ð¸Ð·Ð¸Ñ Ð½Ð° живо и запиÑване, Ñлушане на радио канали, електронен програмен Ñправочник и броÑчи. Frontal de MythTV (fins a MythTV 30). És compatible amb les transmissions en línia de TV en directe i enregistraments, escolta d'emissores de ràdio, guia electrònica de programació (EPG) i temporitzadors. Rozhraní MythTV (do verze MythTV 30). Podporuje streamování živého vysílání a nahrávání, poslech kanálů rádia, televizní program a ÄasovaÄe. Blaen MythTV (hyd at MythTV 30). Cynnal ffrydio Teledu Byw a Recordiadau, gwrando ar sianeli radio, amserlenni rhaglenni electronig ac amseryddion. MythTV frontend (op til MythTV 30) Understøtter streaming af Live TV & Optagelser, Radiokanaler, EPG samt tidsplaner. MythTV Frontend (bis zu MythTV 30). Unterstützt das Streamen von Live TV & Aufnahmen, Hören von Radiokanälen, EPG und Timer. Frontend για το MythTV (έως το MythTV 30). ΥποστηÏίζει Ïοές Live TV & ΕγγÏαφές, ακÏόαση Ραδιοφώνου, EPG και ΧÏονοδιακόπτες. MythTV frontend (up to MythTV 30). Supports streaming of Live TV & Recordings, listening to Radio channels, EPG and Timers. MythTV frontend (up to MythTV 30). Supports streaming of Live TV & Recordings, listening to Radio channels, EPG and Timers. MythTV frontend (up to MythTV 30). Supports streaming of Live TV & Recordings, listening to Radio channels, EPG and Timers. MythTV frontend (up to MythTV 30). Supports streaming of Live TV & Recordings, listening to Radio channels, EPG and Timers. Front-end de MythTV (hasta MythTV 30). Soporte de transmisiones de TV en Vivo y Grabaciones, escuchar canales de Radio, Guía Electrónica de Programas (EPG) y Temporizadores. Front-end de MythTV (hasta MythTV 30). Soporte de transmisiones de TV en Vivo y Grabaciones, escuchar canales de Radio, Guía Electrónica de Programas (EPG) y Temporizadores. MythTV frontend (hasta MythTV 30). Soporta transmisión de TV y grabaciones en vivo, escucha de canales de radio, EPG y temporizadores. MythTV-asiakasohjelma (MythTV 30). Tukee suorien tv-lähetysten ja tallennusten katsomista, radiokanavia, ohjelmaopasta ja ohjelmien ajastamista. Frontal de MythTV (jusqu’à MythTV 30) prenant en charge la diffusion en continu des télés en direct et les enregistrements, l’écoute de chaînes radio, le GÉP et les minuteries. Interface logicielle MythTV (jusqu'à la version 30). Permet la diffusion de la TV en direct, des enregistrements, des stations de radios, ainsi que le guide électronique des programmes TV et les programmations. Interface de MythTV (maior da MythTV 30). Compatíbel coa transmisión de TV ao vivo, gravacións e escoita de canles de Radio, EPG e temporizadores. לקוח טלוויזיה ×—×™×” של MythTV (עד גרסה 30 של MythTV). תומך בהזרמת ×©×™×“×•×¨×™× ×—×™×™× ×•×”×§×œ×˜×•×ª, ×”××–× ×” לרדיו, הצגת לוח ×©×™×“×•×¨×™× ×•×ª×–×ž×•×Ÿ הקלטות. MythTV suÄelje (za inaÄice do MythTV 30. Podržava streamanje i snimanje TV programa, sluÅ¡anje radio programa, elektronski programski vodiÄ (EPG) i zakazana snimanja. MythTV elÅ‘tét (MythTv 30 verzióig). ÉlÅ‘ adások, felvételek és rádióadások támogatása EPG-vel és idÅ‘zítéssel. Antarmuka MythTV (hingga MythTV 30). Mendukung streaming TV Langsung & Rekaman, mendengarkan channel Radio, EPG dan Penghitung waktu. MythTV framendi (upp að MythTV 30). Styður streymingu frá beinum útsendingum og upptökum, hlustun á útvarp, rafræna dagskrárvísa og tíma upptökur. Frontend MythTV (compatibile fino a MythTV 30). Supporta lo streaming TV in diretta, le registrazioni, l'ascolto dei canali radio, EPG e programmazioni. MythTV (ãƒãƒ¼ã‚¸ãƒ§ãƒ³ 30 ã¾ã§) ã®ãƒ•ロントエンドã§ã™ã€‚ライブ TV ストリーミングã€éŒ²ç”»ã€ãƒ©ã‚¸ã‚ªæ”¾é€ã®è¦–è´ã€EPGã€ã‚¿ã‚¤ãƒžãƒ¼ã‚’サãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã™ã€‚ MythTV 프론트엔드 (up to MythTV 30). ë¼ì´ë¸Œ TV 스트리ë°, 녹화, ë¼ë””오 ì±„ë„ ì²­ì·¨, EPG, 예약 ì§€ì›. MythTV sÄ…saja (kelias iki MythTV 30). Palaiko duomenų srautams pritaikyta(-as) Live TV & Recordings MythTV galasistÄ“ma (lÄ«dz MythTV 30). Atbalsta tieÅ¡raides TV un ierakstu straumēšanu, radio kanÄlu klausīšanos, EPG un taimerus. MythTV Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÑ˜Ñ (Ñе до MythTV 30). Подржува Ñтриминг на Live TV & Снимки, Ñлушање на радио канали, EPG и тајмери. Bahagian hadapan MythTV (sehingga MythTV 30). Menyokong penstirman TV Langsung & Rakaman, mendengar saluran Radio, EPG dan Pemasa. MythTV-klienten (opp til MythTV 30). Støtter strømming av direkte-TV og opptak, avspilling av radiokanaler, EPG og nedtelling. MythTV frontend (tot MythTV 30). Ondersteunt streaming van Live-TV & opnames, luisteren naar radiokanalen, EPG en timers. Klient telewizji dla MythTV (wersja 30 i wczeÅ›niejsze) obsÅ‚uguje transmisjÄ™ kanałów radiowych i telewizyjnych, nagrywanie i harmonogram nagraÅ„ oraz funkcje przewodnika telewizyjnego. MythTV frontend (up para MythTV 30). Suporta streaming de TV ao Vivo & Gravações, Escutar canais de rádios, EPG e Agendamentos. Interface MythTV (até MythTV 30). Permite televisão em direto, gravações, estações de rádio, EPG e temporizadores. Frontend MythTV (până la MythTV 30). Suportă difuzare în flux a televiziunii în direct È™i a înregistrăriilor, ascultarea posturilor de radio, EPG È™i Cronometre. ФронтÑнд MythTV (вплоть до MythTV 30). Поддерживает поточное ТВ и запиÑи, проÑлушивание радио-каналов, ЕПГ и таймеры. MythTV rozhranie (až do verzie MythTV 30). Podporuje streamovanie živého TV vysielania a nahrávok, poÄúvanie rozhlasových kanálov, EPG a ÄasovaÄe. Vmesnik za MythTV (do vkljuÄno MythTV 30). Podpira predvajanje televizije v živo & posnetkov, posluÅ¡anje radia, EPG in Äasovnike. MythTV Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÑ˜Ñ (до MythTV 30). Подржава Ñтримовање ТВ Уживо & Снимака, Ñлушање Радио канала, EPG и Тајмере. MythTV interfejs (do MythTV 30). Podržava strimovanje TV Uživo & Snimaka, sluÅ¡anje Radio kanala, EPG i Tajmere. MythTV-frontend (upp till MythTV 30). Stödjer strömning av direktsänd TV & inspelningar, radiolyssning, EPG och timers. Klijynt telewizyjny dlÅ MythTV (wersyjÅ 30 i wczaÅ›niyjsze) ôbsuguje szpricowanie kanaÅ‚Åw radyjowych i telewizyjnych, nagrowanie i harmÅnogram nagraÅ„, a tyż funkcyje ôkludzÅcza telewizyjnygo. MythTV ön ucu (MythTV 30'ye kadar). Canlı TV akışı ve kayıt yapabilme, radyo kanalları dinleme, EPG ve zamanlayıcıları destekler. MythTV å‰ç«¯ ( MythTV 30 åŠä¹‹åŽç‰ˆæœ¬) 。支æŒç›´æ’­ç”µè§†å’Œå½•åƒèŠ‚ç›®çš„æµåª’体转å‘,收å¬å¹¿æ’­é¢‘é“,电å­èŠ‚ç›®è¡¨åŠå®šæ—¶å™¨åŠŸèƒ½ã€‚ MythTV å‰ç«¯ä»‹é¢ (最高至MythTV 30)。支æ´é›»è¦–直播串æµåŠéŒ„影,收è½å»£æ’­ï¼Œé›»å­ç¯€ç›®è¡¨åŠå®šæ™‚器。 Hierdie is onstabiele sagteware! Die outeurs is op geen manier verantwoordelik vir gefaalde opnames, inkorrekte tydhouers, vermorsde ure, of enige ander ongewensde effekte. This is unstable software! The authors are in no way responsible for failed recordings, incorrect timers, wasted hours, or any other undesirable effects. Тази програма е неÑтабилна! Ðвторите не ноÑÑÑ‚ отговорноÑÑ‚ за неуÑпешно запиÑване, некоректни броÑчи, пропилÑното време и други нежелани ефекти. Aquest programari és inestable! En cap cas els autors són els responsables dels enregistraments fallits, temporitzadors incorrectes, hores malgastades o qualsevol altre efecte indesitjable. Tento software není stabilní! AutoÅ™i nejsou žádným způsobem zodpovÄ›dní za neúspěšná nahrávání, chybné ÄasovaÄe, ztracený Äas nebo jakékoliv jiné nežádoucí výsledky. Mae'r feddalwedd hon yn fregus! Nid yw'r awduron yn gyfrifol mewn unrhyw ffordd am fethu recordio, amseru gwallus, oriau wedi eu gwastraffu nac effeithiau annymunol eraill. Denne software er ustabil. Udviklerne er pÃ¥ ingen mÃ¥de ansvarlige for mislykkede optagelser, fejlagtige tidsindstillinger, spildte timer eller andre uhensigtsmæssigheder. Dies ist instabile Software! Die Autoren sind in keiner Weise verantwortlich für fehlgeschlagene Aufnahmen, falsche Timer, verschwendete Zeit oder andere ungewünschte Effekte. Ασταθές Ï€ÏόγÏαμμα! Οι δημιουÏγοί δεν είναι σε καμία πεÏίπτωση υπεÏθυνοι για αποτυχημένες εγγÏαφές, λανθασμένους χÏονοδιακόπτες, χαμένες ÏŽÏες, ή κάθε είδους ανεπιθÏμητα αποτελέσματα. This is unstable software! The authors are in no way responsible for failed recordings, incorrect timers, wasted hours, or any other undesirable effects. This is unstable software! The authors are in no way responsible for failed recordings, incorrect timers, wasted hours, or any other undesirable effects. This is unstable software! The authors are in no way responsible for failed recordings, incorrect timers, wasted hours, or any other undesirable effects. This is unstable software! The authors are in no way responsible for failed recordings, incorrect timers, wasted hours, or any other undesirable effects. ¡Este software es inestable! Los autores no se responsabilizan por grabaciones fallidas, temporizadores incorrectos, horas perdidas, o cualquier otro efecto no deseado.. ¡Este software es inestable! Los autores no son en ningún caso responsables por grabaciones fallidas, temporizadores incorrectos, horas desperdiciadas o cualquier otro efecto indeseable. ¡Este es un software inestable! Los autores no son responsables en absoluto de grabaciones fallidas, temporizadores incorrectos, desperdicio de horas, o cualquier otro efecto indeseable. See on ebastabiilne tarkvara! Autorid ei ole kuidagi moodi vastutavad nurjunud salvestiste, ebaõige aegrelee, raisatud tundide ega muude soovimatute asjade eest. Tämä on epävakaa ohjelma! Sen tekijät eivät ole millään muotoa vastuussa epäonnistuneista tallennuksista, virheellisistä ajastuksista, haaskatusta ajasta, verenpaineen noususta tai mistään muusta epäsuotuisasta vaikutuksesta. Ce logiciel est instable! Les auteurs ne sont aucunement responsables des enregistrements défaillants, des minuteries erronées, des heures perdues ou tout autre effet indésirable. Logiciel en cours d'élaboration ! Les auteurs ne sont en aucun cas responsables de l'échec des enregistrements, programmations défectueuses, temps perdu ou autres effets indésirables. Este é software non estable, os autores non se fan responsábeis dos erros na gravacións, temporizadores incorrectos, e outros efectos non desexados. זוהי ××™× × ×” הרחבה יציבה! ×”×ž×¤×ª×—×™× ××™× × ×חר××™× ×¢×œ כשלון בניגון, ×–×ž× ×™× ×©×’×•×™×™× ×‘×ž×“×¨×™×š השידורי×, שעות מבוזבזות ×ו כל תופעה ×œ× ×¨×¦×•×™×” ×חרת. Ovo je nestabilan softver! Autori nisu ni na koji naÄin odgovorani za neuspjelo snimanje, netoÄna zakazana snimanja, izgubjene sate, ili bilo koje druge neželjene uÄinke. Ez nem stabil szoftver! A készítÅ‘k nem vállalnak felelÅ‘sséget, a hibás felvételért, rossz idÅ‘zítésért, elvesztegetett időért... Ini merupakan perangkat-lunak yang belum stabil. Penulis tidak bertanggung jawab untuk rekaman yang gagal, timer yang salah, waktu terbuang atau efek yang tidak diinginkan lainya. Þetta er óstöðugur hugbúnaður! Höfundarnir eru á engan hátt ábyrgir fyrir misheppnuðum upptökum, röngum upptökutímum, klukkustundum sem að fóru í súginn eða nokkrum öðrum óæskilegum áhrifum. Questo software è instabile! Gli autori non sono in alcun modo responsabili per registrazioni fallite, timers incorretti, ore perse, o qualsiasi altro effetto indesiderato. ã“れã¯ä¸å®‰å®šãªã‚½ãƒ•トウェアã§ã™ï¼æœ¬ãƒ—ログラムã®ä½œè€…ã¯ã€éŒ²ç”»ã®å¤±æ•—ã€æ­£ç¢ºã«ä½œå‹•ã—ãªã‹ã£ãŸã‚¿ã‚¤ãƒžãƒ¼ã€ç„¡é§„ã«ã—ãŸæ™‚é–“ã€ãã®ä»–ã‚らゆる好ã¾ã—ããªã„çµæžœã«ã¤ã„ã¦è²¬ä»»ã‚’è² ã‚ãªã„ã‚‚ã®ã¨ã—ã¾ã™ã€‚ 완성ë˜ì§€ ì•Šì€ ì†Œí”„íŠ¸ì›¨ì–´ìž…ë‹ˆë‹¤. 개발ìžëŠ” 녹화와 ì˜ˆì•½ì˜ ì‹¤íŒ¨, 시간 허비나 다른 ì˜ë„하지 ì•Šì€ ê²°ê³¼ì— ëŒ€í•œ ì±…ìž„ì„ ì§€ì§€ 않습니다. Tai yra nestabili programinÄ— įranga! Autorius jokiu bÅ«du neatsako už nepavykusius įraÅ¡us, neteisingus laikmaÄius, iššvaistytas valandas, ar nutikus kitiems nepageidaujamiems poveikiams ...[COLOR=red](Kodi.lt rekomenduoja/siÅ«lo testuojant šį priedÄ… persijungti į Anglų [orinali] kalbÄ…)[/COLOR] Å Ä« ir nestabila programmatÅ«ra! Autori nav nekÄdÄ vaidÄ atbildÄ«gi par nesanÄkuÅ¡iem ierakstiem, nepareiziem taimeriem, iztÄ“rÄ“tÄm stundÄm vai jebkÄdiem citiem nevÄ“lamiem efektiem. Ова е неÑтабилен Ñофтвер! Ðвторите на ниту еден начин не одговараат за неуÑпешни Ñнимки, неточни тајмери, потрошени чаÑови, или било кои други неÑакани ефекти. Ini merupakan perisian tidak stabil! Pengarang tidak bertanggungjawab atas kegagalan rakaman, pemasa tidak betul, masa yang dibazirkan, atau apa jua kesan yang tidak dikehendaki.. Dette er ustabil programvare! Forfatterne er pÃ¥ ingen mÃ¥te ansvarlige for feilaktig opptak, uriktige tidsur, bortkastet tid, eller alle andre uønskede følger. Dit is onstabiele software! De auteurs zijn op geen enkele wijze verantwoordelijk voor mislukte opnames, timers, verspilde tijd of enig ander ongewild bijeffect. To oprogramowanie jest niestabilne! Autorzy w żaden sposób nie odpowiadajÄ… za nieudane nagrania, błędy w harmonogramie nagraÅ„, stracone godziny czy też jakiekolwiek inne niepożądane efekty. Este é um software instável! Os autores não são responsáveis por falhas nas gravações, agendamentos incorretos, horas dispendidas, ou quaisquer outro efeito indesejado. Este software é instável! Os autores não podem ser responsabilizados por gravações falhadas, temporizadores incorretos, horas desperdiçadas ou qualquer outro tipo de efeitos indesejáveis... Această parte din program nu este stabilă! Autorii nu sunt responsabili în niciun caz pentru înregistrările eÈ™uate, cronometre incorecte, ore pierdute sau orice alt efect nedorit. Это теÑÑ‚Ð¾Ð²Ð°Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ð°! Ðвторы не неÑут никакой ответÑтвенноÑти за иÑпорченные запиÑи, неверные таймеры, потраченное Ð²Ñ€ÐµÐ¼Ñ Ð¸ за прочие нежелательные Ñффекты. Toto nie je stabilný software! Autori nie sú zodpovední za zlýhané nahrávky, nesprávne ÄasovaÄe, premrhané hodiny a iné nežiadúce efekty. To je nestabilna programska oprema! Avtorji niso odgovorni za neuspela snemanja, nepravilne Äasovnike, zapravljen Äas in katerikoli drug neželen uÄinek. Овај Ñофтвер је неÑтабилан! Ðутори ни на који начин ниÑу одговорни за неуÑпела Ñнимања, неиÑправне тајмере, изгубљене Ñате, или било које друге нежељене ефекте. Ovaj softver je nestabilan! Autori ni na koji naÄin nisu odgovorni za neuspela snimanja, neispravne tajmere, izgubljene sate, ili bilo koje druge neželjene efekte. Denna mjukvara är instabil! Utvecklarna är inte ansvariga för misslyckade inspelningar, felaktiga timers, bortkastade timmar eller nÃ¥gra andra olyckliga effekter. To software je niysztabilne! Autory w żÅdyn knif niy ôdpadajÅm za niypodarzÅne nagrania, felery w harmÅnogramie nagraÅ„, potracÅne godziny a tyż jake ino inksze niynazdane efekty. Bu kararsız bir yazılımdır! Yazılımcılar oynatma hatası, yanlış EPG tarihleri, hatalı saatler ya da diÄŸer etkilerden sorumlu deÄŸiller. Це неÑтабільна програма! Ðвтор не неÑуть жодної відповідальноÑті за зіпÑуті запиÑи, неправильні таймери, потрачений чаÑ, та інші небажані ефекти. Äây là phần má»m không ổn định! Các tác giả sẽ không chịu trách nhiệm nào vá»›i các bản ghi thất bại, bị đặt giá» sai, giá» lãng phí, hoặc các tác dụng không mong muốn khác.. 这是ä¸ç¨³å®šç‰ˆçš„软件ï¼ä½œè€…ä¸å¯¹å½•制失败ã€é”™è¯¯å®šæ—¶é€ æˆæ—¶é—´æµªè´¹æˆ–其它ä¸è‰¯å½±å“负责。 這是測試中的軟體ï¼åŽŸå‰µä½œè€…ç„¡æ³•é‡å°ä»¥ä¸‹æƒ…æ³è² è²¬ï¼šåŒ…æ‹¬éŒ„å½±å¤±æ•—ï¼Œä¸æ­£ç¢ºçš„定時器,多餘的時數,或任何ä¸å¯é æœŸçš„ä¸è‰¯å½±éŸ¿ã€‚ @PLATFORM@ pvr.mythtv-5.10.15-Leia/pvr.mythtv/changelog.txt000066400000000000000000000261661360567320200215440ustar00rootroot00000000000000v5.10.15 - Backport fixes Fix allow backend shutdown when GUI is idle (screensaver activated) v5.10.14 - Backport fixes v5.10.13 - Backport fixes v5.10.11 - Show label of recording info hook v5.10.10 - Sync upstream cppmyth (2.12.7) v5.10.9 - Sync upstream cppmyth (2.12.6) v5.10.8 - Update build system version - Change header include way v5.10.7 - Force allow shutdown when deactivating the gui v5.10.6 - Allow user to configure color display for damaged recordings - Add setting option be sent all EDL as SCENE rather than COMM_BREAK v5.10.5 - Sync upstream cppmyth (2.12.1) v5.10.4 - Try to fix the player hanging after the liveTV conflict - Get the best candidate in EPG for the new timer - Enable support for MythTV 30 v5.10.3 - Add the implicit marks for begin or end of EDL v5.10.2 - Add option to set default recording group as root for recordings - Sync upstream cppmyth (2.12.0) v5.10.0 - No longer handle file caching v5.9.2 - Fix initial state of the addon at startup v5.9.1 - Fix display for video flags - Sync upstream cppmyth (2.11.2) - Announce as frontend - Add hack to work around the PVR startup flow issue v5.9.0 - Builtin files cache is deprecated: Prefer file caching supplied by Kodi - Builtin files cache is disabled by default (see advanced settings) v5.8.19 - Fix played position caused by a non zero startTime for recording stream. v5.8.18 - Add new hook to show recording status - Add new hook to show broadcast status - Update translations for FR,ES,DA,IT,DE,NL - Supply fr_FR map for EIT categories v5.8.16 - Clean recorded directory name containing special characters v5.8.15 - Update default settings v5.8.14 - Fix time conversion for 32 bits platform v5.8.13 - Update Danish translation v5.8.12 - Handle damaged recordings - Add workaround to silent API error introduced in 5.8.8 v5.8.11 - Add a workaround to prevent the backend from being stressed by repeated calls from PVR v5.8.10 - Fix timeshift info for recording being recorded v5.8.9 - Sync upstream cppmyth (2.10.2) v5.8.8 - Return PVR_ERROR_FAILED on API calls while addon is not initialized v5.8.6 - Removing the dialog to notify connection failure because a deadlock v5.8.5 - Implement new requirements for timeshift support - Fix GUI deadlock opening dialog to delete last played recording v5.8.2 - Fix playback stop when seeking beyond the end of recorded stream v5.8.1 - Updated language files from Transifex v5.8.0 - Updated to PVR addon API v5.10.0 v5.7.3 - Updated to PVR addon API v5.9.0 v5.7.2 - Sync upstream cppmyth (2.10.1) v5.7.1 - Upgrade dependency zlib to version 1.2.11 v5.7.0 - Sync upstream cppmyth 2.10.0 - Default start/end time of recording rule for backend pre 0.28 v5.6.0 - Updated to PVR addon API v5.8.0 v5.5.0 - Enable radio flag for channel with suffix '-[RADIO]' v5.4.4 - Fix cppmyth build for uwp v5.4.3 - Sync upstream cppmyth (2.9.6) v5.4.0 - Updated to PVR addon API v5.7.0 v5.3.0 - Updated to PVR addon API v5.6.0 v5.2.0 - Updated to PVR addon API v5.5.0 v5.1.3 - Discard upcoming with invalid channel v5.1.2 - Sync upstream cppmyth (2.9.5) - Fix http chunked data transfer v5.1.0 - Updated to PVR addon API v5.3.0 v5.0.12 - Remove of never used addon interface function v5.0.11 - Update Debian package control - PVR addon callback way changes - removed old no more needed version functions - set dependency versions automatic during build - removed never used kodi to addon functions - build system fixes v5.0.10 - get rid of _USE_32BIT_TIME_T v5.0.9 - Add new setting to enable/disable usage of backend bookmarks - Fix install path for debian build - No longer handle demuxing - Launch client init in background - New setting to show/hide liveTV recordings - Fix: Do not open dialog while playing - Fix french translations - Sync cppmyth upstream (2.9.4) - Silent failed bookmark - Sync demuxer upstream - Cleanup addon api - Fix error no error reading bookmark - Fix incorrect hours to display when g_bUseAirdate was set - Fill flag 'has bookmark' on recordings - An option to prompt to delete a recording after finishing it - Adding new section 'Preferences' in settings - Upgrade the demuxer to support hevc stream - Add a dialog to retry connect the backend on startup - Replaced custom Dialog class with standard Kodi API call v5.0.0 - Initial Kodi v18 version v4.11.0 - Handle recording last played position from the backend - Bookmark at current position in a recording when you press record on LiveTV v4.10.1 - Minor bug fixes v4.10.0 - Sync cppmyth upstream (2.8.1) with support of content-encoding gzip/deflate for WS API v4.9.2 - Updated to PVR addon API v5.2.1 v4.9.0 - Extra timer info v4.8.0 - New setting to send (original) Airdate to Kodi instead of the recording's Start Date/Time. v4.7.3 - Recordings: Separate Thumbnail from Icon v4.7.2 - Updated language files from Transifex v4.7.0 - Sync cppmyth upstream (2.7.0) - Support protocol 29-pre:91 v4.6.1 - Updated language files from Transifex v4.6.0 - Sync cppmyth upstream (2.6.0) - Support protocol 29-pre:90 - Support protocol 29-pre:89 - Allow to keep live show from EPG screen v4.5.3 - Updated language files from Transifex v4.5.2 - Updated language files from Transifex v4.5.1 - Keep original air date of recording on update event from protocol - Sync cppmyth upstream (2.5.2) v4.5.0 - Cmake: rename find_package kodi to Kodi v4.4.1 - Fix includes v4.4.0 - Updated to PVR addon API v5.2.0 v4.3.1 - Sync cppmyth upstream (2.5.1) v4.3.0 - Updated to PVR addon API v5.1.0 v4.2.1 - Fill PVR channel UID of recordings - Allowing to disable auto-expire for any recording - Minor improvements v4.2.0 - Updated to PVR addon API v5.0.0 v4.1.0 - Updated to PVR API v4.2.0 - Updated to GUI API v5.11.0 v4.0.1 - Updated language files from Transifex v4.0.0 - Initial Kodi Krypton version. v3.4.6 - fix timer update caused by invalid epg ID v3.4.5 - Updated language files from Transifex v3.4.4 - Updated language files from Transifex v3.4.3 - Support protocol 0.28-pre:88 v3.4.2 - Updated language files from Transifex v3.4.1 - Updated to GUI API v5.10.0 v3.4.0 - Show stream "channel unavailable" when channel tuning failed v3.3.9 - Enable buffering for socket - Sync cppmyth upstream (2.4.0) v3.3.8 - Updated to kodi.guilib API v5.8.0 - Sync cppmyth upstream (2.4.0) - Update default EIT categories - Sync demuxer upstream - Add EPG Entry associated with recent Recording - New french translations v3.3.7 - Updated to GUI API v5.10.0 v3.3.6 - Updated to PVR API v4.1.0 v3.3.5 - Fix issue when deleting timer rule since API v4.0.0 v3.3.4 - Updated to PVR API v4.0.0 v3.3.3 - Sync cppmyth upstream (2.3.1) v3.3.2 - Workaround for Kodi bug 16141 v3.3.1 - Cleanup localized strings v3.3.0 - Sync cppmyth upstream (2.3.0) - Support protocol 0.28-pre:87 - Security fix for JSON parser - New setting limit_tune_attempts - Add EPG Entry associated with recent Recording - Improvements with API 3.0.0 - Notify user on addon failure v3.2.2 - Minimal Support PVR API 3.0.0 v3.2.1 - Stop to iterate recordings map until next change - ScheduleManager becomes thread safe - Sync cppmyth upstream (2.1.0) - Automatically fill in platform and library name v3.1.1 - Updated to PVR API v2.1.0 v3.1.0 - Support for PVR Addon API 2.0.0 v3.0.3 - Don't apply category overtime nil (0) - AVINFO: exit on parse error - Fix race condition on opening recorded - Sync cppmyth upsgtream (1.5.1.3+fixes) - Miscellaneous backend fixes v3.0.1 - Updated to API 2.0.0 v3.0.0 - Updated to API 1.9.7 v2.3.1 - Updated language files from Transifex v2.3.0 - Fix crash on thread stop - Set of fixes for timers - Sync cppmyth upstream (1.5.1.3) v2.2.1 - Support protocol 0.28-pre:86 - Sync cppmyth upstream (1.5.0) - Minor changes v2.1.1 - updated to use new libplatform-dev v2.1.0 - reading ahead: wait for 10 sec - demux: set read timeout to 10 sec - API Guide service 2.2 (0.28) - Enable commercial break and cut list by duration v2.0.10 - Updated to API 1.9.6 v2.0.9 - Process subscription queue in separated thread v2.0.8 - Updated to API 1.9.5 - fix crash parsing invalid frame AAC/LATM v2.0.7 - Merge channels by chanNum/callSign across sources - Fix preferred cards for live TV v2.0.6 - Enable feature "undelete recordings" v2.0.5 - Support service API 0.28-pre:5.0 - Sync demuxer upstream v2.0.3 - Sync cppmyth upstream (1.1.9) - Support protocol 0.28-pre:85 - Support protocol 0.28-pre:84 - Handles MasterBackendOverride (kaptain-iglu) - Fix compile error wir c++11 - [pvr] Increase API version to 1.9.4 - [gui] Increase API version to 5.8.0 v1.11.4 - Updated language files from Transifex - Minor changes to conform with C++11 v1.11.3 - Updated language files from Transifex v1.11.2 - New method to handle read ahead (live playback) v1.10.2 - Added getBackendHostname function v1.10.1 - Options to disable channel icons and recordings or fanart images v1.10.0 - jansson 2.7: fix compilation on ios8/arm64 - Cleaned cache by max age - Improves loading of channels and recordings - Adding WS API Security Pin parameter - Adding episode info (subtitle) to EPG title v1.9.29 - fixed resource leak on file cache failure v1.9.28 - Updated language files from Transifex v1.9.27 - change library name to Kodi v1.9.26 - fixed deadlock when activating the addon on some darwin (osx, ios) runtimes v1.9.25 - Handle GUI events to activate/deactivate power saving mode - Don't send WOL when power saving mode is activated - Don't block shutdown when power saving mode is activated - Handle hang: Always retry protocol connection after hang - Handle hang: Reconnect event handler after hanging of control connection v1.9.24 - Block backend shutdown by default: New setting - Fix refreshing recordings and schedules on wake up - Updated language files from Transifex v1.9.23 - Handles version of services - Allow HTTP redirection to get slave previews - New format for program UID string - demuxer: optimizing, fix PES header - Fix category override - Transfer sub channel number v1.9.22 - Fix identifier for DVB-SUBTITLE - Add setting to enable or disable EDL functionnality - Add setting to configure grouping for recordings - Load EIT categories from customized user file - Merge channels with same source ID - Fix codec infos after stream parsing (AAC LATM) - Fix crash when trying to show recording from unattainable slave backend v1.9.21 - Updated to API v1.9.2 v1.9.20 - Detect audio codec AAC LATM or AAC ADTS by parsing - Enable EDL for MPEG-TS stream - Fix timeout: 60 sec to hang up - Fix refreshing artwork after program update event - Send wol packet magic to wake up backend on startup or not connected v1.9.19 - Fix seek stream defect introduced in 1.9.16 - Support protocol 0.28-pre:83 - Fix XBMC crash on exit announcing disconnection v1.9.18 - Use unified interface of CPPMyth (80c84fb) - Get setting of slave backend to open its recording - Include API updates for protocol 82 (0.28-pre-1917-g62be166) v1.9.17 - Fix buffer request limit v1.9.16 - Fix timeout on buffer read in rare circumstances - Not open dummy file for transfer - Recording priority is signed value v1.9.15 - Manage late spawn response - Upgrade to jansson 2.6 (security fix) - Fix parsing of 'airdate' in proto v1.9.14 - Fork of pvr.mythtv.cmyth - Use C++ library CPPMyth for MythTV backend 0.27 to 0.28-pre pvr.mythtv-5.10.15-Leia/pvr.mythtv/icon.png000066400000000000000000001525751360567320200205160ustar00rootroot00000000000000‰PNG  IHDR\r¨f pHYs  šœ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-Û cHRMz%€ƒùÿ€éu0ê`:˜o’_ÅFʨIDATxÚìýw¼-Iu ?Uv:çÜsÃä™!N€a€aÈa$’„¬d+Ù²õÙ–,ÉA~_[ú¬ðÊI–„ôSå`a ‰8„aÈ30LÎ9ÝpÒÎÝUßU«zuuuïÞûœ‹ßßg6¿Ã½sîÞ½;ÔZµÖ³žõ,qåϽOþ„îÇÿoÿߤ”Á÷Ô}ŽÞOÒûB¯6¿¯{Ï*Ç ½g?çÖæ»Ú^ i­[ýžþ›ÿžÿŽ~êþ­îØußßöœ•R¥ïðÏ¥é¼êŽË:w~oý÷Öý4›~¡soú݇ºk ýý®Í¹-:o~,­5bÿ&ÔËw«ãé0þýæ2ŽAQzðuÇns/êžSh‘×ÎÅ?¯E÷£Íçè;Û:©ƒx-:f›gRwÜUß*—iޝÝg«N£üoM޳#ã¿—8 ¯ÐMÞ¯£iÚ™Ú~¾­¡}µèWË8ÚÞ;î´Û¾—¦Íu,cXmví¦Sã0›"‚ý¯ýUŸuÓÅi[r£¬ iyßñ-ÚI–‰VuJ«w?;Ü"£¬ûݲ¡›]­í5„R›eï}›´cQ˜¿(óÓM!¤ç ÚÜÓÿ7¾–M/—Y‡rÙ±Ì.zÐ7y?Ç=°si¸þE9c›s:èÚdX_í}Ñî¿ßM!5ˆÏëà¯ùôþéXãr™-›·V½ïÁÝU.¶ÍýÜ/èµhwßo*sÐß:wª6»ÿADÀÙ3þ&PtÕgRk#-ÓéÀÜV}ÉÓr¬ºàÚî˜M@WSžµŸ‡{P.¾Mø¿ HµÌ}«;ÎA,ÊUŒj™ë®K|,5XF“3jãÈÚØ„> ÇùÕÂŒd£]äAÛ/½/§r¹ÏéÀ…ñmBàý†ÿueªƒÄ[–)[îQ_dø!P%î7ò:»v›í´E‹<à~Ð麘U»J%`¿Ì*;s“ñ.û»P~•E2°UwÿUÖT›Ý?ô¿î}ºÀeÓÌÿF_r‹Â&ô~YT¹ ß´Yyg[¢þ½,`¥u»P»‰L²h]”:4‘J–M bW[Dœ©ûÞºðÝ7zBûCÆÏ]'üÕF›°´6Îõ´bËÖ]O7pà‘ÅŸGy‘¯ž­‚,y$'aQj³*èØ–ê[ç¹èœüg°Já 1¯ƒÆšZaºåâiKÙtàÛ^øÂÙ" 8%J¥”Ûyí¾ûÝu-âeÂ2!é2)M›{€%CþÀ·ˆcÒýoª´½¹y¶ç¬þ%*°ÐBÊÖ L›üZ{–û¼9d¸ K)Ö‘5…TËÒoQlCK)dÊ…0–ý”8›RŒÖ†¸ä3X6’©££.󽢦¼ç;áÓ•ïŸNnF]ú]çdÊ¿_àŒC‹»é¿ÛOSiiÑçš8'²*pº/«,ˆ«h›”-tìƒ9ë ¿éš¸#_–IŽ€¾MS‘ÞgšÕ>2[ÝèOGdÑ÷Æ~è,ò2Ž ºàMÐÆ 49)åʆî/¼ýÔ`ÛæË!JkhGô;-}·;‹®x~Ü&Ũ¼g•x™ôCkЂX˜"p°î#GøK†:p.-Ó­E O‹AìæËYöž¶½ÇÁ÷{'úL\q_- g™î³ò¿•]LŽw›0étGm"$ZŒu¿¢È-Z¿'jòZó;í* µF @ÛãòãDQTrm—Øð·|¾Ækü4Ïo)_ø]¤ ‘Q[§Þ¦ªÕ¶RµÈ¨—ÃØPl5 wÝgã¶èë~ étµï÷;Wí$#⬲`é†+¥E’$äyî>'jvZ2Zg -®PŸ/ìù|)%¢(rhÕ¨MD±,ø¸LîïGEm[a¹q¬ÑVråAžC ýÇ2»k]'`c €æH @²]mUªr[^vÈø³,Cžçæ&ƱÛÝÉ!H)Ç1Ò45Žb>‡ªyØRJg¨RJ(¥+UZ´þ9Äq ­uÉ©„ˆ>yž#Ë2!Ç1â8n•Bµ¹ºÅîµpQ"ž 5¥C‹„0B;]*»ŠJð=6ì^ê3-£‚…Ç[ÁYÄ~èzuáSÞ^‡n·r P|ú÷ýF)Mçè”3LkPZkÄqŒ$IÍç˜ÙßÑñâ8F§ÓÌf³ (æZȉdYV OýgÇ1¢(rÃ|>/<¯@p q:b>Ÿ;ÇÔ'Ð^8Yz *«DM̾:rQm$°B7æ>½ãR@[Çp\~Nôg¼½cX„%œî´ ƒðwNJ“aÎçs·ëGQ„n· Ψèz¤”H’ÄØt:E–eµù>½€3~B­}‡îÛ|>·ß H)œSàÆÏwNîP¸#HÓÔ}÷~û29o[6h“¨Xé”–M;íÖmϹmäÀÎ>^•2`½‘ø 9aQ‹èחΪÁý~€À6Χ‰^J;:…šôßZk$IâŒj:"ËsÀþžvöÑh„ù|ÎŽ-ÜîEf³™s¡s ã—R"Ïs÷ÝMщÏò¼œûû÷wE2,¥Æ“ æó9:ŽK)Ú4‚¹ãµ,a5íúþÚwbÌ…vv¥tà:)&GJV-6ELmùƒÐW\䌖í/Y"ÐÖ ,oÌ!'²o?íÉdä´“Ó§0vw!f³™û½I’ ×ëvwwñÓ¹F‘,9úl(Ú!`Ž:¿Ój“²Ú®kŽÂºŽ:±ÍЫDN² fžçHÓN'&®²˜Û×øáÖÕ"zo%Ôo!÷Š,»«/®Ÿ.`»í3i¬ίjÈ©¸¨¦ÏoN–eÎhi×##×Z£Ûí¢ÛíBkÑhTBøÉ@¤”ØÛÛÃt: –©â8v<åæ~I‹Ò ^×&C®‹„ÐJ¹ÏòÔ£„£c“³™L&%'@ÇUJa<#Ë2t»]DQT[&Û¯Ô9 :—¦œuÑ߯E‰m‘#k*Í-S"lJa–¹‡mÀÖ…U€ý¨Í†BýÖ¿cðA”éšêò|7ît:èv»nÑÏf3DQ„^¯ç~ÏC{2jrÃá£Ñ¨ò0(œ'ã¡ïãux?·¥ÒÜ|>wù»ÝôyJU(º ˆïþMy3Ç!xÙG!³Ù Y–¡×ë!I’Vé@]®ÛDc UAB_$}íG>*˜,_So»û·5ô`®³¨ÂÒš›`RO­êyu¿‹Ýú“BÒп…*­¤ŸY&*ñwBÊé§Ó)f³¤”è÷ûHÓóùÜíxq;ãÏó{{{Ȳ¬4Ç€çô£Ñ¨²ÑK€åþüÜ8Ò_Glá×éþM)(/ 4¦.ô§cÐNÏË•œˆDN„œÕp8t޲)¬3þ6]w!°o‘ñ7í¼u¸G(J\¦LÙf&AK!XIáŒÆÕÀÂp°íyÅu»y›Þ2;wÈa„ʲ9¿ŸÛS­›kš¦Îø'“‰û=ßùµÖ%ãç;0á{{{Ž\à •åè÷dX~ [±ž¿, ÷,¬³$ ’w†Ž@¸¿œÎ“î}79ß ŒF#äyŽÁ`Ð èZ5¨ þvc¨(²L{ïÂ]¼­Ì×l§Kó±\=ºˆ÷—›/. ÖÑvWéÈ«»±´ˆ ¼‡˜N§.¯ H’ãñ£ÑÈÕð;Ò4 ‡CÌçsDQT ë…˜L&EÞÏ¢úwæˆ Ä¯Ÿ×íÉù5å߀v7½…}¾îÞ„´P'"ËçÐ÷pç7N¡”rN`€iÑN['æQ*j ÕrêM[d¼Ž8jnj2Z¶W¢n×ÿj R©;ž\õƒå’‹^ÙxW¹ʇµÖ˜L&ÐZ£ßï¶··1Àš&˜LÆØÛÛ«°ô›L&¥*” SÔÀ-JÎT“2*E"•]Ž]‹JI‹rV¸Ӡœ®ÍFœ¤s#/’Sà‘Ët:ÅÎÎÎÊ%¬°×¤äSºfïúýHà«Q_/3€·êy­â¼Ú€ˆm^²éË–Q­i+x¹LýÔ÷ÌD”I’Óé£Ñišbmm yžãÔ©SÔët:è÷ûvçŸ`wwÏ->ÚÙ PÇ¥—Œ‰“€üПR8Ž­q—¯‡hžçÈl”R'⇼¼\™eYÄsa\œ¸ï˲ÌU5› ò9ú~N æåHÂ=èþÏf3ììì´Zh‹vIßøëÄ<¸Á‡˜‘ˤM$_¶¾iM–y0³D;¶?Rl™ãʶôÍE¥“E¶Aë-ê$I$ vww1™LÐï÷Ñï÷1±µµåwfyž—§!³Ðœƒ3‰³î×n¹S™Ï玛àc „ôS9‘;Î} 4€“›8ë‘—MÓ4Å¡C‡^ ¥Äh4Âp8\©™ˆG_u9wÓzÑKöø!;ÿΦèc?aüA)H7‰¢.{ÜENK„A/£¡Öfçç5î(а¶¶†ñxŒ'NÖÖÖÐëõ0N±µµå@8Êˉ°3]èL;[E.¼¥P™n§Ó)a dè¼O¤ :Ž¢òÅ•[¦¿£‘Áºj#QÊÁûûµÖ.ŸÍf0‰®œ&+íîTã'lƒG°.AÞó0 ÜùÆqŒÑhT"Aµ©ü´ ûÛŒº^6¶q !`´MKq› rUß¶ý«ç}N." ¬B¨X4¢‰ÅÅkðT¦ÛÞÞÆÖÖ’$A¿ßG¯×Ã|>Çöö¶ÛÙ(îv»HÓÓéãñØíô´+’AY‡Bc­5:Žs$ôgƺü¨Ò@?Ôêëw òØñú½R “ÉÄ9Πʅý˜#^ÿ92nðÇt:uˆvY)¥«„î)J( Ç@;7+3=ýŽî™´ÿ±ï&¢9^íõzȲ,ŒÔ,ÄÍw@¸Q胙ù*“®šž{X@›Òø~‡¿Êeò¯e щp]7ÊQ»Ý.&“‰ûûÉ“'±»»‹n·ëq¢(r8dü´H‰Ç>™LÜ®O 79ÊýÍR#Œß>K /¯ù@íÔ\Œ¢þà Æã1¦Ó©sq‡Œ—æxŸÝóÉdâÎçèRŠ`c]9žÐç“Ä8ŸÜ‚žIKo&çÆ+Ü©S›N§RâÈ‘#®BÙÿ"BÏ¢¿mîÛFT¤í÷µ³ÛD+w«”[WÚ2©Úë½51åßY–a0@J‰­­-H)1 °··‡ÝÝ]æQîŸe¶··K]'MðÇw. •)-à€v6Úi¸(_ð¼^N;rÝk::Yô0}ÃàÆL o*"ÔÞïð%ÈÀ0^åp€ )¡cÆÖ±RJ@‘ý‰Å#8ŽqèÐ!—*4©ú´É§ñþÛ‹®áÙ×~mòãÓVãßÇ÷,[Š\”vÈUgåµñÌ¡÷pÕ"ðlmm9´2™`ggÇ-!ó„êÓNL¼€Ô¾Œ“H=´û=˜ld$\+—ôx À5”wqqPb%ú幺’}!òôݦܗ—øÿ³ÙÌu¾p˜{/úÈ9qžD–eަ©>¡ûÈIR¼:CQB¯×Ã`0pϤÍΪ÷ûk)Ä·XnÑ‹  ˆöž×J-Åû0þ¶3!—´rÄ"¹J=v0òSZøƒÁ ´£sgÀÁ8Áškæ@Br\O‡ö);–ß%Ge1¥ççoþ½ZGív¼­—œ o¼á?UпãÊJ¸ˆÏÖ£R&ï*,¾¨((HΑªô Ì$nA§Óq)uHîîî–Z£ù}¢ 9—Úoþ Cïñ¦­_ú×<§–zmÒàFg±ÂX±6ÑO› Ã2¥Ké­:íwQª+w:Ìçs×zKa¿ß‡”§N*åŸ<|FÎydYŽn·ë¤¹ˆ±G /ë ´ã¥:BÌùÎï÷ΗzêÂL22Ϋ÷1þ9^¾4ŸÉœ ’†AjSúor\œX£µ†bÂ"•P¤CNŠ"ÂN¨‚ð‹C‡a<»ÝŸ§Õ•;ŽÒÈø”¤¬”Rè÷ûn×/‹jh·ƒSîÏÑqnÐ<äôõø Ƕ{%ËâMNŠç˜Tå ãQˆí?HêWàçJŒ¢”ÝÝ]lllØîÅ¢ôØívKªÃ~ŠÃÁ× û”¦i©š±ÑTÈK×Üëõ0]+55]aÉ¿ÆÐâåXË¢\¿-ñfÉH{mÅMÄ·6‘îé(Ë-SíX…ÁXwoäAx‘Ћ ¢ßï;þx·Ûµ,²Ü-")¥îhñS~Já<…§ô'‡K¢Óé¡HÅçðû‹ÓäÂvW³%5^&«xQ›“S:A¥5^›_Ê£®…£ûT2$ 0)¡HˆÈS\œÏ/ð¯‘s†Ã!Ž?ŽÇ;;;nwÏ< 3q1øup‡O綈äÓ¶¶M~ÛTê«|¶ÁXöShK†[´³×±*’Q—åÔh ©ßï;¤¹×ë¹°“ ?ŽcL§Ó’[Í/ÙÑNM;ý7Ïá9øæƒl|árC« ½(ôŽYAˆ#àvxýœW>ˆ'2„^¯ç𾋇œ…Ûô½Ee×v8r_›Æ‰öz=ôz½Ò= ”R…†‹œrGCå"úw]o› §I-ªi÷o÷Û‹.K‘ßOξ*!¯í=«ð–<šÂÊ3 !Îó½^yž»þ}’é"C£š5}ÎoÅ¥²Ÿ`赟ûñü߈ÉlžâðÎ?æl63tXÆÐóÅFù§óݘþ›¢‚à@¨¯éGÑýÛîî®ue•án·ëÄ<ýÈ„W Ìù ñèÑ£8óÌ3qöÙg»Î?w^öØœ^]”Âíút¾¡.EŸÏßÄëo5ßo Ãoš«è—ã—¡þ¶:]溪ÎeùÈ¡ ðlºÙÖõñr´Èz½f³&“‰Û™àB¼ël2™8…÷(&ô:aÒXu­“œ¸Ãw4Ϊ󩾡›Já±ß-ÈuþâŠ<¼òÁÑwâׇî'õàûí²L¤ÛÛÛÃh4¬H‚Q¯„!Å c¸sìîîâĉ8uêvvvܹ9S–j%–'@ mš¦®,KçJ©ZHF{‘!,³ƒ†æðÔU–¥/›O·‰Ú³W ïWá/ÈUD:B¿§µßï;Iš¦.´÷‘cÒÙ£æ*Kñ…Î3Ïst¼Ý¿.äãŒ=NÈáà—þq⽈ïÎ9 <×õUi÷å΋œE@T‚ ÝUR7ò – ƒÐk4a{{»нí÷û ŽFÍ#_鈎CÀa,¤ „ÀÌV`[¡jÇRD,ª ¡i>º¶%|™°¶ê€uc迬ZÕ¢Ô¤©"¶, ·l±/YFÑEË´ùÖGºG£‘[HÄuçu”OS¸Ne?™¸ž7º8BùŒ=_—=ßÍ‹N@,ëÑnO%}¾4Ü»d0´P)÷çä ½½=óÝ5`T§ÓqÓ‡¸òˆ€WY¶¶¶0Køѧ‰­Gy¾?mˆˆR¼,ÊÓ!úý~‰ D=ãñ¸‚«C!£ôÛy©JÓ"×…ó~´×4#@/øíGgYì²8CÝ}Ø/žPIÚæú!Ãç2R$ÁóOÛ¤]·@Êç%öGöyÞÊ ;%%]Öû†Qw-|çχÔuøwñž| ÅùgBäá‰Îo6›aoo¯Q žÀ9¥ëùXo2,Š,vvv°½½]D [ |€0BóÝ,@æhˆH8Ìh4Âl6Ã`0pÇ1Æã±{nô]äàIZ}QsÏ¢z¨wßÇršŒ|¿ßeˆ9«Žù^EUhU1žº÷ÈeÐý:–ñõiÒnîÏ®ãÊ=yž9ý~.XÁ>Ÿy(Ë»öjç x9!íZÜiùT]ž¢ÐNJŽƒs8žàcÊ”öp’5(ÑùM&“Ë.´Ó8'ÀÔ‡}í~¾cgY†W)ðï oGæš`Ýz8"Ïsǵ ÊM·ÛÅÚÚZé>r`Ôd2ÁÞÞ^ý.†ÕT…~~`îÏò Þ2¹¨UŸL Ÿ¡rß–4ö:@±1X†êÛît:æ¬4"õ‘sÞ}Î “OÈ í¼Üç—‘|Cà/¯U“H#u¨VN¥H2`ˆÅÈëúÞÝu;8?_Jƒ¸ÔØp8ttu±Ûí:.CίÉ/9’@êÉ“'Ýpî¸h*`æ!Óï÷].Ÿç9ÖÖÖœ“^[[sj@Ñpz/MWò‰QÎ0è¾!#jêã_TÊ amsé6`ß* Z>”¤Åy‰¨ |^ÍN#®›åbûùÞŠ>©ëúN ÁÏK-¥¬_ŸÒß}!NÿaòÝ{у£ð”« þàS|©Y†J”ÉpAétêš‘*a•%=QÍž/rÞ ¸··çÞ[W^¢™„\½˜Â÷:båìdØÔKÀES¹“¦{ÐëõœÐêp8ÄÚÚ677[qgg§¤^DÏ·ßï—†ä¶ÉëðáÃÁ²Ž¯¿(ç^D*ÚÁ§.[v^[Xõü–½Ö ‰­Í‡ñóéf9äØÎãÇõ§ÏRÚ0ŸÏ±Ò™/‚É'äð‡á·îú¹ahw&$ŸœÿNŸªK`á¼KÏä¹´ƒi§åÄ.»üÝŠ ÐŽZøqc0¸Ü›*Jiäù¼Dþ!ž;IŠÀ(ÔçJ|ésþïôž“'O–ˆLÜø©)Ë»>±¾¾îfâ-æ‘X(œåk§WB˜µå鯺ûWÈK”ëÚ6Ö-«ÙÑfªsìçÐuƒ@ýˆ Ïs×ÕGaµß\Cï#@ËoÂ! Nžá,¹Syq†Rþ*ú7†˜‡\qg::ä9—ïâd0” ¯­­Õ¦Fý~ßñæƒ;x snswâú‡æ$r²Pyæa)E¥ ´sQžð?êáØ„9†Ätz¢T{÷Q}îP+¡ó%ÞC¿ßw<üýƒiÊsݼ@?Ó^ohC¨iÛ1¸L¹s”?ü~¼îÚnÀUÐP EyØÇÁ*¿'ž;nØ~n_×9W·kð¶[.óåƒAüó“ÉÄÍ c$£ð‘˜È09¹‡>G‹>”×p6xÃyú moo»¾ú³Œãkkkd•R:tßVè;CóýŠ´ÌïËx UCh÷§êUR¶··+ù8b[vâTh÷çJ¨æ¾ Q¦®½{ ­ò]K¢õû%$…œ^[‡ãR€ºœ¿¤N4Z8dà‘Å8–¿Ú8b §ŸÖ´n†B|ÞRÝœ‹(e:Àüi?¾¯¯¯—gP4B·v8Zô„kîAØÀh4r§oLboll¸ÉEë &§IrÛÔgopÖdˆJKéJʤØ8k’dÞÒ4uÍE>ÿ ®œÜ&ç¯ÛD¡¢ÿoËêT~_CòZ&ToÛµ »²îÞ´}F-&®„뇉ôC†šY/„€ €dM×wF|·ãlJå¥óà㯈çω@Ä\äãºIõ†DH¹‚1Ï)Ô­ IÓ4ÅÆÆvvvJLÜQÙÝÝuc¹}a±RN"Üpö  ýÞ•ŒF#q’¬RJ$ü„RÀ$I\Õ€ž/÷Ô©S˜N§& hˆìBà oäMáþ²2Z‹vü&.}«]xE•lFX«h;<Åo\‡Î†j”< ¥EÅsÖP­œë÷ù†KqøÃ® ñB£Ç)ç C¼!‰wÂ¥i iÄ™'^ûúúzåzhRoZâm¹ôYJêÒ˜N§ƒõõu ‡C¤iZ¢ Ó9“s ò…úM íÂÔ—ÏÓâWð´ƒFQ…€R9~¿Ìg%¤LÜqxEÏŸ¨ÆÄ àR©¼ØÆB‘^ú¿ ˯MA^à2‚e(¾ËƒVNI|6®%Òxç»%íœ2êËEñÍÙ}tL瀠.\L sì¥$¼îîŸsœ$˜Û¨…€?n€´X]BÕ©¹‰" :>EY–aww×¥ušñ”ªPcW¢{Ç5¶··•·î¸üwTêëv»ŽÈ‡ˆPØÏ©Ö=|$­Ó¨û>Nö"çÄ#>y™dÜCÏzñÎ[ô49€¶ÌÕ:'Ó„3µ)¹­¢¥¹¸»o±y=.°\Ol[7ômŠ\^WJ…¼OÜ¿éu#´9zì¿'t“8!†xé<‚ ßñchÅw<~ü‚S_&ÜP*ÀÁ3>€ƒ 5Õ4õa÷z=W9 ~ úÓùI ˆ¡£xYA9VÂK•Nkkknˆ*—#|€:ûñ‰uZrr9 .JΓ’8æÁŸ;a.!•)Ѱ¸y)34"lUvܪïY…Ê»¬Àî¢T¤Í5øìÇEQG ó›A_ΚrÞˆC ‚c¾ökþ|Gç=|wäM>\“JN´¸‰½G!9íf´ØiǧZ5Ÿ§Ó)ÖÖÖ*øG§Óqù>ofâ÷‡€°C‡wPNó%Í}~OyÓÃáÐåҜð°ò9 >HI/>™6£ë¤û¹½½íÒRzÚÙÙ)QoûýŽ‹’#¢­-§ÝWðiÇxCëÝßOi5ÜdÁA¶©§¤ˆ›øÈ~øBã¹’V `=ó>ŸÀ/ÉÕQ<}cç??7'„iwŽÔÍ¿—Xq–Q>O¹,u³ñ¾|þ}T‡çâ#”êÐu’üÙÆÆF…ȉw€ÆÇ—sq ?EI’ý~µ»OÀ§ºÅåO8jxB¤£n·‹ÝÝ]dY†3Î8ðøã—Ôù@’8ŠLŸç˜NƘŒSt-a¨â°P–tóËi>õ·­3X…Y¸h÷^æ}mÊx‹PýEiÇ"¶â¢ûס¯¾qr®0E¸´ö”cÚ¨“pÃ࢘#t’“ÉÄLdø~ãè;ù´ZB¬ùôÄf@˜M'ây÷úúzåܨÎ= J‘ïM8¥Ü Ô!Úäð(ÌK½¸àixf³™kŠ=ý€‘§. å—ô¼7660™Lp÷Ýw;Pã¤90N0›-HÁÊ¡ræÚú:çÈF;&eìô¥];Þ'*•ˆ—É—ÛbûEýÕõÛN"Zf€IÓ{Vá Ä‹ndÊŽR ±çý¸Á†Rˆ¹Ã_œt BšyŽé‹Rúù+© û%µµµŠìW¿ßw»×- ÚïÔ‚ˆ¼¼ÈAÍ9¤~ĉRTW¶5–æ úȽOW¦ƒôù)âàÂ)\·GLÑ6B—yç_“„6wÞt>¼Mûĉ8qâD…nMçHS†f³)f³9†{{˜÷Ã:Œô ¦“ òéÓãfL¹ û% @‹ŠØï«íHð¶H õoãˆö«D\›4á¼üZ´~àïôu!Jo³Q_ñÇWÈ ƒ\c€ªœt4œÂ >¨œENƒv4ú¬² ¼¼ý–/f!„kwåU žöÎ@=ôÄîó‘øÎiccNÇ©ëP®O;>oLòUxýú>× ÈÀŸä÷pÆäp8,•ݬ¯¯cww·nr'@"ž”6øxqã×ÖÖ\›1¢Éó{O:…,˰¾¾^Jaêòtª&ôz=p&¹HŠ£@Û tüþ:WY„X›òsª¯ŸòMgSäy¿-µvÏsè|•gP¶‰+Ïs@)¡*¥Êerêe~MÇ ­×¶9üª ݲmÔ«È­ÇuÃ=ùEûÎÿ®-=“‡¬‰Ç' M& ;Ò÷Ò¹»»[ÉåùØïÝÝ]È(BÊrx®M@΄zÿI*Ëoqæ’éJ)¬­­•Fƒ-Z,d„¼˜”‡¸¢¦Ó©Â¯ÞðÆ.ºïtO‰ D¬I¥„F©ÉhkkË='¥ «v¡ÃŠ„Š0b>#VÒÏ[¥›¯J–Zí»–™ñ·êùî75¨ðü( ¤ÈwbWðvrÞŒr\¬Žâëá˜9¿dEù8—û&ñ®ÄKõrÿúhW¥ò›“:³Ã3èz÷vwB®/{N»ôææ¦Ф<™Ëžñp>Ÿckk ÓéƒÁ Ò6½(Ä%çEçOíÀ¾;¥4œ¬å§Qþx32n^A(EnÌ©“¸kä±´ð¦À€e߆ˆ?¨Þ³Œˆç*ÿ¶ ·`Y6ßA´¯:Š,^ÔüšèÊo¶®é¡1±hQò“Bu¿9…·ÞòvcÊÑC㺻Ý.Æã±«»IÃVôbcc£Ò"„À`0(µÇj­‘Íç6ÿ'*.@«›Ç1Ž9âF%IbKæØxu…@£Ñý~ý~¿âÚ¨¿¡òt‰ª>ë…x F;:B‹ŒG4>ú¨‰@ K\¦-Ïuá¼²Wñy4âM‘,k(×ï÷KQ—Òæô`“ T™…4Ûë !2ªápˆC‡•H@È¢È }ŽÇc@ÄÞuû’óùÜ êз:¼nßµçÆCd EH¶‹„r`œ$à‘z#œÓtú ¢RB/nUµý–»ú~Y‚Ëèø/3Œã Ê‘íéÜ«¿ÖºÜ\G]4ÂØ„Ú`´À‘mG.ʃRVPøîSC!Ïg¥¾s~ ÄJ#Z0σéýÓé´48“/jBÜIŸ “!#G–ç9>\ýôgÒnN*?~í3'µÖ˜L§˜ZàÑŸöÛvÁ—R9! vx¿MSÞêóD¸ñ“^7‘R"îtLì`….­v„t›Âþ:¹±:ç±lȼªé²e¿6”äUÒ—…)@“— ±Æ„S2ø¼6Ìáà\xÊO!¢Ò¥›—_x4¹]Ü~Ðñç©m—ó ­æ£¬y-žŸ75ü9­ràN§ØÚÚÂáÇ+<¿ñe}}£ÑÈMK"2Ÿ\̱J7H=ˆF…Ñ5Ô•oùNíë'TÄ‚”«æPçßîî.¶¶¶*Cš&H:¢K´vmÁEåä¹]±.ÕõŸ,³;/ƒÅ¸5¿Koî@[çÐö{â hÙðŠ+Ñø3ûBóþ|ï©ç€1'èp–'£ðí,¶CZ}ôD‹¥(€ôüú.•ô(Ôç‘7j2b>á§©´DT`R¢®D®ÒjÂ"Ãîî.:ŽSÝ%0Ó7ô¦yz¡ÿ.íp¶„—v0ßÛBÔí!Y?j–•+ >ñÄ¥ù†œïÐïu!fi‰É6íPþú(tp;Ðe 9Ëî¾5'´`´Lj±Jî¿  ‡òùÐxíz*¤(Q_]SL€äcŠÒŸ¯XË9Tq2O9ö›øµÀ'Õò :¤‚Kßã;4 U§:·Vr5_béù×á+“ ÉCTç£ÄyÔıb'r=î 5û4¼´2¨üÞ£÷`~ï±¶û NöÎÃú³¯FÜíCÊ£Ñ;;»˜gsQ¦“N`’¦È€F¯¢Öo{T¹„¼ê+þ/6E «ÈŽ-“/먖Å«Õúk5 yU!¥´¯åŽá š0ù±@ž£TÊ#ƒã©/©ñÈ; ¢ÖR~ì{aô¶··K”§$ÞAe=¿y‰¦äòùTk÷óbjú™Ïç ®¿Àh˜& ,%Lƒ:û¸ª¥|g7’f#7¢Œ?>8dpµ»£ýÝðÑ{0¾é“ø÷ßózLF»øÅw~³ñ“é£É³yÅТ<<„7E2Â$Ï¡E{¢˜¶3 ¿@AÚ “_\¶Nß¶lwÐQÁ"Ýþ6¤¡euþ—1|²“¸ p⇿M¡}¨ëÏßÉ86ÀKƒ~§åÛ¼€vqêÛ÷Ïk×ñy|¼ª@†F-áî8Rí!çÁǃûM?Þ‡œŠÿ  Gàkýû¾# ûL`"Nñ÷…z *ŽÁ^ëðá»1¾õ“øo}~èû¿¿õÛ¿ÑÞ&=%ˆ(ˆSdZCÀ‹A‘rCG'äi¾8€v 2g’8k+sɺû*”Ù¦|™œ¾íüÁe°‡6DåMØå˜¿õon“âL2ßip¤ šäºøŽ_iôa¹¶c—±a#ä<(¦?¦¡dè¼)†ÞK%,>í(Ô9HSx¸6 wttþÓéÔE4l¤É³¸Gzý@!!NÆíóò9Vâ·LsGÉ+2|BPQÁ1ïû=oÄ¿øál¢ÑóÉro"íIBkèHCD1¢¨Øõ»ÝŽê´‹ÎêROFe*ÅPreÇD-Áb¡wSôP|÷r<ªñÇ)é4.±Ó·ýþUCÿTNØ­ðs(¿žËI%|ñùƒ8âO¹|HJÌO|b 5Àð!¢tŽ„¸…M×býúú:ööö*£­É‘Í—š|V"ûÚÚš)ÑÙ>{ÔuþhGG(¤ï!J0á\Êœ—ùt"Žöóûjñ­öoØ&«ÇïCtïçñ3?òøáïÿ^{#cìóòÑ„R"‚ŒR¤IŠÔž9°,ËÐít0ía>›W¦òV¢JþRà‹h—ªšhý¢_f¤7¯8¬:|CûLFÏâV ó÷û»š«šF‚ÑÃâ Ý7PÎàa¼ß㋚ÝU"ËòJ5ÀÝ@qYž€†@žg‚J…ʱ÷¨e—ß%©¶Ï«¤@áól6E–™^ÀêÖÓŽkJ¯ÓÐ#+î×£ý1âÔdCc´ýˆ*ÔùGQQ{É¡ÒnË+)DåX gûqGVHy™¨höè=Hïû~î_~¾ï»¿ ³Ù³ÙŽ\òÄlÄ)¤Î‘$1’^i·‹85œ º‡ ‡Chè…Ñ£ R B)Û ([-âe9ˆ¢ž áÁ^W É~‡JR!~@QBʧ ”Ê‘e¹™-§WžR@H)Í û,›#M;¥ÐÜ»Äd÷$Ôxè†UˆñÙph\FÐI¢7@$#ä*Çdg?òÜ–~rpöO¡î?.ÆY‰¦ƒÏ¦Ò~Çö}7cøÀçðóÿæãÛ¾å›1žLÜýpk@e*C"©¾ovþ´ßGÚé•vÐn·‹ÑhˆÙl)$ÛÙ«³!Œ ^á‚|ãpǘM0íBè" f¬£qÚƒL{(Å´¢Þi¬ÚY·¨ÂÐÚP‚µö.3ópa$P' îϧ¿B´…½É»w|³Á:´Ê1Ÿ›žðyB]ziîžó4h; Çìæf¦@>âÔ#w"ÎFؽï¬g[8ÿ¬3pö9ç@+…‡N>„GNÒ3Ÿ‚yoɱóö7‘©Ã=¹±Áz déºh&€¡õ{¶·Ùc÷Bí@rê^œ{dçwÎ]?½^'NžÄÖÉ“¸óþ0œ‹þùÏD§X;v.úÝ&Ó ”OX(•éßvgSCóí÷ÑôI#©.¼]Úw°Q¹a„gøa~I#Š$Tn .›Ï0›NÊS‚íÔ£ùãwCÜö1üêü1¼éoÄd2uä)7íh6C>£I$HâÝN^q’@ëÜÍ0›SìnïZAÈÚwÜÌêßBç@Fß5búø};âŒAGÅÑcG <öØ£xô‰ãx|ôÏ{&dÜ<|:GΆt ø\¾«pUÊí²mÁu£É±,Sb,L©©‘ä#î¡P“Â>)Îߺ _wùKE. hh |øã×á±Á&°vÔ„®ÊΣÀä‘;1yôn‹&xÓ‹Ÿ×þÀ?ÇÙgCÇîš”ëF#ŒF#|ê 7àÏßù.ÜñÄݘ Ž¡sþ3‘éML"‰Áú„&šÖÝNyžaë¡0¾÷&¨á)\~f‚oÿîoÄUϽƒAý^ßÍã#ÀrwowÞ}?>ü±ã½×~'>‡/» ½þ&NÞ}#ÄÎã‘tp"ÏMŽ­L»«Î3ŒuŒäüK1ŸM0ŒÑ 0¬šn@-ÙĨ§ÈK$zšçæÓ1†÷ÝŒxtn‘ÖZÙ|šõh(¹Vèn=€_ú™ŸÀë_ÿ:§žì‚Y¬áP?…Þy©"žoAo?ˆY’b%ìœr)1 ¡³ B)L·N"¿øì…U:Ö Ùx㻿5ÜÂ!½ƒW_ñ ¼æ{¾œw›vV310™LqË]÷â¯Þý|0»¿î…ÏF´¶ %L,9±oã^dàmtV° -¼âqC@ø )ó÷ƒA ÷EϽÿ÷¿þWà]Ðg777!ç¼ãæHºkÆóCbrüQLï¿töð#ß÷V¼â%/‘#‡Ñµù²bº¹¹éòñK/¹ÿàM߀Ï|öóø½?û_øìmŸ.z.„Vˆ#‰^ÍèÞkO²<›aþØÝÈný$Þø¬óðÿàâY—]Šõu'sîÏX__Çgœ‹.¼W¿â¥øþ»î¯üöïãƒ'6žq¦݆ÿð=߀«®|¾M{ª£¹Æã1þËÛ~»ÿÈ Ÿ…™VPyf«¦ XZü#”^ù@#ýÙëõÐISŒÕýñCø?ø<ëò+\[sh !Ð%Î?ÿ|§Ià/Âíím|Ó7½ /zñ‹‘e¹ÑçU\žóv÷öðŸþû¯awoXQ€ækIk - $^gsÌ·ÃøÁ[qñ±.þÉ|3®zá•8º¹‰.äʆnMà²Ë.Áë®~9n¼ùüå»ÿïÿìG1>r!zç?²3„„Ò¦tíÊlmóûâ÷e`±] oq™qUrTùs¢´û@RÚ­ÜéƒtE¹ fŸ÷ºáøgMÎ*w v‘å¦O<„ì®Ïàû¾å øgßÿ½8眳]¤1™N/LÍÍÃxÃ7¼/¼êø•ßü]üÎ_¾ÝË^è ‘ÄÑC®L8 ãSáÔÍŸÁÙcø™õÝxÝ«¿Þ¥¹RÈZ|§Ï|æ3ñëÿíñ¾÷ý þã¯þ>Ð=‚ä£xë¿Á‡ø‹Ø~ßþ¦Wã“ÿí÷¡†ç!^; ¡bLFC£Ö“¦HÓŽ«fÔ1ú*e{)öîþÞôÌsð¯="«ÐDáæªKþ÷ <Íq¶è•$‰ÑPìv°m@= eëþÙÃûoFo¶…ýŽ·à{¾óàØ±cn=̘ØIÓóé÷ûxÉ ¯Â ¯|>¾ùS×áßþÜ/á‘áº\†h`¢-íÌa°‡eg†œB]Ëô¢Ïú•ˆƒ` Ö# Òsúï"b…¿¨Jí¿JAA•xø‰Púw ¶Çð‘»qA2Â/ýÆÅW\IWoëÙ(ÞÜÜÄ¿ÿ‰ÅeO»?õ_~ {ÙK‘Dk›G§]h¥09ñNÝø \ýŒ£ø÷?ú³xòb>›Uè½mˆ ³™éF|ë[¿GŽÅ?ÿéÿŽÞ0ĵŸþ,¾î•// Ìௗ¾ø…xñ…ïÆ'¾É—BI@è.æ4AWÇI °ó§.…v•Ñ©ÇÑßy¯ýž€´×Þ¥%ï÷ånÛ×l63Ÿ Ta#€<›C=v7žqöüÚ/ü.¾øb× µ¬:OÑá/ÞþËGñoî¿à†;>ƒÞS¯4N NÍ")¡WÄøº×+2 Û2W&Z1þÀgeZ¢Okõù&,WŒÕUfÔñ…4;ù(öîü.?,ð§¿ùK¸òWšh€=l® äwÈù?\òú[¿õ[ñËÿñ'‘ß~-&'Áxçæ“FÝ‹“Ÿ~7þå_€_ù…ŸÁyç‰%õøÍK~˜Z÷C:¯xù+ðk?óHò ~÷÷ÿÐ1úü÷O&;vÞüúW#?q/&'Â|´‡ùd5Ÿ™êS!>uêvvvÑ×Z 5Ëç>t'žs¦Ä‹^üRLm>ßtî§ûGk ¨:Ïjï£Á€LãÑüäÃxÆ™ëøƒ·ý\|ñÅŽ¡¬ª±©úAޱi]d™Án.¹äüÆý9¼ìüÆw^|´5Ÿù*Ï-ÝX/ÌÛýx÷û^Ÿî,:þ²}Ëíþ š€!"… ðæþoyž»jKÈ1ÇИÍ2ä'îÇË_ò"¼íÿ:ä:ö Á {ÃFÑkÍíúèu»AÆ!½(”}õk^ƒøòÍxÇß]­®Â|»‡ÉÍÿùÞ·ààa>ÏÜh«ò,=»óIAØs Óæ7ygg¯|å+ñ}ßòüΟ¼ŸüÔuxí«¿Þ0á¼÷Ng3¼ê•/ÇKÞý^\÷èÃÐI²—#ê2Ql9ñEt3™Lœ,Ñ„¹SŸ|òÑ[ñúøfllnbÇjþÔ$UrNÃâË UV‹¸5K.8ô¿ŒcÇŽ9á®ÊüÐcakk 'OžÄdb¾;zO¾àIX¬©Ò÷L&<éü'áÇÿ?ÿ·ýÛŸÁñûoA÷É—@wvþ@ ȱÛ†š 9@!r¢¢ùËŒ _ øóPÿ ¨#Qˆ ˆ„.uç™ô¡héäœþò\…n7Å?|óëñþýO¹îº8Ž1Nqßý÷ã£×|×~ú³xేйBÚéàÌÃxñ ž«_õJ\vé%èõzÁ0›7?òC߇o¹Ÿ»íÓÈ„ÂOÿð·ãû¿ÿûŠ.íãñwÞu7®¿þz<ôðCxàÁ‡qòÔž|þYxÒùOÂóž÷\\v饥 @¡×ÞÞ~üÇ~×|ò:¼ãÿ/ºênP&M'œsÎ9øÖ·¼Ÿúù·Aoƒ²Ópd¢%i%Å¢\ºÍnA˜ŸzÏ>»¯õ×þ=ëMàD¨×tMT~ôñ¡E/Ú#! ò¬qÑO§S¼ú/ÁÏÿìÂgœQ^²µ½Ïñzüõ_½ ŸÿÊ­Ø01Ï3Ä‘Ä`°Ž§]p>¾ã[ނ׿ö58|äHpMÐ\ˆ¼àJüз½ ¿ðö¿ÂüÐ1ěҖmªfÉ22c5ixUJr[X€›œùO~S‡$¡|ãwe@ÀÎ~/^iAÏ'x nÂÏÿÌp]m>@³³³ƒC‡•yÜ|óÍøƒ?úS¼ûÃÃpb"Œ¸¿t /Š€Ñ6Ô|ŒXåø–oøzüÈ?ûa\tÑEµ¹öúú:®½öZü»ÿá­ßòVüÄý˜oÕét°³³ƒk?õ)¼ó¯ßƒO|þFŒgS@ihCC@Í'PQ„Ëžz~ü_ü3¼ê•¯@’$.zð iss½æüÃïþ^üþÛ/ùË‘€¸N·‹“ÇÇüè¿ÆgË>ùR »÷€85@H T‰ÚBAO‡Èoú0~îÞ„ú¡ÂñãÇ+ Áí¢=¥t©æ> pæ™gï¡”ÛÛÛn ²h9ªÛU~á?Ci?ÿÃßsÎÞ?þÎÎâ8vš¨ êºë®Ãùo×ï|Àp úˆºk´3`vŽlû èù /»âbüÇÿë§pée—Õ®‰N§ƒS[§ð#?þSøô#:ç?²"íqbx )_TÎk²¯2ŧɉøRü휆&Õ•Z\@œùO~Só<¿Î pÑ >’HBæ3¼Ú:jˆñ#Ò·‹ãóùïÿ»÷ã?ÿÒ¯áÁ Dg 2íBi@ÈȄödÅb)‘w1;ù0.>÷(~ó×~^tQ#ÚMúêw:ÜqûxÛoüÞùO ŠSD½ ÄÝn1Öj(¥¡³²Ý“³!~ôÿ#üóùgˆãÈføµ»ïõoùV¬÷Rüé¼"°{çÿþà÷ñïþûï"yúUè9è®CE)´”P0×]ꢴÜyŠ´€ùã÷áâÉøã_ÿEl>RQiðÉ»ßó7øÿég1›Í!"i7…7¾îµøÏÿù1*iàúú:ÞñŽwà—~åm˜Ìf®åZ”zGÌÿIÇù0TãNíìá•/Þþo :.Ÿç9ºÝ.â üÞïÿ~ëí€<Ù@´n;!" Š d ÈÒ’Ùr䓲ã©g ðoûe\r饕ï¢×¡Cø£?þSüä/¼ É3_Œdóˆ®G%€”•4`‘˜ç²³ÚòùW¡ÿ]ålÀà`ЬÀ¦<&Ïs«ïä!zÚé`<ã—~åmø?ú  É¡3¡Eivœ@&ƒÖ’!Dé`rí0n{èüôÏþ<Þö+ÿ}ËŽ •„ƒ ‰ã$Á{ßû^üÂûU<¸3Arøl$I"Š!cÓêŠÈ É(dÅãcÈwOâm¿ÿçˆã?ö/ÿ…£ßr'0Nqøða¼õ¯ÇÏþâÅç>ÿ¼ô¥/©8BšÀóÒW¾ Ïû«¿Á Ç„²Ètœt ӴȬVb¨L' ò9ôãwáoºçžw>Nœ8 Ç÷ööðÛ¿ûv<²;‡ˆ;ZPÓ=<òè#µÌ3)%Nmmá¡ãÛ@B™èH!y[²‰Vœ¦£dCb€„ñ*Bë0¥~¿»ï¾?ýŸ~ùÌõˆƒ¸Ó‡ˆRˆ8Œ;IÇ=#rÐ Ñ ƒ\ÛÄÝߟø©ÿ ¿÷Û¿‰cGŽ×Äl:ÃÅÏx:Î92Àñéùt„(6)˜Òr§mÂÿýŒö:˜š“ñ™AìŸlÈxý¾r?$ÌU %tpîœKÒ{;;øùÿüßð§ïz’Ãç@vûˆ’´L d D)t”i×ÌŠ—–w âH"îo@¦=|üË7à“Ÿø^ûÚ×ÖÞÔ,ËÜ€?ûÓ?ÁOÿÂ/a$ûH7 éô!­ÁÉ´§ÆéD1 $!Ïg˜Ï¦ˆú˜E1~÷OþÏ»â \}õ«‚åÃÑh„«_ù üß|;þÛ/ÿ ^ô¢ l2™à¢ /Äë¾þU¸á‰({b¡¡T•Í!“Žeûóÿ É0 ’fÛã¢Þ ßòæ7º)Cþ+MS|èƒÄ 7Ý Ž@$= wµÙuCUjŠ¢q’@¥³Ç d’BF1¤Œ ¢A5¸AlÔ‚•¤Ôêœt·ÛÅí·ß†õ“ÿ×ßvâͳ!;kæY¤]È´™ö!ÒDÜ1áº&TWD6‡ì “.nºÿ&üþ;~?ùãÿ*ìæs\xÑ…xú…OÆ#·Þ´*é@F „Œ¡¡, Z t.ÃÍ_¤AІ:¼êßú]˜• N,$]š ¬sh©J-©ü3RJœÿe¨ùÓ!²™qºQfUR£V!{¯2 p¿QA¸ä§±pû׺àð…Fs|€·rýü†w2D¥úý>>ðà/Þó>DkGõ6 Òdw Ñ`ñúQ¤›g@ô!^; Ù? ºkˆû‡ ºkPIº3@¼vÑ¡3ð¹;rc¸B¯N§ƒ›o¾¿ú뿃]ÝEÔ[3Í"i:½Cˆ7Ž"Y?ŠxÝþ¹vñà°ùsí0:›g`pìtž‹þE—ãó·ÞƒÛn¹¥*Cf »ÓéàÙÏx 2üÖï½Ã Ÿø°»·‡ Ÿr!¾þë^…ìøýÈöN!ŸŽ uŽN£ßë¡ßï—´þ¤”HâÑ|ˆsòãxݾó,Cîá yžcmm ŸøøÇñÅ›nƒNû@ÜÒ>dÿä`H{ óQãä#Ä.âÞÒõ£è> ½£ç {äÄ›g!Ù< ÑÆè=bí(æé:tH× … î€$ˆúÄãã'ÿíOáú[îB|èLÈn"íCôÖÜyÊÁ&¢Á¦ìºë½5ÈîD—þ\‡èm@ö!Þ<ãþøð‡?|>Æ \üÌgb0XƒžO,' «T,Bs/W)ß-3Š|Ù÷´åûÙ€öOYç¹|ñ _‰F€è§)%î¹ç^ÄýC@g™võÖñ¯F4ØDºq éúˆÎ²Ó‡Ž;Èe $DÝôËtÚC÷ØùÈ7ÎÁ­·ÞTJ?'ŽÇî<‡¢Qw€¨¿ÙÛ@žô‘'sƒMH»¨dw€Èþ=ê®#l¢øLôŽY‚nør©Ý—ß¿Ùl†³Î>Z+|î‹_ÂG¯ù˜S+â?Y–a:™â­ßü<ùpóí'OFȧcäó™i­Ž" }lll`}}½^‘fÜ„]ö<ûÙÏÂp¸ç˜h¼A+Ë3üúoÿ&:Ò>r™ ‹:˜"ÁXǘ#´ >gRãQZ>D·‡Î`éú&Ò#ˆÖŽ'¾v¢¿‰Îá³ »‹tw²wèô­l5-$é³»ïº _¸þËkÇÌNŸ˜ Aö6œÑGÖùÓšiˆ;îG¤]ˆ´Ù]C¼~è p͵×! T1ÿ­pôèQÓk’Í­ñÏË“x–™å×Fä£n°nÛYÂOðß„0@“ha]ºø&víŽ"íA$)öŒè2Þ½·Ž¨»†îúá"'S@FP‘uœ"1do"Jp÷=÷TrMþÓíõ È'&âèôè‚î¬a.ÌE $]ÈNÒ¦ˆÈ´ Ù±¿ïÐÝØ„Êr<ôÈ#ȳz–Ûææ&Å!ÁýÑ;Is?ÞÝÝÅÓžö4¼á5¯BöÄýȧCä³1òÙÊk'Žm+n4ÛÅáÑ#øÖo~34£Ëòû¼¾¾Ž}è#øÒWnA48Œ¸ÓGÜ[CÜß@²véúaDž‹Øê~Œ¸j„(I!’.DÒÒ>Dwt@:@ºqYÔÁ0Ði¢»nþìô!Küõ t{v=D©ÉåÙšý þ§=j! (¥m£Ô<¯¤‘ö‘}î=5Ef+¡ï6"&:ŸCçs–Yª¬Öja~ßlü«ƒ{mºO4œÓ´ r‘@AÈAø#Á|YGýtQDœBÇ] ôÖ÷OûIQÚAo0€°l<#;nv#›RP‰¹6àÓ)›„hÇË(BÔé!êôÍnÒ]ƒNû&ÿO{˜)`2›G#¥)Cº†‘ˆƒMˆ顳ðØÉ](•Õ.°cÇŽ€±·Oá\wÝu®…×7‚Éd‚·¾ùÍ8šæ˜<ñ ‰fS»8óbf¦TÀðž/ãYœ¼àJlmmUÎjéý®wa¨"$ý5Ľ>’þÒµM¤k‡ÐYÛ@ÜéU8ÿ¥¾À„4å·È`4ZgšÖ1Éá,7ziHŒ““^©Ñ?ü|¨®™Ïuú½õbM$]ó¥¸ì3ô#ÍçE›JÊÑó1Ê%N:ÜG*´ÊÝZhð×Éœ—Sf][“_–É·¬Â/”ª7~­¼ÁüÈ&Ùægò~C­¤µNddÑ\ƒö‹´ wmƒ†©ñÆI│ÊD$eêØ2F®\Hœ:y2ø]åÉÁqÚElk¾:î@¢›Å5Ë2ŒFc+dRÐ:5´ e…„Hzè]ð,<¾7Ãh4©ýÞ#‡M€¤ƒ±ìâ÷ÞñŽ /U.ºè"|Ã+_‚ìäÃÈÇ»Pó‰qÊHw H!‘wï=ïùö·:^†Ÿ¶õz=\ýõøÌn@¼~Io€¤·Žt°a~úëHzk†p¤Qîê+†„rÀDQŒÝÑãéÌTNddwçqÚ1“du JIš\®?âÄHŽ¥ –©eÒ±µCþáܾã™5ÙçÙÁl>ÃÃ<”zWJ!í¤8Ú óÂøUžÙ( }™Ï7}gQ¥/Ojå´½—µù}¤ ›H¡Þ& yKjþ€iS(A!²µÝÈ1LxÂÇx‡Ôm!#ä2Áñǃ ¸¤ÏEqЏÓCÜíCG cËüƒc€eYæ&úò¥m«3d„xm{“©‹uýÍøÐ‡>„õõõ’RÉ eyŽ7Ó7áˆØÃtû8ô| Í>¾5~­FÜgŽpÕ _ˆ ]8ŠŒ Ï_¿ëÝ8>œ=1¥4aÃhÄæÚ¥”ȵvXNÈP´åvð]N ‰Ét†ÝÝ=C,FÅŒ…ˆ“iÚ1Rn^ŠQy>ZAÛˆ 26a~ÜqéŸ1DD¤(YÚ€|в´ä1Řg9Nœ8|>æ>ÅØè¥&Ü· Iºfwok„+©ó,IFZ5ç¥a‹Ú BÈr7 ÷Ћ¦¹ø€ÈS›S*kHBÚNbžçöüû³ôIl±B_/ Å1§xx;œë•*B JÃ&‹ÄiÇ¥f° ?)OÞ©ÔÚ7±m›nê0€HFq‚hp#ãíüg˜N§nÚ?ÏápˆK.»/¹êù=p†'ÇdoÙlbë¹Óí'0èüÀ·½Å9+ÿzÓ4ÅÍ7Ý„\ó ȵMcP6$ÛqǦ7FCR7÷ß, Œ†ãp8Äd<ΠÑkQ$ɨqM¸u#¬$Z3R–%ûzApÎVµb%Ö …2µAP«p¯×3a¿Rl®¥ª´/«ÚÓTïo[lÝ¸Ðø=PBÃÍФmOú'uÿËKsãíŽáÏZ›ù°d¥4¦ó™ë‚ó+äxƒQnNݳž‚­ðˆµ#n÷7¥3»ûG‰ •icÕ¨Gé•Ñ3TJ!·Ñ†Ùtì{´ª< g¢Å„Kk£Baç(«_Xƒ#ù‘ƒŸê-Fížu“~„RÊÌÚ¬IÊŸÛû23ÚHˆ- öQ¹}QØÏi¸úùs2D–…ö¡É.%¡†Üßÿ¼² KC;o=ŸÏkD.ƒÍí"yMëKgщ“ ªÁóJ¿\G*ÂÃá3ÆÿoºNe‡h$ii·d°ä¬§àË·ÞŽ|ô']îç¦Óé?ô}ß…51C¶ýôtŒl<ÄøÑ»qÞz„×^ýrL&“`¤ï~Ï{qßã' :çÐQê(ÖJH(!LÞ¯4T®Í[»K«@Gë&di×§™t§Ó©M¯êA@¥4 E± kQ÷:€ÙÚ´}Ö¡Á(ÕµQìþ4O-0°:›Yeç_ì[î3ç@À`ÃWȺ²†ŸøçÄ Q£hÛìT^ !~}(¼r}æQ„(Žlמ.‰†62·ü&ˆ8F’&Áùy<% ˆ ÏsŒ'cL-ë®é:Ý÷ 'Hûkœq>Fý3ñÞ÷¼ãñØçŸF¸ä’ËðŠç<jë1d“=ä“!òoÆ7¾üù8ãŒ3*€X–wÜ~;®ùØÇî!è(…1´L‘ËØP‹å³y†élŠY6·y›Bôj’”qT¨òÐ잆˜T!¯M/üÑYÔIXŠ^Pq?¨<ÿ„6þEZ— lmXy‹œÂ¢Î¾¶À`UÎ[/Øñ=À/Xÿ¯q‹ZëŸã;¾í[ÑŸÀtëqŒ¾G; o|ýkƒrc¤ÔôÞ÷½w?rH{Ð26„)#r˜2¦R³éÌb¦ä•×Ý·\A#„®L)¦þ„^¯Çf0˜æ£étЉ%'énˆ¶·0½©Ò‹J»ÍGÑ"e‘!A¶¤>ä2m½«F ¥¾6ß×GÑ@ ²ï“M(c›É%fØ„¨­"T4àmϵé§)7áˆNKFÒTZìÄ‹° ’Ú"§@Áí¤K?Tóu:(ÊžIÝ£ça¯ãï~/FÃa¥NMV?ó™xÙó.vCl?ŠozÉå8vìX%B"Nýý÷݇O|òSÐiIo é`ÝõÃX;|‡áÐá#8´y‡6phóÚD¯ß_ÉXâF)MŠ“niš”îõüSõ„˜„‹#¥éÕÊõ䇢€VZsiCÖYuç_yG $§ Êå>¡Ôÿ=ÐÆp|, Rb;æ¢]Ø€¼"˜ëq>\š„k9"²uèf 2ŠQ§K3ù¸Ø¤™òS(uWõr™-Ó?CƆêÚ}Ò%øâm÷ã#ý¨“÷1‡8‰ñÖoz3’ÝGÐ?7¿å-¥á¨g¦ŠrÍ5×à–{z릕:î¸ú”v!¢ 3ë\çó²l¥›:eIHäÓ4Eʆ°ÒÜDRJÚÛÛ3ÕAèO!È P—¤®ÊË#€º|õU†E›IÛ°¿M¹¯É÷kû®"@À®X ²‹C:€M„ŸXÇB|ßÈe$¡e!¾@!%«Ïf3‡*‡Î!ŽcdÂì²! 0ÕUL¢-¢ŽÐ §’|ô¶”fÆ‘²`b]Ÿ»/‰ng×foÁN÷þöï>„—¾ä%®­˜_çh8ÂsŸ{9.}ê…¸àܳpäðá v_’$xìÑGð¾}YÔ1ú q*JË3ä³ :AalîÖP³±KµB¢§Å½3¹¹Œ"ûlÊâ0Ҧěµþú«²D)€Ò ’J„ vʺaµ‹Ö¡Ryi T p‰™€ËNöYª’о…}Rä]<ù,€#ÄuŠÀ>Â\7‚¹øŒt4ÊÆüLÌ-m£íBIQšŽ3›Í¦id,¦þÆ–× v^eY†Ø[˜‘·cÐ.OÈvшc¾'ŸÏƒam8¤.\€(‚ìBïI—à†[?Šë®»¯{Ýë°G¯Ùl†$Ið¿çÛqöÙg—¢þŠ¢×^÷)Ütç=ˆgvüŽáý›Ÿ5 é@ÙL/ÒrßÌ jŸ¿Uѳl0&Éࢸp£Át±µ+ÖÖïîuúïØšÎ6H}½á.?`1È P7r¼„ø ±˜ „:¡ëeÁùNÀQò T#ÐNUçñÉÃJÛÍ¥JC„Â(Fy¿ìâ’µœ†"ŸÜ#³ÌI!+¥ɨ4òŒÒ¡§¶_)„ÖȘslŠr’ ›ÍÍ÷  §H6ÏÀÞ¡'á}ø®¼òèõºN›Ž±··‡+®¸Â©…´üqüÍû?tÖێŸ¿Ž´¿Ž¸7€Œ;Ð2B$$"ÛX%A!7J?¼$ë¯ÛL—¢y–a4–@[÷ü¢ÒŠ…ÔEæþçÎø[È‹HkÇg9Jo¤­F6RöŽ)VêÚîæKíüªÎø½†!ƒƒ-Š¢¯Cö}£¯ Uèþì:;(åòRšš6 àN€Ö¦p7TqÐì3u)ëÇrš|Žyà!=<Þs@iHžgÈË"OÅÚãdÙ“ÉY4HÌ´Ÿ¸·î¹OÃõ·~Ÿÿìgpõ×}t¬›ïg" ‰Ï|ösøò­w">|âþâÁ:ÒõM$kˆúkiJ]•f åQŒ(N‘ç™ÃüçŸW¿(’Ý?Œ'Ìò~R ÈãRkˆ8²rîïÏ“Ð6ê+¦t‰€(­hU‘*{¨ýÞ"`ƒIu³á ¡Èã`Â~µ¸¡Çñùu Q¨¡Ø»ÂØ—öò…?BQAÅa L) ÝøòCc£¯© ÈUŠÙ!'º©ô~_Ö*LmµýÓ):Q‚È–)Õ¡…ÃU’) ÐyŽy @꯻ÏB@©“ÉÈâD! Éá³±·v6þþCÆóžÿ<¤ne˜HÝ«ÛíâÔÉ“xÿß}º³æ4ñ¢ÎQ×´ÑBÆVaYTŒD)ÃЛæS·k*æ­X¨,lGežç˜GÈã"é u=™Ô)B,`î“gxUPTK„åƒÖ E6ÈÁ‡ì`$ b ²ú¹.çÉußUÁy2ì_ØË¯ ã¯ÕÔ <ž\”;7•dBá}Ý1aqîêÿü8¼¾Êß8G z‡¾—G„3Qa sWZãi‡ q<$‰HVy¨CŸy¿™i–ÜG&b›×r!R÷®Œ¾žª1Ë_9÷€œNHYÛr>U¸>+åÄ+¨™FÚªC’¦HÒÈDÚGtæ…¸ö+ŸÆ¾ðE¼âå/Ç´aç¢täŽ;îÀµŸý<äÆy&ôïœÂ²ˆS7X¤XªÄ—WZCv×0½R•¿²,ÃáÍMÄI‚™„RFŸÀvQ»a!¥ßþ÷Þdj‚7"\&Çdz¤Ý…7³©ôVNoT©LëožçàôŽû@]·^sc,cü-ºúZzØo0~Á~eR4Y€Õ‘3B7¦îAÕW6 ÃÍX‰‹3Îê84”Äî`²hŒµÏõçyýZ^ëÌ6£² ጢÃPZ΃ aËc"‚ŠDÇ0_; üð5ØS!$&ã1>ø¡aoš›A±ÑëCÜAŽs¥‘1Z1Ÿ+@GsâϵŽàvÊFGŽ¢#5º¼Òô˜A Q$MšÀð–8Ž1›™É¼í†‰ÁJ¾±éÒX~dvSH(󯋕{›ð‡Ò‘–Úù[või… 6‚Ïý/©q£×,ÒPŽI(—3Úè¶âå—žE^šçÆ@¤—G–êúy†™Gf©cR‰‰FW…¢z?U øHî:e™ZŽ»'“G¦[®Ûí I@dJCA@Ç=ˆ3/ħn{Ÿºî:‡„×ûþÄß}ôãkG ãÄ„üQŠ2-0Ïr¥1Ï2dYáf3Ó0M-#Pa:›âøñãÁï›N§8ó¬3qÅ%OÆ;"),3Ò(ÿøGIp8Ü3;ì¢5‘Û*ƒÒ¦7W•Z”ÞÚtéµ]‡mxÿílK›î>ö§Xðï|×׌.lB6&j¨š!Ï»ˆ’꺢’MÆzÎ ä»u2Ÿi¦äº]žM„4;tß« 8Óê÷Þ·½V!lÓ—qœØi;1â8Œ N­Ã,à–›oÁ|V§pdF§ðƒÄp.LΟö ’.T”"f¹Â,S˜Ùó¦ŸétŠù|æÒ•8N £Y–ã±ÇCE•¢étŠN§ƒ7½ñ1Pc¨' µB$8’¶¿Ø¡¢(Â|>Ãpoùpz²‡ÑØ·ÎaÒâÌ•íéG½á×­»P¤·H‡@—$ìÃauÛúù\ôMÿ~w1Ýuavà‚Wì£ÜM@ _q,ÀR8—³<¸Æ»Å»0³8E©#§´›;ƒ®‰TŒã2 •`yˆÞI‰$MÑévN ™2§ˆÓ0<…Nã)Oº›¬ì7Ž%~ø!¼ÿ#Ÿ€èm êöwûˆ:}þuzFj=íÙÞ Y)éRÞš2ì̦¸åÖ[ñÜç={{{ðqoo—\|1¾û›_·¿ëÈÓ.âÁòÙÔ°ÁÕ8F6`ûÞ¯@MÇPÞ†ËÎ^ÿîån:1Oܽƒvi«V¶üÛ`pË(éÖQi¨åü(úUô}«?ÛÙë˜~~ú`U£ë…”3ý‹ñÁ¯¨Ë{xx\qJAÛ‘×Ú SD( {ÐnÂ5ú]yô³.åòuD ?Œ¥4½Z;‡àWüÇ8‡ ‘€AÃÑ\¨ôº³vZE´ø2ÅP£m\rFÏ}γ]4ÿþþCÆöxŠøè™ˆÒDܵêʉ‘ÆÌESu£Å¬òäð“ð±Ï߈oüÆmçdùk63QÃ7¾á 8ó¬³ðö¿x7Žßñi¨¸cX22cÂ"‰ùt‚Íl/¿ìB¼è­ßŽóÏ;kƒAp\wÉ ÙíËUŽ8PÉij #óz°L¶Ñ(×þ±DÈßÚð—2~ÖM ÝCØfRë¡óRáïŽC'ìÓEm: µÖÖøE©æ«”Bä©ìøH<-Ìò"-‘¡¡¦Õ~þÂ[J)@)Ê Gô½ÜJ¬?¶;×-N]R™E£ ë?6%ÐÃSÀñ{qõ_ŒÍC›•¾r~=ô>ò±O™i9]»ë§= éue¥¡çs S%=~~NÆ¡&Èçs(-oœî¸×á‹xÙË_†“'OV¢ú‚+¯Ä…^ˆ»ï¹>ø}ì1ÄQŒcgñcÇpôèQœsæØØXw„­ºGÊ % !…•ç6ë¡hog\¥_£T¡ ièûÏ#µ1þ¥~ Õ{Usß7~!øÆ¯«ä šïŽC¤†eS:¸bå¿zêgõóJ™ðšJW´p¤•þN¹#…æMÝ€îaÓ92CëAì!$!eʆº‚;„yÕßI:–eЩ|Žlûq<óXÏ}öe¥ïƒù(žØÚA|æEfHgÚ7ƒ4“.tÒ"3F›†gøÏ•z!rq’@¬ÂìØSñÑO\‡\õ‹àWyô,>ŒcGâª+ŸowYøýÊ…üM;cqïEݦµ[›:½\/ Z“VJÏIÕÆòóÙÏá¡“»HŽž¸cFš9ö%@&•Ùö!tÜíº0øƒ\?‚ÉYÏÄ_¼ÿÙÜÄK_öRL&dYÖŠîºÊKWH>æ¼Ýì¥å™ë`¬Œ¢L¯n+ÒÁ ]œÁºß|¿«lê¡_´èåñü+‚ºô¡>º bmS?ðA«êï €ÆnöÆp!*¨kp¯Ðî¡Q!A9ïA»ÈÁ#"‘³qS…¬þ]žgf`'tE5hhº5•Ò(;€|6BöØ]xÑ .ÄÑ3Ît= þk4áoþîƒfX¦5xšôƒ8…–46 ‚p ÍúÈEqéOÆx´·ýáÿÄãO<×¼ö5èt:µç´ˆpbPï“FsP©œ´ïÍó2ÖÑÙPɺÎëס(+g•·åCþê¿é–Ü|zOƒ—¨Ø—X|Ü '@×:Ÿ8Ê/J ê"…ÜŽÖJ’¤”‡ÝLõ©†\R Ӭ×C3ŽHŒZkŒÇãðÎ×0ݬF½Êm®!Ê´ü!FQdþÍ~ÇИK#ª111õò]!¦ÈSÖÁdYÌ3DшŒðÅìÁÛqQ<Äó_ðBÇnôŸCš¦¸îºëÌîä\3¹Øþ 1C: ç?*)ë4…Ää"Yñ•"í!9멘*ß}×qãÍ7ã›ßôF<ù‚ [ºï"G@çže†Ãî¼ë.@k<ó™Ïp È> 9¡µ@1ª¼.ò;ŸPkHˆ’r-gòë"áÎ<7 &;£1þàÏþƒ~×4ú°ï¤VÁ´:k(­‘å9²Ù Z(@e˜ï<ç?û™8ûì³1+œõ(Š0Nñî÷}¢k¦'K;¢[¤= 2»¿›ó¦ëI*œGA”bG¦/^Df†@ÚCtì|DRâÓ÷܃Ïÿâ/ãù—>/|ÁópÁ“Ÿ„õõut:©#3‘Ó"–ál6ÃÃ?‚¾|#¾øå¯àñ­]¬¥žvá“Åt^vÎQcëäIdqÇDuRºQm†=Y´M©ehgË”Âÿú›÷ã#Ÿ¸*ŸQª«„(ÜóÀCÀú…nBUÊñþË|uÄÑPXÔÐøŒ&¬xËDEƒùÝÉc—ãäÞz¼=ÙÈæ€ÎM:ê@ö{@›…G%AæyÍ:‰²ÜÖ•%)½7¶‘w¡'¨éÈf@>·m‘)Yyn¥Mþüáà‘ÛˆŽ> 2-fü!6fRQ䆫ԧeú+95Ó“ ¡D„\$È£°v"#ÛzŸ¹ç \÷•?Ç Ñ¸àÜs°¹¹‰~¿n§‹,›cwoãñ{{{8yj 'vFý ³ÆºØÕ ×ßûxÙÉ—Øjrý, íCÈÄLŽ–‘ªmDÁÓŠº^€Rç㱋p×xxbz:žù PÅ®/:‡€8-ÓŠbájÆ¿`×ul½–Ó{}t!“Úä. ”%Šy6•aIcÔI:ÏŒ#‰Ræbó½IÇ\_œB »H3º–^Ûv<·4îÔ¾.ð‚¦<¾dëu]‹9Ä‹Êm¢÷ d $­ edŒ»;ФkþîB/T$ÆCTO^È!L ,1½í2é@çsh+6aœâ"±¹³`3 QpþÉ8Bõg÷ü ÍbI:j€XFPi:Ÿ#Ïæ`”d’"éY…ž¤‹ È2äß…ç>õ<<ù‚ ±kù÷>ø8ðÑk®ÁˆgŸ»Žó/¸ÀÐò¯3Ïs¼ïï>€I20ƧOHºù—nç(ó8(¬©›8dï)GV&ûX§E¶kюΨ<3÷5ÉÝHmŠ–h‰kjá“(Ž!e ¦½[®ÑÛ4ÀL“0²'¥> T•h¨l0fc¾­ðŠ {~ŠÙ„(R•ˆ@@K€å0=_޵·¨ÔçòvQ ñùÄ߀ا«Xƒ®:Wgpˤ ‚"«U.#—O9¤ŸvTB[ ±HŠ<îÙ¶N!i¡%i÷uλÖhZ4´´*i§Tä‚lØivÂÛ€ÈL7’Qqƒ#Fÿ‹" Š ¦5D6ÅÚÖ½xé×] )epêÚÚn½å|åÎ{!zG!ãŽÑûKÍî?ðfSQ‘Qõ>UéH2z4#:i!Iþ,…¹§Jù­Ò šŒ\-LßѸ T…0e½Ü#Ø dÈ,¬•Âf2¢ÂÒVi0¯ˆ&*D›9Ï pî¥&p–_\ÅJ%>•qÜÕ–ÞÇï€m["[^EÌA! ¢êŒgÐÍGI 5…½Ô¸Î°Û:à<•kÓî¶ÚºdØ¢”ëµIàEDÒÑàQ7mÅ' HmH0~§X¨‚·7“#Ò ÙpXPž»‰‚QiÀÆ<›cþè]¸äXOÆ31¶S~ý¨FJ‰¿ûЇ0Aâd¾¨î/¢g¦sü›ïzÃÒŠ6_{•_I’à“ŸþþäÖ‡#ObÃ" "°#7ŽéÒeãç¶'ty É|ŒõÙþ¿ßÿ:tºÝV2sMä«(ŠðÿüÞ_âþ|êÒBÝùÔé ˆ–Tà¶)çm›]?u(]ÉUëh£"Pª¶)3ߦbÊIƘ%„0®ÁŸBä×ÿ}¹+„ß+!*<-ÚÍòÉ.’wãE¯}!„˜L§•(jcc7ßt3n»ë>ˆÞ¦Éû;=ÈŽ÷%⛇໾ë»JJG_{-ÿŠã/~ñ‹ð¿¾ó_bÒ;tÖl¹ÖÚíw}Á©µ×ßÙwÇë.2~øŸþSŒÇã}]G¯×׿üelï¾H&&-¥ôG.šdp¸4°Gà(š:ÇšøôAÍzì¢ËM»8ïBäì8_(4DòëÏœž\ :Ë1{ä6\¼¦qù³.ÁîînÅxœV†k>ñ ìfä ç¦ûÊN21`¢+÷ù¯9€Õ_B;v®¾ä|¼ÿþ¦L˜ô,(l$Ðèc[#Ù€Ê G'ñÃßý£ØÞÞ^Ø6½è²,ÃoüÞ`;:ÌÆ@’›Š@Ä‹[…€\u^*Çí7-ù²Ž`'°¨E5t¬»,ô{m«ºÔ„K• 6Jœè²Ùèâí‡ðÊW^EÈ<¯¯µF¿ßÇ]wÝ…[n¿è®9rŒH{бýtj>K(íÕ¼{¾áÕ¯Àßÿ?¿…<íÛtÒV¤®lŠÍÖ( O ŒÊ+L‡xÑÙ žöôgeß–b¸ÿ¼ëƒ:Gùœaéx¢AI˜cÅì?hK"Zäj«d˜¥ãÕ;Ÿ€×ý}"O x¿€_nãØAU°Rí½­GñœÀÅ—^Šáp%–ç9¾xýçqj¢ õëOè'ã-ÔÍ$üÚk¹×p8Ä+_þ2œÿ[ˆû&;6l–… ˆe޶¨-ב߉7~ÿ7 ÛíboooŸ¬‹¿|ç;±3É$3Tg"8iž¨&ÄA¤³…HÛˆÀϯÛ:‚ÙÈ…ÞZ;f¿CeBßqCås¹™9” »ŒSTõTq+G§€nÂ+_~„Œ‘M«Ã>Ó4Åc>ŠÏéèÎÀÔúKµ,5ȸÕXò¯½Ú¿f³Ž=Š×¿ôJüÖ{¯ÎîZBñdx÷ ~‰.^£â3âüð¯¾:(ü²Ì+Š"?~ô¿ÞclU±q_ð«ÍŽ*¾IåE´f‡§]·éÕMjãêÔgÂՀ øjÈuòáá&å]¾î\ýãTÉ*¹qPã!.êŒðôK/Ãl: ª !pݧ?ã{SˆÍÃfZãבi&Òö!-8Ø×ÞÞ¾ý[Þ‚ß{ÏG‘ͧéIFõásÅž`_ÉøíŸ§Ä7ÝspäÈ‘}ïþƒÁðGŒGŸÖÎ(ê¥Òë²baå"n°Þ¢y¡öFõÙ¦è`?ŽÀ7|.5V‰8ÜE7Ï5¬ìâ,ŸçŸ 1ÎBé Ó•xßñ‚^Ž^¯‹ápX9çN§ƒ‡~_øò-ÐÝuˆ¨cvü¸ãr%"C¢² ékÀÁ½æó9Î?ÿ|¼ìâóð±‡v »} OMYžHÝNÚ¤ÆSêÆÓ@6A/ÛÅ·¿åMÁ4pÙÝÿäÉ“ø«wÿ tg½(ýIâ,w6²ó©™/tq®Þ.Ë̤R„6CHÛà uï©Ï´/å; _¡¸î%-S°<}ÐÃ-œÛÉpÉÅÏpãÆBŸ½þ†/á±í=ˆCç@[柎RH™@ iu `x_s~ô´ßû¦)^ûê¯Ç5¿öÇ@ÿ鸤~‡(@ n”ÞBØ Œ÷ðºËÎÅgÕz|Óù^wÝu¸éî€Þ¦í{H :JÀc–Xš97r¸1–/K9F{| .œoŠš 84ËÀ—“ ý.Tº Ñs›J]ú~mšfü2žÿì °±±ÝÝÝÊùõz=<öØc¸áÆ› »–ø“BÇÓ¢jyñ :W®Ïàk Ø ë¦9/¼ì%/ÂyïøS<”ÏMçcb{dÄUC±°‰G…;ü¢wâ?øý†œ¶Ï禔ÂÛÿà #ŠTÒâ‡GÁœ¿ê¬âÒŵ)}hÍÊ rß@aSjà‡ðM‘C¨&ß4P¢ÍûBˆ>{/”†¨SápœáÊç<Ûå{|¤ó½éæ›ñð©=ˆõ3­·œÿØôÆ û0…ж,ý5˜ص×}ýî÷àßýäãèÑ£•a*m_Óéçœ}6^ü¼g㟹HûˆR³éé†~—_þzL&“š0NãÖ›oŃÇOA¬ŸéJT÷×IjZ›©­Ë!àÿé@)…Nǰöþç_½ où¦7îë~L&\rÉ%xÆ9›¸iû„¡çsÛö- 0°$êÄCÙð&»8šäxÍÕ¯ÄÞÞÞ¾R•N§ƒ›nºŸúì YL&Ì XPHxdô‘Šû2Ç>ðIäó)„΋š2 FM§xt{±~¦5xFùX.0–áYÏÆ5§FУ-èñ˜ ¡³‰Y¨+D/î•Æá;ïÅÿà÷ˆRâcŸ¸×|éŽBý‰ÔwöQ>.NÜ’_‡cg>Æ{Þ÷÷ø±þO÷ehZk¼ñµWãc_ø5̲sÌ}Í2@f@ÄA¾úœšÖ~²uÞúßâT“V}EQ„íímüÉ;ßt׆¢[/>.LÑÃv/÷x‰P—+%PDÔc‹¹ûxhôýáÆ§0f°ÈµqP|䘀†Ø8Ŏ£z¦ çS³ˆ¬ ¥Q¶QÈ“žýH&]Ç´û×PPLϺU³E>0©iÞéê4ßu‡®BØg‰a…½NXvš&!Ø(fÎM,ûË'€”îWÒÁ®ý,¾÷~úý~{ióÇxÞsŸ‹³ŽlàÑ–y6VaÚœ{ðb«ç:Ü“6»xþóž‹¡YõÕëõð÷ø xä1`íÌ‚ø±ÒŸäu¢EÆ_–[ÌäÁ M¥áQMÛñ"c-3ük]¥Þ¿ò@LA^ð|¨Ùj² Lv¡'{¦M3›•µä¢ÄäüIßµüÒÕ•J“Ó$ËÈ* [Od–¹xøÂ÷!ˆ‡$¾çÙ:m† ؾ†žÑ7äÎâ§ŽLÍÍv‘…‘dSxâÔ×~ê:¼þu¯urk«œw¯×Ã7¿æeøÕw}˜’9 ÒjLÝ8q{Oà;¾áùRî«<)¥ÄÞÞÞó¾÷C¥kæZ£¤ø‰S&dÚ¤Ìÿ®JïMn#1?˜áœ6¼ l¨Q»4åù«„òu¨}]z°*`éîíLqjŒ[J ž³ë6ªÂ:Jm`ôð…u*ºLíBƒbZ!ÍÈí •¯n­Z›b¸{°@ÃJÀ÷ :svFi¶åT@¡0í®a#ßþí‡ñõW¿j_×0™LðÊ—¿¿õ—ïÇt6*§gµòÚì5áÈü ¼ø…߇étºoÞÿm·Ý†/Ýv·¥ý&ŒökI?VütáÎ__§|P—ËbÀG ™§\Mëôbf5ï=HyQ oÑ¿-tÖPEN¿ÖÐBš¿“¤F¡Š%®ì'܈*‡íWtl `4ô…°òÙ…F?V¾W:›AOÒÓàìP–´t&¤fsê@Ë…a¶ð6KÛ½ïðù/^«^påÊr[Zk>|/¹ô)øè}CSsÏæ€œÛÈcA¤›Ïðêç>‡67ky ËDø'ai¿i±óK»V¤X"¥òeÆá¥|Õ)&q´°¥éoC4äÿ‹ÐSáæÛß³³pY0lÿŽF»ñ\ 1^V2\[ã+‘ÂÆ,4¦É4ÎRŠÞìó‘®ÊNÙQ¿Üå(iòóO¬@…ŽHÚÜæÔ2jOƒe7Ö?¡1_?ïúÀGñÜ+ž³¯ëèt:xñ _€ÝøçPƒÃŽCÑ™ˆj64…Áñ[ñÚïýGû.Õ¦iŠÛo¿_üÊ-@gÂqá¤%)ѽàU· –¡öúÌ‹.nŒ“X°øQê–àŸ.HÂ#&yiÃ~+«–뢅’RŽ+c Ê‹QX~ŠE“’¨„ãB9]³à­Ž¾6JÈF~]·®”4†ÖÚH‚l Y´Sxh$\‰5GÎÅ ŸOÈa‹™êCgàó· ÷Þ{Î?ÿ¼}W]ù<œõ—ïÁ#ÙÌ ¹©7@zb! TÛy Ÿ{]tѾ?…xÏ{߇±.Ú€oÔ¨$¼H‰k¸Ò¥¨ãVÚʰ‡ç£Om:+(e(ÔªFú49‚VFÏ!©ó›aE–ÇocTÏMØ¡Œ9©C¨]åŽQ ¹:ÁU‹MLÚfʸQä4øCH&·Å§¶øÊÑ´vP¿Ë2gXú½Œ€´ñà|ôãŸÀ÷~×wÖŠÊ´9ÿ ¼òÊgãÏ?q#vm%DzîTƸd|sȽãøö·¼ yž¯üÝ€Õû{àA|âºÏØ0qÑù'öÞˆšû#éºg?L¼$£øqójšP뺔—)Ö g A+áñاÃ!,L¬12‹µ7‹?M¡x S›ëZÍXî9&Ù^`M_·¨H)TJÐR¶žåüígnÂ[ß¼‡8ŽWŽF£^ûu¯Â;¯ù¼‘rKz 1‹jŠ;ÙÓ;#\rÉ%ûÞý“$Á'¯½'ÇÐO¼èɦÁÔZ0¸ào>*ÙWn6Å hI5µ’@AƒÂ©“:nj:pN"$F pÒÂL¤'ª@ÚkŒ¦na‡þO}ñNÃýþhWvR-ŒZ„5uÔi¸lÙÝQ>ûñϺކU¯Bà/}0:ep€ÃÑÝ{qÕ—;Úïª?NúÈGq|gX8Çü«iùÕ>§Ø}gq@ªxëã@Ò7Q@d•tdS¤³-|ÓÕoÙ7ñ'I|á‹_Ä]>ô—Á?NçdÇ©e€ÏoêÓº4¦þ-®8Ô @Ì[jï=¸.ü÷À#µ,1jD´'|BŒ:7½x±Ñ4á ûbžN°Ò…v eÀºªô|QÍçE€XŒDµRH³Köá3÷Ü„'žx›››+æd2Ák^ùR|ôú·#[?æY1€st —‰pÞ“Îß·àg–eøà‡? •ôÌnO¡ÐûÓܩ–QuýF]S”­òë%ú‹†~@ufy0Ÿ ?œôBçÅF@¯n-y˜8Qc0zÁÿwËUÝñ—¢Í„Caô§·|î·d»VèÖ×mN ƒâxuJ ¤}L{Gð| I’¬|³Ù ]tž|dìžòYц­2ˆÉ.ÞxõKgù¾î—<ð¾póFÒÑ~;¬ö/½ô‰~TµŒã$üOÎ,–Þ|ãC}I¡ôùV ^—'šøäŠ:ðЗ=ÒíôÏÚE ÞãùlÓwð÷Ö8Ã0î6Çq÷†ÎÉýäì<Ë×åÏÜÏ)½é¹¼¿¿ ÞSbÃèR‡Íóðñ/߉“'O:!ÖU¯çu¯|‘1þlfÛ¯Ïñ$¹…§>å"dY¶¯{Ç1þúoþ¹ë¯Iï¯Íú…G%ÕªËàb¯ —êÄêÆ!i½¤#Pe‚ˆ†Wòó_&X ]>7Í I«0"­¹Óð m©2§.çÌÔôÃû VÌ4ê8àîyê1>Ø Û®1üºä`E ­`­ë‘aË=1‹píg¿à†µ®ê.»äÊ·lbøù8~^ð¬‹1 ö…þGQ„{ï»×ßxsÑó_Ñû‹Ã¶Pzà*\½«b¢m7 ßÕGC¨ÖbõÕbz:Pl Þq02ÔÞXzþºZö1Ô€š:ôÞeÎsÞácµ`é’)TÝwëÕÓ¡KëJ·7rÿÞhÜÂ+=¡c;PÌvey®ýü xÅ‹¯j¦D/¨>|—=í|êÞS@2âk˜àê=¯vðË2¯}ü“Ø)£÷'þ%6ô×6`ÏÃ÷Mpûe}B4:Û8~ñ§üÂ:CªY؋斅ÀÈE!{©)Q7§2uÇâhêÂŽÈU" Ô«ïÀƒ}°LÀPDS—:ù5êнWþÆ£šï€6ôà;î¿ÿ~\xá…+—ã8ÆK®|.>{óÿB¶v˜îâùOÚÄáÇ÷Åü“Rb{{Ÿüìç ÛPzýþús´4À·?Q¯×QRè2Ÿ‘Í9¾½Ñu`_ˆØÓFŽx‰¨~ki8Á¢…¶áe 4Ú1éÿ¥D]ýá©Éiý]׬]M¹‚N À 9ŽÄÁ8…^;ïýðÇ÷…ŒÇc\zñ3qlcŒ¶í=×½ò%®ô·ê”Ÿûüçqj4·‚ŸqYï_Æe£…—Jñ{U!Öéˆ&Yp/ÇçÞ… ¯¤4þø]Z-ªmÒ\¬åˆrx(ü0¡®4â—žVà iŠŒøßcü‹*)ÇF*=ã†èÍ¿‡¾§¨Y_­Q¨[:oQ”û‡ñ•‡Ä#<²¯)BqãeÏ¿ ïüÈçñŒ'ñcÇ0ŸÏW¾_¤ôþÌîþq1 &éè¿ë”…'ì±`}é¦'·“º2`È“Á§Hmt^k­ƒd­v<Ök„A’àg*¥ûãƒP¡hhÐ ¬Ú-fêxY|Çé-Ö9Q^+eÝÀs-­×H,ŒþÂ8ZÇ?ù™}³Ù Ï»ürtõ/xγ\³Ñ~ÿ/|ñzâr{Þ6í9ÊÒºTˆ¡²²ñ–>à…øÁ\,LÕ"ܪ\â[$=td!J#Ê7¤Ñµ-ŸZ¦)~©vQ/DÐp*õíRÇ¡.‹47U®î3•(U’kÝ bN‘‚Õ'ÌûGðáë¾€¼ð¹ÖUÓˆ~ôc˜iiKTó'Ô_¡ÛLTµ:¢}QXÞÀ1'ÔöôÄõ†˜´Ç¼[{ÖqAGàïî tÆÒ¿{‘€… Hºböòn.6,*Œáü0ôE€.+Ø aÔ? _ºñf|ý«^þUÇâ8Æ—oü ¶gºIXï_k@gå(‰;5âðT’îkk—5Â!åȽÅh°E4`QíyÿA´ß7¶™h"ôÔ8´&ù2W¦åïRªÆ1-À>4OVr&¡2N-HÖp¯E8M üÿ@€æFïó"»ç*ð =§IúÿQ`É YŒR'i0•"$ûo½ \{ó]xÙ>úVy !0NqÍuŸ³%¿„åý©i`‚(Ÿ»VR¤ ÛE%¥UÕª ªk)nf-¨ë7)“R ƒïP˄ӕ¡ÈW³³»\š/Bg–û§«9ëRS“ÐÂYØ{ŸÞh¸:°9:”¶³ÀêïUâȲmÉM –» =äX|<T5Ñ‹²’Üq(±.f$:ö\^~†22Ÿ»ØÑÜtó-xÎåÏþªišâË_¾§†`0°†|Ò¯´é*{žÊ‹nDd…Ê‹º_u÷½²*ˆ¦¼haéÅÊAª ø·hñërI ÉI$i6OÚ¡ jÑ.¯ä L Z¢c¸DМ­XGÁD9ünåP¼ô§4ìˆ ²Fk1PYС™ŽÌíNüyå†"ÆÚ6tvÍ*·S‘£@š$Ý(vó]ºØMÉ"ô6ññëoÁ¥—\üU…˜Íf¸†kýó9€=WYDtJ•+i,$!•YÀNtCä[$7òוj1ÆI{èµhÈ=Yy¼—^¹pÑîéƒ{•ågÓðÏ£²^€Zª®Û•Âdžsà‘Ñ-7ê°#Ñu“qýpN×6Ú9¯µú y¹òhËœ¥¦á«ËÝuµìU‚ý¨yØÙºoŸ¯\LOÖE08ŒG}wÞ}/žþÔÓ_ìt:¸ù–[ñèñ- ´œ÷»èFX~•Ms–ªÉb,:ý7Ù’LÕ‚²-Ç sY¥™çnÁ`!`-Ϊ°(‘–mÕŠÓö“^ ²'©$Øb$%B!( а„Ó‹è¸Uô6 Î‚6R^8 Ñ5q|@ˆj†§tP@…½H瀀:7÷ÿÓ3Íg6lö…cÁœ€. Œ¯d$qŠlóɸá¦[qá“Ï?í`àl6îÿò´ïÄJ Ì åt:Ïí}€›x„þ!CÊçÀd·)§f!û2€¡i½¤…–ï$ZL# õéׂ†¡›rdZÄ„œª:=AQ wpæ‡ëMÈZ:©á…—(ù@Ç6ƒ2E "xFîš umÝd I‹?T®ÎÍí’’!mZcˆ’š[æc(Ò)\i7=ú¾ngý~ÿ´¥RJ?~·ßÿ0Ð=TÖ.¤¿ór6Ñ©Qˆºr Q™¹­Ö"ÀéÀ^Z¦TxAú*ÁΉ©?ª¤\!Ÿ—™sœ&î´íî/#³‘)e…n"Ì㮿ñ&¼üÅ/Äl6;- Îqã×}¹L ÏNd.ÂzÞýi7¨¤c@Âl ìM‹g—ͼȊEM!€´nØ WZF¡‡Ê\ª}zàƒ`>Ú^G ò…ª@»®BXt‚vCåÕQÝh%]ÍOB+ÑxõB˜bqþOECµh¦õùø‡¨¨¿V¢ çØr·€|6 ï¨•$©p!# oÈgýQX¹2,:ÔŒˆ™°Ó}•mêÂï|W^1FEN Š¢§NÂíwßÄÛæ³ATâd¢-¤[ÆÈã M(Ê GI¼­ËQQH/avq¥ÕvYH刚I<‹ÃPOè Î™Ô 夈áJO¬$žµ‡5D‘Wv ÌïR*%Št@ÆÕ€î;ž0»ª¶Î£;ÀÎN‚o¹ÏγV ©{%I‚Ï}ñzŒu\Vû‘IAúñ‰kQbò~)½«<’¡ /otÏœPe@Õ³½8¸ã¶-Ùñú¬æ [Ô²ï½!·_èŒ]ƒÚSòé„(BÅÚ°[T£¾˜hqQMm:WÝ^! ³¦Ú x$ÃEx˧Öv.¤¬öÒW.³*Y~  ?we£ •FXפ9TÆ 5Àhé¸ÙÚTd\ÕË+Œªˆ2¢P)ôæy¸éÎ{ñ¬‹Ÿ~ %AÒû»åö»ÓÏvúE’­õ¨xŽqèôí¹‚­£9sð| ¬yïq8ƒfY¹¤7öÏ/kÀî ,>ØÖ;7•+¹?o]öÚ?K#Ádö‘GÌó]²Ó¢S`§ÐÎ.š·Öe¼‚ÄWkï‹O)®“y¶E„Ö€*Ýš³óN 0pÝ*+ou½¥T€ ¾‘½Oy•^MדÍl^U£8Z3„óȈr éàÁí?öÎ<ë¬K¢(Â]w߃­ñèv™ˆ‹õIQ‹°‚ i׫) ËÊý/¹u¦|#ѱŒ€BÍEEƒÍ@:¼ÐBeš¶h¡Öenrcó¹u¡ª‚Ú#©@™*r€+¨h]Ü8¾@Rx$y­ü7Ç1*£×5²59¿(ƒZ•TÇˉ©@……WžkpP ÏshÕåÙâêïup2qÖy;' ¼h@‡ð"­Ps’s)ôÚ1|æ+·ágžy`%Áù|ŽÏ\ÿ¥‚éG?¢¨<ê›T€â¤ ’¡sã¥Ù~tXÙ@X… õµk9n–ëuÆ-ËñgÌ#Ukд£ V£m“Ç:m³¨þýìSõàbeP(Âá?o=ÕÚ’6Z”ðJ}ï>˜ÊLÿx:ì(K†OQ‰©ÜV9D‹º{A5=Р)‚te¾(€ð³k ¦<°[—²`ºNUÝü\„0†×YÇ=ÇÁöö6z½Þ¾ïAǸëî»qjw ôÄJ¢È|oÚ+€\ÏÁøü–lêõ§Ø(˜#õLðt’"iÃIâj>Û æ³_¡ •7ƒZ®w@×ÔèQ4B%µ`ÉËçº:0¥‚˜3<¡V7!˜ z3Ôdåq Ðé¬Aæ 5Úoœ©‡1êôa" ÁÈ¢5Ç„ó˜ZWÁU^ö’Ö H¶ËIö}¥t©æ¾ YT²’³¸/Þt;^ñÂç훘ç9n¸ñfètÀvÛø“ôŒáS™°¢Rÿ‚¿Aä&½!rÎЂ‚„-@rÌ'(3- )Ý”(dÁ9 Å–ÚÒNSŸ¼.šd¸ÂŽO©­xÀÙ„ÂABNC‹±)÷WåüŠ3ÑúÜb EéÐ>×¶HøbÑÎím¢Ú1WrP9‹ºPÃÆ®,wÀ+*¯OEå|üþÔ)I;$_MAIj>ŸÏ‹ÔBxkEh”8ö¾3¢Ýóðù¸ûá›ñ¼½=¤iºr*Ç1yäQ<|bÛ";ä3í^¡ÿF£FM¤ÊÖE>g¨*Kø;5á¸Huã˜Ïª]‘ôï¶ —êßÁ®@¾q%=¿ÃF'‡ËD~zB¥‡.ûÇáx`Ȫn.Y:I¾•–^éÕž½ãÒ-R¬«©ãÉ˪òkݳq;»d•žç/ '0tý´UÜ5çÕNN•1Ì眀*Xp‘åPœÊˆ¥(P÷©¢­ \U`+=Šû|OÊ…+;¥¾|ó-È“~Qö#Å_ôá"È€p'˜iyh2¶ë´³èÞ¨ÌðèZ•/À*mš1QPbùì;ŸD,~^ü|hp"Ÿv[Ú¡u9riÅù~]}‘!¨ÌÖ”½î·º®ÂÊgþ߆£¢aù¡°ÃMt9¥RºÊ¼TcÉ-0*}¨À%õ^°hN–Ù| ËIÆS}œ˜€ÐE—Ü|fÊZ{©bˆl]9QýÃøÒ÷â¢'Ÿ<ÏWbîîî⮇:ÛO²ß‚—~k»btßR%*/6Û!"Ý2žÂéÅ? °*󌋂òð±…ò¨ð«Kêþï'BŠœ'ÏÕ äÓ˜cZ}…hÇê«‹jÉãšÀ[d„‹ZKiE¼WÛ ¨ù”&ÎÊ IËë%À_ç,)ÿ·á±Ö& î&À|Z4ËÑ"®tá@„fè¹óOÌcœ8q›››K—Ó4Å¿ôä(¢ŠrçŸ,¦—*Âý’R’*s"ˆ)H;§®["èÉê&‚Š ËÛB ‘¿Ë-|M©A[ rÑå³âf•dÂ}ÐK³\Ôî>­HJ a~Ù­’>ÕÑw[Ðy³r‘1ÈŽ×L+Žì¢Ü¯ˆ¢’ª\’º¤*í³sÈQû/‰"TÖÊJlÛ~ûù¸Ø ¨ÇG¬ ‘9©(†îlà ·ÜW¿äùKÝ )%¶wvpσé  üÆVí‡ÜBÙåúYý‡7Ë1J€ÎÀ\k ï`d+” Yîqa×WwUn£mœÅW£Ú£Uónèg•ò"¿QÁÝÕo2ñÔgê[0âñ*‚éñ+HH­;¦”aŽ{¨LÆg p~Ïé]u¡¦"kÎË.–™’øäõ7Cç94qÍZµ Øñ­= sÔ̵ç unrݺ`‡€,ý‚è…*y¨±•Úêµ"Èfe½}Ú8\[6«~ ã‘'Ç©S§°¶¶Ö BàλîÆ(@’_2.7ùmá.ÜÏ‚¦Šã6òIû¦’à?Gb :ª¦LtÏ-87Ê}‡rÛL¹¾¿/£U#¦áY›œ‹S`KçäyCž÷Azè¾ ìô¡’[ŽŠH%B`¡n©ìÓ [P(µ÷Ö‚c¾¡kð ÞS“NÌ=·ÍGÀt ˜îó¹1š<óz+t5¼ ` :Þ`3î¼–mjÇu÷VzŸä;¾xKÍ3*3÷nnkå<Èf¶Œ–Ù]ÙöÖ;£Ñ…ˆŒV˜öŽáº¯Ü…#ë=äÙ¼Faªúxä c NçÏÓüwd%]iÈðß$/ž©L M8éV¿›ÒúŒÛ˜s“1ÛÄb‹øšrî¯5‚ •θ†v^áìÞƒ„ ”t ¨×¼Û´âj_Õ'0vKpB•CÌ@‹­` ¶Ân ô²U H³4GÇaøâh#¢‘y|Twn•"©WCŽ;P:7‹—Ês2fKSATAÅ(1ùiló_•%Í"Kó !ƒ”ÊpEZØ¢6Œ&£¥ü;µˆü|bŒÅ!è°ŸáŽ@Îb<|bdŽ•Í-ÿB×g¢µBî‹:þâ´ é(f Áûʪ%œ %&¢‰;ãÏŠ289¿ù§Ô¾OìÉȦ•AŒ*РRã†T§÷Ãצi9n—ñ(œÂ«¡‡vl÷waºí öó# ¥¾(}Ñå]K / eç_×EŠEI:À b¢\õpå?vJ×bE]¸Ž¢”ÊØì.„P^­u f£Ùìo¡EqQÿ&Œd  ”ÅÎì"(ÖàCÏÐïàkÊïÚä­´yVìŠ$B¹³Êl”y»c^¤&Åέ2 Ò¦´ÆçP¯ˆXÔQE6dÖ°†¸ñ{ÀqãO:UçC•.<ãO€æ)•=mu .©Öߨ"mb–6EæÙðÈG$(ÊÙw¨Î!"¯ÎÐLîk) )@ø ^¿òt x7/Ž”ó+8Ü„=ÜEÕ~¼Êð‡ÐT þ•F&ª)wDaD>u;”bøä®^ëð¨ÌëWÊþ{lóqÅÀMž×¢šz–ư…úE¬Ñha«sqáò¹‰H`¬ƒ.ŽÌ–•69w>+¸M™vlºnu²ÎÅJTÃt¤´Zvý¤}Û'Øùé|J-×yÕÏHê ,b•<¨cü¡ÈCÅ‚.ºe5ïÛ` ¥Ô@" /ô%@:µ\ɲñ+Ô¬ÃÊlÕcªGYèª×-ÐdøºÌ„ §R2`ÃU™õô ¸ëqÞ.ãd¯"Vÿ¶ŠÍDnQV¼B c\PUm?Gìñ*#¡±ïþº³H&×…ä…ç¹¥Ù’Ò®L,D®®u“=ó~º_Z‡#R9¿dúNCÒ×JàÍmLç ê˜]ß_¿D Êçe'N—*¤C”Hnq9Dmªû‹ªzoÝûu q϶RXÁh sÊác¥Já£ôz¹ê#I©WÁ0mRQv„oœ•^`°”ÎÀ“/G »pQEÀQ¬sýçotÓ"¬•(X$%“‚àãc J•?²ŠpJisÆœÅÒý¸¼8Lýឯ¶"ÐÑ"¼‹¶ÞYûlUù\dØEÙÓrK”š¸‘(U2Rþ%ÛËšsàÑÇRJ€¤ W´®V”*;%è¡ Î'á’2‹¢¥‰µRz“%k@’qo¬Ç&/&ÂKœ¢c <¶Wʲ†²z”‹ú%ê¢8âÊ«ŒuÌ)/oß—g¦Ï@ÅVv,Ô¤ÃlƒRKÞZ*¨àÁ¡·(øÔ3à{–»ÈÉ/fEEÃïMqÆ/«›„S5C:›qPJL4G Ëz-SˆÊpP¦/§ëH7ºÜàš8ÛDL’Èòæ{¤ë†ª6,Jn˜uÞ†ÍçògU@+ÎÙbþ19/Øïe&•^¡Ê5fß‚QwΪhÃ%0›Ú²]Ð#k¤ª˜è ‡4£vŠÊºfÎb´ZåE¶ŠÝ+)Œˆ=é9?âŽÓÃ6zËÝ‘ü^S*’ôÌ=)žÖð}<†W ò¬ ÑÞ$¤(-¸¼'žs¬Õ·ííÑ~s‹(׺ÅcÁt =Áó\ê£qJ¹'êiä’ ¨f¢yBqÅyb›~Þï&ר€@ü€`Sˆ*ÚV9±Ú} äGQ^Îôåm"6­6*xy/Qì¬Ü¹h‚EÁj#0›OÚ/È;¹×Üã¦!¡p6us"CVxKŽš‡å;*¥¿"\qò«" «çî1‹DŠŠAlÅ@H€BxŠT‚zÖÉäT¢ ¨$¹ÉÃ)Kcób3Tеû»°nÉí/¥(æš#”³z‹°4¬«³úÕC)оp¨™#ãüi_\Áa:¬éwœ6›(;œÒð akøm¢YT-üA&|±ºé¸rññ¨ôÄÉOÜ*_-¦…cqh}nÙ}2Ð aoBž—Ù¦<ŽÙû:›8í››OkŸv7ËYèÝe²9N]‡õÓ“È UmJt¿ˆP™1>c£Ÿ*U˜RêUÐYUÉÚ·—óÏÃ5×+ÐeQš® _Š«Ê¶/À¦>cKø¨t`BiɨÓQaƒ®Û«¬jSZ”¤žêåbŠ>š.B žíqÈyžNuÙ6a;¡å$ñ í†W  'já”ETä¶¼*B“føt¦Òp Q%(qœFË‚o.íÒÑ¶Äæ§¹Õþk³‰A‚=[¬oÎw:¶×HܵƒsãôK‰¢Ã„6^±‘Ò‚¼õÖ}†ÕÕÜ@eŠÔ’ qÏ%/—KæyÑ32~â4Ä]“R&£ó2I¨p ¡x¥%Õw±ÉJ›-ªO%N"aà^ˆòé?D•™Zm”Â Š‡8>ÑÈ ·i£ Lv¡`YV oýó¤Ð•ƒaZ‡K‹RZϬ¼N”«DÐá%·Ðu¹T ¯†éþsÇŒ°pT¡éš9™raž¼|rˆ¹®Aî˜Bé@ž³1(³»‘ùï|Väÿäø3Uš9Ól‚Nézý|?¯J¹s5^DN{¶4¥×åòºG ›šRaŽES‰Œ—~•°_ÚªWU„âPŠÆƒ×2ñj« ¦¿ï=%­«l1˜ [Ú¥uY0~Ç—$g5TG²Þgºšvë¸Ò2X¦Y/xÔ„£ ¤)Z©ÅB Û´RÔU Q™(‡ŸêS]ÕAti.v")‘dYQVãQT>tÌf*4L‹šò̽V&è€y\Py–*Ÿ¿òdÛ|£ãù½Ö6¢ª‚-vóÖ=­­(jÆ­‚˜„^,Ô" ©Ì:Û¬ÿIû†ääGŸôy]ÎâJ9+4«¶œ%ªDrX¼`ëpœ ¼CñR´ibÑ5-µ>J ªù.*+é*ó®T‡­YÌ%œ!¤1Ȉ”Œ ô)ðû­‰Òî«wËe\´M ÅöÛ—³y’kXt¡2»CÆvâOÆBs|©¹Ç}hpp|–_n)»yÎvµ˜l4`Ç};)U–‡( Ãú•TaЪžñ©ë–?íàq <äät8:^´ë;v_æ1&½hFF&ä?¼!¢q-²®u—È/ªš3·bص.3”m@{ãÀIB‹0)G¤ñÑÁÖJ¯©Hk@Ø(^-¼½'ðÎMK}ï„` À„ªz…–%q„‡à)Â^J%ã‚8Âs^"-9@V™Ì&Šë•¡¹DROÍ å¯¥];TDùùÐwП䆈wl›ï¤ ñºãZGV¢gå‰PZ[ð8®®k¿NÎ#Ní á µNÏ84Œ¤´ã3ª3Æ/iòêºF0düÒîükåŽ?…¹cè& «a2jòp]#†¬†:ÐÐ]/ Àº(4³Z‰9SBCÐþ·   焆CVÞÛ&BPEWx“c]n¿ ¿W y•ËrZ˜wÞƒQ^(J=èm^.lÈ¡WÐà¶ÆÊ¨·’9:sÀ¨® Wp'ê¢ÀÈtÉås³È¢ŽmWá¦Dy`iiôu‹tÀAª‰ÏgÆÁ$Sßî­™]:²ÑÂØ{‚•êh|ôÀ?rR»¹|„ªÓ VpŠ=¯@P?Þ6ÇLzfמ€ÉÌÜC®nUù~OVHóùî‚¢š¥ %‘0"P£"°7½—·]Ö¡¹R6 ªž¬6²X ânc¿q[ç’Ó2±uV¯ôW “ò¢‹­14,RÙÝ)P2ã¹–¦jƒ\ÜB-¥Á$\$@ûéïN7^­Pë-9KÑO@¶ŽÌä—œ”2»0±ùâÔŽ±žÚJ@TVdΩ0®w̕ʆ,SygV'?í¶[WÁl\ ”ø õÌËC6ymßïí(ƒŸDŒsb6gÑ]+ ¡ð°=›»6ïQFJ”c*#—“t¹¿¢»f@[¡©Ä'q °1/¯ºQ' îsÛƒ ]·ˆ6€Š:Q%Ï’ñÐåg5åKQ„³Ñ =%Ùf&¥(†3„@W~ý2f ªî¾¥²,3à¦ô…€Ò|VLå)ɟ˲N æV,#Zíq .3‹›Bt!˜._ä±mêà¦5ëšù >_@2>¿ÅH|3éÕœùˆ‘–d¹º¥ØºÐ¹ÅT|]ˆX9χµS»Y“>¯„Iw¶Di“‹„òbŠ‘öJiJ™ÎDé©:;´`Œ5Àªš[R£;ëjŸ@\ÍçùLÓšâSkü5;~è,xÀD(ãyó|†"ddwN26ë JL¾Ÿôê7S57Q•jCêCö=U`½`Gh‡å—ï@´Wjk¤5„ž^” GW…;¥§˜›3¸lZ}8còJÈá±Î?_ì³Ývõê(L )¥QAþQžàªÏFÌç¨ðúu AE&(Øîg(éÒýÐôY¨)qʳf!vB“Ê€éÐcÏs6´ÜuÛ£!¢2ÁªxnµŒQ~yÝ}ÔPD¥s©ˆ×Bëo,*Hh©âT¼ßMÁÅkTQ~ ñù9ûÒÍ4Táu)¯½ smu‚/Ô@ŸËçU~‰,DKâð¨¯eÆy¤½ º‚m >du© E`,˜¯cÀ©©tC*ÍJšÑgÙxó $Ó¬D5Ñά”*í²!'ŠÙîp¾×oËë—1 ÔáYA£æN&çF4“â ä•Ü¡Ì'3MH#6ªl7Ÿ f­¼H›ò|ñ5h]Ö­”ÒŠ—0š2ízy\Poã”!áyƒAú6”{J*Ñ[À9øb%›‘]g9À]Ο £¯ÝH©p”²á NMWW= ?¼’n¾Þˆî65{>UH—kݺ&¥¨TüïU/­¹²1¶òª'VœfÌFWst½v±×w•<“•¨_ŸpBð‚OB‘1 f^ŽIÝQY Xe¬¾@•ïúdŒ–jKF!qMØ6Õ GÀ—gã”^»`gCs¾ë¦² öðÙö|Mä"6ñèµ74ÓvõQxœçÅŽYBü‰±È:ô—WNYÔ(Yéš*5|”’˜¨(Z„«¦¬^C÷XÍ€YV‰”A™†€ò~d¦¤]‡CÅåÊù;ߟ1„eK}KžsÝÂlÜmE¹M h¨%ƒ.ªCWÕtI¤’Â¥ Ô6OoøCŒŠÝ&tiÄOpÀ¬¹/5u|ÍêêÈYsló™Ù9*Fà R OœšU1Ÿ²”€ rÐ.%U¡QÎàs=1sNT èôM ;J X˜Ï̵¸É¹¬¥;g­ÝAl aj2— ‘!{Qû29mg4ä"ò¡ŒÞËfKéÊén%u”a œìŠ$Ùã´H㈶L˜ |¾µÅ“csš€¨r(b Ê2Úq\nIä;¨ÞŒºÂ×R7ŸŸ2¬ò ÍâÓŒ¨Ê ÆÍÌGSÊŽQñàƒ;¤.„×Ý2VÞ(c³ÐJ“Y8Èc0¥MJ"RKQC&Ç•gEdC¸5ÅpcÌlX/<í—7šN»ì¸ie4JmIçž@&‡q‰Šóµ \6ò©©ÝwÖ¬XElp¹ŸèÑX°/hвæ# y:Æa\v¢°Æ"óBë³ú4ªT`;=WZnÃ-‰×Òœ@’N·CTü4ë)2ã,ÊùÀ´x†~-lJw‹ûÝŠ Ì©ˆ¡:àÍ|ÒX…Þ20ù*š€´ )U3瀅¾n`bƒªkyêõ8ÉAÿš\´„bŽ»Œ=ƒWÞý¦§•zÆÇùy¹gÕ®<ÞRÍw,aQæùÔ6ÓV60ÑEÈÌ)½¡®ËÐSz¡2`¼cË„6%v˜g6/$¬% ò(Ç× ¨æRä6×ç38Iã/"Þ}^„Ñ|5ñ`ŠM¦èzçÅS 72Ü‚¯ÀôHøH÷‚o.N#`V¤4Ú3þ„uRz¯° ˆ¿ãq¾»¨™ïÌÛC¢A >Ò/ªÁ@IöXW#îTMcSó %vU .„À‡ÂÏ:Ž=T•UCÓcÆ bQ奣f’IA½R»¹ðË‘³Y1Ÿ/šò4LDÆà绫 ÐÀÏ&6lfZ.ñ0¦ùy”:(i,qˆ§¦T˜M AP'bëÙŽM—¾×þLGEÙ²Dû•^Ddù¶çE…À©±u§4GegÊs¤—ÓŽO(?U%ëÌu ŠFefFv"­D¿syÑËƒé ¼‰©¼&ÐIÁWâUÑ@.‘…¼n¶J±¨§ûÄó.WDõ- Ðç­Ë’a"08”ÊŸN<30W/ÔLãÐè€p×'Ë‹6ŸÙT F9GxS…¢¸èðrÎf^¾úlÞ¶¢añ Õ³©Uîµ)ÊlÌJ˜Q±;*T@¨F^¡ô¦ÅdžÜvøÅ)Ð;d9ýCÛÜ]4óOæFdDåÕT•*:ÙÄ:tV"aÕõ˜¯Ã(fé$9MküqH8¥¦ÔêGÇ•ûÙ¬*¼kŸÊÖ}žW904Z,ꬥ³VTEüÍ(Ÿ!n•ƒs½4ŽÈs….´P «¹3?Få¿Ñ<Ÿ¯4úX”ç¼—F‡5ä÷®^mw¨@/¾*P‰ˆ„‚¼6û¡ÑV²,û:K}¢|ÞŽÇPo=/§Ž6+”a›­#Y§4ÛH kþœ)«ü£Êå;ºo2*ã.M¸áù¼kó´þ6„ŸOÌB§1cŽì£ªy5ÿÍ[€ýC&ÝmY6(o(·¥›ÖClŒß/&Í®™Cu6ÛÔü±ß•a»|²»Èø‰=šÍ±¸—´NL šëû¹nh‡¯5Ì€ºP¥3L{=Í^îGážôN×íDÔ #Pžd\Êíí›8 ”%’2)ÊP>Fâ³Âò¬^Å(d´q Ì™ì¡ùjæ }‚qÊ“jÇ[ˆvMl¾lÌ&póé ½W¨ ‘¢­ûårê1\•')v÷ÙØF¶­¸»nþ¤hÀ©?%¶ßß~§ÓM±%E[ã.vðyqÝ0š4”åSÔȈ/tl˼|`œ‡~dቨ2ƒÑßë „´Ä¡~9b+¿kS€EÎÀGü+sTÁ,ôk¶ypÑPÖñ˜„äý¹ÎO H·^{à“®Th¢ЉŠù†Zo Àùÿw%ËqëH Ù-ÉvøÍu>a¾rþwnOÖÒM˜*¬"Èf[’Ÿ#t°­è…$€ª¬\º@eÏÌÓ5,  yxrÂ¥hj=»½alìÉmGd^?Æ›°åž´Ì5Iiˆ¾>ï€[(é£T××òãcùü——&¬ÂbÃu«¼þhzä=ÒÐÐF£ËE¤ÅW‹ Mê[Ç·ÆR{áôÏs ÅýzþŸÓb©ø–ËÆµHÄ~ôûÌÊßÚœf³Ü•é—ú“1±ÖXs)ûÁgɹƒ EX®ØîßÿùïǾ‹ßþ{or°¼Ñùô™#¥5áY÷Ÿ6Ì5{ɶY¿~ï»$;V9È„ã×@Èåêt±”×DÜñõÚ‹¶BÏT ùÞ‚ 뇺¦yÄ[O«iM2Ùs+ù¥cßaEª2^õ²H%#§rÄŒ|¤ùwÖNÎm&"Æðïö8ù¶Ÿ¯ßéDù~Áí*d?ëT‚lš7"é¼×xÖY Aíúª¶^ÄBM'0|x'ËûïìÖ´ß”ô¼ª&r?å5·Y!ö=µaÖòP޳Ú# dGÝÓò½ Vg÷{ÂÊ ˜qm‡¶ Ú™þ¶< Ùr•q™°ù&&ŠD-v¢ڳ¯mÌPfEóEÄ<©”桃óTª…Êrôm U£½·É‚Ä<¢ ùŸÞ…¾:Ñ,ãIÌÅU  •ÍÙ•ŠÈÏ&©X¤µ.r&{”çzÏà CØ{ªê´ÞÀ8åç–h.ŠTzZ ›6l¹––†´ÌÜz~uö¿Œ2pÕc{ýà ë™×vK+žH#n²V˜uÝŠ`;õ¦5½ß«Ì¸áF¨!ÜÄÙ2ÓX&%Ü“W–àp#(‚Ø|)5+1dÓ«~wlýÂu7°A„(ÓKù¬ß{ú«<|WÝa¾SÉQŒCQö,Àl RMi’V%ÉgELXB Ì?êHìªãé²£€æùNxrØÊíØã[Šð½ë†ÛVÅl=¸æðâI°áˆ;…ñ ÔUSœ² |¼8xlfŒ«jj`¸ûiÑ~`ô˜¦õ…\U ¦¦ Õ a>¬7-žÛ÷:ké‡Ó‹ÏsxŲv’A©î&' Âð^¼ù<[Yol˜¢lñÙmÅ.-Í»¾|–F±¼x•¼änOˆ¸= &‹ST'uÑ:xÑ7bÍܳxç ÉÌ›}Ü„§zoª4×Ìñ~‰hÈiÑòeÕzù÷DîÛøXHTÃI—ý|ØçÀûÍS«’k:ð§¯û0…ì×I*`«$OV]é$Ã9¤ñOÉíúX¯¹êª#äŽxrny5­ G‰“¹c ª²örk®„ßÉ,;ÁÃkÍ=‰.Þ¹èn¾MfG1ލÎ8Ø(\cÙ¡Œd|†ÅQ|½¢xÔM—¦íøÑißþ6Õ…§YþH¡$¡KâÛÞÜ"Z²`¦÷VuÀ: ,0ëe¹‚™äy™ÅVaJ”À佡„oljvs©·¥þ ¡+‘§÷Æ‚òŸ¿QËj< ŽN—†ƒÔjC6‚0|ÑwæÀÙuP~²?Z9ê.oðx „çÇÙÿÆûòŲ­$̉=_x"ld0øBsÙÝûÎŽNÜáL)/Žl¹Lï–áqÚ¨ìVi‚M¾”ñÝ鱜Ò95âò휠ÇI€OäO‘‰ˆ«Üeú¢ àÞ͢ƵŸu¾Ç½¦ ïÆ/:œƒáD 7Q÷z~Ð3ÚùR”n7£ÀS»Ñ^@ÇIJÁ€MzûAóÀQÀ†×m1Œ7ßp*Àõµ<,ãSù?,̺¹š><®o¾B¶Ô8=ˈðM€Áoåßž¢soÏŘ3QH’¼¿š>”v¼vžƒ²ØÊ4;Mbñ@d §þôj+ãÑï˜ÑôïïÀzþÆgS!œúãƒñÿ7QgÊį§ ¦õýb àÖ ]ÈÃÌk ¯W¡äÃ}Α€£º|(ŸËS9Uû¾Øú~Æ"ïàvÃq_šœ×¹V‚{j1VƧTø°=¾êáèˇQsØüÄûõu°§¿zȉž{ÀƳœÂMNHDä(ˆÄùã8c.UêÛÓ@"žÈü€Á–ò¾S>“á§î­å°~úãÜ®iŽ: .Çü1œÉvŸžUL˰:æ¤FÎIoTÚüO.üÔNžCknO}6oˆÃÌm Ê( è5Z.2zr”ëiZil³ÖÛݳ]Rl‚¹("eÁ³ñ'ŸX™ËÆÜðЀ¯¯ÍFÚ¿‘Gl§Lb.zì›6òáV³\{ýÛ¹óÜôþ!:wy–Ô´Xp%1fÒ÷ÜW…¹-«Å XÁ5€nÁ«¾†ðŒèq¶‚RöŠÐÝqaÇö¼‚|Q"ÒdCµ†)NoòÕ4µŠµâgt_ÕÆÿ ‰ûð<·¹poñ×ùígR2oüA+`BªA¦#×pí£ëSŸ³îõ˜Î çèí2.N'ÏB”dO›Ü‰#CŒ>q¾:íù»8åJÌÖ2·…YÓ˜‘r×Ü­7ŠùæLààù{3Ÿˆ¯Î]Þš1k¤> £Â0Üß8" g펃 ³ö½©ŒC°¶¤F5È fšm¢ÏítŠm¿Õ¡á’¡× ]ª!Ñ ü¹ Ö:ò"¶–Úý¨ìƼ=FCÚ8øP|¤M€îú®éÁØB\kï£ òd|¡k½.“‡é½ðÕQÊz ÞNWu*˜æö)½èÕ¡¿ü*xý×W}ýÁ€ƒÄº>|®9¨Ãi.UÇ( ¿0–÷ǵ ÂH¨(©hµtLeÔfêõô©& ¦*X:‘gÞ•WŸëzb–om•ý^·•Ž8ÈŸUK“6-MÖ­21KÆñ(kí€'ƒ–áô6€ZîS¢-‚2¬Û+SB!{õñ÷ïÞ`ÞzÛo¢Î£sQ$¹3·ç|½yjZìÞI¹òY §HpÓBgÖ‹v;ïã×§LÎT sîá‡s?ÊÃÊs9åX¯C×]67U±‰[$¨ãü­`ï¿Ê†‡€ŠêO¤gÇ þ‡s"½©Ág/KðlÆr‰6‚D­•V¸c“ k±ß«j+Æšþ£^kãûØsÁr&ú¿j –úb¯ Õ…TgÃ6Ùà3Ný¹Å5ã",†ÇÍ#,O ¯>~Ð×rGÁî&àKÿ…~’­²!Qeÿ€ùÚ°½1ovõÄ´(‰9ýµõ!»ëŠÚ;-ÆÊƹ ŒÍ/н” àá‡ØJ½5ÁäÀà Ànì0îBóU<ÿ&ÙN…=x})X•5àciÿVÓ‹ãþF`yñn#ÈUåfCµÍk}똴7âu­óÒÔx¿ÖT&bhk ,-¸›a€¯?¢‘W)÷q´Ó“È„á ¸7–øÐ©?™t“¬i°«çÛÜØû/(EŒ/ž2!Iôa+2̽¯oDW•1´5',¼ñvåbÁ!àË\Z‰ê¨‹ Ú$ÁC`ÄӉǾG_>W„‡åóãûUëïTxôlš†Û‹€«'ˆO¦KyÝÓC#ÃXB¸ÛT!ÓB¦–©q&ØFë&¿dëþ˸å=/ØÁõ…7êÔ6Ï’M¤¶ˆ?O?¼Ó§»ª üº-éàöÞ&9ÆFf>¹oçŸþPíõ¾”ò+£rp¿Sîß=÷·kѨ¹ºüCZî|àñ‘ÌÒc¤ Iôéáþ ¤&Ý„L`d"„Z²;Ì/ Šæ*œ€´”ùñgy¿ëk;=ÀG¨f(©yØþ7÷,°å~ç¦Ãiî?ãƒsá¯òžÓ·z£ð“(IKæà@h x$|¦2Ú‘¼Ú§µk3±¨çý×k ü íˆs]Må¨ë’Öþ˜"ËkÅ~t‹8lzÜÿ6¡‡J*…4ÒˆÂ5! \sÂW.|§û¥E¹ž) ­@j€ ¦ÌÙ}¹„ oÜu]}YUa7”טs›Ÿ'b…Aäñ;›À$LÃ÷çÂ'úYÞïýYª7n1fR,çÞC•Q¦¨¦æixz°õM»¯4^÷ñaîO 6süòÚai35‰9~€ïøý­pž;§ÊE/µ5’L¾DÈÑô'oU,¢l<“d¡5v!D .~hÃuBc½%bõUYæð¿Ù¼?¨éï´* Ûpñ š Té›þ¾M ¾ÏÔN\ŽêÍ¥S'»áÖ{àºOâÒ‹ò"Tè½™•É÷r¯…ä L˜aVAѵ9 '{ ƃŸsfGªwRÄ–þÇÉý*×wR†¼[kY¶r3{6^¾“½Ð³vSA§æuÙ[AÍô9ÊÌäôZA”‚ãy#Ü1p«Øk r3jDYñô/qŽ‘Q'®!ûp(ù’^ÿH/h¥QZq©å;7&Æ,ZÏòTpºS-3f‚ÖÙó9‘ÅU^U¶ߊcçÉqìXj‹1‚D¤I­U«áÂÁMÍ9e‹ €kžD]¸ˆûÏH€r¾ªÚ4”Wß›7м³ç[PÞô¸…ñx[Γ³ßè\‹/7¼)P™–õ‡gÄÁÈ„7Ú–Áq‹u‹Ïö\l…œæòqÒ ’NªEõ?±ð‚q¶·õA_‡óSaÓ奎œÝTTxÃzÜÙõ÷<Ëõœ¥\>=È úNb[–œÓR†·®wtî<4{¯Ë/ç~ ¯,ê>Ä©#£¾Ò’iJÃY„ÙÈhW“QXÔ# ñ55C“êgÚ©§nOÖØ#g¤LÙÖý¨^«ÔgåÚèùæ,ǰ–ÝÖM~KâèiTàÖׄ7Å%Éú¹~ƒÞØxÂ0}'?œT‹T>ÇÿZךÅ3ïtIEND®B`‚pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/000077500000000000000000000000001360567320200210535ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/channel.png000066400000000000000000000154651360567320200232040ustar00rootroot00000000000000‰PNG  IHDR¬¬æ1GØ pHYs  šœtIMEÞ  + `}tEXtCommentCreated with GIMPW¯IDATxÚí]itŵþª§gF#i´[–,$Ë–%dl,° aË!&—ãI€øAXœH$/yJ„¼$l//²€Ùbìà ‹ƒ°¼°%&Q¼Ê–,K£Å¶dYKOOW~tL„g$Y£ªî™®sæXÌi¾é{ëë®[_Õ­K0†V_« `*5æk@¨¾þû:ÆÙ\<ïHñˆëÏIxÄuŽ‹ç$<â:ÇÅsqãâ9 ¸Îqñœ„Gâ]!Ý]]=ûöîmÏwíâ% Ä»¸¬¬tNnnÎzUUAïoƒs]×#†a„´oåÜØ !M>ÐI) »çâÄ»¸¼¼¬6??oÃÈ Îù‡ßB‡üíþÀ?l¶þÞB)5ÜÎsñFâ‘xÏ™3»TU=oO2Yãµ 6†ñfKK[Sooï€Ûy.^Ü‹UÕS,‰¬Pà Îù‘HÓ¦MEiiq‹að†ñw¿ß÷üÒ¥KÛ\2¤©¯¿uúá.fŒà d+Þ./Øà/”Òý.R/)?.¬P à ëÆØfÏø €¿RJ5— ©‡§:”¬‡kÇXŸïè`Œ=à‰††Æw]2¤žš"dÙJÜÈ9¿qöìš]<7<¬­ommûç†Kã©)HÖÃP¢ªžËU5pymí¬¼^ïjBÈZïºdp^\&$št9…¬£àmð{RJ;]28oÜ„M²Æ6 ÀS𥔻ä²/ž’ŠaÀ8ñ|–xÀûŒ±ëcÙ.¹ì‰§¤9YG¶9þ@ûºuë~3mZÉ).¹ì…§Œåí›&dÅËÖu}EnnÎK55³î*++ã’Ëxj‚ëüiJÖX<ÕãQhnn-,,x…r;Ì… —\’ð½a}iNÖ‘x ¼È{™1vªK.9xq kFÀ%ëañx1öcì.¹Äâ)ñ.˜ê’5!Þçü1ö'ÆØ<—\’sºfά¼Àï÷ýÚ%똚ai¹77446»äš<<%ÞÅ„Àë’u\z6圿_SSuo0˜•ë’krð”ø¯KÖqãù<ÏÕeee¯TUÍXLˆqÉš\<5ÞÅ„Õ%ë‘á‚b¿ßwç±ÇÎ^NY àm—¬ÉÁSâ]œ™rÉ:a¼OøcìwŒ±—¬ÇSâÎÆQ]²&O™±™1¶Ü%ëÄð”û]²&o*€ÕŒ±gc.Y OIp±Ï%ë¤à ‘1öuƘâ’u|xJ‚‹}.¹& /à/¯^ýÄL—¬ÉÉézÀ+07yçYßeZ¡B€BÎy±¦i¥òÍkHž¢"UUU—¬cÂ;ònUUå÷vîÜõŒKÖÑ©¯¿UMæv—••–˜a}*­g¨Pì’õãx‘ˆÁ:::¿Û×××ä’5aqm"?Λ `€c­Ï<Îù\]×}nX¡î&„\J)}Ý%k’;ÆdeeN/,,<Þï÷.PÏ Š¢Ì÷zÕ‚4 +"nðCJiÄ%ë+ʘ@ £³¦fV€³aîŠ:@ Íbà\B)íqÉúq‚1Œ1€ã\à|óG>l)·XB)ý›KV8ÑÆØL˜™®ËÌOñ Û€+)¥¥;Y‘ uºÖ¬YS‡/óx<Bf§ð„íßjhhÜ:]©aLIÉÔ™Á`6 2–BJSpÂöZ[[ûµ==ûúÒ‘¬ ëäa§®n®à WX˜›ÑSaÂf¼£¯ïà{÷¶o†[§+õb$k£É W!E-8Çþ¡¡¡»vµ<íæt¥h@ÏóZoÛ|2Ô²’Rz_º5a®T‘cÀ¹0Ï]èpuøOJéíé@Ö‹aÓQ*©¬¬¸0#Ó•àduáWVÆ–ŠJÕ‘“¤»®••§edøoðù|ó,…=`Åá–sÓ¢NÒp‹[]ÝÜÏø€ã*…­piluÉ´ÉéJÇ-n”Òg,p1€JaË<Éó§êÈ·NWº‘5Žªp €Èu˜öÚ¡C‹šššH£œ®´%+PJÔÒ{Ìð¨5#wŠö)Uõ<—™“jý«¸dMÜ(¥{(¥_‚¹r¶Ý)º-!äIJ²²ßff2R©?—¬ck”ÒWC¡®ãÂ9v‚n«(ä”ŠŠ£~;}zyoªô‡â’uìx¡‚;šïß¿ÿ™†Áßp‚nëóùNËËËýct"æôþžÓ•*x^¯—Ïž]³˜rÌlb»ë¶¸,Ñâ‚úCqÉzdxápxïâÅ‹ï¶d°wmNVø€_YKÓŽíÅ%ëÄð(¥[œ àÎX%Á¦ºíU~âäþ .Y“‡Ç;æi‰ÍuÛ«(¥8±?ˆKÖäâ1ÆŠaÖ°=ÏÆº­à|JéóNëDµf3”iZ˜ôôôd ‡# iÃC.Y’–¸ ÀmœsMuÛ ßA*ät1Ǝ眿Ç9½„Ö§@+€Ý0×àwhO÷BÃO>¹Žêº¾ àA›ê¶­¡PhQ(ÔÝã”þˆkåÚµßYv=ˆnûö¦•prNWYYi]NNp½€a¬ÀóžðB¢£yœVXÇ/}ÀÙ‰¬1x7-^¼øgvéâæt•••ÎÉÉ ®<ŒE`V\yÀZJéŽT‹cW¸öK=לI)}ÕÎþ‹›ÓUVV:'77g½ä˜ëOXÓÐи©“zþy@‚î$Ia{, ”vØÕqsºÊËËjóóó6Ø%æÒ´ð&]? u=uð` ,2œ³Üg¶Íþ à3”RÝŽþ‹›Ó5gÎìRUõ¼m²ŽÀ0 þŒ×«Þ»dÉ’7¾Èp€?Ûô‡/''ûÎ@ Ã;çt1Æ>`£ƒÉ:«ªºšr=¥´ÓîRcìD/N§•á¿H$òëíÛw~ÝÎ9]¾"+Ìj¢äb˜eà/-·Iö„Rºæ‘I;ø/##ã?êêæÎ“=2‹°)R­¥Àƒ^bŒÕØY·µÎúºÞ&þSü†1¦Ê™ÖŸ‚dm 40Æ®?ÜÛÖ.R¥ô—~jÿ͇™I!mdÓ6…ë`e¸ ÀsŒ±ë¶·xÌ&þûcl¶¬‘)Ѥk €µiTe» ÀІ†Æ?ÛQ·eŒex•s~‚ ü÷gLñ°'|æYIø)œó§jjfÝï÷û2ì¦ÛRJ kËÂa½Çþû,€¯È£”ÆÒˆ¬ây<Ê3fL¼¨¨pŠÝtÛ­[·kƒƒ+£ÊdÿÝÁËF)ñ.,L7²Fñ!'N™RøÌܹ³§Ûm‘a×®Ö7Ãaý6øo*€zÑ1¿ÿbž‘Ždây½ÞÇó2cl…]Èý®©©ùUUµÿ®[³fí‘1¿ÿbâKW²Æàù-íñö±,4Í%ä[%ûÏk‘_ˆœ *ñ.&Þ4'ëÇd¥Dg¬J( rÀúeúrveeÅé¢&¨Jü‹‰ê’õßÚÅžgŒåÊ&kŒrÐ໲ý—‘á¿ÅëõrT%A½æ’õcít˜KºE²ÉÓ~ óLiþS¥vöìš³DØKêëo-Câ]C*€ Ì]C…Ö§æfér¦¨äœ—¦‰öOg644vÁ…Ÿ‹lP*Ñ-j(¥Ã“ioRëtä׿ädÏSUo­¢(ó=å^¯·8EßÔ;;;;/éèè Ùa‘1v!Ì´q™þûع³É¶7–°“U³ÀiÎp¶õfN‰°Â0Œ–}ûö/íììÁË·¸T¢ÿÚTQJ'Ë^UÀ›¡ÙúM)Ý/{‘aÖ¬W{½Þ{%ú¯ÃzËL†½RëtQJÿA)ý6€éœó¥š¦½Êc¼ã  Û<b×Öe-2ìܹûiÃàoJô_ €“e¯íêt•–N­³¯TUu‘ªª^‡MØžp¥4"ËPRR<=??ÿy¯WÍä¿=fRJÃɶ×vuºÚÛC;¶oßùMÃ0fB~ó,~§¨ ç$ŠßDé¶;½^õv‰ûQ.š {‰ÈGžà{Ö0ãsˆºð Jé½2ýWW7Wy\µ¤‡½qûö¦ùƒƒCÅHÇ:]Œ±™~`±¤°ˆ¢Óg$?ì‹0Y#Sÿ¡/57ïz-™ö:®Ncl!Ì<¬:›Kaœ@)Ý)ùðäçœ%cdŠDŒ×·mÛqi2íUœDVKYxÅÒro0`c),À“=´*(Ù·0d„QŠBN6­ähÊé²ó•Jéšž¯iÚ6Ömëü~ÿoeúRú€‡%…Q$ ~"rºœPcË–mýÛ¶íüb8¬×¶£n«(dYUÕŒ¥’ý÷#šŒ˜ßï÷-ª«››Ÿ,{§’5ŠÇ¹¦¦æ‡úúúÏSUu³u[¯×[_Z:õ(‰aÔ0ÏÏ•óû\ž,{'“5¯­mïÿBÀ,Ll+ÝVQHÖ”)E¿´¤&Yþ»]bÌÿÕde¦¤YñQÚÈ¥×~£¢&áMsÆYT.ÉçtpÎï“4A­ð©dØ«¤ Yc:†SJÿæªS¯MÈýê;Œ±Sdù¯½=ôç|@Òõ²dØ«¤YG¼Q^„¹·Å&dÌ,\¿ ÿuuuï×õÈjIjʲx›ƒ’’Ó…¨²M)mp2€÷m´ÈpŒ¥Jñ___ßï !º5% f"ç„ìUR•¬1¤Ý óhÍ·m´Èp cìþ …ºv©ªºN’šrÙDíUR™¬1¤í9thàsš¦m´É"ƒf¶«ÿBnÀ%¨)'1ÆfMÄ^%ÕÉÅkjj´´ìù2çüo’Ém cË%©)›¼"Iú[:{•t ko``p¨­­}çxÏ&+b?[µêáIþ»[’N½²êt9qÂvð`ÿÎùù„$“œórUõÜ,Éëì’ SÏ/)™2óHíUÒ‰¬Q¼‹/¾¨ ÀyöK$«u­º²   P´ÿ(¥€dèÔÁ`ðóGj¯’ndâQJ·ÀL7×d‘ÕLGvaaÞ5’ü÷ €°hÚãñœw¤ö&ªqPsµh@ŸÕ±]¡;š}©¢.0Æ®ð¿2ÈÓ ÃœG_tÑE»Eû1ö4ÌS…êÔœ£vùòeÛÆ‹—¨æR9Fì£äœÃëõ¢¶¶¦‹s¾Ý0ŒœóFŸÏ÷ü²eKÛœø¦¦”þʪ:ødµðü„›\-Á÷E +X§>À¶ñÚ«É‚)„)zªõã?gŒµ[RÉ‹ÖSJ»V\ àX˜u¨ ¡óà ÆØO)¥»?ì/h—pß™cU*bíU’ôã€yLÍ%V\ÔÁ{1v¥U®ÇÖ1°uÔ`m–‘´"惹ËLèÈD)Õ9çk$Ø{c,s¼ö*Iúñé§ÂÜ4ÜÌû1c¬ØÎ6ëÍv…äåÛËc ܉™z{û^‘`oŽ`Ë¡"`v\ ó\Ö­[w÷Ô©Euv°544>­iÚÓ—oý®Fµ´´½Ç9o•`ï¹ãí߸„Õõˆ'ÉošL]׿QPPðZuõÌogggfÚQ]èèèü>çè’ÐyÑv-c, 2ŒâÜ@$yV‚½çŒ·ãætõõõMV®€ªª×–——¿9oÞœeuus¹]È @=p ·WÓ´z‰{ ¦À<ÍQhÌ?<¬=+ÁÞjÆØŒñôoÜœ.Ã0<“9,z½j!äN/2ÆÊí$…57ïzJUÕg%î5øšè jKËž!;%Ø{ÆxúwÔœ.oš…Þ³ŽÕ±nK¹À ²ÀÆØñ&¨ÏJ°÷Ôñô¯"™¬ÑV`cìÞxé#¶àíp‡²Fñ®• ¦¬—`ï§ÆÓ¿qsºE‰Ži€•^ŽJ`6Ðm MYë˲²2ƒ‚í}},£J’í­züñ?”b¢9]999=’b¸SldŒ-[·¥”‚yjŠP²êº€KJŠÏlï €—ÛK"ýÙöBŽ 2<˜`NWP&Y?2ùù¹«jk«U‰©âX;‹$ì5X.Ú^kò%òáôUU͘2Ñœ®lÙdýh‘Á{”ßïfŒX `ï[úwÀ˜l‘5Ú.p½h²Fñz{{ƒu*¢à½牴·­­ýýpXïÜ¿uc}ÃÆkA›‘5Úî°RZ„’€ÚÙÙÝaü cÎiowwO‘a›÷6Û†d‘«DoÁûLן°«é(ÆX­H{ #òŽàþ-¹Ây¸û3amV­¥ÀÍ¢ÉjòU˜Ò'A§þ¬H{#c³„þ7Úý)$°ii¡›cU"É tùå—õX'ÁÞÓD>œCCÃ[$ôï1£ÝߨoX×ÁÊp·¤½k$Ø{šÈ‡SÓ´·!ƒ‚ûwÖh÷—ð kc²Fñί¬¬Xñ{ ^Ð/ØÞ²Õ«Ÿ˜!êá¼îºk†lÜ¿•£ÝŸ’àǃ6'+t]‡ßï¿A0YA)Õ ~WÂáðÙ‚ÎM‚û·r´û‹›Ó¥iá|»“Õ*yrEÅQ' -v5‘:Ág£àþ1ÚýÅÍéâÜhåœo朷B4;’5Ú23×@üƘ âNÏl‘# €í‚û7{´ÍÜqsº¶mkºrëÖçnݺãä={Úƒ„™0ÏŸzæq¶ +!>Ÿoa]ÝÜjd¼Ñ,Ò^BÈÑ;’ìÝ¿CCà ÝŸ:cn¸á:€¬ÏÃŒ±<_†YQ»B&Y-<૾%‚¬1í¯fвWQHIMÍ,ã’K.5’ìý2RUO>ªú“œ:]”Ò”Ò{ àl°Èp cLHVxK´½@F¨‘„RÚ `ŸØ°G)MtʇÅ!Jé­h¬Û–Â<OY9»šŽö.,±ÿ“]§‹RºÀÉœó§%KaK’¡º®k‚í!8ìù@äÈ©(JDät544†·nÝñõH$ò‚D)ìœxûe'c…(ê*4 £Y°½•‚ÞV‘#§ßï«Ó¥iZZö¬äœo”¤Û–˜-‚¬øpWß"øá¬HVèö%ú“^§kpphxß¾ý_SU5$I·ýŒ(²š÷k4 ~8gˆ {8ç‡y…£6éº^gg÷û„oJZd8]Y­{Þ-x$)fŒùD…=‡ „Ç裾a'ëlª?xU0YàQd gdd¼'x$!0Ï"öèºÞ'8F/H”·7Ùuº~(˜¬Pñè£æCЮ&ÇÓ$a$)ö„Ãáý‚ctf©úQ']I—J(¥¯Ø(¬àœ“ááðI·«© Vb¢À‡³PTØ£ëú~ 茤ö³J Y¡ë:|>µZY£%0÷ I E…=šî— öÄ=rU™d²qÉäå½rdi=‚Þ\Q1z^^n«µÇïþ”I&+(¥-šD‘ÕB+†Ø]M=‚Þ,Q1znnÎ! 1º/Þý)“IÖ˜Ö Ž¬€¢(Y»?v@dØ388Xq'‘Ö‹ŒÑýñîO$BïEVsyÏ'úà¸a‘aψ!SÄH2,8F÷Å»?EY`¿àå½,dSÂ~’íõ ŽÑ5Á1º?Þý©È Îù@cBpÀZ`Ö|í·þî? ž288”ðOd"„e§ü$Ø»eôqÎ M «œó¨èn‚>¯×;DŠ !Æòöio8¬¿#8Fßai¿Üê'Gû†s>¬i7 N rÎ5E!Üï÷‡!áñÞŸ¦…;ãÝ™l²Ö×ߪä×é‘H¸O×ù¦iûúúšìTÑÅsqãâ9 ¸Îqñœ„G\ç¸xNÂ#®s\<'á)®s\<'á)®s\<'áý exðù„“œaIEND®B`‚pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/channel_unavailable.ts000066400000000000000000017253741360567320200254210ustar00rootroot00000000000000G@°Áàá$¬H„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGA°Áðð HDMVˆÿüüððÿ¸ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@ðÿÿÁð cÁZ®ÿÿÿÿÿ€4çNÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@°Áàá$¬H„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGA°Áðð HDMVˆÿüüððÿ¸ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@ðÿÿÁð cÁZ®ÿÿÿÿÿ€4çNÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@°Áàá$¬H„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGA°Áðð HDMVˆÿüüððÿ¸ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@ðÿÿÁð cÁZ®ÿÿÿÿÿ€4çNÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@°Áàá$¬H„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGA°Áðð HDMVˆÿüüððÿ¸ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@ðÿÿÁð cÁZ®ÿÿÿÿÿ€4çNÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@°Áàá$¬H„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGA°Áðð HDMVˆÿüüððÿ¸ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@ðÿÿÁð cÁZ®ÿÿÿÿÿ€4çNÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@°Áàá$¬H„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGA°Áðð HDMVˆÿüüððÿ¸ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@ðÿÿÁð cÁZ®ÿÿÿÿÿ€4çNÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@°Áàá$¬H„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGA°Áðð HDMVˆÿüüððÿ¸ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@ðÿÿÁð cÁZ®ÿÿÿÿÿ€4çNÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@°Áàá$¬H„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGA°Áðð HDMVˆÿüüððÿ¸ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@ðÿÿÁð cÁZ®ÿÿÿÿÿ€4çNÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@°Áàá$¬H„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGA°Áðð HDMVˆÿüüððÿ¸ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@ðÿÿÁð cÁZ®ÿÿÿÿÿ€4çNÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@°Áàá$¬H„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGA°Áðð HDMVˆÿüüððÿ¸ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@ðÿÿÁð cÁZ®ÿÿÿÿÿ€4çNÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@°Áàá$¬H„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGA°Áðð HDMVˆÿüüððÿ¸ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@ðÿÿÁð cÁZ®ÿÿÿÿÿ€4çNÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@°Áàá$¬H„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGA°Áðð HDMVˆÿüüððÿ¸ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@ðÿÿÁð cÁZ®ÿÿÿÿÿ€4çNÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@°Áàá$¬H„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGA°Áðð HDMVˆÿüüððÿ¸ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@ðÿÿÁð cÁZ®ÿÿÿÿÿ€4çNÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@°Áàá$¬H„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGA°Áðð HDMVˆÿüüððÿ¸ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@ðÿÿÁð cÁZ®ÿÿÿÿÿ€4çNÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@°Áàá$¬H„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGA°Áðð HDMVˆÿüüððÿ¸ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@ðÿÿÁð cÁZ®ÿÿÿÿÿ€4çNÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@°Áàá$¬H„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGA°Áðð HDMVˆÿüüððÿ¸ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@ðÿÿÁð cÁZ®ÿÿÿÿÿ€4çNÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG · C‘\~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPà.„À 1Z¥Zˆá³<3Ü!Àµj¸ÿøµÿóA€ûàR”¾‚à±JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JGR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥" ûóô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”G¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆûóô¥/ ¸.R”ˆ¹JR"åG)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”G¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆûóô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"åG)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆûóô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Í)H‹¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹GJR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HˆûàR”¾‚à±JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹GJR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥" ûóô¥G/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".GR”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆûóô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹G”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ ûóô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Gå)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ³JR"Å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ ûàR”¾‚à±JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Gå)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹G”¥"  ûóô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆG¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ ûóô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥"G.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ ûóô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HG‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥",Ò”ˆ±JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HˆûàR”¾‚à±JR"å)H‹”¥".R”ˆ¹JR"å)HG‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥"G.R”ˆ¹JR"å)H‹”¥" ûóô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JRG"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆûóô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”Gˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆûóô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥G".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HˆûàR”¾‚à±JR"å)H‹”¥G".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”Gˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥" ûóô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)GH‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆûóô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JGR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆûóô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".RG”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆûóô¥/G ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Í)H‹¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".RG”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HˆûàR”¾‚à±JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".RG”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥" ûóô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"åG)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆûóô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹GJR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"åG)Hˆûóô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ³JR"Å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹GJR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HˆûàR”¾‚à±JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹GJR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥" ûóô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹G”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆûóô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Gå)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹G”¥".R”ˆ¹JR"å)Hˆûóô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Gå)H‹”¥",Ò”ˆ±JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HˆûàR”¾‚à±JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Gå)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥"  ûóô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥"G.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ!ûóô¥/ ¸.R”ˆ¹JR"å)HG‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥"G.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ"ûóô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HG§{B*tâ°ª cUz"gLëÑò¸oÕ©!–>‰¯Mî\iÀ©cæ?,}žšèò€–>¯ËæÛlèŸÒ£É‹MNO´ê_Ò¬"8 *:5B+õB/r⣣UjÝU§*Á ¦(‘^W€aàÏÃÑáM¡5 ¯Mî\TvøÂ4NuB+µB'tj]ªu~TuifÒÕ(à *>  ÿX`„U ©@Huì@lG:\Q4uè„\ãhüJ”‰àr§5 @ËÛdG@a4u`a6Âõ† @Óô1èá`rö¬M8Âl„@Ú??ÌBÀ$á`r ƒü¤ ¯uÊ&ÖØ›@ ‘hü ÿ‘!z€ƒü@:²uïÀlM  ‰°d@Ú??  'P„@N½ð&Ð `È´~ ˆ HY:€ƒü PGBÉ×¼±6€6&À ‘hü ÿ²uø€ …“¯xbmlM€"ÑøAþ@(‹'@”„!dëÞ‚lÁlˆGáùH@¢?ÊB°½{²Q6„¢lÙ6‚ò Ôä!H½{°0M &À ‘hüVB“…é0òáz÷¸0›WM˜ ‘hü ÿQ0 p½Aþ À 8^½°GÂm›P ‘hüX ÿP`œ/N?Ô' ×´blà °d@Ú??Ò"BôÀƒýœpõì†dbhè² m‘†s!Ñ7+˜OרBGY ÜÙhø@£ÕâÞê¢È>†–M{:=¹ÌiE=S«µN´ò¯*¢ªãóô¥/ ¸ s€*>ñ+ Ê™ýé\ôw  ÊºDQ¸ÉIZIb(ì¶  µD"(ôGÛNmbŸÄQì¶ ÖzDQè€cTR"Žà1¨JÕ4ˆ£¸•¨JÕtˆ£´•¨JÕtˆ£°f ÍWHŠ;ZЧ¬ûÄQ§J1³Áö„¡#¸U¥$ÀÐ$¯LQᬄÉÉ Pü JNI꤄M°½pðP I–®Šz  IÉ Jz  IÉ ]ÐÀ‚(A$Ò@”ð`ŠÄÐI4!¢…€v9É'G$&&“8'$v €Á‰ ’i Y €W “A$Ò@†Š>R (y;ÙÐîDÂn<0°’@±†^= Âwµjhð¢Ê‹IZÈkM4TêäTë[::´“é'(à*>ÌÔé\ômzßGCÊöî_ÖŽCN¦(øïA·u ;,}pØhù Š?66a·¢= (èhø|š=ÙÄÒù¶d¥¦ÑGèõûÕï8£Gª‘¤âŒÒ”ˆ£”¥"(Å)HŠ94³xŠ0ôzÿýwJe|ü–¨A7k¹É©ŸRá¢ÎW¥?ש?  eÀÁqGæ@Ñ@ýz,ŸQ’˜.(øX é0n÷Uõ•´QóÑeE±Ê‹J(ò"§W"§ZÓG^“M¤œ #€*4oû À@X¿è€ _q){€gÜc(û€‚ÀÿX }Áÿ/G¸T€3àe¢à ÿ0P®à 8¨ ·—¤€Ï”~·€ ü?ñ^ ‚ì ¯yÀð2ׂðEÿ²‚¼x"ÿÙA^ò4ð2Õ` _úF ÕàŸ'ü .A¼ÃÆÏ”~‡(où ïý“,oú ïý¸4˜ð2º .ßô @ ßû@ApFÿ J0NÿÛ„ôyŸ(û ‚ÿG@”`ÿ´oú ïý¸T€3àet@`¿è€ ¿ö€‚ÿ@”`ÿ· | £î ‚7ýP‚wþÀ@\¿è€ ¿öâRÏ”}ÀA`Fÿ°J0}þ°@û‡H>Q÷ÁÁÿ0P  €¸#æ äH>QúN›þ:¼À‚¼ð ¯y‡¤€Ï”~¤@w‚/þè G9Áÿ ÷—¤Ÿ(ý.YÀ%(ž@ªÀ €( ÷Ÿ¤Ÿ(û˜§À‰ÿˆ õHuñá¸(ÜŠL øGÐÀ0 @ µXÌRp²Rc}-Y± 'Ø¢Ujhà*pÎ*??JRú ‚›³Öa„½€ÉCëçŠ%è !”>}É¥£âòj4Àá‚®§!”>·“J{ƒ. >8è`°¨€† ºà7(G} zWGÇ= (eqáWU¡2(ùØšŽ>e©uML*p 7W•àzh¡”xSÕl/û“ÊÞ³‘ïzà£îÿí ¸ #Z’¤fõÑ÷_ÑýÆ>*·€é¼Qô7²•Vb$Åmu"Ê‹B5™x£Ï¥ŸIiL*pÝEEÃ<dÛT\ç€y#*&‹À,•OGçé{_Yïd•q=†¥ï¿´'À …ÃÑüGëý¦% ~¾’ŸiIR`º‰t/¹@¢€7 h ¾¬tÄé€ …Ì—Gò€ Cšô@- h ×Õ-MX©Bà—Gòð Cšõ- h ×Ò°þ”ö@6´6´0  /PÐÀ&€½}7€Æ·€î`LmË@nШpÀ&€½}__XtÀP6ä`7 h Ð%4ëëÀ7MV&¦*´%%¢„´_SGŦ΂ÓW&1´äÑüÐj ÷Ñqi«)˜ …Òô>™õïÀÊf)€ ‡£ùðÔ Ô=}$Ôפšš@l.±´3á¥`?¦¸`×Ô’S\*š@*º?“€Ü0  /Pá€O_[­4­0P¹’èþHCž˜–úú¢ ©¨Ai€ Á.æ¿îm½ê MVJgÃØGã?®þõ#Á*OGçh÷£z ’z?7‹@úŒZë×GroÕÉ!¦ Pô~”*%¸`×ѸMpúi°¹€*pØ¢EPLð@ë”2³¢(÷’G¶ Æ²ôOáâŽúRhx£Y©x£f Þ¯j¡âN!#™ä±!{CÅHñ¨x×(eCÅPù f×=¦ú(ö’š*0ñGd)J¥FhÒÒS£bVœ u¥h“Ñë©È u‹iZ{Î*paùúR—Ð\&Å+Ã<oxÞmI³§Û Mî\tv&Кµ­$4XEUž×Àw§?E5Ñ㬽@G ôEyk†é^"ŽºMŠ9f”Q™kr^ˆ£¢¯{w!íÒ´E0lÝP’¨rT4Qò^oÀ'*LQᢎ[Ñ&KÕéÅÑ‘`%P•{ÆJ2ÄJ˜•wäUèuVrö‡Š:7•퀣OÀBVˆ£ç<ë•@r‡úFE3ùÿº@hå?Ð2(ò<ÕÀg@l4Q×I© kIžGSÊö3¦µÑG‡yé£VG•ðÑ*??JRú ‚ ‘M¾£ÂÏí‰&q× µ÷žâ£õ :Oº€À·f¼,ñsGô`„Žô6, _7z<€n*c(þp'ª6 ‘!^ùãÑàâ e¾À &à$+*ð  $.@¼+Ñàâ eµ<&‚( @ðš X\x·‹À Å@Ê?f|MP,.@ˆá4@°¹ñGoG€Š”~߀˜š X\]À@MP,/x'£Èâ eÑ’¡4 $/iHÐ$½óƒÈâ eÕ@  I zÀ$HW _*z<ÜT £úŽÀ €H®@²”"B¹ùÃÑàâ e¸(ÄÐ ÈdÀ4 $+ÞAèõ™5¨À:, $+Õ`(_Ü+/=KB\5¡<àJ€œ ^~K†£õ|zM0€EÓÐpé4| é4|ÊmOà&Ä2ùþÐLù)ü˜7ÈxQ2ŸÑ"*E.\¹råË—.\¹råË—.\¹råË—.\¹råË—.\¹råË—.\¹råË– "\¹sú"¤ESùQ2*&SÐOÂÓɧ ÷€x÷€xºz@  èG6ž€¨¤ê&ÓÐv€A] EÓøƒ )SùR"¤RåË—.\¹råË—.\¹råË—.\¹råË—.\¹råË—.\¹råË—.\¹` "Ë< ò`@ ÎC( bg ˆDªÈ¨A,vàfXòt’u}Yý;¹8ƒ$úh55¯«ô9hè$€3…1H àÜX"±! Qæp€ì•¼àF¬sBzGxTPÁ Øšà?€¬Yÿ€Pæ“ À¯Àø%¾×4Ô \ùxwD``Â`¸˜8ø›¢bpé-æôÏf*ÅÀ 1p2?€#ÀU¤==2` 7€hæƒiè„B€A )&ŸÃ$A’)råË—.\¹råË—.\¹råË—.\¹råË—.\¹r.\¹råË—.\¹rå€"‹ØYþe4ÕŸÑ A´K(|¼§GByÈHTšÏÑ 0á˜Ø˜Y0 À’X‰ €r7œX^Mgè@t¿ød €èðÀ€ €¨"€(h$€H`À‚(“A$Ò@ƒZ³õ(Ðèÿ ,a€@t¿ø`@à AaÄÂù\tE‚y0¼DƒZ³úÈ@âyb3øÒ@C`CRh$€!G`Ñ @š XÂÕZŸ,–Pø†K(|V€T@š Yba Ò`n€,ap3· ¢¼¼ð ÂÀ$H^!!M<À@´À¨íȧ˜Z­&E?“"¢dO…T¹råË—.\¹råË—.\¹råË—.\¹råË—.\¹råË—.\¹råË—,"×ßÕêÏØzêë~÷*Þ-’FÉzÛøh؆oGdÅ„Öp q7€/µâÆ|er[«xÀ=Ä4€€Z‰A¸Í†ŽÕ¦x€ ¢gƒw6a¦´²¢®tü|“Å£Ä$=<ÀÈ€2€"º ‘OP 4BÐ ´4Š ‘ERåË—.\¹råË—.\¹råË—.\¹råË—.\¹råË—.\¹råË—.\¹`"úP°k0Ù<*³ì bÿùUöN õ¿ÊÀ4ðnà=Äú„G‰¼À4"Ø lò,‚âØ0wîûx°€‘€Šdà;%ïŽR©â@&:€@/ˆX 1¶6šŸ ÂTQ*Ÿ$5RåË—.\¹råË—.\¹råË—.\¹råË—.\¹råË—.\¹råË—.\¹`"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"]u×]u×]u×]u×]u×]Gu×]u×]u×]u×]u×]u×]u×]u×\¹råË—,"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¯|¹råË—,"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë—.\¹råËŸ¨§Ì¨…O„—¶§‹€:L™6Ôñ0äÀ€I‹OO0𠯃ITõ“ð±•!Û¾<dWcÉ¿GNˆ~Mv¼"A+‹ºíET.äWc4Ý`qt´»þ)ëz㼉«Ïšµgl2Õ4Ú •Ê®å„"TJ¨"ºë®ºë®ºë®ºë—]u×]u×]u×]u×]uË—.\¹råÐ×ÿA…WØd\›êóCÄĦûª ž4N¦YÜZÏ©…ß|J,@°¼ó† ®@’G6µùÒZÑ\`Ec‹äÔü Të8ËéGè €p)@ÚÅ9l€'€#A&  ;欀0>HèL:,m5ò[lLã¬ÄŽ·ãü"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºå×]u×]u×]u×]u×]u×]u×]uÖ"]u×]u×]u×]u×]u×]u×]u×]u×]u×]u×]u×]u×]u×]u×]uÖ"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®¹u×]u×]u×]uÖ"]u×]u×]u×]u×]u×]u×]u×]u×]u×]u×]u×]u×]u×]u×]uÖ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®G>dÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G · C­|~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPà—„À 1Z!MÁZùa—ÿû€µ…_óA€"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ "pÎ "góΉ1%ýèº:@b™ 3}ƒµÜ,HhìK@$€¹À›z‚i'Þ°b3rz?6G` '&’RŽ-®0†’öv½pF^X 5e£iooÏái§žyç Æ‘èùA¤Ô¢îœÈ I„°v¸àVõ ›{%mqú0€àþÄ´H¢â˜*ľŽ-¯fIטÈË2ÊCªÕ! ¿àUøœ "aþyÃ1Ñp‹£¸3oPM$ûË€fmê ¤Ÿza‡\¾–—–‡a©ÀËËCµ iòÖ`àVG‘©ažyç į#Ñó€©Þõ ›y`*w½H&ÞÀeÇèúá„y€ Œ½8a'^`#,CN«U0 ¨•~§ "a?<óÏ<óþ“–£áröµ“@/&#ÛÀNq™W²¼RÒuíLrtÝ…€ì°(‹å°qyÀ­@QÁ#ÿ8à %ø@c‡À°À¥x C¤äi BÓPp`x³Êèp¸&²ˆGH!œ˜€4¥p.Ðà&†}Û(õ€„‡’‡½HÈhÉ÷ î2õ`!+ÿÚô ˆÚçM,@ È@PüáàrÁô‰± ðHÿÖ^Üàa¼!S€gÖJ'ØòbzÈõN©€ˆ@Ig•°ø&€¨bi¬ àE“8J ÈšŽ¿$½€ôßÑñЍ/>‚HhFz ïŒË˜à'd^Ð –×-VG, &“J°þ€¸á4Èê&d‚Gþ0Ê€BC)?„À €¹„i(@ùÿ³T&8À ÊpC~ ?ú Àx ’y/n@€ €œðC \D2a$¦‰£ §Mš±0 ` I€C€À&ÿäL!”YÅCÐQ6LLÍ×ì@0¥ÚQ´ßØ[Pʰ¬1€tXC:Ê!… ¿ù)/ÀT=»d€ÀGp 0CÈßýðâÀ•‰Ž6x¸¢_ÐŒØ ¥x0ŸFHtÙÌÀA€ ñ}€lÀ‘ÿ¼@!€é(!›°_"@ ¤Î²‰ð €@^+­QiB §M/fWκâhr’‚ö Þ„ÄßÑ«@5ÿ£ÞÀ ³µÈ5T|°Ð0 ;rˆaEoþÚ¤¦80š3}ïB€ÔþÏt0€;&ð„p»™: úÓG—èþz@üÒê‰à‘ÿ¸aRBÒ!{rÀ‘ÿ»€ ¯¡ fy(Ÿ˜d.´5 ÄÀ#2ZhþD d *v`ûªuôÐ ¥£ç}y^2ë,˜2É z?>’ŸÛÀvÔ„£È÷T 'Ž»Ø€bÐßÛù‰gÂKj?(CÒ„ÎØ…Ò=ˆžÐ€@üÒ’€ _ø.½Ø° H}E8|€‚Àå‚G}Ê|Bµ%ÑüÜ €è‡Ø””.90ù0†q·×ƒ@;!p”}yÀ €NZý©`:+- 7›GáÉ¡¹;Þ”nq@Tj2î |ûPÍG£ê :ó^œ˜IטÂÈ4éê •À2¯Àtà"`¿Ï<óÏ<þ‹ÀüW€Í’Š P Àª`!©€ à ‰€9†*ª :ó€Q] 2®!G^Àj{Ü{QGÜ €uéФnmagV7ɨýIƒ7½I ¦ò›z¢&æ ê´úŽ€ Yݯ<‚fØë®‘× /®6£î€b—uÊØmÀ¼Û»‰4ÕRhø :ê´€œ6¤…Â-`16 ?#(÷ ¡©¼è@0Cw¡&ò eiõF£Å‰ˆc®¸`&GÝWe]íОô}G퉠PbnxX¼g1—7ï­ £ç†à‹¾¼GyðÒEÞ¤šŠ—£@7úóDÂfÈ:í€i—¯:Q" ßÞ6£ë€j›ÝÖdÞtS½èI ®©ú>8 º¤‰Õ€&:¬'Vm&Q÷ÃPé¹@²•t’I¸€fžÈ«QóÆuÝÔ3?¼ç$]Р͵+®Ÿ¨úÄÅ&à‹d]àÂMÅ&,Ë«QêÔ‡±·w€ì drØ;.x9+W½)4 Kê /ˆG Y†!U'®ÊÀÈG¢a$ ì DEÏà @|À¸@š  }D™d€Å" ¼e&`çœp¼ š  G!#›Âæ7Ž£òà1~ø4=ÀDY(I! pî@»(Xä@<0I’&€Í€€å|4  H&à”ù[fp¸w£òÀP7% öú @*V &P$¤â>®>N?{¡‚lè÷“ 7–Àíz’Ga&òÀ¦M„U0 ­À2´ŸÓ€"`ŸÏ<óÏ<þ„xðAõ@ÔÄÀ¬–  Fç\à¨ùC 'ÀÁ !‰4ö˜…¦ÚÀ®é>¢]¯VL&†—ׯ4s¶»†Ö;®ŠH»¤2MÃ,‘wd›R©ôx€2?^p£¯F‘úó…XiòEHG3oB’Mç€36ô)$ÐtÓGÇÕ`1:°ÇU€Äê¹ò2¹Àsq22íòMÄÈÊ :zÉx3n$]Р͵(ùz>¨a&á³¢í“ 7‚Y—=GÔ WL1#y €ëô{Ö€„ ÒgV¤3¾i¦Èdsk„€ä"úÒ€Ä ulP?¼«1(¢|ÒÎñ‹Úæ„0x…kÀåÛµôpÀwÖÁ×0BGho Æ> oGá¸!„ܯw5/w²€uЋhsVŒÞš>ˆa&òà¯PL$Þ\#´‰§M@ ‡TaÕ~§"eóÏ<óÏ<þ,LHfð`*Ø¢ ·¸ÄHà€6  û€«oþ@Üf”Ü‹/JÖp€H!0pi@9H`q|@€¡A„,ÄY=)ôÚ¢Ä4–Kǰœ‹¢†Op þ€À›ÿGV»¡€¢@v0!ÿÑI€NÏúð`0Ž() ›ÿ¶«Æ‹!ÀvCå  <?ïD,«¸ù@’ÜâÕa¡Œ¢ŠÅ÷3ð߸Á`rÁŃHe”M@gˆ€*a¼ °Àåïõ¨b$vd<$Àƒ@```bHpq0¾@‹%ÊÖ5B$¤dVOøN€ïúÑ ˜0˜ŸôH]3Gþ¯¥#åkß Þ^ù€ðH ±}ÀoÐ à™ÿšèdB&€©?ܤ‚@ü Ÿïàà€í|® MÿËùdЀì71,¬ ž Ÿù T¿Üü It‚oüÕ^-†°ÀDÿ¸$'À™ÿQa¡ T5D²°$ßû—À…«b4LH 3¸Ù`’ß÷‹ ŸøZA Q3þ½ªÈrÿuàÀTìAþGÆ@¸&æ³ØlËnà ” ÿPƒ¦ ã@DÀ?c¦¼H˜Y3:\°W BÇé87ÓQö€¨ ™45eɘHÒ¨@ä ‹ÿ : ,a|íè÷±€b^¹Æ£ö :0,„’i3ˆÈšá@…±%ã½*I )‘+j=¼ Í’ÁÖâlAþF@8&¯ô†QúDdw; ïû¹G„ „Ÿö4 €~çR\šŸ+A˜0a°8"pÎ"p'gÕ!$d‰)hÂ@€`…r9$ ùÚ…Óµ ° Cp«X„Á¤€×öàМ¯{¸¡÷ÑäHpÛ€íX`ð’È@vöàWºl`X€X†¨oªH¡…œáTð@(HÐb$ý$˜’j|\C½G„šÜDÂI,;GWà ~À)ˆÝð ù÷X˜Iׯ‰›ë“¦ç¡€‰¹Ð4*Ë‹Þô€®eªQµ;×T#—´bÀ5&4*Ñp€N“³ÑÐà )\ €DjÀ˜šp@½¸$Ø€22õÀlžäGáJ,窮 ¹è·úŠfu<ÙÏ8"p& 0 ŠèÞP)NݯZzF¿¾f‘04÷·÷ä°¼@G½`ÀÔk‘:Ü€›–ïq“ÓÊk…€˜„q,?â° P Ä)éåäõUµ§!€æç€ao!€æÀ…šNPØDˆ­6Ñ"+Eù(+Àˆq^|C“GÙÌÿu‰€9¹íuƒsz($\üú?0‘Úàw€2;\ îÓìôÇÆ.í„ëŠ]Ú ׸UÅèýX͈#- T6 Œ¹ µ£ò€::À‹xް"ëM–¦?›¹GæÎyÀ"pDÎðÄ:??KÛ€bmØ $ÞÎ!9¤à;q’èþaKÖ€‘g!’«áÙãw£ó”¾ŽL@t}˜Jq¤à;º?›Eðý{uè/O„GìñËj?˜rÊÀ}z·€Ä òhf ßj&€œ5·¶$á¼Û£€”œkäÑT 3"ÿÁñ¼8šÄ%îåì·>à€dyhû š@A°'ØG½Èz>½H€§¡îXÚî®WÖoGË|?V¤d$V Þ°0¼­ÛÞÌ0 Ë/ŸÂìƒuÒkUËj?’€ À@¿ðBŸýAL$â3ˆ-îÉÚ>R€BQÞÄØ¤à;X¢¨þ Jx/Júû’3-'‘îXzyµp0'ÙÜUÈ} EÒ&†r½xNÉÀv@f徎‘ ½æDG×Õ$„0×§öñ0Èjðà†ºe 4Nט½O‡À Lƒ +‰¤¤N†¸pö'£œÈd$M)‘ÿ¨ ÀT þw€ÃFþ¿Œà;mÐ (ÀÒ'ÿPAƒq´’3ˆY*%±°dÅ F&’D€í=³bŒg’  ÌQi9Z8`„˜€¨ncIÀvÁZA0 Ó‚ (^]4ë´™"ô` >çuGëàÂW=îW£ìPØ0º$0Ø@2çX$ê¨ü˜‰çäë²È×@P ÉXû¯•ÿ³{ 0›ÈEãóOÐ)@ ƒ€ŸÿÖ¡0„–¹9À9‚lÕ˜†’A4®!8ƒ6O:DQ7•àˆßæð¿Ê`“€ì*Éæ#¡#à ¥&À ' äÂ2OÌ€í=`®œK³€f_ozBh RÙîðÄ*çþÂA € G@€ vÎL/ DLA18 è¡`!ç9>Iɯþéäà;CmÓ$’’#ï`o$_Ða4”lˆÙ6^c^d½¾÷d'@ jKAõÀ1-÷½¬žãw£ô ;Í#- ;ÍŒ#.^H´£ò`:;Xö?µÚA ”‹®ˆÞS·ºI]>Íìý ¼1($¨MÉ€‹ÿDÀIÿÝ€5ˆü$Ÿ&K½­û G†’A41"QȲq/žhÊçøð €5; ‰y¬¤/EÀ€‡Ãv\”53ç"pD ¯>!àÄ3¯Qö@16ë†n@&ÝpÂMè ëŸÑù°5œšH´€‘¬äÒ@u·$ÓŽ£ô !$ÄÊLà0>ÀUGÅ×tR†ÿpq"윓æQñΣ놙©$=À€@(§ G­` F{ÌMšE—ôözG>à @De *í$H OmµãÀO•ïFI> /øú‰f¹Á¤ÖEÕ1–R©9éÞ²t’Óæ€M$¡áó†Ü ¬ÆŒÕQ `¡™ÉˆáÚ¸ ¢Ø1Zó$$+LQ¾:ÜÔ •šéTæ OdT€˜ÞãfmˆÃl1êú(ù!àE\P(€‰ÀNL‡µÞ–£õDÄò“pÀ  seݰ”GZ€Œ³ùêÔ|@€í_]‡šÒÀb6ÈÁ½éÈ£ÑàÐciÀbžÚæ 1‘uNmyr£ë€Xt®ã€1+I[ñz¼ÈÝ9ï(b³H²ú2£j=ü` À ®à` …;°xN‡×TR³Z”CL¹ZÞ 1'5çÀ2Cml&•²}Ï1–)Kê¶j€¨{¾ I×›·é‘]QèÀ ZQ¸uÂÀ €a` PVP ›\¦U©dÔ¼G²5µNÁ›]t±1*Íx0¡WªŽÃh(¿òçÐÔxÀ2&³osÃKÝdÇëšY"¤êw£ë€ï„ÙÀMεRMœQÎ,45‘ï@Kþæì¿·½@ I¥ïÛü Í4Ñò@Lð07¬­pI€ `1d€"×Ñ€ ÀNQ “P ´â7€ ÿXôàHÿ²À6\˜_9:¼œ:Àœ‘ ÐŒuPB²UšGô@ƒý –IˆâCKäZ’ÈiNpÒø”ÿ 0—Þçào2ú÷ üÛÆ€Ã¾»É¹¬fà»A+Sq8"pD¡¸†t`CÊ“G×Îì}ü¯z€Ð+‰‰]è†sú?$n«1„^¨ )Ða%,À,¨ FbóbÉÜ2R\ïu?\à0>è¤2ˆiW#‘uËÑ}› Ðô|lHºà1>âô] GŸh޹z7Ñ÷›„‹ÒèûÎBD=F@bu逩&ó ;:ôÀT“2Ž—£ ÖRj?Ex3ûšLФJ“pÀ./]€ •í$Àe‰=©aºt:&%ôÀU;kÕ€ @@ŒÁu€;-d€Ò9ØÂÀ— n£¤2óÚÀ§ »Ðh&÷dÐ7§«Ø†jÆÑøÐf )Ñ^µÎè}u$û'£ö@À «Õ“½Gó  ÈCq×­ˆ $똘œÖÉÔ}0(”ûÉ`¦×L@.ò &ƒÒäGbCz¡¯ ’b¯B‰ Œ¶)4'Qõ€aÙ7“]÷¤0%~ç€À8&Kk$•Òu[µƒ{¬˜nº©'Ðc’=Ùˆ’4—òÔ ([O/QÒM-Ós€@uéÐ_W¼àI°- ¯z>`i"ïÉ74‘îù “h/GœÇGÜÂÉLÇÜÂÉòãQ÷©&Î @ÍýGˆ5‹´MRo7Ã|R†wj‘ç¼¹ 澊P(}®8/1X$6 üÇŒš?CNÈ÷¦¼7.а°'2\;Ýð*ÝW„w¨˜B,ÿ¼’GÎ KûˆB$^ 1¾ó@S„Y—«Þ@}¼0¶M”^Þô%€Ä”ž¹…EÐ7}®>꾌$ÂgG K\lR“0#ÛB-Σ¨ø€!,#Þ¬%ç˜` À¡ -åÀn•Y”WF]]/GÈ6:çà‹@„ÏÚÀMC"¤õËQú&έ\CÁ6`j"Ž’iAp4 Ò‡äË–è½ QÊþãÑÐÀ@rBpHÿÐÜF.á €',À•ÿ`Tòõ@PÉ@PôÜPÀÐl°Ö ’xiŸÏ £â  <G•ÿ@;ßûªÀ € €'þ@v ¿÷z`*bótðé&ð‚ëboéÁàvŠ?œ4(bfÀ‘ÿ„ÞG.Ä‚ „0ä[Ù€\M½œ¿yr-—î‚ðº7³OòÔó€"pDØbQG”`&8ë×€?`_‘|î{A„Þ‹‘(£ûˆÀJýÊáUÅdúŠ÷Á‰b´ b°V¹ÀEÀå@`]Ö€0dGMýep«È˜÷ ËEåIq{RÀwý$ª>àh ؤñô!Àéü`€¯_#kÂC'êÊ Gô\®ùÀ`¼$˜€WŸ!èš„7 À"Ió„¿<‹&1¥Ô~ˆ`:!ü ÀÞ! ^€†p½ † ;&0¾xð牭(ý¸0Šh!á!…â>¸ˆlܯ„ïpú‹Í$ޘȣõ €8á»¶GáW±Ì‘ ±\*ù ÁìʽUÊz?½–pÜ « hÓƒ à"÷ÁÉbµ b¬€ ÅÀå@`]ÚJHp!ðH2ùã€À¥|@p$)` åä¿B_Ÿ;˜Ä€Àº˜„CÛ907 GÐ28ïoÒò¬+4ièú&tæPÄ£¼™õÅ &5”Ú {¥†½ÅµµH,ÕöN½ì±G (¸ì04®HáÚX¨4¢ê` ’MOQ\/àˆ„> 0¾D±¢µ€¨ À~$ ©€ ƒ4Š8!€8 x$A4a@4µÂn^A>_‹Ickk ha ;‚A`’i @P3ú€ âDÞ2—êÀè¢ $ÂnQz&¥Æ¯/×€<&“}*&x€ÀÒd ’%ˆòåú:GJ} )8J=° 8náëÌ<^÷0mÆ2É RHYlÀ訾3Û+E 5¤tTÀâƒYÈ'ÈÁ@& P âcEib"h Ü Èk @ „ Ü€C.ŽË(¼ àŸ ïM`ó0à;)$‰¼BÀPE@–€p$(hÂ_‚|1-^ÙLXj¾"@´¿,R´M¸ÀäG–Þ`bÄŽî!€€„L•à’ü¹<·¦°eDÌ  ˜Œ"&–ÍŠ/ˆBHíÀ°†¸!€9‚@—È À2Ä”I(šƒ!à”åúz4@ få$+Ý @rÌ Íy£ÞÐ þ÷ ËL0C1NtP’[·l%:\+E¡1Vú`@)ñf .Ø@P˜zK @’ÑcEiqiï#QÐ ms )ª©{Ý#nG9Jÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ&jA‚ÿ'ù?€"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ!"pÎ""pÎGPà¿„€!Z!ÿû¸µ…USA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºïº¿”ðI~+À My€G$ —ŽðÂÀ3¸À ‹€ ‹‘^`€œ M’p„bGàí@H‰²+ÐãćÏL¢‹ÿ@ :a"/êþSÓÄÈ­W]tÿGùOåË—.\¹ï+úñ3Óø 97èÒ@b^€..P]<À+€ @b,D˜®!ȧ ‚BRRt’ª~[@ÄàÅEýOàS'ÅoëDÊ~Z—.\¹råË—G.\¹råË—.\¹råË—.\¹råË—, "ºë½σÄσɯ0lL2 € ƒblŠó `B @Ø‘â«Ì\t0 €@ˆ7ȯA3HˆZDšºë§ú?ÑþPÿ.\¹rçò¼BñPõ„|À ‹€À& ‹‘L˜5˜C!ãâÐ CkÃ/êhWÂÕ½$¹råË—.\¹råË—.\¹råË—.\¹råË—.G\¹rå€ "÷ lüÓ^a “ZÑ !F€—RÒd2E6>M,0a®&"ÈJXÀ “i(üÊiPpÏÅÀäB6A(±Äø´ ±Äúaé !€:,€Gé è¿ð.KÀz~æ_U5 ó€< ” “€ìë`L@&€@@Š%ñÚ€)à$'ëzl "ˆBÀ8€8â& /Ÿhÿâ}¾¸@tdGP+'A˜°ÀÀÁ‰J ª‹sÆ]*òÀð r&Þ FL£à‘Q⢋By„øÀ6Hâ}3ß+áÐ,*1)#¢ã©òZ Úå ¿ð ;L-¼  y:+чúKˆ]©œx?Dƒ\Âx€t`¢ é§ §]N ÈÜ~’è"ý— A ¤˜C@&ÿåîLoû(ò A3G4K®žæ„(R€MÿÙÒ8x3ŒÃ€:ŠÍÌÁ`rHEÌ,Aô$hà°9lÅã>q~ö.˜S€öŒ@;ÅñØ=0ÓÏÖ× ôNÐrÉJ$ Ÿ'ï‡H˒‰àrî`µ°åŒ@ùeœGi+óö@·”ÈØ(7ÓŽâ%äÙEŒ6_ñz›€¢PÐͯ¥r7“MK® G¦Ÿ}$yråË—.\¹råË—.\¹råË—.\¹råGË—.\¹rÀ"eÿ†¦±~€my€‹ K€&±W. z €LVÐB¤Ülåd@ZÑsfz J ÅÒ` ƒd¢˜}IïÅUz¦J†+ª`ˆÙï©„ÊO'S¬å 2¼˜¨T@é‡\š)(€C䦘]3•T艄IÔë~2‰Pmúh1 ˜¶Š¦4lòÐÐdpP†CÜ0²f‚´’äë‡(25è%mäG©¤gs¡§SȈ µ3žm©PB8’ªA …‰%à®@ˆE„›‚à ¹_¿¿‹‡“齡  0_üÀ$!!¡‰$%ù@ Aš  M,L&‚(‚H‚hÅ’¶6š?&`HbÇÑ#^Ü$"Ôj®Ñ€]7å“\tL(øšM‘ÔÖ002”ÔãÝ(o—.\¹råË—.\¹råË—.\¹råË—.\¹rGåË—,#—¦‹À<âëÌD\Z\ › @Õª¨Š¦ÜP±ºzQhƒCHIL⩱˜¿'@ Æ¢†ÅDÔkE ±·4M˜„øØ²1- H*xÇ"HÊznL0ßéÛòl6&Ãi‚ÊÙË‘54­>7Á¨üw’˜ ¥$h"£ ñ øø5#f‘Ã* ÔÔ£0é¥"¼”“RjGân¼ ¤ E¤$Þ‚ ‹{µ@å?ѾÜ+ØcŽáP ËÙ_Ód&åMi©Ðrm¦&ÚiÚú¤^¦wõ5E¡©‚ÆŸ±3ˆE•¬ áñ054Á ²ã`ƆÃ=3v]cM M}›E†#H r€Ü`ÐÜb-~‰€'%Œ6ˆhp€“G +`K,ÌO ÎPHªh| ð*öYe$ÙŸ`b›d¼j  !è7Ò=5MyG I‰ˆ2M5;é-Ë—.\¹råË—.\¹råË—.\¹råË—.\¹råË–"û+¡ëÅ€aÀ¦ðÂÀÎ-„Éz|’’Ò<€¾@‰‰Ae€H S0–À=ÄøšÈ_üÄúhKt`=À#IéÀå4ûn ª|’4@X’K)òHÑI <À€ ©ØH¿‰œ àÎB+Þ€Ic4 ,Eƒ–½º `ÌGnÕÊG5 Àôè€4@ ¾)Dò1 €ûˆßÛÊ×Ñ0—»CBEˆÓ ˜Ò_Z‡“¥jcøÑÀL+2t­O›2t€%€_+V™žK$®JL>ä½wA&ÐÍ̦æ—ˆ°ABb`i–H`°t—÷e6`,B(~F„ÌopÙ=?Ü/h$ÜyX09j®k;A"[–(9ȱ)Ê4}ÉdgÉÉaGdâ 7 /z@Ç—.\¹råË—.\¹råË—.\¹råË—.\¹råË—,"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®\¹råË—.|Ð7D.C+O(—´—93˜§  ɧ˜°ÄáP\ð` @"°Ð“G8 DMȧ¾Y@f!†$ …Ú%áa@vÀ˜•DÈ¿}¿P›7$w³›ÐKÐØI¬¾`g F€L IˆaPÉ:.&Åí"™q—@ÐÀ'Á$è–L| ;’BLzivèæð©#ÁˆÒu46þ ÄÜ'oèGûDÀ C1ÿÀP4¯6/I€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®\¹råË—>$ÄÓSGøEÀˆq0•¼€è¤ŸO0Ä7ÿõ@¸D.>PÄ!pÞEëƒS"ŸÀ ý¨0"`0 ØÐ ×¸ü@ê‚n‚4ü†TMÕ½Â0;¨j¥K¸qFýÖÏséâ(•àÏë̹'@Ó` ’t`M6 DŠaFÇ“RÚ@Í­ WEbõ*I´´lLñ3Öy€ ‹€ €d@"ºë®ºë®Gºë®ºë®ºë®ºë—.\¹råÏ™Pôñp…À¶Ôñ0@À€i(]=ò¨¸âÕ\‚í¯ŸÅÀÛÀ —‹p=34PWœ´§ÅËã9ùÜPø¦Úy¼/À Ÿ‹k˜0;ºt€2„ßÍá~pð¿Zº74éžvüD` ¥‹14¶>/æw ‚Ë9bl&Bgè†MûSr… a"'ÿPA‹·G€IÿÔ` €o>ä¨}1«ÒJL¢®µ€Q±xnÞƒ QÄèi0Q:ï™’¬ÒP„#C0T‚h KF ¦x‹íçÞŠ@@€EB€"Ñ`ÈP(@S8@äŒð!>X* ðV¦B€-´<<®•Á7002Y#Ú[úv•©«†ª&#Ûú›:ƒ&pùöŠ%iI b·EåÀSÒ!†lÔ€4 6 IŠÙ"æpG!!W àðnbòiDÎ7dÒâM2öPð\¨h@gŠ'@0•Íí]ôA‰Þï”æSjƒ€é P ‚($*l`Љ òà›‚ØÄ&B³“R10ƒI ¸U®~ßÉ `7€ÇèŽ!Ül »¦Bð¯Hù F&.~LâëÓ Ö\š_€t\Ä®¬” "ºë®ºë®ºë®ºë®ºë®ºë—.\¹Gråü ‡ÓT×ÜPV’dR$™ §˜`\k—À'ƒ)æ@€4<™LJãdES°î˜§IdL§ôjaZ¶’ÔöÍ!b¢©¹Cй Šƒ)‚äÊ,S˜ðÊE64l°Tå1=Å*¼42@ÚnàÓxš2KSÓ|ËK$ezoÐðÁ¢â`iüà—sø5ȃ ¢oTo!9VÔÏÚð SCSGES$ùàÜ„s) Ñ A|¤Ò>ÐóÓÓi­é¾LÿU¢™ï®N\‰(¦ÑðÙüþ ôÌÛòÓ_=¦†Ó#d‹¼^& v’ˆtôÌX 5(ØH‰©‘éé³aÂESiN¦ öËÆM6¦p… `¼ ´þ™ÿ¹ ˜4b¢É± Ó ôÇ4T"ºë®ºë®ºë®ºë®ºë®ºë—.\¹råü „êcï¹|„i1[ˆßÂÕG&DÒà€í( †i4Àò ¢€n6ƒn>¦µ543çGšHÊx±QRi³SÆAµ‹’ôÚµéL‹óSvÍ¨Š•MSÑz¾ck%ÓpÁ1Þ&§é”àÀ Ð>†&št<0ÚÑNPùºÝj±y' .k-:,ª`u_  Ô@ E–LÜÈ€¬m3ö(tPgƒ‹ÄÈè ·¦•Ó€´rЩ¤e2e­h›  QGâïc?&",©ès'`?M²nBˆZܘe~U4§hÆÁ±Y:HÝS>öðlô[Ó£á¯?1^ïŠÿ ‹./Ó^Å•à+‹F,_ôTºnt¦ œ5OA„²‡“©™ a V¶@¤ê`³ÞÞ)FúÜ 'LáŠO Ä ü/  \ïÉò“L=xÓP @Bað€)0e?€è©R5.\¹råË—.\¹råË—.\¹råË—.\¹råËG "ºë®ý«ÑåèÊ ÿ›Ö> LBšF¦Ý'! ƒEäA„ÐÞU2&È!PˆBjRQ€Rn&áwÐ.î v††{Ŧ+ v· ðÀÀ I¥žØ.O ‚ní±Ô+@:,™BkžÓý%šéÒ ßB ֜Փi¹„¸iEû‡˜ÐcÊ ’2GùâÞã]ò\JDW Ï MßþZJÐ艥¦ŸÜ÷ôdJ—oZtÀ9p a À*…Àž÷UÂy±„ø  –ÍY]@NrhfR+‰ÔdÖÐÅá± ¿ƒO*,¢c€âdão`4š ,úà,ÒgèÈ&¤4ð¨Åí&²í Ò`ÈèÈàÐ×ô OU÷12ëöØË—.\¹råË—.\¹råË—.\¹rGåË—.\¹rÀ"ºë®»å4LäÍï@³2 Hjy…ù““Í À“ÿ¼¯bŠ"Ä.BÞÐæë{ïåí°®¦Þ€–^ãûßkjLÿ#‡“¦û ºo%iBµÅþNü Ň¹Ër ¨S‚¢± ÿî|ƒ—Ž<œg@§à 3 ® |5ÒÀ Ör-)%ŠƒPY(]Á 07—”i8Éë5ƒ€í`Gë"‹( ö Â€ÀZyÒF¨”ÁîDƒLh7(B–@9dà|Xü/½‡,@vòXÍî˜É–ñIGIû]ã"ÀPé—‚¼¤c“½¿½ ¼˜bÔ”d€/`EJÐ 1,  ä½ñœˆ@ IÀv ±€JNÔÆºë®ºë®ºë®ºë®ºë®ºë®ºë¦r —,"ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®\¹rçÌ3“JÆÀ&à@ iæ.!$ ”ðÄ€^`EÿÂt˜4Ps‹'EŒò)æ`àQ €õ€˜¿ð@0&О¨èl²VŠ{á„CÉ9€EN+á0!¯É§Â (ƒ©sÞŽ^ÕGà|m†$š„\C¾ÐLÀT1'8P—€|A€¢´_×j£Ý¯Pwúå£ ‹ð ¹|3™ð“xШJ H@v¸šl’,dŠsDR’À;’„tœOðÂj•œ '3ÉíYË¡ºˆªºÀ"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®\¹sâBM5<ÀÀTlhˆ\„„Ÿ\€SG‰»È¾cQ´B̸^ @‹&s8^DÛЯ0¸™(ç@± d†Ñ5õ5ñÄE¡2!$Ô£ÇUÞ…ža0Dp@0DpCnâhrZ3Å“¤–Iˆa•Œ±y°æŒ¸À²àVLC² 0d`¢‡PhÊ€LvTqqPPtˆaú,»ÇêßbÔ¶°"ºë®ºë®ºë®ºë®Gºë®ºë—.^Á ÿÐ €­ðê.Й>,è¶|^ À1Т‘•»˜ €©&€PúÞƒ¯ ) %oèáaÕ¯é%' œ ’¢t·‰xmn Ò„–Áøƒ$†H€0ýGÉØ]=z;gV€4))sBý“ 5awÕp5VX8|4°ø+@Þ•°0‚4%™Ùc  ˆiçòGv€|¤Y•´G–¢Œ¤h4 À1!ádA¾"]Zn$ÜãxÙ38š&ë›_òŽÑh`%‚´_ÐiGÝòŒ1òQä””Á¥ë‚æø©ò‹ÐhW‰q@df¦y1%Á¤·€ÀŠßò~#S;˜äD ÄØß'Ö¦õW)ä a»x˜ÑdÃéÒZM“ŽÁOð Ô™•+NŠ%ûMë& +nN*‰GSNÁ…fºM3ÿCÓÁ‘2˜7%ë‹¥I¦ÈèÏ!”".. ¡— % ŸI…í¤°ÑwBÕ› – Òoݤ ² @_ÒsA¼êöÔÙµnï’VôÔÁþa0ÿJ!! {E—jutÁÞ"0†lLH ÔY3r0V @bi6(—ìe1k¶ •°‹G†õÓ`Ð>¼íé—õ×𿀆¤¦Å€:á™11´HGMØAÄÐÜ!>3H àDÿ`* ?öY&äs)é¾`f €Šˆ‹Wb+@€ÀP Aýb ?ôA Pˆ¼ðPIÿ²È0‘N^a¢f£ 0 ;ç,¾%)äX`0 !ö°Ý ð"ºë®ºë®ºë®ºë®ºë®ºë—.^Á ýãH4‚`|Тo&ž` Þ 7x¡Gˆ?À€ Àƒý`:À~¼g€¥m‘Bu;ÒtIÞÙGHë¬ܰÈ!eÉ!÷²c ¾x™€ €@ Š€D9Ê¢`Bdq@Èñ‘Ȧ˜v¢žih/uÞ-0ÅZSšàêÅÈYoCPÇÄÎME=Æ–PBàÒ¢bC%ƒJJ:‘å{Ù¤aÁ©ôâj õ‚E¯Ý>˜˜™ C {’ŽÝäÄoÑnÆÈ%qGwÌ´/É€c´Š€/±P ù2˜˜ƒÞqd4t@p”W]`g   UüùôC!†bÎNˆHw%é(÷ †X9qX´;ߤé÷¦ ;zð`g}(U3õ<2 i ƒpÊ`ÜnŠLä½µ1€RçñI¶ºÔÊ`]º¯@Ô+¤ü-nPÔ÷BÁ–9)po†'"ûŸMŠ'®ÚÑa­L'è‡À!&@QƒË†Ä˜Qä=8Úg,Ls“GM 0À&Gƒ8BMÔ1#©é†gî\ÆÃ3Ó<¼2HÊj!4L(t©\‰jt@Ä $OIœS€b÷ž.Ö>·ýøµ*O1:(†žptt]yU¯@!ÿ×$|‡ #øúK& ù‚àÂjpé†åaP"ºë®ºë®ºë®ºë®ºë®ºë—.^ÁbÌÚWÒCÇû­Ä<M1aP¨ÃNæ\ªÓ´%„G‰¥®Ãµm²‚a ¤\b`!þ0oòIi|.KÁ?kì"€ ‘!^l@$ày7$miø ÐED€EäE0Ð9‰ö÷p1¨9ì €ûÃx®HnÃñœ*“ÚÞîØ#(´@$1 CÚ+C'!äƒàÀK‚Úï-d¡\+ÄÔá^´2Ñ(u†ï[¨ü˜‘’YÏ*Uj¿ÑÑë#Ÿ~Þྠ«"ie•ÍÐ IGCõoÅ’LI.?+ìo â}Áá‚P@ 9!èô‡ÙØÈV’â‰àrú9Y,D€EÈb1`I {†ËPL§½–ænîM̧2‹ÎÜ+È(–ä„€D’ÁÈþê9!^Bwæp¯v÷MW'Qä tq×fÃå$2×(W—Çð¸'Ýêh )‡q9Çp®@–*\uÕ¬ qÜ+Ø~—Y¼‚J@ JLŽ«‚ûJ€)æC/Äà©7G Ð‚Xg.,¡äï/Š·ÆÓDÂ@–0Ä¢,;Ýõ;”À‹¹¿ iwäR%ØPUÍ'äÀ0è”ÂÉ~>,o­ÊC@®[-\è„ý18*LÊ6"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®Gºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºG9bÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬GPà0)„À 1Z!¢!Z!MÁWÿû€µ…_óA€"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ "pÎ "p¢ÿ'ù/?œÇ@ H`€²i ìœsíÈ÷Ѡǧ`†  Qð€`†·GØÊÎw€˜¢’Wý¬Ý`MOÝ]¨þè †€Ä¡¿t§?lÖ ª°À4„­r®àÜÉâl1Ðbÿ'ù?È,Ÿ½èX0 Àï )cJBHúðWÕÁóýP"õÀLŒÖùÕröEàÀ3 „0Òº8àÄb~×Íõö`@CÿËã8ê@BRœÛe2gÿ.G "p¢ÿ'ù/ó˜ì#0 ¾ÆGPp›ã€`†·ØÊÎvh7bM>á   H@*×*ê€,0 !«\«Ñ $ñ6;A‹üŸäÿ °L~~ú¸ ~p!ÿª_(¾®œê¬ îBi" Hà|g}˜ÿÀ2øÎ:€ É:¢Ð"8 "pæóÏ<óÏ“@8`!†À 2CH(€—ˆ@NC&˜`þ:PR¤ÒY4G$(Í¢Pµƒêc1ÄÈéèÑDÐ*²Oba\@SÀ"€4,P¯€”¸%€B0!¡cLY7Ø# J[hÏ0z0n &$ˆ¡ƒBŸì ¢?äþu ˜‘0Ø ?I`:O7âYAy`@;«Œ%¡9(ç|n€„I&ÉD2adÂ÷Ê/1°)0 `b#€€Ë·ÆÃ`êœÀ` ɘD"G0”á0Ð%‚À`QÀÇEŸh[ {@ .!Z@RJQ0¤ H×mBI®€!€!½ÉÈ"ø 뀆€(‚Èe“°ŸÛ`¸ðДP±IáD0ΧXtr +üz­«.€–Zq@'Ö‡àù  ðBb¾ €34!’°j„¯txâGå¢ñûŸœ¸!< ãQÀpæGYyCvaSö½üËÅ'À¸i4 $7#rÎ+ °9D=Ìàhä ˆi1ŠBF—Ä"dXà'pB` 7ÀLšF@€ÂÀ±àÀI© T5Üy”,ôŒ10–Õ ¬4ý­€ºù: m ìoØá€6ÀL„H%I@XÙ4 (P ’ À+ Ft”Sà$6~CPxb€ØG¢Å ¥%!J€@v’+$²~”uïm“ðÅ-l:_ÇÙƒ6!€5 „ŸˆÄ. Ÿõ ‰12ƒ„$ÂöÉ)Äø‘ ÄÐ>€:‚Š2Ë„9¯dÓ-B I5%tägdIÿb|°0Y0›Ù Ì=:ßøô€v‚ ˆàDNF€‚3’Q–l>NJ—¼73[Ä(Ô `MGhÒ I 0°ÍɼEñ>0ŠQÁÃà&ø°ÖŽÀCJD 2YˆËØ-[@ø@ PKè&pZK 8Ÿm‘×Üs¤ËfÁˆ@—øÀ€è ` C@ÎÁÜ¢ˆ°¥ƒ“JÄÒah,®wDø ðÂai Å ôu@‚ 'ÄÀ€X5à ªh—»:ï¨üýÔrÌ 4 Á¤Ô§pELÀ!J.fïG·½˜ ~p!€^{„Äd—·;ÜIí¬<1@ @'Ä?`C ×ÔÁô5á ;ÄÍԋ帑}”•À¡¯z€ Î"æ&’,VÈÀ€ Ìá„'ã$DFL!l:dTÀpè¼³à Ïh £ó¤¿ïlªÈ0 ¸ÊCƒØÛÅÝ ;p n½í“ è/}q§o¨þîÍ¾ÌXüMñ CðÁ@G&·&elL-Ä0€4 ¨ž-AEçdÏ;x?@ †ÀTÀÀ DÀÜ!"lº>À ˆ œ‡öt›x^ŸïRU˜â¯1{;Oá¾ä ÁFÌÒ±7eïlëŒ 0zùø ~h!€1Bo¡>?ö&¯\ :îB ¶,4Ã#^¼?8À/®ò@:0(F½h ~p!€^]ÜB?úGÂlRH£ú¡H^Ãýðà€0@2 ÈÛ·÷Ûaœ†P õðp ` µÆ¯dmjL>xÜ»í  S€1,fg]ñ}p?LÿÌ:èÓò[  ›‚,Õ€’À‡@ɦÀ@ ü4y Ø4dœ"u·Ð Ž ÝH2ôà`)ÀvPùx Ç ÿ~NCû’JàPÛºBÑ iB&“R80¤—‘¿¶G&f FBI>ãÀ0'Hb  HÈÌ¢a @© ú  “›€j€IR&€%õ€AÀ|DðI *  AÐ Š@‚HPM;`ÀÏÜ–¼@¤ §€;£Ê„4â xh¨- _d…€¤ˆ< bVu%W@@tˆ"€à’@T@æ€2`Ü„bK¸2¶ëéÑ /”ÖbWGÃ]UâKÑüs}X?8ÿÕ*¾TVùó*ú¨ ~p!ÿªUw€˜ÿì.ç $Qô@ üC/Œc¯³ø†_ÇHRN™è"pæóÏ/ò“ü„V &@à ง‰¸øp¢hÔ04;qЀØðrS±x &à18&€Ty+ãmÄE“?ID£vj-I{jìÀ*&¡¥wBqðƒ;Gèà ° („°Ä“eÐß|ÄB|q06 äçÔĘÜy8Û¦ŒÌ%†hH|F5â—«!vP €MÃ7婯RCGÇÄ´1@P p&’sëÖ€Äà;Ä7†“RÔòpu±0 Ét²¬ÒM̪;ÝÓ|\¨À<0Eöœ}ñ` CðÁ €MY0ú<€ Á H`*÷Ü‹Ï|4x!€i ^û‘`9âkÈ "úãÀ†å^fôÀ†å^fí ¤M‰DGïóA Ê}ð!ÿ±0zùè ~h!€9Bo¡>?ö&¯^Gp  ‚î€ÐÑü @†¥ÄkÖ‚çàÞH@†¥ÄkÖ‚çàÝÄ Cÿ¬&Å 8± ù€€…ý¯@ ÁU @BþƒW `ˆ€*Ñ g"Š6ï®é‚ù‡_#÷×ôÁüïT@ îRi"ÍX˜DÿÀS¼@ÿÀâÀ©%)Qû°@ý r`If'G]`€à €3 -=³·¾^bÈF0(ZоÈC&€è7”^èJ9ªº€tœLaÙ¬ÃpÄÑþz!Ä †!(ï¾z  R>û`  À#‰D2° uû½Ïˆ ~Hä2º „"ü5<9û®žbk©˜{ÙÝ G。ëðÝ çîêÁr6Ò0ÝŠ- xOWï±À©4!¼°ÔòÒž¿ïGT%§œ ¡‘€q¹¢ìK…û^/ôÑüÙÆ®ú¸ ~p!ÿªU|¡šú¸ ~p!ÿªUt€ÿì.ÌšH£èø†_Ç_f$?ñ ¾3ޤRN™è"pÆ_<óÏ?‘¸À;(”rcŽ/)(ï~…åYø˜X Š@!€POí+ÿJ%¸Z}É€z²  K`KW·’4} ÖGA@P"hÜXiG`Ñi`IÿÒÊÜ ;í-Ų¬åÿÀ¹÷‚,4±,PÐP((À6ÀrNdàÈQŠXË‚@‚wýÙIᙑ]vÃY˜Ä"€ ¹+0Ñ„§’=þýíˆ{€@t?Ú”rXCx\žT€` ©D0 ÀÉ(Ø”O%¤%§ aÄ ¯¥2¬?˜‰ÄG$À€ ¿ä˜°Â„2aA޹ "8‚×€Lpj ºlý‹&àbÊ-% _=Œ@@@1ê?! ` äÔðî€!‘À0l€ (M(š†H KÈ HCPG·ƒy4¿ eˆ .HŒX"¨%8'ÜM`:(@9R@$y%§§2fmd(E€5&€^²i $-òæß°s G\L¸ ¡|$/‘Àa€Xâ%<ÐŒØ b!€ZÀ|”J' IçÒ—¼”ô÷÷Ím‹@€ì Ê@` ñ ¹àc“IÀd0tB&€è40š{‹%}Øó¡ÃÀSyY±ÁÔ|ƒlŒ‡vÌìĬÄf^LÁ€€T·p0K'ʸô½Ü_BFãîŸ5ŒÐ‹eÀ0¼¼]›îÀ\Á`pÞä aŠKmGœãƒü4$ó-; PˆÀDG À4ÀoÈ` %’y,¢40 wÓ¬ûKxl€ÀÀÀn Ø”I©£@ñ=íw‘¿v¤üßÏ<óÎ3€"pÇ€ªK@ ¼£Æ{î¤?øjzWß½ùé(ÉÍóïzp‚8ԛɤ°*BüüWCp´{Ô15’§¹ƒQÒu¨3,šYhߌeã/šPCRÄ{@À 4hJÒ8´¥iäíg G†¥ˆö„2ðhkê ͨþîôÿØš¿|üÐÀ»èAý‰ +÷ÏÁ  K¸@¨!€0v·(2/òº–` &÷àý‰€+×€Ë0 {ð@‡þÄÀ먆ÁvA 9°ÇDÀCR€U¢‰€†¥«SØ€¨!€)`*ñ ‚–¯GõР‡þÄÐûçà€€†¥ß@zìM_¾~Gh` ]ÔA ƒµ‘@9¤#ò~?›öB<þyÆp"pT~~/‡ëÞæ”&÷àý‰€+ת`2PѬ)€íÊјŸY€ !€)@*ÕΣà>G×Ú@ AüCDÜ@0Cÿtˆ½^f %1Ù€íÊBYª>¼¨áÄDÒa0éìä]!)ž€ú¸†(¬äÒha3-(Aëî ? |_ GØk6üÊà€j@5/–C-%þ?‘¯@É`9P€;s€V*â-p_€ Àaøà”A¹ÈJ Γ‡ï¾'_¢nÀ 1tMCøgë+þÁÐXM ÿ‹ŒC¬½þÀ1@ ÈEÊ99íÊÐ:CC ˆM (1L´ä`¿À€5 ÆÀP„RHÜ¢» ê €BZ/àdd (XíÈDÆÂ0Ȳо­IKQâà GÀnÀ`&pGÿ²ˆ-`&É„4 (7)98/{ô=ˆ@à1¸¼Y5%qÛ«‰Ç]ü ÊO¹À-a™ˆ‰ Ë€Ð0_ÐaA»1lSrt@€§~LÈ< h 9˜ŠòÖpèDÁõ@`€BɉǢ\CÀø ¤„^$Ew1Œ`; Q„û´PX À(”€˜çZ ËÈhG`8Eö™˜4G€¤9eå#<`@L–’‘ñÙñšÊbÜÆä] Uðý êÀ€ À¨©Á|´šP+¥={DÒ`K Ä[ Žk2 š‚5$€Âø¹ˆe”þ‹(0RS· >!€bÌ4†_€ à6™_âIaã  1ýw°P«iADÂi0 ö! 5 I ß…RB! ’Z”ÀÄ€/Ðri0 G+ÒC&% œ%(ùÓ€‘< [oT¸šéN7ÀúÀ0À ´@¶sÉÄ@H– 0@üðA2‹) (AÀK@   ¢5!€¡ ð<‚Jø4nqŒ)ȺÒcÑù÷® †¥ˆ÷¸40 xp*` X{e” ïq#ÏG÷p ‡þÄÐûçà€€†¥ß@zìM_¾~h` ]æPCG`ítš?J]€ I€ ˆ])Zy!ýë!=µËÕf¨àØh»J;ÀQ '\a`T™¸#ÿî€ÀB Ò4†_%àÇd`èÀ#™h@á\SÛy…†’j“7 @ðÀ/€ “ÊJBp˜0˜‚À¡x4„ZI‰Æ¢ @3€è0¢i@…ÿA‡—±&}Ææ^#KQÖÂàÀ&!l™0zÏJ¶,Æ“¡G‹2º–` &÷àý‰€+×€Ë0 }Ä<e÷ã;ªê€!€0]hl)¨>€ RB)€¡4‘€Iâ`hÀ¡3Œ !†#Žåå ‹ˆ€k°fO&ëm°bìØøÀ°¬AkxÄÀ@€˜ †1€TÀšXÓûh€4(®4¬‚“Žùx¤0$"ËÀ0~L p‚‰© CˆJG 2¥¡ÒNðÅž«|dò‰ †¥€«Ì¼ú(†` X ½×@‚û@W—}è!ÿ±4~ùø  !€)wP0ÖEæÁR—§F… %2I¼áBoQrûk›ö°”˜MH!”€2XaeÓºÕÁ €“0$îˆDÒhÕ$°“RX¯Õ„c´`ÀÏšH’u=¾ba„í`Pd"G#€(iE€ ?¶€.@…Qxî„mÈÐ8 ÈDÔà?&ƒQD>‡ 2œ ’<1gª4gÓa'ùçžtp"pT}Ð@üÀCPÁ7¿xìL^#Þ?0À0MïÀûWˆ÷P ‚ìƒ@sT€ !€)@*ÕÎñ ”­\ïi$Ñý,¤ÿÄ4MÈ3?öH‹®Râ&ä‚Gû$EÔCpíe€rGòÎuõà@ý@Cÿ."ù:úð ~ !ÿ—uh8u‘4‘Gè.7Ô ”L~ø˜ À\BFÀ:&%,´¤¬”ðÿ¯© hå_²jQöÕ“™èý8Àœ Y@P0˜Œû”Œ‡ÙwØKG)?í|\àP4^û°¹€v¾G¤½;î¶™55Ë Hi ÈgÞó ;&âG0²ù›ûׂ¤MÄB_(kº‰¨r ²G£úèP R˜ Ë/ÿóö¹€¸Rk–ø˜ƒÅÞ­!÷ÆÀH&\WÙºWî@, P‹ta©£ã€˜°À Š%˜ å!?‰ÿ=ÔjTøò“Ê…ƒLHb2ØûÏÒôÀ-/ws’°ê?¿€b h4“ ËÜ.倸†\P@üÐ(„R‹Ù|û´TGâyx²Y1Å{¥™,.âØëè€úŠ0›çxímzd„E†|ï½é‹¯s' Ö¸ÄÀŒb€`´ÊÃ%Õ¶€” €;! šS q°€¥“I„2É…òB| >ïba4 ða¹àÒnýq•”ª>˜ ~˜Ð €tb8IdkêDÀÎC B2ú}ÉFÌ%÷ݵÊ,tv§»¤˜€ G‹fžKMÏa€0Ф3·÷£Ñ{É„ÌÛ¤ñ†ê××Aô‹éÍ[]d HoÄÙ†³&`†Åž¨x``!0Œ!úÆ·( u@€ ‘‰ Ê¶\´†™ UÕµ>Û£0) К’t°06bèÓ€€€hœ’Qã.Ï€€ì¬M5 ^%zBz>¾º?µcïGŽ‚"úé  ©Ã¿¾DT`‹¬ Y 6Ü´Àa5ƒ³0¢jq`1®)kÃX1" @T€Å€BCX l `ijµtÐÀ»ÄPCRÄ{Û‚—x€*` Xzà;?û÷a#QýÜè!ÿ±4~ùø  !€)wЂû@W—pPC`ínPhü)i%#ñ×Ú À/GH`–¾1¶¾Dõ$ ð{îÀWô“Küº2BÿAf³>  P0„’‘–ZE@ 0:|ƒ …%,²ËÈ,¿Ä§yd˜45‚SÏ€–•ÀgºZsÛY€ À3(Àî41…˜Lؤ¸™à'à;¸ ¤„_JòyºrR` € ÊÀ`„M`—€,à\g[ijžÐ¿0p[jB\ž“°&GК4R` ôž“­@;2Ñ÷AòÁ CßLØom|Ì?,À0Mï14$ÄsS®(…dI£ðÀ@€@P²° Q‹u ®pxûÂ]Š:8Å BF(1ÇmªîðÐ*ZR}Š ÛXQ³0ˆ°Â’W8 &sË&…01d_ÿs¾€¸Ò“¹Íà@à0rXì•I!-ð‰mGGh0þ¨“Ý%+Ü*` ‘ú ¨k$5Ï@¨!€*D{بM÷!]ÑG÷p ‡þÄÐûçà€€†¥ß@zìM_¾~h` ]ÂA ƒµ±@9²““ vH …—Ø#~i$Ìš¨ CCR·ý„@@–JÀ ˆ€ t3Ÿ`:XÔ›A¦Zæ4A€“@È÷¨£ð‰ ‚€ˆEØ0ÐG  Ñ_ñ!À ä,0 œd$"a 4¬¡€1z€Dÿ XÿÜš1ˆiIn¤¶ŒŒe\´˜Å“@`LA0´/â³n•}=$ ÑÝbHÐ%æH`'û™Èa¼gtzz{ÿÿæû`Ä%’‘´§îvj?‰ ÔÜB“Ïٽ½À ™n¤ w¼=êT N¹JîH0‡ùçžyc“û8"pT}ÀG@üÌ@ &úÉgî¾RB¢@b¢z3ô.ûü1.n÷X »“ÈšI£üüä"¸5RN÷¹Pª¦ˆ&œ¾LJ7äýÃöíav¨ð˜LN!@+/åb²X?ü×jHA¤¶È–$´1ô@/HРɢn( ž/÷H‹Ø€ì ¤dÔ†¤ô÷¾nf’J I 8’uÀMÄ&ÖèYt~úð ~˜!ÿ—G|†úð ~˜!ÿ—vh8u‰4‘FA ü‘|ƒ__,?òEò H 9™0ë'B`DpÐG8ÔšôM\ï—€,,^4|XɸS@  C¤r-ÄÀA@C”‰€v¤3†€`v“À‚€†)) ÄÔr¸GÑ-DßÇ{ÄŠ?³¤!Må #4 |éÁ…þ©$$Ÿù´š?JjBà)-•x*2D{¬€ð˜B‘ó%+÷$ €L‘öªF†ÿr™wzìM_¾~h` ]ô ‡þÄÐûçà€€†ÅÜ TÀ;[Gš?6”3†€`MØuöòó'î>üúC1 1%p?šûh° ’€ ËGÍ¿ÿZ€h•tÒCÇz?P¨pðdP’ñüàUâƒQ¯2 V\  _òpMÿ«ê €¤¡5ÓºC9'b%óBiY<è+"òw#L €Z„„ n9à¢WËj:¸ Pv@¯ù8&ÿÕÐ( qd>0( à=ÀvG|G!®é/ц H`Ÿ†§¨–ß#v¾‘É¡¡¡¤±¼—û¾=é&C/:R”>’±Ûz?‚€€ÀÀ·À&€6ÜRX%ÿéi²^   p†¥.HÉ?a'Þní q½øÑv(8u °„üóÏ<˜äþÎ"pT|ÊAhèN}ï£'/!ô¤ €i‰{¯†cÇß7†ÿ^Ù0š’g|q%4¡H`0!€Á# ¤ÂÃG>1(è#ÖMHŠI|r7ü~r.~ÜNz`Ñ„„!6×®Dð9lgP °À@à @NZ  †pCØ5E¤Gè0„ €&& „LFB™Q|¿à*M¼š+E ¡•Q%tô ô€èà Àª’B0& ,¢¾““ôM!„g” Ô~Ȱðk’CÐäÄ0Ð(M+¥_-«á¿Ö^ÑG š~ì×H¬N„ ·=% À<2E€¨RKü Û§²@€«’¢Æø”Å:í+£ÜV  @L¤à*d.ç†W‡kÈÊ’úOš÷K)üë‰fk0D^°Ð^L>0¼‚Çx ÃxîHI3'ý†!% =²ƒäîÔP@½i]·d`̘1@:ÈP ~°bq\?ì½Ê(/å‡Iöü{,G'¥<Þ'—‡Hc$(&€^¢` ‰HÒC@b‘€]$ÍÃsŠñ p Ò  Ê &“©HÀ|²ahAãþÚííÔßXV†jj??}4?T§ÀU0Äç·¾eXY0š9X½‡ÞÙ4É{‰(¨û À°ø%9ý¢²²µ*,²Z„fÍd!žä£'t'>ö4àPà€0Á¿€ìîŽëH°@$š}Æì¤¸#GæJúÆóW æu‹Ÿ¶P …ÅÔŒ&¥#Š áZrBiÀ*,†Ðœ )¾ä?Åãð‰.ÄŒÀ*´€ñPEà@@1&?Œ0 ØÀš0€1mЂñ1 H4!!^ßÃxÜÍ0Eƒj(pÀd¢’¯$, ¤!¼Ð>‚Z“€LCø/ÒFø gQðÕØJ" $À!!ƒ@@`s0!IŽ G?ú`;OHalµy<¿Ï‹O‘§L¬ÖÙ€ ÀcÒe€v^åöèÑîˆ?\€9B`jvKÐà C ¥8e[κ/ÊÓsì$TKx@€Á¹49&£´nŒ 8€€ƒô”Ž@ ¤ÇHÌÔeè÷Ì„Q$½…~Ó>6Ï?n%‘- ÈÖßÊ‚`§`(Óÿ:ƒ0’øA>ÔÈ„ GÂWH À¯Î!9h@ äÿň™íÀ@P0`$Ä– +‘’zI»`þ†€À@tؿ䄭ÿ ÉMœKc«ÌÀ A þ „Ì þ~àˆ )<DBÀ†Z &BÏü070IàÐÂÀÁC)9ý„eT` b)¸&|í€'(h>¹ !&å818ü•r{KãìòNÉ܉%Ü’»p„ÀÀ:GrCÆ€¼AøÔa)ÊЬà~ˆÈ\†ŠÄ²ÉAH`¨± BPà2¼ÈTÊô~z¸‡¿ NÙûsª©{Ê&€Èé `W” §rûtƒ~áù À Q04ü€™ˆ`_þŒ“¿ãJÑèüýÙb¨ 3& HAx‘×—¼„ôwʸ~{ Z ˆà @2ZIœšL_û&t0¶ÏƒàIG¼A‡†£ }ˆ±ãø]‰Û‰Û‘$àà-ò âP¾0Cp ‚ò p€h€€;¤,œ´†»¬Àè±¾‹vRƒ¦Ë°b.£¶ÈB¶§žyç"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ!"pÎG=°ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ""pÎG@°Áàá$¬H„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGA°Áðð HDMVˆÿüüððÿ¸ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG · CÉœ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPàß„€!Z!iáßÿû¸µ„DCA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºï€4GÔä2?+à­^DôIGׯ0†^ä¢ÙÒ$J @€ €€f@',® 1^ˆüL€Ê~YHHÁPß¹õð&'§g€tB;UГ¡ü¹råË—.\¹rçÄ¢ûeDÂiÔó€/n8J0$ð  `ht–ÜšÀŽÅ @€`~a&ýÀ†PÂF ˆ_úy€ €2Ì öG?qÚ²à`"BƒK>µ.\¹råË—.\¹råË—.\¹råË—.X "ºë®ºë®ºë®ºæ߆ è¢Þ AÑD3½4æ<&’Cà(¨á4’@A z(Úñ@ŽÐˆGkõtä òåË—.\¹rä7°‰0štL&MÓw:(“¸ÑD˜5Eziy@Pè›âˆGDßWAû_«×]u×]u×]u×]u×G]uÐs "ºë®ºë®ºë¿@„ø1Á< å4LI‡<‚i üñ¬K:Ú›HB<BxºBQÕõ€±Ø. ø”~'ëPôNÊLI,Á‘dÒ»@˜èò §¦’(0hg zdR×D%ZJÚ›3’ä8q@¿n†V|òŠ'è„^å‰úó]Ѥ׀¸+ Ÿ‚î!€ßâbDDÀ(6G¤$gY(<ªBÑ4·íYté jF+€yâ`ü0x€u¿H¸¼ÔâF’€Ý6(-·ÐÔ£áÀv(·(÷\bZ°éæe¤åwÀ,-¢À`ÄhºXe'ý%ô:r¾#b/¼0y9ˆÞ€¯Ïà)‹sŸÛ¦Í%?Ü.!`ßÏFÁ`rN„߉ý^%s{?þº|؆ €©# ÞM%ž!BGÛ»m$ —†â–± G±Pg?ùÂh†}ŽMiš‡‘ˆ0bCF·'baK9v|MbFa:Û~›4 5ÏCD<ø“D„XMÆ{mM'œÝÎ’BB  sSanM%f_YcXxŠ &™å’ídà?˜Ÿ$ggÌœO Š&R­¾Z Ñ…“Ív\m;vøg :¤5†ÍÒ7tSL;0 ÀŠ$ÅîtQ&-EziåŽG‰¾(„dMôNv\¹råË—.\¹råË—.\¹råË—.X"ºë®ºë®ºëàœK0‡6¼†¯Rt€ù²C®u6œ0âø°fÛÀƒHGaa²55”éC£440 ŸÓ4×IHsuV¸6(†uÛ¨¯²f¤‚£xv€Ê8E5É 46 Š¡¼ˆ°+H>äŽæ[ŒÀ^_úò@þ†€Oî8êc\G¢f~”Žƒ‘Ô ¶DÜŠÀvµÀÐá¹"/¶i$ÐCÿ¯i°Â© pâóxa§@O†Sa`&ðäÞª$ÒE$“MB¥¥ütÉ0 €©ñ^I”áQ;&6*¬™˜èùD€è S©ûÝpÉÆqðÊ$ìØ¬*¸Qq–•_¤3RÏðh`!ÿÝ–IMÈWNxèR>( bTÊ’KGÆSðÌIDXnAq`&,MÂnDÃjrPé\¾j%N‘1@‰ÿHMäqeþtPƒØ¨…Ò‡$à·"ÈC¬@“éµ@ü ““‰ä *1'¾"@(, $$År‹°¯6@#.°¢‚IÎ `–&Ã2qû‡ÀPb@ÊxÎÎ:Ú›ƒ&®€I€ôø£âÐt©§å ÔÁ„(šš@§;.\¹råË—.\G¹råË—.\¹råË—,"ºë®ºë®ºë˜# ‡Ž€t³dïDÜú²½4š@Ž˜®¨ ÐÃXØ ÀÒP 7úJWM–L8É)ì} éBŠ'`(Y|¾¹°àMš );$›•P4˜FȧY´Ñ˜pi&&긚I‰€:‹2F>ž€hÀtXà¨ÀtÈA÷"ˆè}àé$ÐCÿ¹ÔZA þ®v£û€åGâÏÝâ‹r“‹A—øÝ‹EÐi”t€Ñ^!™d´’>ÉN+C+нYäÄ€¤7#‰¿œÐÀ-”xøaçÝ…®¢Ž艅™@1à)De¢îäzL(E@rT“ DÒITȼ€å *N€”H€¨:F>åmú~œt“ôà EØê}%` o’SP÷ $údÂ!€¸òwI½sÃ.ò`.H €GtyvDÓ$9 uIÞ’: Ð*sÓeô:9+° ‰„Ð(¿ƒï$üªz3d‹ O@Pp&—Ë>dsTOBpèT|^x Oôü0¬EµÈ|w†”܇'€æÑÉDÛäšo?ÃQÁ€R&¦)ÌË—.\¹råË—.\¹råË—.\¹råË"ºë®ºë®ºëÀŒ§Íʼn d¤æKÒPƒÐ Ë9tÙ‰GÀ G 09!ŒI',ŽÖôÚš ’QïÃàÐÒie« Âwà™ÿº›I{¾Àynp«HJrG\¥Œ½Û4ÊI,wläƒI\熄–K9̺(Û–üåC”—GÂ=좜‚ÊÑÈŒE”ÂÅSäÃ1ä;RJ)'~à;èä€ÐÀ2œ—fäZ% ¾ÎIÉŒ†v6 í‰ @¾ŽC3CY.å-ä©É9#Œ¸üì€%É'Y¯u­GdKå8TŸß\—–Ž1#c\]7P%Êèâ ø?õ0ÀûoM†$CIegÑI+s˜=Dg¦ÌXÀ °N:@bÿ·â®‚ ¡'d¤—ÊÛ€òÿõ4%qDø@™ÁþÀ ·¿ÔÑÉ ”k€{$k™K—.\¹råË—.\¹råË—.\¹råË–"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®Gºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë—.\ý 1!r–§‹€0à À#· xÀà& ½ŒHïL(¡ÂpªÄÒòÁ$Àì²ÒÐo,}gÃó@` ØÀde1²r`@FD"aÚ&†•‘Õ#zºëà¨!@7óí š^&-$蘓ð˜ ^HÂ. `ØÝ ÀG†ICð†öÐ` ‰2@t÷í9ª0åØÛLˆ4 ø †8‹ dÎðŽ~’¹ïK¦ ¼“œ?(c H‡ =Uu×]u×]`"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë—.\ð)E€5å·€LMÈ„\–áÑevõéæ6“z@È|Ñ%¨ø"@€'¿I -Á0`G1/€¯âŠHe}²=h0` hA `@ð ´lWh„†<ü Bëe#@‰‡hä‘‘˜v€vOŠAÕÚÍSŒpôëP“ð˜@€ãƒ~èðE+‚€G&6¸“eý@ €.$Ù@‡ÿQi?Ö©÷¤SS¡$Ó`“d3ƒÈnI‹E4h€:2!ø C + >’zL…G6íu×]u€"ºë®ºë®ºë®ºë®ºåË—õ3&$“„À:Ä‘„SÄÁÀ2̸@T²(¸pŠÅ¹”ÅâäÒ΀Ÿl³é¡€ Àqfµ5àp”cp\è)hÌ “P­ 0l¢‰÷ Ÿ˜iÏÄo{…@ ¥Œc°èW&¥ßÅ’…ÓÜev¸Ä ²G"ÆqÜ*: !À(B°² œ–ZÛGç'S:d\2À.J3€Ü ¯:ÌÀT·Åœ¬™¾ôÉîZzvâ€-&s‹+ˆûÄЖ~€  µ0å`€©4bha`ŽiG#x„GH 0yH‰Ânve!| ¤ Ô€Ûl€ P0¤*ðPu0H°&C8@ X!€A3@è(€n°(LáÒ9{g<8ÛS:& Îž‚G€ €GRR<œ‡ô÷pAüò \”dp€‚­!\tê$ªa Pf°À¡e¡r¾¦y å•#Ö 9aÞ2))ùÓø|nM8hgI> 6K¦²F-䣈ú&0òn gþ,à1%Ä>ðæ@Ñ@\íÔŸÀ Àè@'×!„cý0[~Ü\4膈±E…Å€ë7§ ̼3`Ü“Ä ]É:GI0èm<À* @ý *¡ ~±07°tL&Å ê`¾lÅ ‘ÃCr„­(ÐÍTp€[hߊ§¸Ò"³2W¾ ƒN=P"¸µÀ¿Já8\’Pºz`z„p~-Ê RCÐ è4·ä"g€A~ÀhÖûf˜d "Ô\L›ƒ(Ø7æ(± ×)>¡€€臉N“ G°ü”ÂV¨å\Rà€`†¤¶°ÒÇGk„æ;ñt5>ëþ&†vëZÜñÆR¼€Â`Èh$qFÄ¢ R %ôpýpÍ€6B/¬ü& PÁjáðjBr›ÎpÀ(d0 d2i)Üøˆ(M˜Ð%ä“I€†”P Ó´äètÈÐ È ;HýûÉ é?¸âv…ÎXTÿ ù G73¯ »ÍPyz,4…˜–LDòv©†«®ºë"ºë®ºë®ºë®ºë®ºåË—õ(&$ü&Ð$Œ"&$ü&Ð$Œ"Hë… ÀÐÀÀkýx°Äš@!ÿ׋,ðê×v²½¦@1à8@‰Ó ð E6¨!êÀvˆ„«Ø/ŸLŒÀÀ'Ï‘DÔ„¡à ¬eÄÝÛH6˜.f€@ @0$AœãÊÐGD0À0BÐB) 1¼˜pTpåXKŸk¬ ¡™ ÝCCxETL 9Eúf ¹4 ¶‰h=NÐi€t@¼3S—0„B&tõóà P„B8” Ä€† ´ûÛS6É€€gÒ—3rlZCs¿€“[À&ÙKöü7SeóLLˆÿ0 âi`!%PЉ1ôKOÍ6¹€d<+À !2&Hø˜GhNA}å¡ nw¦@ P,…À¤>2€<Ù ÁrC@§òTê¹0p,8‚`j y1@ F)¤ (á…ö2··3S ÄÐb§Ð$èéYИ`Ä÷‰€0ùâЕSFhØ$Äq(Ð €¨@ º`$€L Ã"Ò™$²ÇÊ×p%‚ùô@í=0Eô@¡X ø † “d¾ŸGwÙô'þ&Ð"Ü”øjb¸g½Â«¾‚A zrB(4S6pÀS É>Ø€$ù!PÚhÐ eÆ"H ˆ`;ê¢É7Y S Œ “RM Fs  ËCŽŠ&-=Ï+OÛÜ€ªÉˆ&pÀÜÿPéñ ñ…†#îi+o ™•ö·òµ6ÍD ±4#*t Ѐ©[ÿhBˉ£Fè£nýè+0Gˆ@‚‡HÀ8‰€!›“ˆ´ÈØÀÅc Ð#‰ÐEe…@1&%?Ö¦Â=%0( ¡ŽÍ^ði ©øûU4M #è4Tä„·TNXL€€q Ï®hÀ'Pì-Ìáq4”™’ÄÝWM0DÑè0ïP*Må!¢‰@ø[´X'Ÿ0!öF:ƒHE ##tóXè¡¥£öOÂ<°4 “]ÀÉn!†%à6É‚-'S+‚ÞB¥Ë¦µÖ"ºë®ºë®ºë®ºë®ºåË—ô‘@°@;0@ˆ05 ä.R8©#©‚'0Ñ0ðÀ!‡@“¼CÐj‚y½—• ¦ÌÀS Å’`ГP»€\1?œÌ7ÐÛºA±ß\‰; J4°å¢G–,ªa a&°€`|B‰Mè]ry!TÁxõD0œô죃ˆ± &€²ýÉRðѨG *JJB4O@uÏ…²gPM!W@ ¼Y+èñIA)91e¾Ø½§ÔÔ jó+Aða@ Юû@ƒ@l½¸„!¤"ÝYï'St‰€ K/mâ` É»À€vR`×ÄÀÑ¢7 @P bÊ&$ÜÕÓ©G¶TÂ`<bbà €4IÐÒ`j€nŽñ+ÜØ€K úHkû¹°hìVH¨3è¬ÄÒg çë„sã!é€À ., 9¾Òx ŠâÊåb´`1 GAA(a8ƒ$–þmr͘G£†–ø˜…l}‚/† H›-z™ðõ Â|XÅé$0κ&À*Jì52ÀÄÀ c‹DZCZB¸”li4`Y1!‚ë€:%ï~G!$‡À`¸T€2÷L/¸´pz, ¤oð h ”°âWþŸ†®O èë¡´Þy¾Ð`<#À6B ÀÉ ’PnƒGRè`‚¨4“’S6`ÀXòI0À¬ù$™!ÚvÐCÑ4èíP@ Ã@¡-”„ÝðìnrR“‚h˜`;‰ K´B,†WÌžJN;Ü14Lï¡£  tÅfG Ø`$˜zÀžP‘ÈÉ"é=®L#ºÚÂ]%ø´$“`‚Èl\²R×äýv¬ñHg}E™(XÙCi¼˜g\²gT°1=Õ@`€>„É/s+Sa…gà xi3üO QôoM&@” Á„KÌ|Ä„¡†)DiúšõÌ& 䕆 œº-òz;y4Á,m€ëª@tGiCHD½:`Á”aÒ|a‰|@&!“>IÑ v$æ‹JõЄÒÿFQÎ| o1ùò†˜F’ŒVä²û󈪻vh-el^͹«óð2y:¥ÓÍ% †ìx:W¤O.\ƒ¼ƒüƒø"ºë®ºë®ºë®ºë®ºåË—>À„ Qé‚'1!¤.$:×JP<Ÿw{ΊlÀ€0ß–<*H`çñÖ¯úk£Y‰h!`GÏÎCv,.0@ˆè +¤lB¿sêüŒ„™råË—.\¹råË—>7¤Öß8H Ƙq: J( N$£{`'ý@U †Ä0_3=­$š\¹råË—.\¹råË—.\¹råË—,G "ºë®ºë®ºë®ºë®ñ Á "P¼À!""à :¹Õæ<“AþG DòM?øX\` p€Mè£êü ¿—.\¹råË—.\¹sã&“X|LŸõÒ` CT&Oúˆi0!€ªù˜i$ÚI4¹råË—.\¹råË—.\¹råË—.X "ºë®ºë®ºë®»ô @BG€túcnŒPRœ´†'"\üXÇø  vx¦F YRÄÈøoFNÅ•  „0 øÂ`áÔLRËÄH–*áÊ€€¡†X"€& €ºz€=‹¨4 ô3,ë× ¿Z €'!ÖXؘ>"*`Hˆ\䀪 ù½ojNj,   €G2ùÚ&¦ÉEtóˆðFBàU áœk“ˆõ»ý€™¦@‚úø„€ Êp_[åÛ·&‚P‚oþÃUˆ€ì4™¹ø.ŠÀ€ãîÛ‡¨¢‚ºGXÇŠÉsH ‹=¢’£äݨ@ÅÛDÀÁÐ P¯ª»: I,4 ,<âsÁ¼3¹Š€ !ÿ¹Q šI÷I&y`X ¤(Å$¶;H@‡ÿ!Þ8ié­¡ô*0ÄDÄ£4€*î™ïH:ðp€Â+-Ég@P˜lìàKa¡p FÞn«¢¡Å$HN+=R¯à”— €¡„q7ëc8Êᛄ‘O ‰‰É /–]·cXCPg@^­9ÐðÀ¡`rˆ}h$ªÛ@¥”Z@:G?Gxd/‡ã€fИ$°öR¸‰Üš&@38¸Á9LCÌâàSu&àg‡¦`4“ $ÒåË—.\¹råË—.\¹råË—.\¹`"ºë®ºë®ºë®¾Áx““^’JqõˆGÈ„Y+·ƒJHÜÖfði0†B3q7uÅy 5Ó„IÄ0€’aIãܼ{@&»“L%aÈéÝr¬o5ô`¢>C¼GY 1wH+µfhXl®¸BÀsee߆]vàW@g¨¸ èùIº–Ð`“ X&:%ÝÁ$5 *Q'@‹e@††¯@ì™Ã²­Õ[<˜À6/£ÔY|—™( RtJïaÀ4'V–tK!€ñ xá¥LJr30¾Ñhw¹…#¤„I€bI@¡&8$];@„ØÆ@O€le¤Ë±DÀ `ÒiðG°i4“ZMÐYÔhP!ÿÜH^ɇÿqa–šÒ! ü€Š8i%!ò@2?ù€NY%!õÏ­§ ¢h!ÿÂi'x¢h!ÿÂi'zAÚá/!(†r` Š!³&1Ù:á8°ôÉ…DQ4˜¤À:Ó’²à(’g t á"ýì×hnR@¢Æxh.xJè€pàT˜sq1c:N¯yDÂøi4fÁ%ñ0 ~z{6ÊFÁGÍ®O²€ð¥Ôw@‹Iy0@P]9`z…Ï®Å0†™ÅÀÊbhg “àÐÃ«Ü ÷ÌÀi&I¥Ë—.\¹råË—.\¹råË—.\¹rÀ"ºë®ºë®ºë®ºû¬ ,_ =h €À®°ÅÍþ­™a„‡³À]8b° ËäLA¸Â(È0„BAåûïÍ`à;p]0ر @—%€@me÷àB´e4GP!?JI.aÄÙ!  Œx°9 ¦uŸÜã‰ôÍ]–JpÎÔn÷ º%¬$0C4”_FScP—è4؛ܖJ1ÀzàvÙÀ†5 €R†$È—.\¹råË—.\¹råË—.\¹råË"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺ë—pþϱýµh`¹5$$£²ƒ—$´…'厧§˜B!RˆH—aK€ Aõ$”×pÀ›ÿ°` †åÀ€ ‚ûñ0 ÈDÄ»¼Zz)à`@509È@dh`Ÿ@ q«A¤Ôb’ÚB;ê˜Êê¼ÀP``òpH2†€ ô„#ÄÒb1io!=µ1©€^B I)°ô`GŒbÙÔ˜ÿéH°($",7l>FM]sSR”a¼è€=Ò3’Á$ð&ÿì™4À" @¢üLÄ!.õûSV€À(M@À&pæ"Éå}dÈí'D¼ÉmW]u×]u×]`"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë—¦å~„™]z)‰|–’B ÷[wt¡ý„ö‘ƒJç'ÃWàÁš´Ý>vTKÈ Ì^qgzÐÒ\3„çW¯š@b`:€4( tpV2ȼ#u ƒ7ØUˆäëÍ)Oæ:¹¶º`;bRŒe„4fÄÌ>´°\„Ž¢ŠË‰ 6(˜x 7ó°ŠüÃùí[P¦YÛ‰2pƒÕ‡Éÿ¦NýRí¸è$áÆè˜b’[ŒG@V¸5A¹‚— èG¹*"à&!æLX?¾uz`M? м€Lzè^„W¯A0 ‡ÿHZ&„ÿé*Iš´°Œ|MYÅâù+)ÂO\‡p\Ú„D¼ð\iÑC5 "ÃÉ÷~‹¶ã¼ž[ bVæÅ ªÙñg@@‰ÿp ¡ÄÚè@,À4D`Žœ",´„%ì3 „P”=#Ãà%pAö!Q€Gþ Žç} y óy5µ“- P i0=Y/u”Iˆ!Ñòà  ÀRE%‰pÏtGÙè(Dß  =§µj P?É(„7ÃÈ3’±!Qþ¶£íÇOöWP•[ø7s:𻃂l½:(˜9żCÈSÕmu×]uM`"ºë®ºë®ºë®ºë®ºåا"IÑ0@†ÒNñ0@†É2¸CÀ5À8 T „X.Á¢ (GB:³ÂþL €B€ "&À!@ \BÄòdhÜDBÄòdÐ ƒ¡†VÐ^@iÀ!CX Ä—@ !€B,PCzE¶ÔX Ș¥€ @¢ƒˆÚ G@;!ñ÷Í”> ’•áp¤€ô”Ö„ð)ÂR„ð ËF+D (ðˆSË÷†ÄÃà J)Ç´C˜øo¹G–4Àªæ€2,n€32&Я ^„€ìÀ$>Òå0¨°‚Ä"a"õÁpÎa`;!†¥ôL&ÖÐ!†>x ÜJKÙPÛ•8Å|¤ ¬&éc9Cl–€N@ôLŠBh˜•¢¹ˆ€iøN€CÀI˜³ð‡€’½ÂxV”  ÐI¥²¬…— Ð*}êì@ F F+†€Ø€9HRÓß®}¿·ãü2½ &²xJKOâ~Ь0¹ßžA‚5Ô Õ \„J.&†hÑ@U!§G—ÓÅÄÒâÓS]u×]u€"ºë®ºë®ºë®ºë®ºåü4¡àA çˆ ¹` ÒP~¾0£ Àv¥I&€ä;@€%ðàJ+(ŒìJ‰4 |?'‘´Êéï³Áˆ÷ÒÓ &(´@@ ø!Ê`@ ÐÜ´ D0¤™$]“H|a½#à”^ï÷ÊŠÿV`…'@:,@!HÒjG Ç ø ’$p¬î€Î€tL$a0 ¤X0„W„Å™pV*›vHÕî D\´h’L„@:¨]†uáÓ¯&‡ °+]”Å(%¢Êeµ¢½ÀP¼JŠ@{$5šÀx¼rbc–€ŽÇ|Àn½½´X °Â ú„A€a!©rù)áÍôº²¶U{‚°?bB^ Љ ÐÚÐÖ”^}@t’XgG+’PtR@Àhкééã‡A®Îžr"o dà?BÛÏ­&° % “yfei Â³k…°É¤  +•è3<x„L/“žñÕàÄÂbÑ Ä”JîRÐ8Ü¥9±\=V×}”9“_}hÎXh`oéÛ sމˆÈhU×U¿”Ih„ŸG´`b7¸ Að èÈ6 ÄiúŠÄ‰>°C%& À+€CÀðˆÅá0Gx\ýpž‹rW$@&ÅtJĉ%”5W BÌ%€€ô‚ÊQÔу¤ó®ëéZcÆ&”M)‚bÃI¨f)aÀr‚®Úèw(4îÀ3z,gÊ›‡î Âó0`,†X @KXûç\#…90!.&†\Vç¢I1,cžIcîë)G‹,í…À!å“:܉”ð<»¨Ù@Ê1-´dèA‰äÔ¼G©0ûýµvð˜'@!B L ð<ppV”L$á4 ’` ‰8D˜h`Ü"“_Àcö%®Ñ†”z2B9Ø ×Q d¬Xw²Á»-ƒqÀv¿”Ž>†ì¿7/(`z$éMêËÅcD×ô¥ÊF fBM¦WÆöOÂüžžÁc (ž€ x ”Œ8ïêfººë®°"ºë®ºë®ºë®ºë®ºåϰPGJèN>°Cd0 îMÔLl;¾}{3š¡2 Þ@A Ë,ÒöVƒ×]’&dƧ¿‰„Ýú;.º$Y !Ïw€BI›!|v]Ãç’ |ŒêuVû@®ûbŽVÆë×’É¥‚B YjØé"À  (I÷ j!@²QÐ? ˆ\³.𻢊 „$†Aÿˆ2pÄ>žÍùæT—¯–µAˆ_ >&o‘Ÿ1ÇGØ`¦¶[ÓËÓ„$¢ÀHt“Hi/TqŠ”Çj˜ÎÀZND>^æÄÂkhó.›M‹ÒÑY#N“wèÈ4 uHù#@pZêÙ—‰0€5ÉHgºEmù¼Xš„âPcý»IÌ$°Á#Æ-©—Z  0J8@BB ôà…åaùåNÏ_ Àº@ª>ßˆÄ )wr„Hš’tLK”¸W`¶¾Æ €gV »zk³äåÛ‡g#@añèø;G×È#ŒZ…5€ qê¸(òŠ Á8´ )8 ÀÒÊ+;€qpñžDÂ^ǪAIÉàwWd²hk€ 0oŠÈj艨OèROüœ¼­^ÀÀá Uæ?,Œôʺ҉‰¥”I 7P¤.±£%Dó®lb ¸|LYgXu¼•^£ÐÂ`x~‰¸»©ˆ®ºë®ºÀ"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºG뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG> ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G · C׬~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPàN"„À 1Z!öZ!¢!³<3Ü!Àµj¸ÿøµÿóA€+óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".RG”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ+óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”G¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ+óô¥/ ¸.R”ˆ¹JR"åG)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”G¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ+óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"åG)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ+óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹GJR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ+óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".GR”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ+óô¥G/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".GR”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ+óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹G”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ +óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Gå)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ +óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆG¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Gå)Hˆ +óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹ú P €`Ÿ&‹F+ŽÜ¤u÷7ê° @3~¨ ˆe£ ”žØ¤eì?^€?\ÿ¹ Ž„Z€@ÐCþðHRÈ×–J@Ž38Ë¥ù,óoäÔ‡ê\×)JD\¥G)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÜSÊ!§‚“ð¯®ì€9_ü(@¢òP‚Á {ôÀ!9/·nMÿ3{øx€À3À¢î_Jwûls®%é  CÿK"^nê&í‹K²AÚå)KZnR”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HG‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥"  +óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹û ~¸!ÿrAµ€ ‡ý॑«ÁõÁû’àE¨-?ï€,yGˆà"ºÀJ%ñ‡ëÜ—)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤Eéˆ!€9 À°§¿A_Ÿ@b`Cp,iïÐWœ’']Ó/〆¡€ÿ¥‘/7z@@CPÀGÿÒÈ—›ºÉ 9H›"Ž×)J[Qr”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)Gr”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥) +óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".]  À€dùA¡£KP($°õíƒþ»  ø@t–&ð–&æ`òuõ/Ò_úëýþE¸É€:%çGJµ±a¬­: Ï΀Œå†· År䢃¿ßð«¤P ~pfá5dò¯@  †`ÒˆD¢ºòCSŠq{p–Íj¼Pà¶H!1_±- ?£öZâãøšIi¿”€<Zj O@n_ -I?|"â_¡‰„ÒÀ jJOBJûïŒúø8àà À@B¦–€œ99^êG¤ 0¼u‘E¼4:—Ò@ @§§€hÛý§À$Üpûp¸j[P”Œ×ÁÄ” '”PЗ€$bVã¹|‰½ÝÏK‚¡‡ß¸X"_BÛ§í·ÿ²ÿ¼°)jQ’f Ýx –„$'éÁû^n„Äe“ýÐKO:üP …8 ×Ñ|_¹_ŽÅ¨ŸµŒèp8 @a4¢jzP7r±_0yh¾¤ˆÀ ÀGa T…ò%GÅ”ÑûµÒ&€ìšCÅ`Òúpb!ÌÜö¬ð¯ßuy”ëù@` Ä ”®Igt ¦`ßÉ×—¾ÌPØ ò5ñŽ}ÒCóYžœ»ï€;V Å”Q4¢jy{üJÈù]–5(¶€œPÀ(P`É íºPSa,ù:ô€ú‡ÿ0pHÖ÷hJJîÑÇîÜ` ,­Íö‰/ïG!¼œ@ à Üeãñ_b·ËY;{½ó‹u€ ÿ÷Ü,”D½À€€=( ‰Œae§Ž!×÷€`€\W &“¬ye%ì'n7a5ž!²ºøš¹eß΀hý81d ÞqE³$IÊâ;{Íߢ·û¾WË×ÄÀb À0(²û†•ÉEñìw×H˜ ”fQn¯|Õ€œ” ¡¤"ïHgGúS8n÷”¾â¤ÿ¸àÿœ«ÐbÜu%þŒ«ùx @@~&ô`Òb ˆZI¤¤#g‹MØ8 ~˜‰‰è„$Øþ¤§‡í}=,3t²YÑc”h«Ë@@ T¬Xˆ ß>Á¥¡ à"_Áírßœ;û`2Ÿ|PÀ@üõ€¤ €Õ…r–xàÀ ÀLí‹ Ä’’¢ÐnŸ_bİ “G°Éœ¡¤„î„£ˆJ?Î(ûHN (†þI]Äãw䜠÷– Në¿Ïô­!p&Ppj2Bñªõ>n×=Ÿö_Uë3#Èß 0hÓ€$bS‚?þò&÷¢)ZÐÔ€€„ŸŠBƒ~/@*ÄûÜ”QdÔâŠBKJ{d#ÿ²î`·Î«d†Ž¿ÁóËu ÿ÷ÜÀ\ðéÀ7ìC!œ£àGÔa*BB·½0` X0Ô ±)ò +$)ûíw3xŌ٠!Ÿûtp%Žì,!%YœW¬–! !É€;+“ @i\䣾ú¦ûhÀ¡ ®ïù¿°iF0þ¾(„âЄ£º²wºõÞM&pÎ?X!#nð‚Á {ôùô †ä0GBÀžýr€€ä‰Ö¤Ó/〆¡€ÿ¥‘/7Gz@@CPÀGÿÒÈ—›ºÉ 9H›"Ž×)J[Qr”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)+óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹–€ðˆA¤ÞqHéG Ö{¶Ÿüèì!:”gNÂçοµÈiØia¥÷Iiéá÷Î ¸$4d÷ø…¹Ù,Hëé·Â@6h Ž?y@U$¢”"ê+?¾2CŽOž—¬þ徸dB€) ŠÁ¥tŽÀú9ºäR’JzOšþÀ®ÜGBˆ¶Ð@&@ @ bs hÔáù úÄ®ÜGBˆµ€¸¿»qÁG¤kÈGbUÕÉ!÷ò–9ZÚÄì2ayÐÄþ°°$\zÙBQÐ’„æèù÷þ¥-¬ïÚ€f\ *žX ‰G ~€œ4 îãQ€#»À‚`]€È ¸°2[X½òÈ?¹p KØ}¯ Þý¸€$"q`ñ C/²~‘s€€9 &r€®D‰H)!¹'ÿ ¼ÌkàT·wEúÀ€xpÀ€€Ü”àXÂS¨x ÒF¼—- åŸNFA×èÀ€"À CC à;¨ #¡€lKwîà”ÖÀ Ðp I€G;5 a#FT1ÃÀ-K^B”bySåoÞÇ>4¥½í€v_€BCH`¤ 2ž‘€ gnp«ˆÀV]‰¬° ÀË †`HÿÒÞâRÃËèe¡+;ܽ˜ €˜0“@¨¸)0¡¬¡à7C…^2•”’»êz7>ûà €`É&¤ü°2˜Ħnà‹ÿ…½À¥&Y|¾þ[5Þ²ù4˜ã hèGÎÎk>p»Ü`@d/ø‚PwüÞ”MIGUѹ÷° 0àë€Ü”á#;ñÃRG±Ò–‰ã{úvk? ´r‹FJ›¡9÷Â/h¨ x ¯é17€ëðDDîYAÝÆ ÅR‚ƒRQÞ}ßÔ¸ ÝÔn,–Y™b€€¤7À€œ˜„‰™%ñœS o|åýØ€–*°1¯`€@Ø3”›òHjVZGDñ³kñ¥Ò”ôŸg³]¥Ü¢Êvއ=Ÿ3Þï#‚'ø‚PwüÞ”MHaÓJ2oxÀ °  X4ì”ñ£ GŠ’=‚”­)éïå³\¥)T®R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥" +óô¥/ ¸.R”ˆ¹JR"Gå)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹G”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ+óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R—D0 &|Œ*ç#?O²ÃGΖßöË‹çRì€`´ üa4 €Hœ10çÆõ½Ér”¤âå)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HˆG+óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹‘|>Ö˜!€PÁC@žûýÌB!ßu³ r-¢Keþt¥èÀ 0!© €ô²=ç-Ò‰øu¾³GÃïr ` GÿÄ‘µôpü@Gÿ°À®¹ƒtK(hÖÀvÓ–Ýšÿ?RTæ÷±Õ0Gû(‹t!Ssú?l÷ä_§ûgÿm÷èÛî;Üpà Àbý”’ƒ¶A1!YŸ>/Ü`ðI8Ú€ÜUü… @.Gn8#ÿâžÄL¤ +†“J ÃÊNN'~„¨€;&€À¼L-!‰Æ£°¨à ̤Ìâ¯óÝ/@ ¸ ÿ`-‰¡Š Øî98MçïA(èÿs,7{”´ìa€&&M&¤aEgü‰…ûëà ÀG€ÄêR„'“Fnχ—ñâ³ &$4VRS‘( v‘ ±`1ˆøÎ‡ wª!j‚R`h¢‹BxVï~€• èû£ýò÷Êúä8ÌIáV 7¢ø}ö4€#!P  &Û†þÄ Ð?›œ‘âO½=xn–r,€o‡_çH¾l»0€0p(}(?\ðà pÊÀX ž(¼xYöåbËìö}-¯åG/ îà €5à„˜C3v,Z9äá;äì”wßo¸¯Òg&2Ýæ‚ÆØ¥/¦êbK (Èê( –¾vÕ†ÃRÔ¥#5üÑðý ïÀ€° @bL…„cxv¾B(… Ì‚‘‘ƒ¬É¤ ÷b-E4ËJâi ˜0ÐÐÒƒ0òÓ‘‚ÿתJ\@_—ÏÁ˜A©}P†I ;/†“KHjyý=è ×/?GVšCZþ€€>Ol8#ÿâî×5 ÉϾû÷}Ãõú&å€\äà B/Œpβ’'—d(#…׉£õü%õ/»9Õ€œ°*„r‰{+™Ùwš0Ω4À‹h C0æ´`×ì×òؼ/¨‚è‚û@GPŸ· ( ¤cµ HÌ÷ò÷оÒYœ¸°yßô“I€6ùnÓ)#oê@ú‡þÀPGÀgî¸@!ÿX ò7¹ú‡þÀPÀgî¸@!ÿX ò7¼ò ÀEø·>0çÖZ’ÓòÿüͯZå´·À/»@vB ã’Â呂1/!€j”“t”“G)I,_çì+ÞÂâ(ßçOaVÜšÇ_Àˆ@€€}‰€;!ð$€Ôt…;ØoÑg^\À@©@:&€À ôà +¡ ë,®bùèt$GÌHáq‰¢¯ã¯¡~‹¾$at#‘ë&@1œk‡ÚPXÞuó@30 Ø#€(hÓß¾˜!€PÁC@žûý€HšÈf_Å@ @ ’È÷$†Àÿè†L& ,´#…~÷Ö FCÐâ`t០冩×Î(p¾xëÓ%<¿ÒŸÓúÿýÿŸ×-?þÙçƒ[5ü0Ø>Åœ 'ó°CðïÞç_¢ï8GØ8 @%éäÒ¬3÷l<¯Î⎩ &lÜW§Gëø½-0Ø`HEɉQyñ‹ÆÙîïšÂþ¢¢ì@~ëõ€ÀO#{’¢ì@~ëõ€ÀO#{É(À^ëà9¿‹óüaÏö°€œ˜¡²7² ÁüvÂýë3ö¹L¼·D4ØD.Å€Ä #ã8iNï}dÈp€=OÃxaGÀÄvP~$òp«ÐÜ(àžÂµ·&Ž×ð2`Ð ˆ}ƒbÇ`Ô8S½‚ýy ÀÀbù(BR’iÐÄ÷l<¯Ît$ ‚;Šñ‰£õüf•àP †Ä˜Q43(¼û€¾¢îù¬.R”œ\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤D+óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥G".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹Ø˜!€PÁC@žûýð Á €và 4÷ßï4„‰ºI§ëø¨P!€©e‘ï=z CR Ë#Þzì!€çØ ‘¯Ýè‚€èÿñ$m}‡þàPÿì0k¯œè‚€èÿñ$m}‡þàPÿì0k¯<@†¸>è,“žË>ö ú † G‘ÿeoY÷±Õ0û(‹w“þÐ&çI#ß×o‘(1Á€'Ù0¢i4›†£²PR du8¿žúæÏ~x&l€(BF;4× KèB· ÏíÈ` È(å@`¾` ‘¾ö|}´xàdÒ•›”çŒJóß ¾²© üQÇ“nÓÒß™@j3Z‚y@ÒQ¡‰p/_(¾Â@ØLGQdkã¼ú€O€¾"a×ôð@ý@ ydÒ€LŽVÅ–-<à­{ ˜š˜( 3¤¾ØP¾+X€–@€Ç‚7þ}„kË‚“Àb²o<03d®ã@ ÖÜ%7âÀ.Hp¶ä€©4††£%`<Ýò0…ب@Å  &!'%#'NÙ8;Ù¿xÞŸ&§÷räkû@‚¸²gé¤ÏG\‰Í½Uñ G$ÌCp½ÀI±xNàvûmæ‹á¨YùWIhïóø@†€0p(ij–~¡4„ØiB“Ž :Ì!€` J#Y/Oñ…þ.æ=ú%(èý_vâuò  @À4±< €è I\îD½xÀ@!µT$A`n@ @À†'ð,X,BM÷š^Ä0ÇÂn”&þ6p ÀP4†YÁˆé `ÿ}ìdG4€ì†M/ºKOO¾x¦ˆÄ€®I`ÒØpÁçÞü@¨É€P£ÃS Õ€À¡ˆÍ#R—í:/|@3/-.Q0@HyבÄø0!^D„˜O²Š10 ¤##^¬?X¾€€øiX9wRRrne‚Y&“RC Hiô§ÿÿx€À€1@Ø ÜÍØ¢Ž?þXÂ=îö{GóØ L ˆR‚5ÄKU¹Yý¡@0И‚Q@0ˆ@ìQ=K½PÀf”€è0 (v|Jà ,RQ‚3Ì.ó4½M/w{Ÿ£}¢ )!‰IIÍÑþøw׈1?ô&‚8‘n˜) ÀdÑ€%È/‰ùw,ÄÿКà E¼ÂøÒgãÑtlÉ¿—ßQÐ?ö€Ž ?|ºúˆ ~€!ÿ°pûGЀáÞÄ4‘}p CþÀ äkâÜûí @‡ý€:È׏ö@!?™0ëú ~€!ÿ°pû®PÖ<î@ ~€!ÿ°pû®PÖ<îb ÀEíxoâÜûÞ‚êcà €0Gø „–ÀK‚ϼ>û } ËÆ ¢±9wh44BìC{"ý0`adÒÐQ[¥)ùc¾4ذ@ÁˆHG (`Wçü½’Q\rÔ¡ýw»+! šä®œ1E—„ã¯'¿¹ÀbЭh‡]Þ h(”á…” ëéÀà ÀÁÀ,ý’WXüwëèäëå–Рɘ††$îL,ŸõÒCJ–ïd’·×÷ëâ @`#‘ï·ß@`*q€ÄöÄÃ!€PÁC@žûýð Á €và G4÷ßëÉI4ËòÀpdÔ¤7ò€ gÄ¿O‘…ûä„ .LBFÆ’²SÄ¥;§‡ûª\LA `DÿÇ/‰O¸vä2jFüíµ%#5ö€(¸é_Ø¢kC‘÷îÍ“„ßhÔÁ RÀ¡72Jì$w½ùþú` ~3`* »-%t$X΢u˜‰¿¤gï0Ò³=¸ h< *X “ÂwIB“G ×Ì/º./†?2p"ÿæ'ªøJO¬èd¸ùu_ÔÁôAý€ #€(ÏÝ`€Cþ° äorAôAý€ #€(ÏÝ`€Cþ° äor`/kÀsçûê@ú€ðÐ*P 7 Ù)”5òÞ}÷@¥òÀ€Ÿ‚7þ}„k¬rÿdÛ^  €4 ~À_?œŒoâ/‰€h°ðâ² ¥ãÃCQ‹GOâ†î0Fkî`Pd0K!–LK0Ò“ÑÛ˜úÄ?ÔüÐ “ÿe€ n Ò‹,ä¶¶GÈ?_Æ@5høº@tÎ F(½Çº6qWÚ€€dXà†BÖJêàOs¸~«ë~¿èIÿ²È6ÒÈ`1I,†Y5,ÃKOOaÏæL(²KèOÜì×óð@ð äÐ'©€ÉB€ž"ß;¾ÈHY(¹¹( ׯG¹÷h PŸûΫ4¥.»+”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ€+óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹Ôà0 Ž¡ O~¿:¥½ÑÎNûˆê¾úˆ  I¤"ót'…:¾¼ðrNºf_É@ Ð0G…—‰÷›¾¸`¥ºHD1 ÷|²RG±»š×HÈ@ÐÔqYô€D1Âíˆa‰%ö߸ë2“˜ûï‚è%€  <´òv¾„–pLßö5×4XpAþÀ’Ѻ à Gè-#}þÈÀ0ލ#Y-`ÀÀk%ëIânT}€à @2 `.ŒK Z ×ܾûýÕò½ùÓ_a'|l¯G F`À*ðì?‚î z­Ãq·éHd0Ð*’XjyimŸŽÙ¶¾r`ù°heáá„LJ‘/¡€ÀE€œ†B+:CS‘ƒÍ>øEh €P¢@b2ó}ˆË%!‡ÖŸÝ~õ@dÎé?`Rx…½å«Àvri '££‡Ã½é”‘‰Ü]ÌœûßèKàí'& ä† ;ìÍ}Ð 0 Ð –B ß$G®ÂqœG¼ø`©päÂnåD÷lI+@¡úòÈe”(ˤ¤Œë¿ÒÁh|r°¤ä£…}zà$$À ?,¾ ·È@ ¿ã”ÚôPL-=†p«Ÿ—‡ß¬/Úvô›Ñß!Š‹5Æ1?ô!‚8‘ouÿÿþ¿Ï÷…1?ô!‚8‘o0¼0™ðít£ºoå÷ÔAôý€ #€/ûå×ÔAôý€ #€G/û¼‡{ÒEõÀ úÀ`'‘¯‹sï´€öèO#_çÙ€„“„L˜uýH?@ÿØ 8€ ý×(?ìОF÷ ?@ÿØ 8€ ý×(?ìОF÷0`!€6Wµà9¿‹sï¯ë9@zL,0¯ƒ³r}ò}ì€@p€ÁT1XwØþÏ ë»@t‘¢Ubì€ v€; Û¡!éG:øß¿EïÑ÷ßï»ïŒãï—€8סˆ(_Ãr€Ë~„‹ìÿqæ\à1&t„åÖ•ïÂÝ `U0Ð †¤ÀÄì%9±ØŒÀb€Ä¤ŠFJxVÄ{è  @¤ÏÁ›”BG}¹éãÒÄìeÒL!%)ϾÂìÒ^ÚýEñCPä{í÷Ä  @t#‘î0€à>Ø0ûç€f`°GPЧ¾ÿ|0C ‚8G†€ =÷úÀ@HH™L¿‹íTÁ3cÉŸ•ðæ8/^vûpa  cv%†9CÅáÉ×ÌH@àhܼÍ@nèøœÜ;ÛRbrÛýÇY”^kó÷Ôô€v‚ÀvL!nü0§H®ž@¼øà`B¾׬4Æß¸ÿû8Œ÷Õ@© °†¤šž”—ßû0¸ßš Ôækå&&r°#/þoÄeß Iþú Gxω`†¡³r‰ŽhIù÷¬étì:DÌ«ú ~€!ÿ°pû¬PÖ¡<îP ~ˆ!ÿ°pûªPÖ¡<îB €EíxCïâüûî Ã90è wÌåôáëáÜûèàú`»”©[üØ Ö1‰C*ë‚X¶d•} `d¨RB90 îù@\²›ãÀp”;‹¾r D¨@,¿è`G›ÿwÚ€  4¢hg’¾N÷É€2#Àe` R|òwèüz·Ì%®p*wt~­ mó€(‚WýìîÜpÀ@€+ˆ =ä0“Ø5X_UXÀ ÀD‰ ¤Äoÿû#ßTzüšô òhjŒB Bb-¡3KëéØ>”ôaÞþ8À €tY@T@Sdå”^&“KË78jQîUôÀ@GÀÀ ÃI©è J`PwZžvÛÍÿ_3º{ä·HÛ2›ãšå)K¢Îå)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥" +óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹—¢Z˜0š2Qð`F/倒X̼í)By]ôþ{ûÀ G €3¹?P(Y[ör¸‚ó ŸtïÎ7èböXÄ8öÏp`©zÜÂïî€&¼úp!%sÃCw(­‡¿I@Ü×õPÀÀ€èèadÐ옌„ºK!¡J6¾WÏ“†ÿY"hhîÍ@Ëd¡¨IE£% Ì”s¾÷Ó€‚RRMËr0ð1€'(VÀeо_ þ€Âo „ mþˆ ,˜ž€Ò’RqèNèø;®¤@ ØRJ„ÀÒjGØK+ G÷ç2ù¾ß \oÙ²„\€y‰ûP ¿«$¨†  ‰¤2nHhÛ€(LÜ¿–¾‘›¿•zpAp`ŠÀ‚HA4ïƒ ò”×€OÍÏ ^à!%€HNèN Fûæû±ßuÙ¡ûÆìOýŽV¹w@€\'À´l冤¡8ü®„$gÞ>}C/|˜n$8`c0?ÃŽ¾yûÖQ¬Pb1HÏÛëòGY“C@Ê^¢Úå)Kj/¼ÄQ0™O¾ ¨Á¦|‹,ý}\0@€]ø P¼ŒŸøÒÀG”Ûß «Á½(`ùYºõ¢C7¿Ñ÷™tTˆôïÃ8&MÝ â:ÒF|S·|„8öX\É Jlx Ô­hawöp v –`œ†LFÌ^&—“Ù}І ¸ €@„'&¤† *BÜ1œ4˜Y[G÷9Óµó|_ÔåÿZ@v5 ÔàÆïo}?\ €Ä$.BÑ ‡±1¿ ,½¸Þ®3{çRäô]…„¹öiÃuýhÀ @ °(Xhbû¤²j•Ïý_&çÉÃSë)&“@oñ“B_ÑõÀ28 @bBä RÄÆü00²öãz¸Íî €@`P°ÐÄ0­û¤²j”oèÚù.OD¼5>ÉUŠÆ5\§Gïoω<~¥.Ë+ú@”¥) m÷Z@§í÷~¯…~÷ÐH`P†¤’‰¡…“8´tp¯¯Ï[µXìÝbn€cöožß†¿ÑDÂ4 ¤”L ,5<Žž·¼@ ®Ñ4 €Ÿ% ÁŸ†B–ÒÊÎÀ*˾Wƒ[6ÛÍ?OòH ÇhÄËûÐ €°°Eà A$  šwÈH@€¡A¥» ´t',Ýö÷ G ¦oÿµ  g3R‚†{Øt€è ¡§òa{mŸþ3«kí ‚Àx"p ’ÐM;á`e3!ÀéÞI(mýT @*° ƒa˜°À„’ÈD=Ê]vn%\}ìv€#dÀÒg£çêøEùó§ùÏ8ýc€N?=`6£J ,šœ‚’ÓÎB7Oâ6]áÀ€ìiA4]À¡ ,•ÔM,Sì%b¯”àGј#l#4ý?Á`'R³F&¶Ø ÂŒQEfB1ÛhÒ—wïc•F×Èà1‰ €tC!ìLoà /n7¨#{¤ˆà PØ,š†¿t–B B2¹ÿ£kä¹=KÃSîTV(cÖœ¥½¿>rÊ(šRCQ’Qy’ŽwÞZ]N·³¿¨€7*Ù ) Óp*L<”ŸöLð…Š½¨i04„‘¥œ‹GG ë¿øþ&ý›m°ªÎ_ô¤êVhÄ˸„B!hB@ˆ%QØx¿Íüß%)wÿÓߨì×)JNW)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)+óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"åG)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”G¥".R”ˆ¹JR"å)Hˆ+óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"åG)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ+óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹GJR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ+óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".GR”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ+óô¥/ ¸.R”ˆ¹JR"å)H‹G”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".GR”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ+óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹G”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ+óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Gå)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ+óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆG¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ +óô¥/ ¸G.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆG¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ!+óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥"G.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ"+óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HG;/ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HˆGPà°„€!Z!¾Aÿû¸µƒ33A€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë˜G/þCrig$¬SsòÃQ¸AÝ^Gÿ#ñRR`°_ý†EHâ)£‹& 4°Â¿òÔdJ0Ð#€)@MI™råË—.\¹råË—.|@n‹ B,™‹ø¤´ãÄk ‡ÿdÀGŒ øOà`$†L(ô$hÜwR?~°ÿܘ ø ` í'ÒåË—.\¹råË—.\¹råË—.X "ºë®ºë®ºë®ºë®ºë˜/ÐGZA @v ÀKÿ°È¢ÉDZA @v ÀKÿ°È¢ÉEHšš"„ C€(à QD C€(à Q_?Òf\¹råË—.\¹råËŸPCÿ²#€H&ár@¨!ÿÙÀ$?ðºz,?÷&GþX{Ið€‡þäÀHÿÀKOi>" .\¹råË—.\¹råË—.\¹rå€ "ºë®ºë®ºë®ºë®ð9 €ì G˜3“@vM(„ƒË HÌx¬¾f€@ˆ`Pð @N¾ÅƒÒ“ @´õÎ@€180+É U (Î`À8& A©“üH@S“E y(²Æ ¬ƒ°N–°±>Ö8žÄ|Eµ õî ‚Ydê,$Hev18âÄ`Kÿ«ä˜XŒ øUttã8¡ÀK '§ç1ààñ¸µð¾ÆË‘N'×¢qäàG–"…#°…ÂG€·ÃÈ&EÅuà˜Yû¯ÑÊØ[° ò?-«C98ŠA"ú#‡Æžîp…BΠöFGY ? t<>FY ? uÑ·þ!¤À$?è0h]ø†CHÿ À¡uÖ‚ƒ@pR Š Â@UH8.ày»cóU¯˜­]P ,ôHÊ ,ôHʶ1…f,7è :‰›€Ž÷Ëwdï¸~PvK~"˜ïŒäup¼Dî×À\'YùÀDNjЉ˜oaÄLpæ€?#ª½(½mÖ?¯0Ð<s=8õò8qгG\þ8> ÏÀHÎ,Î,PXïñ#ë²?0@™ÿ¥ß0@™ÿ¥×h `h ð§ƒ@H'€ Oú€HÔ¨4˜§n}@λ‚þ ²BDzó x ~`Íþ/õR ð&ÿäøÐG5œ`& a€ •ßmÎ~>‡ É`+äx¼ÜÀXšÿîXÑ$0P`Üî£b ÿµ]u×]u×]u×]`"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®¹v\bI)#Cù÷Æ.4Wq<Œ¼;2«g§€à?ðÓ5„Œ@ÐH:äŽ"øSeŸÉØñ²©$Z"¤"`ä0GÿÒ""``Gä0GÿÒ"/‘ZuÐ/ìš Oú€àR ÐÂLP"Ð$'•†lpyÔ~vcãï[<¢€pP#€#Z@ð$éEà G ᬑŒOª ÷—‡ÀG€`Aú‚?û“@° @ ð!ÿØÐG@ÈpRa€d–ê݆ñ3ºY‰õâ+Ð 8 ~ !ÿ A ,Šˆd"` Ò1Æ)ÎqÂðù¤f¦ sÍ9û`ç>,˜Y{d¥$À1œâ;’Æþ¥n§_s©–5Æ—Ï-!?‰üœ:–h÷ÁÐ[hÄsîd’Xa¸ñ‚ÊÍR’w[}d»´AÔo2-¶ÏÍ$b/G±§œI—øò s(¦YÇ]ªÚp ‚ÀìDç ¦îèíÉÜh98ž;êÙš2SñÉ`în8Ÿ%€ÐGB.º<ɹ’4®rIÆîë9¤•ï‡|®@¿äÃI@*O À"JÀF*ÿ2ÊbJI áÄQÃý?á<ÿÜ@¬+"ÿ2RúCG9AŽ<© í¸´ã$ìî¶ÇÿvQ<ÉáG“¯¥Ô‡B‹H þ^À<Ü`ï²vxøQäëq¥RVGèd$î,]ľÕ®;ÄC& p×o›@P@†Á€*¿ƒðÁp#ÿá`+б^´EI€‡ÿdБŠ?û!€¬ahà*"×éy‰<{mù$]áØ~¯<€tcyÀc°p¾é²á8¸;·ž;ˆûëOJ²rG?øáÂ8u~IäjôŸô À¥E”IŠOú€àR¤£Œî8ºÇ‘ýý‰6üGƒôŠÀK0àGÿÑ<)W¸ˆNrØxtZ“Ž ÙØ ˆ3q`|ãÉ5ÇÆçqÎâ+ùEà G=È:» b…8 ¸T’ÀH#à®à™ÿµY]u×]u×X"ºë®ºë®ºë®ºë®]ƒ­@`"ÖpHÔ2I@9@‚æBÅŒ~NPµŒâ7óÐ=ðî¼p$"ÇàkBA˜í#( Òw8œÂòâÐÜÿŽFc˜Øó9Sîs/ÖÄ4 Å e‚_þØ" $â¤Õ'"l¿G…zÐÑPÐÓÁ É€–¥DÐÒNp&X•@|\ŽŠØˆ$…€ˆkä€4@_Z"†ç»Å†ç»ÃøŒE±Áõ±¼´œàÁ/ÿd%`£‡#äòv‹IÁ€Žœÿö ž´(™ŠØp@z9Ãäcpâz áäîøýh‰.3žÇà¡Ôæ}É*^W¼;\,dþÀ{¹8§/âA$ÎÁ YaÊet! žG!N~FûIÄ€ÐG?Ô__’ƒƒAü v°€[bí& ¾†€‹±Î¸$êÒ‚ü¾#~a…þv÷€åÏú<…ž¤•И¼4l.sçψß¾ -É*ãÀ÷=9†IšþòÎ à<èÂúBG3 [‡X’ ŠÐÞ5±ÈAØ‘b€ñŸ¿÷•øËÀ8éæ˜0À]†è,£àÂ`È¢Ê$ÄÂ`È‹„ZþY`ˆ‚ #•!$€è´œ0L9 $V‹x˜’#ÿá00$0GÿÂ"+cQ78bpýÀ52˜œ0ÁÕ¹ºº’“‘Cº8ЮIÒwPÎÝfv3¯ Kv¸çWÀ'Ç¿cˆµ¢ÀpŒëãRG#qˆÛ‹Î#ÉQ¡ <Ä^¦†ñßî¾y88AÒ Æb?­žIHÓÒ8ƒC !Éz@ØŸö À¥Z;rwÕàÀDÿ HD€ J€ÙÖ„ †a¨=w~#ãÄ';›~ `¼N>ØeúìF†œÅñi'hþ¾?,t Qi[œ$'©òØà6f¬üþNÕ±=jÊ5°6,G` Å‚ÂêB-ˆÄtü„-ú°GTA³øÑÒJ/†q¨a¦9Ÿ„>·UhÔÊ`òy•Sv”I-¹Êæ‘[€ \ /³ ¯Ä`9°AiI$`AOǤˆŒÏ×ù…´À%`"mÙä”vða1AˆÝ÷cwÄêù%,µp§Æi'q£ 1 +2I¢Ërrt'¿²pÎ'GAÇ$Ó/k5ŒH Å•œ/gøŒ9>´d‡b@JÌ8-xÅLHC°ßÒâŽl1G_f@G‹ÿ‚’±JáSßäÕ€ÙÿS†qÎÝœöã¼bJ|ÒÉ1CÜÀ/ç'£­€¾¾4vè5GDpëØ–ãˆÉ|rtšÃ°“zùÛ Y.]Ç FÅ ÕâÄð¯ˆa[âÉ£¹o„2ež !_~_(Îj=Ç~ùckÎØrðò œ- ð¶ÜŸqC™‘§gEç`ÿ¯#né_È1ÅñÀ{ oR.\¹råË—&éˆ"ºë®Gºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®G3 ÿÿÿÿÿÿÿÿºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G · Cå¼~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPà £„€!Z!Úa_ÿû¸µ„AA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë¾G(/±Iã‘ù:(4bÁÒF¬" hà£MŠ)= eÀñc3,„r:|LOúúà–a–·ÿÝCŒc€Þ} “„Å‚ “ÀºÐI@šÖ(™À-ý˜ç‚@†=xì£ûe×ìÏÁñëæ'¨Mn…Šby@•ÿ¾ “’Ä8;¹?98å5n/spï‰îG­(%(fî5 ÈN;=¾ç'oœ\éeäü„…„$ñ®†à?[`ïö=ƒÍØõgÆ(ž`s¾5¡GíÕÏ5xPð¾Â æ Y‰ZN-%2ÑÉe)g7çdã?nÇîÜb{züc¤ñ€  ’Y'èŽ.ûnu ´˜QI/‹ÈÏØXU` G‚%€"k„_W%€PPoì€Ñ£0ã8ωÂ1©Ñÿälý›aÛ,BŸþÿ#~.HÎì§ä_ò!¿ð÷Y9ñ8o çî¼÷^;·‡ýðN?sõ†(7Î&¨A7#ò’+ö{¡É²kd§„G–’AXo…+uè“ø¾Ûäø„oàçPQäO/—ÆõHS©ŠžÒÛ^Ý*Fqã° ÿRÁ¿9ë~÷#r>µs¾qj#ñ}§  i»ù…1áÊ÷²ÏBC~B_Ì4˜+‚Cda¥ÃPv+jÒAg“þÁ0ˆr <˜ÿö € C±Âu¢_ȵE]u×]u×]u×]u×]uÐL"ºë®ºë®ºë®ºë¯ƒG¸AÄ à!‹ÿiÁ²ÂÝqIð8‘þär®™8Ä?0s¤­á˜?õ€ÿiYx¬8$’”ÄÂÈC€—ÿE[W)qªN€dnã¾^?VÛ[ð1‘Ö1!«“÷Â8öQªvÒJ$ L’‰(ZqA_&üc!CK”.&þx#Ø&)3/ÔK-dÄsCydÔ$n’C€ÐGÿÒÖ¸nPhG!€(hð0XÓË4pïA I Ž…€ ) B+„ƒ>VsR T•âo0 à’& ‰„Þ1ú‡?ýEiˆ¼jé‰Ju)H¼Ÿƒ0@´§ú¿\š–Éù]Ô$‘à*ê%ãP/o ¦Àw˜ Áÿ ¿ý®ÅENC€D"€'!‚@ !¦ˆ"W|4 ‚ü“AþÉ TÖH [u ¯ðG’ܧ‹$=fDÐ*ôCû&‚_þø1‡ÿDÐGB‡Èµ²(†HÉ4˜Âðx¤‚P™‚†€¨g­…V( ¤’Ê) ‚°HÚ&@Cb„Và °CR#€0h%€X!€) Àš `ìÀò%h Š ®è,YH‹%…áÐ`0ü!“ÈeÎ\H-8!壈ÃV ,6&ÀpãƒIœ(šTGM@ûàM¨ÜI@—ÿ¨´s„ò=pÿ”¿üáà6ªJH¬ÝR` Lý!‚`ÊÙ0óÎ,¿‰$!N°”¨i|#çœëAC 9?ý¶ÇÿÕ¶ú¯¬€Z@‹/’ÐRAÿ ã8òÃ8ó? çÉëVÕºÑòqå|–Â9Þ,5©F9 ì!ÔN…ذÞésÀ°c€¬ äóèpy¼P¢Ï&?ý‚`â‹G@ûÀ·Ì3­Wò-]u×]u×]u×]u×]u×A0"ºë®ºë®ºë®ºë¯ƒ¸ADà$BÖ¢!Á'ÿJ+ŽÌèä„î„áû¨‹~} Î…+æèã“‚QÀ#Ú OÁ¬MAÉ?R@ùIÀF‰ÊútpÏ+€à°&+™ƒq¨ú1yN®9,ä”ÙûrNXÏ«w‡öÃÌÂaLE#,°xVêƇ» ¯FD?—G³åŒCŠF=j’Q%d‚ ¬š 貉([»€Žµ& ÿ\À 2& ÿ\À 2HúÜU’#ÿ² $Gþf<,ëÌ’HH ¼C?û,IRI W#A¤0Cÿ²Ä‘4Ögmv‰ y&”žŽ)Ý– ?úRGB .øxâ|”|½É Ãǰ¡xôúO+¡IZŽNx‹€÷tuë3Äo}'–ÅG€Rƒ‹0Ò’ÊâÐpµ'+éƒI8Î'›‹·Ãˆíët:qA<#SÌFÉÇõjFºù¼zzÿÂ|¡ëøQ!À–ó|ðîøýÄYÂß ÔP„Pä0H@¤B(r$ ÒsD+s àÿ@Tÿè¸7Aÿ@@+Pú —ÿEÁ¸ÀšÿöB°!ij@Wˆõˆ7b±`°GB.†‚€ìGÀ‹«qRË80À0YÁ€ŽÁ„j7 ¯@h!€) Àš `™ †¤0Gbh%€l׊¤PÀ‚_ýàÔ€à 8pKÿ¢cDúó ,ò` ÃA,í9(ÿð0ÿ÷Ey0a –v€”ÿø û¯˜øµ¤*YäÍ€‘`—ÿcVÀ#‡qydF»%=Úž¶Ì<ÂHñxè44`ÒZ tü$®Gèâò•[ó¹',S‡”‘KGá;ëÃØü±á_ö†âq?y½Ð«Òr:{š‚€zX€$‡rù™Dž‹Pàfÿù×߯…a[+M]oÒ£{$·’‡‡|` ”ë4Îlxô¨b »­­¶A¯Ç£)ĤðädpÖõ¹2¶Ã°¿”œK%c‰A¤±G X´0 »‡O…“‡SzI}ý.\¹råË—.\¹råË—.\¹rÀ"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®»éùÛ;Ž ˆ¬Ë$ñ‡»fÁê'¶ëpIØóŸ`¾ÇG(õˆÂàÀÓ°#ÿè`%ÿê%̯‡ón·"Á¤Ð€ˆ GK4U×]í'‡Vû–'n¯¢xh#ÿà&UãÇð$°¿±A¨Á H¿üEúºïdìyϰ_c‚£”zÄap`iØÿô0ÿõðþ`­ÂöäX4š `Šºë®ºë®ºë®ºÀ"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®» Ĥ’C0òY9 ÄsÇiO€Z&ø}jBÀ¡¡¸®ÌZv f@¾ÉPIQÆGŠn.±ØÁ•b[¸ Ò@$é@—ÿ¨ƒNÀÿ¡€—ÿ¨‡€²µ(˜` Lp(i¤LLp(i¡¤ž&§®»ÅJAá ÿ€˜eE ðÐGÿÀL2¡bº¾Ò€pMR/ÿJÁ4H¿üE]wÀ Ò@$è`%ÿê"ƒI‘ÿ¡€—ÿ¨¯a 9(À¨°Ð‡ `U]u×]u×]u×]`"ºë®ºë®ºG뮺ë®ÂzQG†‚?þ`•_¨˜š!—ÿˆ¯™A 8,À $j3»]¿‘0À 0I4ÿèºÔ˜À,KcÒX×Fd?K3}à哈5à¹ÇæXT¼?p£åŠPXU~´%¬¤«~g3,Îc­ ;á•úÀ²,ÑÈŒüzG’ëØFì±€ìO¯‚’ƒ·Î€<à8â?ZVŸÇ§ð¿[Ì4?þpKG8¢Â¸º™`8ÃÓó· ‘屆cÜ[þü>¼1ÛD#ÈèçîÄn$ƒ›á ¶[ÎÙ¹cº_¦ÁÁPj& €#׊”ƒÃAÿ0ÊŠAá ÿ€˜eLD"êþZp#_þ¢[cY À²3œãwrpyÏÕ°x¾î@ÂÔNjó‰ÂGŽÞ `p+RHÉp„ì4ñIÃó“ð 8¦þ<ï[ŠHý ¿ýDPi ?ô0ÿõ"jàf†€ä8 KB ÐÐñXZ!¼ZŠ“K)pGÿÜ·$)ikUᆡ`BG@åry°ï£MjÛÉ =²s8å»' QÇ£«º¿ª«®ºë®ºë¬"ºë®ºë®ºë®ºë®Âb¥ ðÐGÿÀL@Ȥÿø €GÂ.¯-8!‚8 ÿñhÁ À —ÿˆ€˜v¯R@&,À $jÇ`i à’5c° µóëàM $8%ÿÑ6&†’@Žœÿè›Zb¹Iĵ„äbGéK¶›ô·Æc¼QGÁÿ18˜EþÑ[M?ž)ˆÚ ÂP9.9#3ä6HÓŠ,€ÿ˜È5Í®ì-‚ YøŸµ§ Jpäü¨²h!ÿÚDG×0?Œ¯Ü;nÜÄŒˆŠ‘À'BÀHØ@8r䔂Yh@ôìOÛ€Aýi‹ 8—ÔŽHC²€%H Ì)Õ‰;¥H–ðŒ@e_]nqI ËAéljèǾËäí»1&¸ÎofÎ{sv¼Pi!À$èáÃB@ P}v %–…°ñ@#ÄöžI`$V'!CÝ«ŒP Ò@$è`%ÿê"ƒI‘ÿ¥_Gþ¢¤M\)¡ 9â °*3 áùv–ña 9(À©‰ÿ˜À 4-Êb,<<ŒºÓáìÙoÌh¢8–—ZЃ6èôóF„c™ðß+}÷9¹ç1¸>©ë®ºë®ºë¬"ºë®ºë®ºë®ºë®Âvû%]C¹¹8æ©ÝÐGû׆ o(^" ¿°ˆ£Í#K—Z‹-…€©|Œ©òRa ¥b8F;éì2ÞàÅQŠÅˆ¬C’¸°¢ŠOû=ÀoÙÍĠÇÖöQ`xÐ.ƒœ‰¸}j,‚ß”^Û¹)!AØ LrUˆÚÝM_a¯‹$© ó¸ ØîÐ>ÀÆ|a1áÞq`<Ø؉«äÎ_FØb OWÙ,À+KcF&JXon§Qç:®˯@6R ®G§/|cᆯ·o›¯%_s˜X£+V hd€Û'ýœFfÜ\bŽ ðÐýùù§4`߯ýA[ É(ìàI$œLã¹>òFcÊá™b>ç‰Ï…ã«íl?ŠAä ?[‹ Q+!Ó»”²”í¶ì±çIAû¬õˆq|ßáu¨·âÊøa @%ÿØg8þ­ Áí[Ùa¬KRÔ€±ˆõÁGè¢ÈEì¾áŠËࣖe|‹ Ê–GP%€}8ñ¬‹¹$9$DXIxæùµôqbOÄ{Нa¼‡ç q'»b/ù Än=Z·•—ËS„H,_8r Ôà4Y(Ž%b+[ Yo¾Á0ßÎ&#p®ªù0ìœÃƱÉÝN¢~¶ah–DtŒ÷cÄ“ÎÊ&ú 'h8 "pN€ûÀï|xG„â,L,M8$p "pZß%8¥¥XáA£yàL8Ͷ€XŽØè`>"ªxʼnö 7ï8S üEb,È÷btƒD'€ï"F…k§³0ÍXíã\ÑäE¸ð <—ò1<‡ŒÂØøÿÿÇ Ëåà88vEú㇓…ßÎq¡Çš¨)bb{‘ÃÀ†€jðå¯'‹€Z Ö…¼üRÀGëÄö5j '¼Pži8s œSŸ|€h$?‰îF„ëܰ…`õµÄvÄ`öF;‰Ë½ÄðeÄaBÉÐ Ì?ö,KûÈ€t¡ÀB±€r÷ˆ#+f4ˆ Ð; _þîsñ÷òp‘Krt ŸþFðpY¢@]~wŸ¨°x«ÁÌ=…ìy€uîÇèÀðèŽ=nèÕ˜uè'…‘  Éñ;…ˆ¿ùf€zÎøüƒ{‹GÿÖ%LñƒÂÀ|E€j!È÷ÄX˜XšpHà"p\ž Xæ²ÖOS¸¼¼Ø…‰¾€\Àõóo¡&ˆøGâ"“Ž?`«àHžr)ß;à;ï@.< €Ï ¯# 3¸Žç°â#5îg÷'NOš#GÃ…»‡}{ÄäOÇ@¹>ÿaÃÈ<죯‹žÍ9à,×Áȳ‘oƒ™9¯b ÄPyÓÏñ&&øwzßþ?°Ž˜ˆ¼èWðƒöNr“bD_0þFn+èÀFôüVçî®°ãc€Ø¾%Æ 'üFxÃÎâ~af©VÂø‘üEßý DÐ BÄ‘54 "pZ°ðhÿó²•}Ïó9?a&kèGJsÇ*yþL±ñb£à¥ÿÔŒbr#qK#ôs@÷ÈÒ9>v8žë;¤Œ|‡€¼P°©çû9ÜX5 ö8y<ƒ|Ž à½ØU?Ñœåö°îà+ À=¾AxŠìÞÄr-ôGv[‡ð«í“ÿÉÙOï¡ksŠG"pÎ"p1è ±¢@êBïÁ#ć…›{ÃYê…abmG±Ús„MfS‹4]¹ôê 9g¨VA…‰µps€"p1Ä×ÑÆ¸øŒ9޾ÔqüQäõgÐæŽ,¦¼ñþsCéÎH#úvB?þéÁÎ"p^J…žõ<óø9û ?¸ À6;ÄP6A DC…ÛΛb9ðîFYâGñøõoOâàÎ9m`¸ž=ׇ™{NpPqpsÌäqÍy `@GF4W`«æáaðÿ|OxP¢xTÃßÄscT—Ös<7hÂr„ª½Ìi„agŽˆ‡(𠸤p£€"p^ Ô À20s®ÇÞ.rŽÜ=¿ ÿBãŽ8àRÿ¼xåœqöQÀj ÈY—¤@¼PPy¸xY» oN<8‹{ØeÌmèrˆª<^8œ{€ÐØŽnGlðÄ_3€G擜L± üäëȸñ#„æ\Çj_Xøœ² ¾ð4€ ¸«àG'Q<ŒëYßÖÄO9f“Ÿ‘TµÞ 0ýˆð0øƒ ð#Ìƾ\øpy÷øxà ðäb)ÇÀœx†ÃÖw½í¼Ôÿ4D…‡¯@°ò<=0´Mðo˜Ä@Ò*'Þ ,¥ÄåÕûsÌ‚Fnê:óÖF Gˆâ°xOÔóø¸=GÀˆ~qyPYD°g{ÁÀè#ÄCB÷P¥ý`z@<:擵ð §Rð zï‡ùȾ›÷Èwýî"œN'h8­xÁ#Ûȃ‘@Xç x,Q8pêg#^À`œ  ˆ¶€j¢ô¸ŽN?R–Ü@Ú¶Oe¸øÂ@á÷Ñl9tÿ%Àt€¬êwPŒH/5££ÁœXŸ¯ð„1Á`E×¥‘ÞûsO?™ñ} D}ôîüc¾ /²)<ÃOÇoDzï8ð4.r.ïh„{Ø8?¿r8¨¡NEhñôÿ ‹3°Ž;ÁDq˜åà¢À6‚ãG1 ÿÿÿÿÿÿÿÿ€é"w p¿3€Òùü@3…ž-”Ì¥­:póùŸØ3øƒü˼àÖ v€jÛÞÀ¡"ƒØŠN}ÌŽ8‰˜è;Ò¡G"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ!"pÎ""pÎG · CóÌ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPà =„€!Z#¡ßÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë¯Gœ6Èî&®ºë®ºë®ºë®ºëÿ@Íê뮺뮺뮺뮺뮺å€ "ºë®ºë®ºë®ºë®ºë¯œ5"„r-]u×]u×]u×]u×¾ô¹à,Õu×]u×]u×]u×]u×\° "ºë®ºë®ºë®ºë®¾pÛçWžá³Õþ€\FÄK÷¯UÓV9ž<äx¿üpú÷°þ˜¢|Pëþƒwÿã°êðFGð2€ ç;ðDqgu|^#€NW¾ðR.€>y@°#ƒÈ^ÑDða­g²zÏèu{€>8@€áÅ@ãÿï^D ˜{€|¸à;ˆµwà€€g_1`h€#,ü[_ðÀŸ¹ÖûÒ瀳U×]u×]u×]u×]u×]rÀ"ºë®ºë®ºë®ºë®ƒo²ä*çZëzá@.Ð ½_ü{ùG/'ÂÄký 8bq?«ß§+€ü-ï.È€Fßþ…ή»ÚiÑŠ,î|ùÀ@Ójï ··2뮺뮺뮺뮺뮺å€"ºë®ºë®ºë®ºë®ƒo±`Ì$åÜþ€Ô¾ß¿~ûâF"%uôP „W¤HVÖù{÷×^ëú\ÿ]ÙËÿí÷œGÀ_üãíõ×]u×]u×]u×]u×]uË"ºë®ºëG®ºë®ºë®» °à8€8«¾ŽpWÈvNh,áìõ5iÛnA«¾” `WÏÐ ‡WÐðž"ÕWrp€Øá t<û_^ûèÃëèŽûU×]u×]u×]u×]u×]uË"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺®ùƒ dÿõÕ×]wÐ0yã«èåÌ<ƒW_/`Éÿë¥×]u×]u×]u×X"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®»°ðÒåð‚D€ÖÿN@«®ºë®º=–@œW]u×]u×]u×]`"ºë®ºë®ºë®ºë®Ã윪ë®ýkæ¿O À}]wœNà@*®ô‘€=ÕøºeGÓyàÇUÞHøÄp9_KÀ4¯Â#‘íû÷ï¿ÀW?L «¾èœE¯9`ÁÿçGÿ“µ^ûõUç……p7¹@×Ñ8.®ºë®ºë®ºë"ºë®ºë®ºë®ºë®eHðò&¥Ï€ÿ@ýKø}€ –µWÐ8ÿ½úÕçÂÇq ‘ëèüŒõäjýã-]ïñè€x@×o¾ˆ#Ȥwø¨G¡Ý`-€8Õô=½Ôʳy:ß»ß|@Ó¬¤_â+€qzì ¬_^* gÀ>'^";[ª»ÅãDÁÁä.u_§'ÿUî®â:à,‚Ãëð8:ªë®ºë®ºë®ºÀ"ºë®ºë®ºë®ºë®ƒë¾,dFx½r :àªñ·<ûU| v ‘fm¾ùØÁõôèÏ«½àà:€k šGÿ hS¥(•åˇàû}ø5¯®ý#|:¾ D‹ À€ŠUã£@éCø‹ÅpØŠd¾xàóϯ°hÕï¿IÄ@-jøÀj°"÷¯ˆ ÀdôáÕøOéš®ºë®ºë®ºÀ"ºë®ºë®ºë®ºë®ƒï À=;WÙ;²®ºëÅëÿ@lr¬(ÛUû¨šE=š¾ ŸÿÀ@㬗°aÿð!ë쟫èxy8‹oG¯}¥x¯·˜ȈN¿Øàl_Ò÷ß@2 m}€Ì U×]öR ]õ ºë®ºë®ºë"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºG뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG0„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬GPà „„€!Z#.Áÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®GÊ–0ª•u×]u×]u×]u׃ç~¢-]u×]u×]u×]u×]u×, "ºë®ºë®ºë®ºë®ºë®ÊŸW]u×]u×]u×]uàþ|ÑDZºë®ºë®ºë®ºë®ºë®X "ºë®ºë®ºë®ºë®¼[Ï0ð1ùäû~îê– ßÿ^p0ÿÿ2"ÊýÀúñr8 ¼@>8LG'u¾ºï 0Ê`ˆâTE¯ Gú¾Éç8œ>¼ðgÿóIð¸‹^€ÈQÀ@5X4 pÕõUú\p:½À@Ê"\øãmóàˆ°"Õ×]u×]u×]u×]u×]rÀ"ºë®ºë®ºë®ºë®‹zq)‡Ð ˜•ªõÕÝ=ê뮬‘G¾®û W]uÞ@Àò5µƒ:ßW{ Ð0P¨ ªë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®»=‡žxõøÀ9ê•u:ë½8á5u×|‰À8«®ºë®ºë®ºë®°"ºë®ºë®ºë®ºë®]ußbdkôñ ä5uàÞ»ÒÁ@ê»ôÐBÍ«½:LJWœ°fÿøÿÿ`Ûëßzr"UÞy8`šoß®®Ë ÿœMñçÿç˜?þ¯@ÝUßadð7«è€yÕuG×]u×]u×X"ºë®ºë®ºë®ºë®È6\¿Õ€Ô‹Wþõà§‹"€¾|QøË8ã°Œ uy¹8Êüý}€×^@qØò]uèâ¨ë®ø˜Oâ‡À?õwè "Z/}ðL;€|Ðr±Í_¤`WÐzïÔzï@8ÕwФà!_„AÀU×]u×]u×X"ºë®ºë®ºë®ºë®]äƒÀŒ@ÍW]x1wÄÐ5Gޝ^ªü'`r­ÝÖ‹'EzýGÕß Ì"ý~Ð8«_+ÕuZûê«—çuÆãGU,ø¬ÄåÕß„5]wà <šø¥x€•_!ÇÀ3 «®ºë®ºë®°"ºë®ºë®ºë®ºë®ÏaÜ|}ƒ}õ×]wÐ4þ¯¶_ÿ6ߪ~åfâ>Wéo±æ×Ñ 4¯°fÿýW|›ÿðèâpµöF$àëâP#G®®k%Ö#»ýB‡×ÐrÈÃÅ€¶¾Àf>¦­2 pÛõußdCBÉÕõÕ×]u×]u×X"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®Gºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºëG®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G>…ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G@°Áàá$¬H„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGA°Áðð HDMVˆÿüüððÿ¸ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG · DÜ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPà G„À 1Z#ŸAZ#Jáÿû€µóA€"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ "pÎ "pNŠß,1ÁÄKá˜ñØÁð/ ÆÒ,Ž~u⿾Iây1› Hà "pNGŽ"V88‰|30}™ƒà^£p+€qv+óøŸ|þ'ß8.Ž "pZиWÌ8rñäPÞàaÿõ2€„F"€wf`ûã ì"±—Ë38eƒoÿ‡_ÃÈÀÏÿöÁP<€3¼9Tþ//‘¼‚Ö$*ûÄ—ÿßÛŠ‡8äè@4 °<;ãn=¬p½ÃœäŸÁ‹ÿÏ”;¼0 @xà`ÿû':î7VæG««1µs¸‹¦“ÃÇÉÐá8àGð`È…ò>Mïøp4€ aˆÂb8§¼Vÿ¼Dx 8 ÄìO½£š¾6"Ö"ßÀ# Ãïƒç;ÞŒ€Aœî#Ùƒ9ÜG¢ ñ\p ¬p ­ 2 ñ¹õϽŒ~…‡‘f?^t8>"M|>ÎçÿÀh‚-ýÀPÀ?‰ç,üƒTŽz[N Hç ·Œüþ'ß?‰G÷ Hà"pX„þ ù8xuöHŽ&û¶fXìà,§ûˆ‡ÓÏöO ¾MŒß}¶`àc¾– AO?Ú̾Âΰ§û÷Â/²}ò8>èræ_o‰Ü‚A¾ÖEü "pÎ"p1‰€Ôpb*^¿E‡ uúÇaç¼çÞù¡áÔ†¸GEˆ•~±ØE89À"p1†f(>uG`¦'ÞÛž°û3‡ tˆ÷ÅŽÂ&9)ÎGÏÄm#ß<;´<\fRáŽáÀ]áÀ]|Xì"c°Šps€"p^ŸÈ˜¡á×ëF¿X‹È÷ç¯Àd"y—ëôà8à«OTâm«ñÀný0A8±BïÛïÅaäPø°³@<¿¤ðÝó…U瀰 K Ü]çà³H„r9÷âG9ÁW’Ç€¾ÉË¿¾,v1ØEúе,œu?à Â0™~FˆEèùáØ¨ "÷ÏÄmq\?YWÙ8œG¿d62øŽáÀ]cÀ_|X鎧û" W΀#Dƒ0ÒP£€"p^€ýùÎáÄKãâ'#{ÄNF÷б‘æ"ò=ò-ðñ÷¼R5€L§úŽ…‰"*Ç®ð×;ÙžòØ)ïÝmyæ¬ÿþºñÎýƒG¾;‰ä€B£ø¦?‡IsîÅ\g‡æ\ÄîG½³­Á˜c]7p°4ÛÛˆ€ð:D¬h²5Ṫ_ÿ˜ñГr¯ƒˆð±$`;í¯‰ÏkaûÆ$œG¤€sxÛÕà> ‹9ðEœƒ ¾ v¦;×ÅŽÂ&;¿‰OÿáÒø y§W"©ýÄP ÛOxÄÈ´È·¯GÏÄiÎá`>]óñQ¤GaN¬©ý›€ÔêXà, ˆb]Ôp8GÖúê,tÇk˜¦p0ü8‰3*úÓÿÕx+ýqã€×ÄàëUøÐQÀ"p^ÿ"j48‹cˆâ ÔÁ7Ä{8„ï" 'kðI˜.êN~óÀ~à¹\ ò ¾¿õ~:oß¾¿ú»}ô,:ÿƒÈý÷â‚€;¿Ö!ËÿꞺoß¿~ýûG÷ïß¿~ýû÷ïß¿|¨"ºë®ºë®ºë®ºë®¼r÷ß@,>Ñ[GMûë¯vÝ7ÿN8>ÿOo߯õ“'€Ì:ǯ°ãWÐ7h½õ×]u×]u×]u×]u×]tx"ºë®ºë®ºë®ºë®º/¼›ŸçS_Óâ-«÷Dæ¶Ý¯ÐrÔºø…é€h62Üß‘,EÕu×^¿Ë$9smò˶ý¿]7ïß¿~ýû÷ïß¿~Gýû÷ïß¿|¨"ºë®ºë®ºë®ºë®º/¾ƒÀX:ß^ýÚ]Ò€/·×¾º÷Þ“;Õ×¾½ò뮺뮺뮺뮺뮺å€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®º>¼^ºë¯}uïß]u×]u×]u×]u€"ºë®ºG뮺뮺뮺뮺뮺뮺뮼Sëõ§$ƒPš}&½g×]²qâH4‚²yråË—.\¹råË¢ "ºë®ºë®ºë®ºë®’u×}‰y‰W^Kß¿}øÕÒç¨ÿþ¼ˆ͵¯ÐjFW¿ú\ïélj Ûÿ§¦«ß¿}uþ‰Ç‰ ÓõUZúj Ók®ºë®ºë§€"ºë®ºë®ºë®ºë¯û×ê½Óö±à×GÿíW|9ˆ¶ýõ×¾úp»ú¤ñ×û ]¢›G&ÿélj ÞébG×i?ÿ‹€8 ª¯W®•m^ÿÑ8ñ8‹U·ß`3U]u×]u×]uÖ"ºë®ºë®ºë®ºë®Åÿmý¾©¾¿ø ×éç¨ÛöÛMxKýÐú½ÿɬÙK­zü}~À[¦ÿÛ^¿H >¯°· ·×¿úkWïž¿ÿŒ·ÿÐ4o®ºë®ºë®ºGÀ"ºë®ºë®ºë®ºë®¯ß^ýÿìý‚ƒíûë¯}uß@_Bšß¿}ôŠ<Û}{ëß¿ú~º¾­ "âsÄR|.+M²!uu×]u×]u×X"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®Gºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºG7_ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G · Dì~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPà]„€!Z#ƒ!ßÿû¸µ#A€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë¯G¯}u×]u×]u×]u×ý#ð ­õ×]u×]u×]u×]u×]rÀ "ºë®ºë®ºë®ºë®ºë¯®ºë®ºë®ºë®ºë¯WzñáÕu×]u×]u×]u×]u×\¬ "ºë®ºë®ºë®ºë®¼º÷ï¿ûýø¸Õ÷«ßý"ÃŽU]ó°hÿø€G·ÿÐ8_¢H$[~úÿ¤Hãñ×+²ñáÕu×]u×]u×]u×]u×\¨G"ºë®ºë®ºë®ºë®»Zs0«¯q5Fß¿ý0C¯ëõ»h«£¶ý—4hmý?2ÿ¤ðëù@^Þ¼†A½{áÄ9o®ºë®ºë®ºë®ºë®ºë•"ºë®ºë®ºë®ºë®º^ïÐ9¯écCˆ·ôüÛ÷O¯Ó|@]‡ˆˆ^y×ÿéÒÆ‡mûë¯Þœ‘­/ß@Ï,°¸ $ŸoÝ7Ë—.\¹råË—.\G¹råË—.\°"ºë®ºë®ºë®ºë®º^ëß>€à /éÜ•u×ý:Î Uï—/ýÂ=zLïO¡àpÕr÷ÿNk›ªë®ºë®ºë®ºë®ºë®ºå€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®º}x7®ºëß]{÷×]u×]u×]Gu×]`"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®¼ýúº&ŸI¯@Ëë®ôŠ­O¤×]u×]u×]u€"ºë®ºë®ºë®ºë®Ÿ]éÎ «¾ÀÀ-Õr oÌ9c€ih÷￯}ÎàjÿüêôüÁvýÿÒ;‰·Ë¯~ûÓœ5¿úE Öé/º5„Ý[DxŠŠÕJ뮺뮺éà"ºë®ºë®ºë®ºë¯†½Gy¡õëN«Ý7jÿãoôàëýƒH…[¥ÚÁ¬}¿}èsïö8ëúp:D·ÿH¼‹o×Kµƒ‡ÿ½«ßî–E3 õ[ÖœH‹~ûÍ̯ßèIß¾ºë®ºë®ºë"ºë®ºë®ºë®ºë¯¿þ7ÿ¨/Þü#ñ×ôàp‹oÿz¡Ðœëv¯vª¡ ‘íõÿ ð/ørÀ8r0u]äÚÈ$ W¯¼ƒLOw¯¢„_쎢}¿úG@æ#[÷ï×ú×ûýkþmõ×]u×]u×X"ºë®ºë®ºë®ºë®Ÿ]ô@ìúºë®ºï" ¿þ±ÖcT¾ôøÛ}ußX¥¿õä·ßDqâ/öò ¿ú~¿o¯úuÛ÷ËêÒ3"|ä{˜©5×]u×]u×]`"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºG뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG3<ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ뮺뮺뮺뮺뮺뮺뮺ë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬GPà$„À 1Z#ó¡Z#ŸA×ÿû€µóA€"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ "pÎ "pNŒ ððªp\ƒ­0HÇ<s8ø ¯š(:Ž "pN ˜ð²5ðÈÈGÈOÐÇaôÇaô4Ø8 "pX„ýÀ2 •wØp¾#ˆ°þE¿±ËEÁÇÇáAà4kÚãÀ6± "cÙD\q>ø4䀴‹yöã‰ÇDB?Úô@xЀ¶ØBU3¿ˆ4Ð;4G2kÅE xf[/’·ÿâ?'syø1üã̯Ìq<]ࢀРâ6 4èÖñ„“¯:q 0w¡D þGó¶ÿ Ž€t~LjÀ{ܸŠxŸpßyÄaàÁÿôþ(45¤Ø8"pZO¾A‹ÿÕ9€/¼‹(GÌN/ÿ™FÞ9È×Ã78’ Àíû^¿^ O£ìÁ ?Y·|ÖiKyvÚ%åúhP æ³ÉäëË×Î÷É¢!¼UˆÀBb-Š|1ö<8|­ò>ûF·ŠãƒÈ° ß;‰¿ G¾`ð¸+…ñGŽOðÀöã”EÄv‡ }ztÀ‘À"pZ‘ª«¶úÏÂÈ€rñVZ„½ãDXþ*òq¾cr5ä€ç±Â·ŠØšÀÞ6ùdäKÁ«Ñ¡ÎácÁ6x ½óXF'N ?ÿx$F;2îP9€ Нœ 9Èúcð ¯ßoo‹f"ßó8š³8š§ŸÐ8šÀì8šD’>'_À.£D¬<˜,N¼G"@ñ„aÌÄ=ÂõìèÑÈ$Jg<âp×ÀŽAl§$W§æÀ‘À"pX„þ”Ä€€×ÞùÔ sOôLJ¶û‹ÿï¡÷ÚŒB¯"G  ox±¡LÀ™‡‘-zû õôÆphÿûîcÅ÷8à‘參‹ýâÖ5v>ÈÌÆS]‘€kçÿžD¥)oä 8𻥭1aDìUõŸÈÐ$p"pGÎ"p1éWÄœ=@3¾D"ß ÁÁk ;N¡"ý`eï|'®€í89À"p1ƒÀÌ9â\ _þ»r5⢀_d\@¾¡p¡è„gPˆÏÎ×ÎÖ`}ð £BéÁÎ"pbó‰Áz` ïÜ}~D_1Ü³Ž¿Vöýk÷ ‘½â ß6Gð#úyæú¡@4ºtfl(Eƒîã÷9aaAGÍ öøDp  l7¼å€n;±â›‘´þv((x ƒì@x)-¸#@E¬ !â¥á¬iŠ@ƒ8ß#ß ×G0žN‡s"ß#D$#…›OàqàÚ+€€UÁj²GËäKãó‘|]…C€]C€]5â-Ò0g8‚äâGÀ9×Ôe?·¸ÄZ7ÒP£€"pbø²<$ÀŸ}æ²ïŽs7 eÆMÀ6¼`yÓÿ"Áó‘(ÝpכĨ‹àÄ‘Pÿ¾üwAÄ ¼V®BïĉàC›ÿíWÓºˆ¤ ÁÈ󊶀o~B2‰á×Ÿð ­ØœNß/úóß¿]zºP<ýþ€X}¾½r©êÿÐÀ^u¿~ý÷Û8 ¯ÚXð²G7µ~é#‰áþÿXÚþp Hñáõu×]u×]u×X"ºë®ºë®ºë®ºë‘v_ü¨ ª÷[÷{ÿè 2 ûqî/ö»þIÖýÿÒÀknÿ§GõV¸µG¾¿é¹ .¿Ù8Õu׿}wàx«®ºë®ºë®ºÀ"ºë®ºë®ºë®ºë¯>½ÿèÀ?·ïÝn÷ÿ"  ïÕßaXÀ®ºë¯~ý÷Ùʽ÷Ñ‚-û÷ïß¿+GÒÑk®ºë®ºë®°"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®Gºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºëG®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®G;®ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿºë®ºë®ºë¬GPàÁ„€!Z#ןÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®GËcÿ÷¡ôÃðpÕu×]u×]u×]u×}½¾ºë®ºë®ºë®ºë®ºë®Ž "ºë®ºë®ºë®ºë®ºë®Êœ€EÕu×]u×]u×]u×]x>u*뮺뮺뮺뮺뮎 "ºë®ºë®ºë®ºë®¹ÙtÀ +Ò;Ÿo®ðÐpÞì “ìœ"ÝÕW]åHb]ó«ã<àÊ!BkÏ<žàhp€8öúïÒ0šô˜#×Ä-GP9«¾kàÖ6ïw]u×]u×]u×]u×]u×G"ºë®ºë®ºë®ºë®¾J]×tÐU^ê¯Ý-ábuvN:\æPœþ&®ºïHÂ'µWïZ÷Isý늂¬ƒ­Ý{ëŸB Õþ“H5]u×]u×]u×]u×]u×G"ºë®ºë®ºë®ºë®¾]kþ‘Cêï*,Mò-} }«×wVá@ [ï›Ý^ùñi­Ô½GõwÐál‰W_õ¦¾.¼àÕ×]u×]u×]u×]u×]tp"ºë®ºë®ºë®ºë®º[Z¤z¹×z[€Òß^ú÷×]ëK×аÛë®úòq®ºë®ºë®ºë®ºë®ºë®ºèà"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG=x7®ºÿï«ÓõRåïß]u×]u×]u×]u€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®º=åÇ}|^—0AÕ×]s ‹Mo®ô<o—]u×]u×]u×]`"ºë®ºë®ºë®ºë£ÞLX ¤l×zRe_ü#‚§ÿUÞx°‹ƒ‡€8(X &¥ï®»×°úô¤=ëÅÒ¨2Ígò¯}ëý.ü >¾@46hG €å~@¥Þ:,“­Bï]Ô€€äT÷¤ àú»ô@¾µÔõ×]u×]u×]`"ºë®ºë®ºë®ºë£X6çÄwt;€ºŸÞé܈…ˆ½e˜|›þvïõ`ÏÿâHÕúÖº»Ð7…^³ý(ƒWêÏ!÷]AGƒˆÌO¯ 68=õzFÕÞ´úWz|D{ýÐp0€ ~ØYíÿô(y:ß}žN·Þ—0A®û_ÿU¾ºë®ºë®ºGë¬"ºë®ºë®ºë®ºëeG¿^󬀷¯1â/ëMýn]“ €âæ#ê»æyñ÷Ž—ëÅÛÕuû¢Ç_ªë¿‡Ú§r,ö`Uª®È`Þ8Wfl>·ï®ú ®¯wU]øà°å]u×]u×]uÖ"ºë®ºë®ºë®ºë®Ï`“µyà൅@ÃÿípÝi·×þˆnÚWœµMß„@ªºï±àÍÿâªëÉuËßG¿}wØ€_o¾Úß~ëú]ê÷ßFÀ;º¾ Õ­µ'®ºë®ºë®ºÀ"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®G8ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G · D, ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPàU9„À 1Z%HZ#ó¡³<3Ü!Àµj¸ ÿøµÿóA€#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".RG”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”G¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"åG)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”G¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"åG)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹GJR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".GR”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥G/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".GR”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹G”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Gå)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆG¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Gå)Hˆ #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹—TH É <Ø!}ƒCº?ÛâNÇ{•w@ A 5pÀ]@frÑ…é¤ïEÏ^¿ö QùHÂhhÀ0 7¹a¡ˆJ~̾+_¾ÀÀP GGb® †‚³#e™­É‰ÿ¯ûÁJRô.{”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"ýÐ ~°P @Ä„ЄLܤ%c~7]@à@€=€:!†•Ê/÷Ø0­Îµx ~ !ÿ˜ Á3ÿ}Ö-?æ øÓÞX`a\ n38ζºRžKgçßÅú£GŸÔ¹®R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥"  #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹—tœÀ`PG<5× î€‚G jà€º‚`å Õ$ïn¾ÀÀL Gr¯¾_``&#€9Wœ˜0›r÷‚”¥ê\×)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EýD?ÿÌŽüÿ÷Ýp@ÀCþ`¯€ =ÈÅ?ó€#€?¿ý÷\°ÿ˜+àOyÀCŒ¯Gu¤pûø²OŒ|o^ä¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ€ #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R–  À5!\¢À©±Egù› òGÙÕ ë¬ R 8i 4 ÂzKûb}ì5ÈÀ…útB&€í€ÿø˜WþJBѯ|Äh @ùa©ø3~ ˜V"ñþ¼àÀ€7,”`(YãþR²ÒÈÁþóƒ@œ7‡µÒ’×ãðƒ\À8¦op°0D¹ ä€\~@ ‡à|pÀô£d‚PÞ¡ € P‡±3ð%ˆaƒIÿ Ÿz`€hG° ƒy0dÂÈEà<^û‰Æ|/*€à(YÌùd²ð¿Ïå€Ô ²¾J÷6퀂 jà€ºç:ÌpŠ#]PC€ Að×]åa„=‡'îÝ×öëãe'À@ €+ pÞ è&††ðã¶þ¾ÉaÈà @“@l`h-Œ;`§ü„a?^Q41»döÚëBz¿‡Æ€ ,0Gyd5ðìØ/Ø2ÈN@ HE€ÁÀK’r°„'ozRÁ À”PÐ  ç’C ONÜ;ûÕI P´†”’‹Gd¡9¾ã¾ö ÀQ*Äïè%ãïóØ`iDÒYIÅ¡9ДwßÞK退àKA ° K”^å†n“ØHá÷ÌïD†L²X*À¤Ïrè?n„°“q@I–#/‘¦fì0  ÙGkùE —ÎÂßnÌ0*ü ¤†Kå–ž°íŒÚÌ@:ºú‘Qa£ß øa™?@ œbCCq\$ °¬t†Ó°Ñ% Ô†âøIA@[Û€<Xüš~‹&ìI-H)KOÈw¸¤0@`$†â`k≥t…œ9î> evÀ#îGµ%ð55&/Ð` 94å ih@èÑÙG¸›Ð‚ã:PÔ"`&ÿÕô´€œðhiX Bþá¥}÷ûž„£‘ms@‹wã¥Èi¿€\˜`ÐÄ1  Ó±{d¨xΜO¨¤ÔB`i5;ü„—ö=‘N×\ˆÀhÂ9ç€?0 8#€0h%€»ÒŒ€Þƒ¬7t=úAü`@Šà‚H“7þ®: @.2@a©I0¾œR Ø § Ä! K…‰¾GÝeЀNxh`!C-x¢³öƱˆÃúµçð Ã×tÝ7à€¨ ~2~€t Ä††Œà! `ê@Lˆ NÀ;1dÌ(ax5…ôtØG÷x@à>(h ‰Ž ¡ƒHã!½8 ÀL@2&¤„CL AèNYáyRÀ:‰V#÷#Ç /«ø €N3& †PRNN#|~âºì÷Ø €–åºAG€wÆ'’’$Ëãß5ÞH@6K¹Ö7_L¸r VC@ihÁ™¿ZQ‰÷¢ÀøÀ¿Ø  WØÀMÿª @ü C\ÿòF÷×¹Àt¢ƒJ~îãíKèí¯â@@ @.l„”¤°Ô£'Šn^ß>±ˆ÷ªH ~\ `†CY81Dû×\Èè°Ô€ !ü’Ò‘€VYgïr@bhG¬rÀ*(›¶‰¥%8_ïÀE½–ÐB“÷âûWÃKç_’|– ËÅì0°~r!Ž-;oƒÐÂï¾Nß}÷Ͼ^úý÷Gûï¾WÝ__18rX &€d—¶%“ÄsÐ#j@`„ iF@`oý½ø:Rê€-nP ©ZIˆeóƒ±þîÛ§íö?µÖü¨€ Šn)Ée–#,<ëØP@Gü0Ì–€œÃCq\$ °­ô€„ €bC,†Kå–ž¿ÈÛ±›X vÏ~`$²±á©è(02þÜFy…€1ËX{k£“Sú¯Éð– o(†°®Eוp^ø¨A07”MP&² à*_Éï}  € À4+†¤X5<ÂÐð·%ðä^• I1;£ò’Žûçß|FúI1¼”#¼ñ4¼G}þv¥êð`0åû€ì 1/€Jƒ gy{Ò,®žŽe͸Ü÷õ@ü@Cÿ08pKÿßuÁ ù€L¾F÷ ?ÿÌŽÜÿ÷Ýp@ÀCþ`¯‘½å†`{© ‡ßÅR|Ò¤ù¯^ä¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Gå)H‹”¥".R”ˆ€#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥"._Jǽ<4„¢8B0/÷’9wÍo±‚è?^Cp @ËÜš#=©4‘}ÀäR  2¿ƒxUðPÀ :Ñ@0X¢ŠÆžjSÍþú¸ Ö@G ÿKóð buò^}˜¡½òTLÆØ%¤}Ñfà@ @uÈ@Wa» šÁ!‰¸áøï`¥Û‹J;ïcö÷p \@0!¿ß†‘þ;µ×'0ÔÀ u» à†‚8à® ®4šÀž#ÏæGn¾*`dÀ07lKßá©I¿Œ¯µ_Y˜ pE燰`}ÐLΛæøûê`ø€:(  @¡GfäÒ`ãú;buòûèÀøg€€Aw`?¾öDÜ~¨ ¾Ä.p [‡ï|5'ûî úÀ4û׋$û òÐ"d#½ýH?^X È@0Ü ˜Q-8¥šz@’Ü ¢ZBxF?Ü @ýè!¸ a,`€L?Ô³À* buÌP›à$ö©Ya÷ò`(L!`B(@:+fÛcÅñÿ›å%ñóGsãzÉOOríµú°@ýA€€h¡Pg,0Ôqì~¾Á~}Õ¸ €c¹À\@ß y÷š‘}(û™tó{øˆ!€Ð „r=Ï~`pGbh%€º@†@&È÷<ø!€h Á‰ –~í ?úÅ8¿¿ß'<@ÀBØ–M,”„›ƒð]õ‹âÀ€ù€Ae†ðo<ý‰‚n€ÌGé¿5ËO6ú ~BI€ Ûä¤3ð3ìxÚ‚ã‚þˆ—x ?º,pG¿¦džP Àtœa43€C¯Ï‰[qû{ô0 þ@ÿ… uù뜀b5ÌŽRí¡·ëÁò p#ÿÈaß]¾D–`+þCÞúÚ3§azÈ@CPÿQ4’Ld<laY¿+_iJÿ¹¤¾>° Cb#€!G@M Ò Oåñ7:2¯ì@ùà:@bMJ3bj__Á$ú°@Rú•€™07p­PÜP#€2-@€`‡üä G2È×—¸Ð("%ÓÀr¾¦ŽXI€:ÝD†üÒÍ ¾YϾÊ¢àƒý7AŒ eÚ HìHd‹î€`P ‰ ; ± —€ÉlžÈ5HÝ+9ZøÙ@úà€ aD (rŠ ÙFG&]¶À·Ú  ¨ ËP˜C-œ”L)%¥±üb7í¬‚  A€/  šw41§§á t!=_ɰ ~˜ìŸç$@¨&€%ô 0Ѐ;̰ ƒPZ ¹ÃP‚‹+ ±ìZy꺂  A€/  štb $x$€PЬ0„Pg|žñ”—Òf¾x ` ø E² ®LHæNSG‡ßê÷Ú@.jBĤðhÈ&•úRÛ:ÿü¦Úø¡dŸufÃQìÈFßÕñüÀ`àÁ/ÿ}×,?æ ùäâúÀÀ‚_þû®XÌò5Ê`€Uí8}üY'øÁ'øÞ½Ér”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\G¥)r”¤EÊR‘)JD\¥)#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥"._QÇÓ†„„¸ÂiC?0iF_.º@€€°ñ޲‹¼w ØBÀÁ{™Yh‹û0€à‚€€wÉìX#€W ß (šQ ¤†'Q{%G Ç}ï¾?|°@U Pet%vRq‰G;ï`l^x,0„^,0ðᥠËÝß\;![·GYÜ¢ÉJ÷ñ `à@€:, TŒB0zyˆØßï¢$?=&™#ÿ/à§Ä{Õ€?ná d!¼¶$#(¤©AçÝ%h_á-±>Í$|YC@)¸”R nIH†¾Íd8@Nô‡É¤2Ë!†òv¶VØGU®â„À Æ›n‘¾þ D`4asÀ‚ÄÀš `î€!€Ð „r=Ï~`Gbh%€½ ÐCÿ ‘ndà:þÿ|X¸Àl ¬4k}¦ø° p!€ØXhÖà!€(}¹0“~vö øà†ä Gÿ¢%â¯jŽ`Bú"]à:?û*Ä4‘ïê0?ù!?þ5×çžrUˆ×è`Güÿ ëóÏ9*Äk”hB6ýx ~X!€¨$ÐaúÙD” Ä{ä€ù`† ‘ÿA„[ëeP'ìÀ@` ê&’oóÁ@†¤ÀGB€šYŠ0&84ÒÞ™dž&æÇ_ÖòûŠpE¤Èÿœ„¢ÈÖ`@ü€Cþâ‘i2?ç!¨²5å` up Ãïã¼ûêÀøà&ဆGSa›9ŽR˜K_)çÝ   °Ð ’B͉¥rgàL I× ¢ÀÀnüã®ró¢þ´ˆþpì@;K’²X¶IW ßÀ;%ì”%Мûã¾÷è²4A©&JIE•þJ›ï„ÜÀ À‰ˆåɘ≻ñ€*Nù8Bð«€d.MÛ£¬t^A÷ñ R>õ`|r &ƒ@©q‰Pô·Ýf^Ä ‚ã€bGWA0 Bø’_Âöÿ /{ØP*MˆjI¤ÒÒZ{¥)ïý±Å»†œ9Ï¡!¸Ëøè @ý Œ Hàê%À²x µ`îÞó~ú@ ˆRCR€ ')ƒ°(Rpé•€–0}ó~¿n ¤²8‘VaŸü»ú ~ !ÿ˜ Á3ÿ}×,?æ ùÜ€@ü@Cÿ08‚gþû®XÌò7¸CG 0 ½º@'¿‹$ÿ$ÿ×¹.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥" #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ½@€>ÐÉ0À!&G`ÔbG8²¸ô'/‡Þà €?ÿÀ4Ô¦0 £¡#ÿ ÉpI=|öŽÖ!€T°Ã½i+&þ¦ ~ÍØà0ð†°%€3“®0@€¾H`!%ìx`GÛ‚Gþ°J<&ðƒ}측¼v«‘eŠ(˜˜ Äd#?êÂúíÀ@0€€†`2`¡‰cŒ[’¡Âõ†—HÞãM>Í”×ï _ì  ï÷¼8G €u€4€Ö, €Ø¬PÖ5gìêifK ÌŸR È:åè€`¼„à1>³‚ —pHÿšóô´(¾ßOÃU~Ìà@’€.9 02bòI@ƒ±ƒ@+K{Å'¿óR€ÒjI¤™¡\º€ À`µ…ÿtìÈ!”¢ð®bp®réZ I]÷i}½ý,`€ ä‚„Ô7þɉ BpG1Ð )N?ˆ ‰…J%†– ó'ô~>å7 hb/´``À€@C€QÀnC ቉x–ZÇgÛaY…ûÒà@BûA(Á;ýïKLÜë>@6Eëxvl‘0ØšhÜ Œ%8†¥‚ê@©ü„Lq€d¤”5†æv|áuT¶éý#M£fÍ~ÿ"ð!ÿk@‚wûÞ8°ÌÈ"€A‰G ’ºy,”JwîHYÃK"À©a¹¿#V‚²=˰¬fR !p*PÂÆeÅ1,¢=Ç¥ªÊûãõ:¯Ý† ”YE‚ö¸Ää°ÑíÝþ/ÔØvØ*jPC,šIš È:ú  @``&<´ .‚Éd 2Hu1,¡ãïQÊGÜ´å‚wü^ ’( –›uO•“ÞÀÂR‡qˆÈqíš4¥¯ïÞ‹õ AG °  ð @˜¬€“p”F˜€ ŠjP À À-“‰@ħ|À-,yZXà—1ÔiÃûØñ¥-ìïªÜ À p!É\¢nÌ‚b‹Â¹‰Â¸w½¨Á@5Ü€  0& ¿óLHRMÄûæ°{œ0!¡™ð»D†!7õÀ@éÈЬÿúž‰ŒO¼Ð`@p €.N&€œ7€jG—ŠJ!n-ùaÿaW“RÔæ8Dñ1ëIn¬­•¶VØUe)tþöm~”HJI„Þà0Q)€,.·w¹V€€€ˆh©0àp @Çü”|Ju0 ÒÁW’¥ŠvZ1Ô_ ß½Ž|iK{;”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".GR”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹G”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Gå)H‹”¤Û?VÇø‹½!4?Pš8J[·,¢’’°~<[Ü&Ä1Òah )9ДwÞžRPz>žû›j‰…$´»ŽžÃ¶{Õ‚å2oøÀ›ÿ·šÔÀ$ ‚8–4÷è+”ÀP¢nOK¨u¨i} ×ðÀ€€ëì„4”Ÿö›¾þÅz@@ðC¢`#ÿàiówA5¢Ó±ÛÙ£¾¹JRÒ›”¥G".R”ˆ¹v€€#Ðe°¸j:q(¡¹·e„ë‹}8? ÿØŽ¥€ uˆ+—‘ά7ŒCß•È?Xàà; Ñ0²Xod Û8¾7ÞnûX H!ÿ8€ÿ—Ä’}1& ™öC‡Ì0¾œ»jR—MÊR‘ᡸ˜RKK±Héì;g½X þP Fÿ€I\ ¿ûy  A @¨#€)`O~‚¹` &äôº­I¥ôG3_À@^Bv¬²ÒRØnnøSûé Á ‰€ÿ¤KÍÛ“QŠ-;½ï®R”´¦å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥" #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹GJR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹—t$Ò€Ÿ“Æ-ë¸Qù Ý Ù(NûîwÜÊJã¸ï§ó–‚rj@@|— A)ÎßîìE±A@I¼´@bLGïɈI]R:Jÿa/ypÀ@B€tÌQØÿù©Oëÿ›î*²‹ lm¹E}ÞíGÔÀ$ ‚8†€ =ú üú¨!€Hp {ô€08±:gëøÀ x!€Ñ0ÿð4‰y»Ò‚ ÿH—›»¨édQ#\¥)mEÊR‘)JD\¾œˆîGRÀºùôà@ü@Cÿp8–5×0þðjMǾè H!ÿ8€ÿ—Ä’}öÐ@Cþp ÿ/‰$û É(QïmJRî°¹JGR"ô€j`AK{ôùôPC *à XÓß ¯8AbuÐO×ñ€@ðC¢`#ÿàiów¤/0&?þ‘/7uP Ò&È¢F¹JRÚ‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ€#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥"G.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"ä_h_OÄ?ö#€)`["`` ËìO¨´ŒÎ}üÅðø_l μ@GÿÍ|KŸI „gÙÝÅ1Ì¢Éxæ³Ãô5÷à`‡þ`1ú øÐµÂY…9Ae’™O¥ïó€è>ßø4÷ƒ¬š èw$$n{/‡Ñõ÷ÐCþ  AþÈš°Àð*Р€Gm‹!£zùYÝö9Är€~òOÛ³µµg_ÄÀv˜ €@òHD'8 –„8¿=¤˜¼Ðã5‚;ܧâ7ïﺓI¡¤2ùa¥¤²Ò¾”ÿÿõ”` 3-=ÄLÞ:ÿ:RûpXtC(„C-! 0OÈèOÿ†8)Î޾>¯·Ý÷^ã÷ºÈd$»uŽöE‹¹J^¸¤§6ÀÀ:d€í9ÿëA3s~5#G°]eÞÚžœŒ»òä0€t¤2ha1L4´‚Óõ»)l”ŒÀ€™ÁþŠ`·kî;ˆo&PÒÉ¥óÒžáØv•_pà 3-<;[€Z*ÿ; ´Œ”''s¾ûî#è>}ÜÐ @’À oÈpÏÜ0±("åÊ´ú€j ®Q-tu²v[që4ãXj‡±änc¯áO uõP@¬àÃA“|ì˜GÄ9І®ÎW^^· !‚ò:Oe±èAcsµóßпD†$˜ZJNd£ô|;îÞù` °°ðøÒÊ’#Ù“@Aà ’49ˆ¾h&ìÌ~*”µ€b€04eõ#ñ<Ìulý¬º¯+áú¯Ð€;¥€Ä†C/ºCSÓÃ2M~p€>’%Æ`0PÞXsÛlMÙ‰÷ài^G“@B,†MHƒ3þ@}|X( À–’ŠJH@:u#·N_Ëâ·!Dú•‡ÐYyò’0À:ý €À¤ãÑÉ¥ Âs½P€/Ð=€ À¡Ž B~·{ôžº?ß/|¯®0,Äžâ-@-ã¯ó¬_רÁöÀv@À2;Æ£`Âh sXÂϽ=¢2ët°s¹?KðëüéKx,À€4pEH G†@TÀ°§ºÆŒÖ.§¼ï‡è_¢ïŒ‚`B’goü "\äÐÙFºÇ1Ñ£{1>ø`‚PGRÀžý~}ÔÀ( ‚8–4÷è+ ,N¬†eü`¼Àh˜ÿøD¼Ýé Á ‰€ÿ¤KÍÝ`Tt‰²(‘®V“CH冖€ÄcÒZrƒÿÚï€! XLÙKÀX£0R(Q·×@3G¼àÃxhÉ© IŽH@¤#+a€`’nÆj‹ Èålã ÀLàÿE0[±>ç†ChņPj9É)9(â>}~‡±düà ¸4Ô†$Ö$$RPwÂnt€a™Iî.¼Cz>¾Ü¤ˆ ÿA`P›Ê”J À{¥ÏA­Ç{8 fp 0ÐÛâºzW³³^ VÌO¿Œ_NÄ?÷#€)`]G|ß}<?ÿÜŽ¥€ u þð"h=÷A AùÀ4ý"_ NCÿöØÿûm}à€(t‰)G/8јþ£—VÔH  CzHeüSº ˆQH7‹ë¸À¨¹ 9m¶µ(¼H°Å$gÄÎÿöW ûý¬@P P(B&“xxah/Aýú¤ ì†ÜB Hah9(ÿru| ÊOqz EG_çª^̘ŒGð €OöÛbÕMÆN÷Œ»Ë)!½‚“Ÿ^ A €¨#€)`O~‚¿>€j`AK{ô ±:Ü Ÿ¯ã€à†DÀGÿÀÒ%æïH^`4Lü "^në ¤M‘Dr¸†²4†M & xih+§ízÐPà03$–¯‰Ž(Ô‰:úÀbC8o !†–M/ž’GÿþȘ†çüf'Ö’nB¿‡‚ò4v30$ÿÙLí`!RÐ4„M@ -യе:‰ ¸4„Y0¼rJÿp;…{†e'¸½P¢¯óÝ/bLN?Ú@@ö-[vbIÞñ×qe$3·°ß'>¹JR¹\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘#óô¥/ G¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"åôð@ü@Cÿ`8¤k|Âúx ~ !ÿ°R5¹€@÷„{Ri"û€€ ‡üà?þ/‰¤ÿ}°¤ÿœ@GÿÂ%ñ4Ÿì€3$ DÈGY×߀‚ù€Äÿè4kï€ëïÀÁüÀbÿô5òÀòæC2þxG~`ˆ#ÿà`ÓÞ÷`€à† ‚?þ =á-ÀN÷è&/î  ‡ý ‚?ý‘56è~LÒÅ-!¿JBû æP´ÿ¤0Gÿ²&¼È Xä%"Ø=:ózFœ˜t3¤>þrB¸à…b`˜d~§î”ñ?Þ´?T DÐ ƒ@B (`S H ‘ŠAh4j¶qgÞ6Gè3Îø8€²5éË%åóîd•šþ÷| !€ì¼þLÛ€‹üF¾ï|H¤ÀhÀ##Ü@àn.Ü„I¾hà'@&!€í ˆ…t‡˜O¾ò°*X HeÃJCSÒŸÖ}ò@@üàÞP"öì44¬ë¾Á³ª  ‘±]"äCëkðÀ€`9Ü À:GbŠÊäÔãߟ‘c€à(‚Q0@ƒ›GŠX‡áõ  €@B+6A ¾‡äÿgºˆ`U)Onu™Em¯Ò-*¸Ù1)Ñ0 ïgG ÙÀ’JÌ…=·¾ÆM&B ,0½Ð’“ÐÌúüñ}„?8„‚2ú3’Š/€¯åÜà !¥€j`AK{ô¨'RC2þ0^`4Lü "^x4¼L)%¤â‘ÓÄl÷¡/0&?þ‘,€!¼˜ÐTîÜß`û¤›†þ’-’;cr‰`@BMÙtñ‚fÁ× €¨˜šÒI@0&1/ãËà#˜/™z»á „$èP23pÝÃR´þDמKG°1B5ÐR i¾`|ðB±@P@#e8GOZSºRî p€ ÃÄ ÀÀñ4˜ŒRÀ(Cdá+qizx†^îþæ%f:ÿ@€f¡4à†€è›˜°Ä·Ç|+Ü@@àCþpŒrAñ¢qá¤Ï’.¢uÖ.?ç€Èו’K! u3Âïã >ú€ ~ !ÿ°Kß/I÷ÔñGý€@à XÖôLõƒì  8¿t„$´ä#?OÛaÿ™|x0 p@ˆE@3&  1Nß ¼40˜à{ÔŸéÜUïÁ @t€€-†N|Wá¬àžø©}ýÌr)‘•hLF÷q`&À5¢À4‚PpÎB `¥ô@ýp`…p @2GÄÍÀ)&/‡èýcîuó:à† †¢bsâà ßqY0 ¥ Ë|n²I[GëýL ,„ZJý +ï¾3ëàÀ 3À@0€14´qEår ÷Ô‹J’~ ÷ÉÁy`Jp ˆ}€G€åÄn4u©3„µù€ A €¨#€)`O~‚¿>€j`AK{ô ‚ÄéSõü\¼Àh˜ÿøG×$èp  ;àˆ…tá|Â}Ö/0&?þ‘õ ?87”Ƚ”443=ÐGZ€í‡¤‹FìPuýp†M, †–M/ºKOOâýàA @ a€` –Lv&±’Ù¸ÁÛ} ç1zB @`` '(¤fAH!—Œ+nÚòËBz®ó­wð€ ²ÆÈ $Q0`Pƽð ~¨0 @Q €d‰„ Cÿ¢bcp>VÌnʽ¨ ÿ(pEÿ‚Oü†€ g,x²iI(° ÀNZ™(I G¿¾÷íDÒ’ä·ºZ>:õ€è –ha4®É NNâõð ïjñÄÒÿ–O¿Aß+, €*Ð9h àv  ÐådŽò!uߟ¥)zw5ÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HG‹”¥".R”ˆ¹JR"åôÐ@ü<_ð§X×_2½¸ ~H !€€˜³€TŸ‹RMçÜà&ìM@yК~ܘ7/ËðEÿ´`»â ?ߢ „ÔƒJ +²JNNâõò Àú €BL(üšxCf-äŒü  ¼ÇvúåÔ1)o·â- ‰Ù÷¿*uúô’ÀB´&†€ }óP ú@è°À @+&—º2GQ“SšéFqCïª~ýÏxÐ1%dÿ™ÇÌšÙ¯åÀ€è Ï&† =á¯DZ‚@2`W/ , §†±£9!ï;uǹ5"lƒ þâZÒ˜#ÿÙ^Tÿè0GT oTZÒ˜#ÿÙ^Xÿè0GT_þÜ †à"ÄKtä>þoon`pGbÈÖ xpCð‚8F½B€r:Gåç_ß/‰‚ ˜d{í·Ä A €L2=æj0}ÒL$Þ€@ý!€0!° Q|Fë¾Ë~zØŠ9š Z ¨åpûï €dM|ÐwÉ)?,Übp¯«É;£ ÝI-ïáà N€ @˜šƒI…#ŠèÃ>áV ì@€%€.ü˜MÉ }ú1$¤4:„ão€. @ܨfœ”'t®¢- Gí¿Ürè(½ñ÷¾Ê¦Ä™4g|„(z¼°ð@üà’`ß“CS˜ÿtP½’ÉO¦¾œ”òÿJ{ÿßþüÛœ$£J‡ck&—ºµø€@ÀCþàÐGdß,¾¨xÜà ’=ò¿j¨áÔ‰5õ°@üàÀ€•€P•ƒ@þ>ù%ØFë7|M&` щa€+AùV€0 áÝ^€ÔG>¿¶†ìšB@iEЂj°C»pù@@Ð @vL™Ë&—‘ƒýÝï›îß_9<lé&€? Ê(Ç|’œ#(>òƒRJG÷R3ö¿Ÿ€ÀÁ€À„`ÂA0¬<ÞêáûøÞÚxÞ÷ͯí€d.BbwÌ58¼#íqÁ€N‚ðÒb{VLè@”q¬rò@$šP`áˆü•‰D6@y«ýîpÐ+Ë)}¢ oýšR—E”¡¨IE£$¤ï’ŽwÞúh@@’’íÀ©3¬ÌöP­€K‡0H«æ0ßëa $Σ‡T’²oôA4„M…ò‰¡…†'‚ÑМ½P 2ˆe’€t ¤4Ž ))a-•…ûóÀ ß2vN¸[ölÛÊG¹ p'Ë` ßÕA @v@T`W˜À0!8oÎid­ÆñH|.õ‚€ Á@/  šwÁ‰~@¦¼Ÿ[ç—! ¾€‹ |‹BJJ ˆÉBwBw÷^«>éÑ#øa{mŸþ3«mgýãuôºF‹{&S_ÝÁ‚(€b CоL@¢ €ɤ"ñe¹A¥$¤ã€òv÷ÄÔéG’ž“îrh @Ê3V€ÁïP ÷Hˆyÿà Ûlÿñ[kíà‚€ Á@/  šwÂ*ñ5: (@,ÝNò,¢]ú ÀLÀ˜C&‹Á¥¹A¥$¤­€òv÷T§¤ù­KI-?¥³_L˜-€6!„‡á„ÜI+‘QÍ×Ö@€9pžK‰&†cˆdÍË)…¶tkâr 5(²!Å!Š?VXfMþޏ`G €€5N°IAœònå6Ÿ‚D!ýð 3¿~„8öΓSî~˜äWˆCýý€8 P¸4 4€' šB -·;‘ò0ì}X@ 0f Ò@!&†¹a PšR2JQ¶¾K‹ú5<ÛNÐÍH —n“ï¢æ€\¨ 1‡Ð €vr ‰ß“ ¡»q§rR;_<• è:è&‚Ƴ٥Gs_ÙÀj° ÈDÀ€d™„_bÃx&•‘˜ñ©+l(@À  O(1 '!M&nŸ°¤¬éGÎ|c†§Å¥0¯s”:ÔÌ>ÿG|Ê÷,ð àS° `^ê=Ì$7„Þøß¿B?öp¸r}<ÊDÀ,~ŒPHP/ †tæIxVàx§X”ŸîïOÞ7ia© ïìPŒ‹Ðtt€G膄nŸÃ Ûlÿñ[kíà‚€ Á@/  šwÂ*ñ58Û0(@,ÝNõQ.ýˆ`&`L !“HEâËü Ò’Rs°NÞàÊ”ôŸ5¡i%§ñô£6kï€%.€ J¾&ĬŘœ‹csõõ@à€€8ü°ŒÀ‰ÿe#–Løy-°ŽÞøeZ ©E‰0é Í׫,™’*ÿGÜà ^ý9:1 5GÀþ+â°’û#ûàecF!Ƕp¸$†žmÏÀ3Æ"° ß®.,&.ø 'è!€Ä#,¢½ÀúEŒ¼ªR7¼xÝ¡¡© ïìPŒ‹”¥-i¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥" #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆG¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸G.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆG¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥"G.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HG‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JRG"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HGˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JRG"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”Gˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥G".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)GH‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥G".R”ˆ¹JR"å)Hˆ!#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)GH‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ"#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JG?HÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HˆGPàJ„€!Z%Áÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë¯G7úW]u×]u×]u×]tØW}u×]u×]u×]u×]u×"€ "ºë®ºë®ºë®ºë®ºë®ƒq¾ºë®ºë®ºë®ºë¯}u×]u×]u×]u×]u×\¨ "ºë®ºë®ºë®ºë®¼pÝû÷ïþœúß¿~ýû÷ïß¿~ýû÷ïß]u×]u×]u×]u×]uË"ºë®ºë®ºë®ºë®¾pÛ'go߯Õï×ê÷ï¯~ý~¯~Gýû÷ï®K]u×]u×]u×]u×]uÉ@"ºë®ºë®ºë®ºë®¼pÝû÷ÿOíû­Þýûõûõuçòÿì¢/ëõ¿øŽd8”–ºë®ºë®ºë®ºë®ºë’€"ºë®ºë®ºë®ºë®¼a»÷ïß¿~ýû÷ïß¿pmÁé l{óŒYD:뮺뮺뮺뮺뮹`"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®^(~ýòë¯~úëß¾]u×]u×]u×]u€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®EØ~ýûåËß¾\½û÷Ë—.\¹råË—.\º˜"ºë®ºë®ºë®ºëÅß^ýû÷ïß¿~ýÞë~ýû÷ïß¿~ý_¿AƒÿÈo߯Õïß¾ºë®ºë®Gºë¬"ºë®ºë®ºë®ºë ü^½^¿~ÿé>ß¿~ýû÷ïß¿W¯ß¿üïñîß¿~ë]êÿßÒ!—.\¹råË—.\Ž"ºë®ºë®ºë®ºëă½u¿~ú÷ÿи mûõު߿~ýûõû÷Z¯üÀ<«ß¿~‡ô+÷àÙïø Ÿÿ‰öùråË—.\¹råÈà"ºë®ºë®ºë®ºë•âAûþ*ÛY…A² ƒïß¿G}e—¿~ýû÷ïß¿ýçÿ½^ýû÷ïß^ú뮺뮺뮰"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºG:—ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬G@°Áàá$¬H„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGA°Áðð HDMVˆÿüüððÿ¸ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@ðÿÿÁð cÁZ®ÿÿÿÿÿ€4çNÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG · D:~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPà„€!Z%+á_ÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë¯G—úp:*®ºë®ºë®ºë®ºè}‹¾ºë®ºë®ºë®ºë®ºë– "ºë®ºë®ºë®ºë®ºë®Êœƒ¬u×]u×]u×]u×]u×]u×]u×]u×]u×]uÊÀ "ºë®ºë®ºë®ºë®¼]û÷ÿ±àÐ'Û÷ïß¿~ýû÷ÿ xÿö·ïßÿj+}t²åË—.\¹råË—.\¹råË–"ºë®ºë®ºë®ºë®¾[ 0G€·ï×ê÷ëõ{ÿÐÜ‚>þ‘à#"Û÷ë­)ë­û÷ïß\–ºë®ºë®ºë®ºë®ºë“€"ºë®ºë®ºë®ºë®¾R ×ÿúÀ×·ïß¿~ýÿó·ï¯úG€³ÕÞŸú¿ûßìußÊÔƒzß¿üp ìzK]u×]u×]u×]u×]uÉÀ"ºë®ºë®ºë®ºë®ºðywïß¿~ýû÷ïß¿~ëwH[cßš¬×]u×]u×]uG×]u×]uÑÀ"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®^ >ýòë¯~úëß¾]u×]u×]u×]u€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¯Ÿ~ªÐ;Õ×]zýû÷﮺뮺뮺뮺À"ºë®ºë®ºë®ºëÁG§ß^ýû÷ïß¿~ýû÷ïß¿~ýû÷ïß¿~ýû÷ïß]u×]u×]uÖ"ºë®ºë®ºë®ºë£àÞôÂ.µzÿö þ/[÷ÿÁ`[÷ïß¿~ýû÷ïß¿ýr¿~ýûõþ½øßïÿ·Ë—.\¹råË—.Š"ºë®ºë®ºë®ºëÁ§ß¿~ýûÿã_ô?ÿßðÿZý^ýÿìÃmû÷ûÓò-¿JõÖý÷¥€8öýûôýGïÐoÿñoßBË—.\¹råË—N"ºë®ºë®ºë®ºëÁ£{KӠ㯴œ€Ö¿W¿~ýô}–‹³ïß¿~ýû÷ï¯~ÿôàÛ÷ïß¾ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®Gºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºG5bÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬GPàá„À 1Z%œaZ%HWÿû€µóA€"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ "pÎ "pLž pø!?€ ÃÀYg "pLž Eï#Àw‘à9ˆ,BŸ|ø8G "pXž›ÃM[#pÞ(fÂSú ß§(hŸýøÞ·?ãÎ8ù±Ûa[#¶Äkj àò×Ð ̾À -x0„ÅŽÀ˜(žä[æ`±@_¿@<áÁlãÎ{Üñ" ¤[àiÖ‡ÿò‰ç˜¯}¡ÄÅBÀ^Ä @A2Rƒ‰÷¸à:F°Â?ˆÎøQâopÜ@Xtõ|9òG1ñ®)ˆ·ó°Iê…°1ÿü ŸþGäKÞ þ8á¢( ¹Ý_0^«e7¯9»«aêØ>!pÒø!€)0hKH Šä䆂P´7oÀxƒ¤ ïn_Œü¢¶7õcm©€xE"@ÁÿâTÞüŸÿ0>ñHP€é_<(9áDh8"pZ°¸qûȤãXŠ“C©þ€ÐùmRïÐ;¯¸p¤ç½¢€i9ÇG¼„`óÌG÷À‚¾@ gîœûÃ|€Ê€бOä@Ù8â|."_nqHûìP}03ÀÍ Uð:¾N<\ ÷ØÈ€/ë¾ÈD8_@Ð:òW LhžF×Ãç‡b6¾xv#h8"pZ°;¸Ox9 Ä$a1@+ǃOÿ™g‘ÀÝó'Ȱ ˆ'ˆ|}¡ÄúyüW""o piÿøÿü޵XòuGôE7 £ïÀfÿð°íOè‘7H›€ÄJ~wÜ ÆÇ`V;ºøf¶ÌméÈ$ Ùø ®~÷€üH0T0šÆŸ•ÿ‘ ×ÄйÏ@ÝÿîËkààáZ"/ÿ“ïÊø|ðk瀳@™À"pV°Ò)Ÿèp kè ‘ý<ÿaàÏÿúú‰â@à"ûèÀ\A8uôAP4ýåÀ}€Ù8_µSü¦ðG€Øäç5µò1ðY:úX  U?Óß@Äê éY÷Ðð,/_KñDAb`Là"pÎ"p3éžiøÃoÈp8¨ÿ¯` €<ŒZÈ÷Nd#ù”" #²=ÀlïN p"p3Är ¨ü;¯<?üð¹@ÙÿáLûÞ)Ë ús!€°èXt¡AÁðàûÀúpc€"pGhG~ÍùeùãoÁB/ÑÄqk4å ¾€?#»ðzp‚~Xûɬp3ÿû´ï²pnN¿œF S°æ¾dFQWàñˆîXWÎs§üö"ŠÄv¾!oà2ì/_·âž±À/ôÏ‘à,–€>P‘̫ΟFˆ'~‹¦|˜,PÁ@>Œp& û9Š~‘IÁD÷à0†ëÅÃïséÿG!É àµâKߤàð ó$ËðÝœ"phF?¼8>½ñÀÊ`ý|{{V¨À ð<Ð ï±#È€_ADu‰äŠ‚N"pGhG\ó‡ÿÄ^(,8h 7CÜÁ¸w'è8 œ`ìØrÖÓ‘ÔFkÅ,ftÀhâ%öÀúyüPˆEˆ§âqj˘Á ~~ÄRïÌ Žxó{é€9¿M 9œ,ñí|@~ç9Jðî@ü}Ôžǘ&ïšïzy¤h8à ŨA¹È*¾`,¤âyð ÔÚó±ÀÁÿð¡4óø§v8þýð[_ÀÐ'@5G 4a;ax<ëæ n…‘Ž#û÷×´ “ÈC ‡_?‡‘ïžÈ÷¹À.®O'“ðz—€|÷¼€6Ñ¢8‡ˆÄl8Zˆ÷Àmr`‘üU?馠8¿yÀÐ'˜ptFrxðhëô€pÅðx¡-tp"phFÀ|Àï `ÿóÈ—È€9ˆ¾< ‡Ôç/Sü€8ùænYÔóýçœ`zG…s€8§úa`ÁÿìOvUôǶŸè@pœ‰Â4p GǾÁïÿþ{èŠi‹ì_§úwO¾@Ô>w´«öÜ€fhRüO ¾Ïâ°5øÅ_bŵöçóÏ,q÷È 7bθÇ'¨—ÙàÀVãï ¸ kä @çv¦» ``ó¯³Å )`¥ÿÚúøøø$à"pÎ"pÎ"pÎG2pÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ!"pÎ""pÎG · DH,~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPàŒ„€!Z%d!ßÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®GƒoOȵu×]u×]u×]u×]xõ.\¹råË—.\¹råË—.\¹` "ºë®ºë®ºë®ºë®ºë®ƒqú뮺뮺뮺뮿éÿK®ºë®ºë®ºë®ºë®ºå€ "ºë®ºë®ºë®ºë®º Ç÷×}€vpýµüðH$xŠÐ}ÿ ìë}à ßÿ‰Ð3W¿ü0`u>®»èànoßüð.+Äwîߣ©EG.\¹råË—.\¹råË—.\¹`"ºë®ºë®ºë®ºë®º Çëß¿~¸·=W}¸€þ¯~ë_à‡H"jî€8h­Ýø…€}«ì€÷üÿçZꮺ뮺뮺뮺뮺ë•"ºë®ºë®ºë®ºë®¼pÚ뮺÷ß`ŒÚýìHëųÿ  8>Éïoß¾§®[ëõè ÙëìŽí÷à: ­û뮺뮺뮺G뮺뮹`"ºë®ºë®ºë®ºë®ºè7Ÿ°ò'€{W¾ºëß}C«ì€28u¾½õ×}€Ð~»uW\Ú åc„aZ®K]u×]u×]u×]u×]uÊÀ"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®rжsyÚ°ü/ÿÖ#뮺ï"GÀg äj]uïß]u×]u×]u×]u€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ƒñ}Õ]u×^ê]^ꮺ뮺뮺뮺ë"ºë®ºë®ºë®ºëÅ—¿ý#¹[ïÐ׫ß|ñ@r8èp«þ‘Ië—ý#‘í÷è qUwЀƒÛå׺«ÿ}~€¼‚Õ¿ú@á_Ï"Ž™€iW^ꮺ뮺뮺뮺ëG"ºë®ºë®ºë®ºëÅß¿~ûì@œD{~ûì<ˆµ{Aô|‚¦µÅª?ôE¤þz ;N,u}¸b}þ€6"½o¯uWþ @‚H@p‹oÿ@Óÿê·ï®½Öîø‡€x$ð H×ûOÿ#»ßèÀúºë®ºë®ºë¬"ºë®ºë®ºë®ºë þ_@7ªßÿ7.®]uÿ €Ý~€x-ÿô(AÿD"G-ÿ캿éñ”º÷×¾¿ô#…Û÷߀À+k}ußeÿóCàoõWèf…ÅWœA4á1€ ®ºë®ºë®ºë"ºë®ºë®ºë®ºë ûè #UÉ ¹!×¾»å€°)q8ŠÛ}ðÂU×}(½¿õn¬³oÅ«mÿ¿vE`Éöúëß^ÿö þ E}ƒÿë~ú÷×¾ºë®ºë®ºë¬"ºë®ºë®ºG뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG> ÿÿÿÿÿÿÿÿÿÿÿÿ뮺뮺뮺뮺뮺뮺ë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬GPàJ„€!Z%€Aÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë¯Gôþ®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®Ž "ºë®ºë®ºë®ºë®ºë®‰àþªºë®ºë®ºë®ºë½8á>®ºë®ºë®ºë®ºë®ºë– "ºë®ºë®ºë®ºë®¼e¯_ýð]]ðx¸ˆhÕuß„ð:úüW¿ü€„qQ€4 j®øž @A¼Z¾ŽÿU“¼Õ_`. ûUÞŸUG×]u×]u×]u×]u×]rÀ"ºë®ºë®ºë®ºë®º-u×]öEÀ>¯¾¿²®¹‡Àp|8>ß¿w wºÁB×^‘„ÀåhÿUuß hkªºë®ºë®ºë®ºë®ºë®T"ºë®ºë®ºë®ºë®º/èvE'Uÿ¢0ʥˮºï @‰×ø‡Õrêë©W}ïçƒÀDöûð¤àà£ÕK®ºë®ºë®ºë®ºëG®ºë–"ºë®ºë®ºë®ºë®ºì¶@:í]ò¼@á:®ºë®ºë¯ûë¯uw`Ä8ˆWmQ™‘›cˆ¡âúýI×]u×]u×]u×]u×]uË"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¯†Þæ?Ôk}u×]öðÕ×]uG×]u×]u×]u×]`"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ƒyr뮹{©u{å×]u×]u×]u×]`"ºë®ºë®ºë®ºë£×]wãU×]uß €ü_€@“ªïÐrÿ÷zü8¸o@Éÿú¯~ýûï˜ C€ŒðÕïß}ƒH®®½ûºªë®ºë®ºë®ºë"ºë®ºë®ºë®ºë£×]ñîá¾Ð5W®UG;ì<ˆ<Õzªï6<ƒÆ#×_0EM^.EØXù7ú×ú h—ø‹…‡Rëÿd!8 ‹<Ø|@jºôr¹Ø2ø O¯ÐëÕè¿ö U×þ€~:®ºë®ºë®ºë"ºë®ºë®ºë®ºëÁ™«½ ßþ8ç«¿œ^ß¾U_ú@¯²3…›W~‰4þ¼áC¡#í^¾¿éñ–ù{뾞®½uW~½}5*¼Güïú?þpý_0´q>¾`t@ú 'ÿže]u×]u×]uÖ"ºë®ºë®ºë®ºë³Ø U×]éM\ƒw×þÀ\E·×]u×¾]{ë¾±'€Î®º÷×^ú뮺뮺뮺뮰"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºG뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG:Oÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G · DV<~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPà a„À 1Z%ðÁZ%œaÿû€µóA€"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ "pÎ "pJDëa ùÂhÜ ‹­œ&H§á8°œÊÇ|6PyÈ`xÊÎ "pGJ¼nxýFáÔØ/ Å‚Gò1ï†A{ € ¼ œ "pVx¢t# (÷̈ @ðS“¬£Å^ ü#€ ¯„Ñ¡Üe1ä{ܰcÿð¨€4 Ñ, ^¼àìFœžâqûöpq<Þp‚0Äæ‰Á`Fþp gPxÎ<‚År|@ê€ß‡NzD߃wÿ×?¬eï3üyçqÀG`‡¬ƒÈ͹:÷Ì&³ð¼ø`x=ƒÑg"pV²0€8¾N ÿï‘‚@\¢`q<|‡à æ2šî”GvjGP¶:P6¾@?ÃÂôæ #œKìX}?×ÏâÀ; ¾LÔçB™œög}â)›PŒ`>@|:œà"phD–g~²rÚücµóà ýsP½ûó2¼¨ l(ëö#G€v»ð€õó" À„FøžïOóO9lÀB¹ÁWë ¯ÈÐ ¿D¿.8 0W5—~g€ù¯8À;ñòbÀ]m~é<;¯È‡_G‡P¿CÀfSþ‘ ÷åÍ»Ìà/³8 ïHPvvŒÀtðdö8Z€dx”ÿ‡P¿pÀà§ýŽÇrâœ$à"phCÀ7° ïnà°ˆ a/ó_èp—¾` ý2÷ÇØOXÂxÊö9¼Hò°°ñÂ0}q`O`ç½¾'0°à!)”ÿi>÷ ÔñÚ 8Míùì8€°E G(ÙâIØÓø=Î #Ù÷jIÁD{×Þ~`üö¶4 ° o?ÿ]ì  ;xk0QkÔ‚!>ù‚ŒàÑ×éÀh{x(á$L/'W†€mc°šjOÇ/,‰È‡ž /ˆÍ98‰À|yö7à®°€_Á`^ ïy×édý/ ÄßËEH¯°#V6Ì÷Çç‡b5óñø@%"Ð Cˆ·÷<;¨‡g<;µðâ-ñùüMG˜¹yÐâòƒœ‚N 4$Àøæp¡cør¬ˆN·ÁÈ„ç.¡~³8€Ü,p#¼€5yú@:¼O0‚8¾€µ‡óH„7£ç‡b5ðâ-óˆÔȰàìD¼íá:øðÖµðäááÂIÔ8“=ïö"^ EI}ÃÍá×à±Ã‡ˆb‰Íœ"phFóÅr8 SýˆþûÌ :ú¹GœúûùþúqX‹OöF«ä¥ lÀ>9ÔÿÁÏÿðÈ×ÂÃÀ|V**pŒNðØ0€ ÷žkÄ‘Èð €å÷À\ÁWÛ×ÐñC=݈·ÉÏ #CÅ3_lï­‡þóØÐå83ü»èÀßBÉÁ{ß!B90›îg8‚Æ 9Tµ§' 8=Î ]÷ßJÜËî<‚h1ÿý8IÀ"pÎG9`ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ!"pÎ""pÎGPà­„€!Z%¸Ÿÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®Gº ®ºë®ºë®ºë®ºë¯®ºë®ºë®ºë®ºë®ºå€ "ºë®ºë®ºë®ºë®ºë®º |¹råË—.\¹råË—/ÝK—.\¹råË—.\¹råË—.X "ºë®ºë®ºë®ºë®ºùÃS~-ûï§«¼€3€ ãð ­ÿõÂïú ÿþöú÷ÿ¬oß^îêÀXHÿùƒÏÿÚ½}u×]u×]u×]u×]u×,"ºë®ºëG®ºë®ºë®¼pßö@X$e>rïß«ó•w©Ã±Výû÷î·î÷ÿ®ß^ýÖ¿~ýû÷ïß¿~ýû÷ïß¿~ýò "ºë®ºë®ºë®ºë®¼pßöW«}{÷ïß¿~úó¬±ïÐjý¯öå¿û{~ú뮺뮺뮺뮺ë®X"ºë®ºë®ºë®ºë®ºì6ÈØ‹¾Õ#Àpv«®û]¾ºÿÐðdÿð;Iªú}*¯}wÜ¿ÿGK¯~ú뮺뮺뮺뮺ë®X"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ƒëÅ뮺ÿÙÁÀ[ë¯}u×]u×]u×]u×X"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¯”>ÀhÒ}]u×]u×]u×]u×]u×]u×]u€G"ºë®ºë®ºë®ºëÅß¿}{뮽ÿôH‹~ýõï¯}w¥Ž "Úž×àEuú ¿þO"Zú÷×¾½Þë}u×]u×]u×]`"ºë®ºë®ºë®ºë úñé'[÷î·ä ÀG€X; éû~ýÿÖ›~ýûëß^ûâ _ÿ=¿Åßhúï àeo÷V(.«Õ﮺뮺뮺ë"ºë®ºë®ºë®ºëÅÿG .ª”F·øõãÄ_Ò4Ë~ý^ú÷ÿI‚}¿~ÿWOnµû­Þú÷{–ïýРÛ÷׿~ú뮺뮺뮰"ºë®ºë®ºë®ºëÅ®º÷×¾º÷ïß¾¿õÛëÿD@ßìàj¯uû r×W^ÿòi@Î6ýõ׿}u×]u×]u×]`"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®Gºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºëG44ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G · DdL~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPà „€!Z%Ô¡ßÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®G¼]¬¹råË—.\¹råË—/o¾ºë®ºë®ºë®ºë®ºë– "ºë®ºë®ºë®ºë®ºë®»*s¬÷ïß¿~ýû÷ïß¿~ý÷¥Ë×]u×]u×]u×]u×]rÀ "ºë®ºë®ºë®ºë®ºðywï¯}øÐ[ÿ§'‰«¯ýÿ‡5ÿ`vÿû~ÿöÀ¶«ýã-Õ{ýkÇÕ×]u×]u×]u×]u×]r°"ºëG®ºë®ºë®ºë®¼—WÚévOß/ÞJ¾mùKˆ¦Þ§ þíû÷ÿZmû‡Ü6ÿésýþš¯þˆxÖýܹråË—.\¹råË—.\¹rå€"ºë®ºë®ºë®ºë®º/È€të"‰·ÞIï˜"ß/óš0 Áÿöÿéð«ðXúU¯þk ˆí÷ïßýiUz\<‚&ß¾ºë®ºë®ºë®ºë®ºë–"ºë®ºë®ºë®ºëG®ºè¸?¯ùÀe©5}¸[×Úê뼂íëèx2»¼ˆ€#a⌠Y¾½õ×¾½õ×]u×]u×]u×]u×]rÀ"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ÏmWƒz뮽ûë¯}u×]u×]u×]u×X"ºë®ºë®ºë®ºëG®ºë®ºë®ºë®ºë®a·ð…[>ú뮺å×^ùu×]u×]u×]u×X"ºë®ºë®ºë®ºëÁ§ß¿~ýõ×/|º÷ï¯}{ëß¾~(€êë¨/ø,x „è «ß¾¹u×]u×]u×]uÖ"ºë®ºë®ºë®ºë£×ƒæà{ûô‹ÂžÝ~Ïðpð×Ù8Â1ÿ@ÇÀkôæ(Mý,,Hq–ýûý^|ûrþG¿k´ŽïÞß}‘98@ ¯ú׎IÌ"jæ[uµâôP M·ÿN@"^é#Ú¯~ú뮺뮺뮰"ºë®ºë®ºë®ºëÁ§ÿ .jïøàp¶ßý p‹­þ.ˆÂªëþ¿Ûÿávýûý]=ºÝnõûïÐ@<½]µø:@éSº`9ê‚Ûÿ§ *ÿÐýˆýõ×]u×]u×]`"ºë®ºë®ºë®ºë£ß 2UöPG»û÷Ï¡àÖ¥×ý>"Û­Þýû÷ßj·ïß_úšß¿ù4 gÿû}ôë¿ì€Öýû뮺뮺뮺ë"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®Gºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®G0yÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬GPàR„À 1Z'E!Z%ðÁ×ÿû€µóA€"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ "pÎ "pJ¡ÜRï§#À¼'áÄ€ØÊœ8 "pJàçpùÎá÷b€ÿd/…‰ð/ B£Gðˆ~1ádou$Ì| œ "pVÐbG߆€Χø ‡qús€ð»ÁÜ|ªrpQª ±nžÖà4ëž:ø\cƒÈ÷ÛÈ:ýUçìÂly°°È„êµX‹Óžo‘ÇÞ*!QÿýgÄl<‰~ƒ/ÿ¸»ÎÄÒuð6Û˜¨ðîD€ç"CÀYïƒMg"pX‚|5¢€dùVo¥…wÀ]|€jGh1€ @ýð ¾°\o¼Yb„“€1÷ŽÁ÷Š'!à2pÃ/bŒœœ8ƒÀSBï·¡ƒ¯ Ày¯›y2LJoÌ ‘¯¨“õÌœ>‡àâ=2ñV#‘ç6ƒï 6F½Â‡,,ôÑ?“ÇßK^-Éb?“‡îÅÜÿ9'¼` ½Þ3€"pV@ Æpà )ÀjZÜSpkÿë"©ü\,G?ü:#Y‚Þø ‡ß@/…¾û©þkneâ®(ÿþl6dh¬G¼UÎÁäyÎÁä{çq:Ï™ïÐäÐ ËZHþüðg¿C“@',i#ûÐÀ¡Ä[œ ™a!áŽ"YˆÊç‚„Þ‡6¼çùæ0xp‚BÀY "Óü;¾ÌoypÈòo°´hôƒg,(‚ .Ì"â%äLJyÁäoy&¾` Là"pT„çŸÅG”OØHTH€e}dLH·‹VëÆ¯p«8Ú“¬Ly 2ïàeAÀ¡~ù)RÔ Ûä@ð8:lÛ P2øªN.ù:ÞQ÷ÉS¬Ëì{о˜Œ`æû""oOòß îußj[€×Â}ôÊ3€"pÎ"p3§Â¯µH´å ‚ àB…øP‰Ì€ã®§ð.p"p3Ä“ µ0帛Ú,HGÿ‡Þ<;Þ<;ÓÎpŠ`×? "C° kŸ„‘ q’¸F)A$o%D‘½ñGðà²?§8"phFb€[²5ûÞLX ¬à¶¿{ÏWŒ]ç“ÀÂhàrÿñ^”=‹3¯8<@}~?"_žZ‡°“oÁ÷çˆã‚ȾýBWÈà4¿€Ýú˜,¿þýc‚©ýú‰#x‘mD‘½ésƒÈ7èç< °ûñcÈà_8Gþ£'“ˆ÷ã˜'‘¯@ Ãô(° ²&€ÔþpZ ð6oŠPDIÉA$o|G‘ü8,ïÜá#ˆ"ľÇ§žJp"phDÀ ÎA€x ƒ9"$<tÿƒ¨ƒ¯G9áw ±â1ŸÉÏxÁ-|˜Á`ÿÿ}Äb9Ž )È÷ÞxáC„X ½äœÙÈšø¸ôË€~o 1c•Àò€[‡€¾(Að@€}G@Äø‚€՜G¼dÖï‡ñ$B%ûð(*ø€p›Ý\€ßmx äYˆ$o1‰¯CsíD‘¼ÀÚ‰#xxÈ´þK„{Ä~×Â=As5íÀã9ƒÁƒÿÕ|vrø@}ò Á÷‚ã¡ ,hÐ=‘5ô¡à²-á°°jÿùÉà>˜ð°¶WŸ^ÿf"‘ohþ×|$!€ÀŽ 4ßv¾ˆÀ`GGPšnÀ @q„‘,ˆD›ðñ@Äð9|"1<~9p…ºóæˆÄ²=ðX耢>‚N"phD ‹C€]Èñª4}žÂ‰||.Î'8àÞøà.Œ ¼EϾ|Ƈlp}ä‡ðè €²ñ@9à9æÞTˆ0ï‘/'£œž¸›÷îì$<,ËÿÀðêøCÈ´µ¦ð $f0Q"*òLxŽÂ@[3^LGr “F½ÃÄœE#…Nð ÀÜh /ŽE ¹:~;þŸÅ2/oH¼‹|GÂï!Šib+€q~BÇž$íyã°óIö¡<`>ï!sð}ò%ä@j$肆¾f(Ààþòïaã‰â‚å˜>ˆ¦ ¼¢?¼„Hä_~ß|3<#´Äu_V(ˆí@'…'ëÅÈ*/ÿ@ÛX’=ðVpÄÀD„PIÀG"phF@4àfÿð呯¢0uõ!Î  }âÁ´o¡aÀ?6òìsYéþ€F XäS_`ÍÿüB…ßp°àúKœUÉÀ.°èP§`8&õ?ßžôï|ˆâæa`5ýôàÂ7` Âï^ù02ÿý€v°»î¾Ö<ƒéþ–9d`#yÜg¬Uà¸à ‡Š—f0«ë`ÂÀe;K'Ìh²0ëï½?"½÷‡'ÿžN½8 ÀGÉäk}{÷ÿÀ^ûè<(€ß¿ô‘ úð3ï¥×]u×]u×]u×]u×]rÀ"ºë®ºë®ºë®ºG뮺óÃwï×õz÷ïß¾º÷×]¤¹áÚ«ß}¬jwãÕ×]u×]u×]u×]u×]€"ºë®ºë®ºë®ºë®ºóÃáž>¿Ñ€&®¿é*ý€BßþÀˆµzð3¯§¥Ž "Û‚Õïߥëß©=Þýû÷ïß¿~ýû÷ïß¿~ýûå`"ºë®ºë®ºë®ºë®ºæûø ÀK Ýû­Þýûÿ§{ý=.½õï¯}ö«~úë®Gºë®ºë®ºë®ºë®¹`"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ƒë®ºë®ºë®ºë®ºë®ºë®ºë®°"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®Ãõw^6òׯm8ðÔZë¯Xõ×±ö,•eË—.\¹råË—.\¹G"ºë®ºë®ºë®ºëËÈÝrdß¾º÷ÿHåžÏoÿŽ`H±Úÿ€Ð#Ä[çëµ¾¿ëõ^ý÷à€]oÝÝ/õrcdúO}éÉäzºë®ºë®ºë®°"ºë®ºë®ºë®ºë˯úGb%¾]ô<·ô‹cyß^ýÿÓ˜"¯ý€¼uô»}^¥Þ¿UÜ­ÀØ0ÿý­ïܵ®¯Sß]{÷ÿ¢)Õu×]u×]u×X"ºë®ºëG®ºë®ºëËß¿Z·îë®T¯5r_~ýõÎËõ©Þ¿WÿÐzíû÷{­û÷þ4ãÀ_n/ô×Ù€³kèáÕu×]u×]u×X"ºë®ºë®ºë®ºë úï {Yôþß_ùpä`ý¿~å¹ï®º÷﮽ûÿØß·ïß}ç#Ô0©éúÞØ‚ëß¾ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®Gºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG7ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬GPàþ„€!Z')Ÿÿû¸µ‚!A€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®G»)' LpÈu×]u×]u×]u×^?ŸLA«®ºë®ºë®ºë®ºë®¹` "ºë®ºë®ºë®ºë®ºë®»*RAämW]u×]u×]u×]u׎=K—.\¹råË—.\¹råË—.X "ºë®ºë®ºë®ºë®ºèµßëäA:çéÌ Wàà­òçïW_ø 0ŽDvžß\û&¿p×ÑX4€ ]÷8 Ô徿=,Dö¯]u×G]u×]u×]u×]uÑÀ"ºë®ºë®ºë®ºë®ºùåY¼=«èx *÷Þ´×ä@¿UÕÓ½yp9¡–ú÷îçèÿn§Ð"ëüZÄjõï hÿð¡Z®ºë®ºë®ºë®ºë®ºë®Ž"ºë®ºë®ºë®ºë®ºè·àå«Êû^±ýÖý/ý@ªÿ#¨ð¼®÷´ ànà’E‰ôà¶UÜ tX›xÚP[]öÀWá .GŽà˜h›8ˆ(ZÀ6ªî8 à9ê뮺뮺뮺뮺뮎"ºë®ºë®ºë®ºë®ºä|ú¤ê}ª.úê[{ë—^ûÓúº÷×}\E]u×]u×]u×]u×]u×\°"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®G‹åË®ºë¥—.ž]u×]u×]u×]uÖ"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®Ï‚N¯Å·­2âÄP„ÄP….ºë¯o.–ôüÑ:—.\¹råË—.\¹råÑ@"ºë®ºë®ºë®ºë£È£ß±”[â8@@}]u×>k#5Uïß¾óÃÀ:0*€‰ ¯˜ÀäÀh Õï½i§Åˆ  ˆ  ý¸þ®üy•w¤pG }>€ßWv¿WIù¢u]éH )t-–ºë®ºë®ºÀ"ºë®ºë®ºë®ºë£òéi®Å;³ˆúÜ4ú4\=1¢8ãê:¼0 î€õäà7&¾ÀÙ•ôEý]ç9ÀÕ^ÿôOr \ø´Õw­4ý¤ ÷h'¸ë¨ü |Ù„ û€vÝ~gp™U^ ëp°4Åw(xÑUò4ÿü‹mz~hšürG¿P3 üPŠNb1ÇŠŒ&‘/_ð ºë®ºë®ºë¬"ºë®ºë®ºë®ºë³ààÐF«¿Z¾ØW^.®âÄ``@;·Þ‘ÜE^ûÊÎPð#zÿ`p‘êÿî ŸÿO‹Mo¼ >ÐûM “^Ÿ‘oÖØÀº¯}øäZòÀ[íõÞp1üÒšä@ÛÀv¾˜à &ÿdP6=¯ "F«®ºë®ºë®ºÀ"Gºë®ºë®ºë®ºë£×]öh+±}r÷ïÿ@pU¾ûad }wÑ8÷û`¥€ÎŸl¡, ÿW}µ>áà[åÿ² … «®»è€¸SïÇ®¾Ú®»ìŠ倶¤åË—.\¹råË—I"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®Gºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºëG®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G4Sÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G · D€l~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPàV±„À 1Z'™Z'E!³<3Ü!Àµj¸$€ÿøµÿóA€#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".RG”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”G¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"åG)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”G¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"åG)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹GJR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".GR”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥G/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".GR”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹G”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Gå)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆG¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Gå)Hˆ #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥"._H1)vøÙ @P4¤#Û†!'•¿_Ï|Þû0 ~!ÿ8ÄX"å’øÝºµ&ÿ¡÷å €€^ÔPÒ`Ë)(A3§l„-ö?aw„¾¤GzÞA8ÕË|ÀNŒ‚Õ¶QLÿåÜ¥)tÙ\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EËXäÒÀ vM+²C ¥£ž´#ü«%¼¸!€€ ŽÐK?Jœ&|ëú˜ þxðEÿ°ÀIRˆÌÀœ†ˆ (°+òCKÿlŒ¤üv¾ë|D¤Àl‘ÿG —ÿ¾óÀNR#e™®€Äþ•ÿï…JRô®k”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR" #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥"G._fÒ?çØ‚`%€"/ŒßfÒ?çØ‚`%€".0 €'à*"ëb >ù`€ ‡ýàTÀ#€ uòÛê@€ ‡ýàTÀ#€ uòÙ€j8tˆD‹”¥.»+”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹on` ¨#€A4ÀØ-à Á 5p&‚XúJ$ NŸ:Gþù|D¤Àl ¿ý÷Û¯ˆ‚‚ €€A`—ÿ¾òÀ5˜>é!o…JRõ®[”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR" #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Gå)H‹”¥".R”ˆ¹J^ð?\¥ &ü@Á ‰ÿa¸ò·ÈàL0M‰ HÍRS‘ŸßØhÀß 44 †àDRc^ZòÜUê  øKà6ÁFrÈk‹ “R”ñ?þOÿÞdÀ€@ @NV/Ã×€--œ@ò^Úó° ˆE`•‰ítrjRuð@øhýˆ`}‡†_€D’°Öò€dGÏpàßÒŒé / -ËÜNÿ_X~HÌÁ\4†Ã1ᡨÂÒJÿ£ N×ù`€œÀ k&€è˜JéAƒ»Ò‚Òû{ùö`@ý Cþpˆ&X"øÍö`@ý Cþpˆ&X"Ô ø ˆº’# ¾p Á4¢ ;,5((¤Á=)Om°Ô/ÿp@1ÈÐ Ð`1`þb¸‡BSÀ"×Ô÷ùöÿ9âï4G xÐ Ã15:Á…':94´…#òX^×i1)_v¶AiÙµðCð¸Ð€e˜„>ø;†,/^@ p €îQìé&˜¼,ÿ“…£ñwÖÀ€"zÁ¸ À§) í‹BPY_ŽWíÅ%½Ñ€ I Ê!“ÐXbrQÄÅs½¡`&&€,¡éÄÔî»ü÷KP'@ €;AÄÒ²Xweàïe½?†v¹·{?Gí¿ÿm—ÿ;^´ø ~pà à ˜°—€$ùŽ8 ÷p#ëÑ逖C&¤ÐL+± (OüN=±?Þ䢒œ„#¥)í‘·ÿþfÙÜ Pᥚaܲkv×óàAü"Æ‚!‡WÜ,ÌN¸ôÀ?N ,h yÈ&üJürN"öÀPÔH+À¡DÍ×±44¤$'ÿµÕzØE€ÄI(G®¬º à#+ý¸®ÞÉ :‰VmÅp;P/.þZÔ” ®„0À*Zz2\1t7Xj9:°À ~¸€ @b€‰€;AißîZ2 ÔòuõÐ*r I@7-!¼¤b‘Ò~F;9ý…ÞpÐÿœ˜àF«€€¤úßc剩üUü~ô À @@¸†‚ 0 —ÒQ/pÌWÌÿðÔwUçy÷ÕAñAü #€F¿Gý.êÐbCF$娖–Cß“|¨°”a0(,·nZ23g_Á¿“«€‚ç€`’xa $% òWÈ Üq/»€‹|.úÚ I]Д£·Ï»vù¾Pü}ÀxRÌÈf!€ Âg$“R€Ì‘hÜ'á{0»€€˜Žÿ¶ä[|MMùäá4$0¢pKKË€2'Àšpb:HD0EPÐ>àœ¤ˆW}0GØ0P…Ü @nÜ41(-HÎ5S¶»ˆJJNJ?Gß}ò¾øï¥À`B/(^ïd½×©v?à À€ª@'ÀX4hS‡ŸqïM(å'£™snùïל?8àRh,„~’ai)=&3£²œ›¹:À𤡀T›€È(Y´ñHÁ.Ì0´Ž¾°¤ÿ´0Gÿ‚h×ÝpÔà0¼–œ³„¤ìëUGæ€%üûtÝ;ßÌÀ5Æ1=0Ñ`W`–#‹ØbSð‘–¢ ~H 67†_à$­¸^»@PÔI 3QDÇÏM)ð-„%®ÐЀ2/I+Gt$¤ˆI_£ˆwÒÀ:Jük™,³È—ñ€@ À4fË€küI)8ae­\ø];øèòh †ì3üJøneôq8Ÿ|G0´C BÐZ2pžìØ·QÜdXÛX¥9¥?m³ÿûm±¿Âú¨ ~ ÀNCH€P¿ˆAœ`oÀ‰ÿeãÖ±˜ï×hL&rj[úœ~dð@üÐÀ O(…‹:q¥2ÿ÷ž'#ëµÁðƒ]@!‡WÜ, /|B!€ì´ HiiRÒŸÅl»Ënœ²†ð(Q£C É Éûýyà€P¢I?µÐKçG_˜Ð?"rvB ƒòNøšVöBB‘ïB!“vRI… 4¤­ Gßpý}àð@€8 '…’c­ Rs¡!ßÜ  á  b„%?€À7ìQˆpDÿÌ;ãGëBhó†;ïJ ½Ù7ñ{xpC A  –~Á¾û|½óî+ÛÀ‚jàM°÷qDœ'Xs¯ï—ÄA A À@ °Kÿß}ºøˆ GH!€Ø ûï0P ƒî’&øT¥/Zå¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥" #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ½€€Ÿd*Gx" bS€V‰í}ìšM,†Xi¥%§§þÿßÖpA°âœ@Eö«ÌËa‰âÚé!Ÿµü¬ØA0˜ U!¥ÿ€¦NrR2¹x¼Î8ëÂ$š”›tÀ6hvAÀÄÀ¦°]`T5)/б)kB_;¯s÷6íd  >~C˜00 †2I˜äîåóŽ0Ë‘KT”;såѽËìÀú@‡üà;L°GEñ›ìÀú@‡üà;L°EÌüD]hC$Ù,È  @Dì’ƒšÍ%×Ä‹ ÿßY=À…ýÄ>8I'¥Êü€5O%ì*YW¸©1!|xnI¿€VŒ5/kïß7¿=ìÀ†àXÓß Ë$¤O#ÙaÿÉÂê!Ÿ¯ã`€òÀ·Å“pq/Üà'4À TîÛ€÷©ÿ®È G˜!€ÊþÃHõúÎ 2v8‚Z.’öà;aé"Ù ×ö„§–žž¿ûñ>ù@ °àÀ˜FMFI šø„øb²Ÿ Hñ×Öo0lÐ샀 €K„éå(Õ[†gMóxjyµ¸ *’a5 /2PœûïJ^°Þïr¶¿¹#p ,y4 !øa$3𠼎÷0Ðÿœ˜àF°â0¨ 9 ÄàG2›x  !ÿ90À4y<°(ü {«æ,>þ?Ï÷ÕAñü #€F¿ýMò®¾ªŒà0%ÿênàý‡{i"ý(à` @€˜]x4šŒœ=iÁû{à I+bŠB6Ûc¶×Û ³€)®_ MñtŸì€3OtaU±öÁ¨Ä0ÂÉ…¬ Ô$¤áù9½ú †Ø†P-( ÷ç}üè!ÿ˜ AGþËÈ/ù/€*eüàô¿À0:‘|V ^"÷@€À†@‚?þ ix[p¨‡è&/îà Aû@3ø&€ }çÀ4(`K¥ìœÁ¨s Omö÷¤VÚ˜#ÿÁ4kïƒüx¢Þxob€ó]9a÷ó”†ÿïD®BÀ'\œü˜04¡_'b7÷ê€'0ÔÀ7ªžP'Gî_•ïî×Â@Ã@aùà‚³_v¾X`2#€!óÀ5› "]"O¼à @Nhp @®íÊ HÎ9Ä‹«¦_ÇÁ  PÿöG¸à @LjøàS/–LKaé@NÁÿmuÁ  PÿöG¼¹×IŒ!þ;Ù•œ«ý÷Êæ*ù ˆ’€Bv2S€n1¼0| ïzÀ@ý0‰¸i €è ¥ûe 磱۞€G«Õ€À$0PC© AÉAàwÝWž”`†(Ò=ѹ)7ùî?í¿ý¶_üí}H„ЉHbh€¡7<4¯Äíþ kªä„ø’¹3òˆDÎyDÍðЧþž!XUÛ€4 u¶ÃÞÀÔ5ØRí@††•Ü0 qù‡÷ö0@@Cþr`#€ iõ]7ûç^|~yP@@Cþr`#€ iàJ1Dϱ٠tnéqwñîG}õP@üPCÿ(à/ÿK¾UϾªŠà0%ÿéw Cÿ°»œšH¾ˆ x!ÿ0 #ÿ,ýñ”Ÿ}˜¼ÿ˜À‘ÿ€–~øÊO 2JL„w¹¯¿€=?óˆ#ÿÙ`_|_zæGÿ²À¾ ,DÀ©—óÀ@àC  Aÿ4¼½à ð!€P ÿˆ^[œÿïÐL$_Þ‚öGfÿðMÞ$à A @w¶Rؘ#ÿÁ4kx@€1€Ü0C~#-ÊÍüúê€'0ÔÀ7*ê€'0ÔÀ7ª” Ä{™$v¾X`2#€.¾ç|0°Àd G]y ‚‡Û‰7PЀ: ’gø_('l%¯¼3_œ÷këÀúÀ x€ì˜À`SÓ¾ÊG /žW=õ°»:9§RCA·âÁ À  ° €Rß ?t|(ÀëÈ€Z‘÷è` 5ØÄ4ÀtÂÐn7û«á^ñá€ø ä0h tZ@žå /?'4ˆ`0/¥Ê4Çi”—-!€k€tY44¼QEn”§õm¯| @üBÿbÐH@„ (,  ЀJ?dìÁ÷±j^ˆJ&¥Àl¾CïúSGÄö·€<x°à1(@:+¤´ŸÌB Jy›P „p3ßñgM!¯Â/á0¼ ?&bh& šW5î98ýÅ{HpC A`–~¬ð (À€&&,frË4²ùéäAÚ°¸!€€ Ž0K?w6ÁªïžÀ_ß/ˆ‚‚ €˜?ôÿ÷ßn¾"R`6`HÿÐKÿßyÀ!› º „›áR”½k–å)H‹G”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ€#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹ Ú4ˆ¿PìÈàôðÒxA½|”¤ÏÁ?Ì/°«Ô‚G ;߀€hŒrÃPž'°~ù|ÜÅœ4¥;‰µáˆ÷ôÐ(‚zx!È ÀLL@£††¤(”V†ñ@ € €2M’’aa¤ÒixbCKí˜r ÊØKñwüfX K Ìd±1å뀂 ˆ¡ 'à€TKÈÀ͉ ”8uäijÎè¥(ÉË¿H˜¥ vXÀ€ å ¨ 3ýÝÀnXá×›¥ G45!½ü!Vᥒ‹)Øj:ö|Ï{°A4%ø ÿk8#P'ÅàiHa ²cŒ6VI÷Ñ`Ó,Ó›À+d¥$²P$ó†Ë#ÜêR²ÓËïÏòÙ³YJ )!¨Ae™(N}÷3ëÛ€?<ÐÓËÀ`΀ MܰÇ^ä´a97‡¥„ÒÃóJ2O¿©€3v´&`dšÀ–ÎN¸LàÐ ÀG¨ï˰3t8SÀºp¦Eâߊ@BðêÀl‹ôà Á €Ä¢i@'À AAˆ @btKÛ sJa 0à@.Õ'3¬b‚Pðq¸ €ZYòÔ¬ô4c<€Â,sïN¬§%ÙD>âPa(`€eÂw¹CÇ^f–¥Îøúz2s{õ€ ÈR`@à Xø”ï¾$€V– ¼—>4Gi5!½ÓFA×/rAPri4FJ%¥#Ÿ»8þp«ÃR ©&8Ãa(É>û  0†€b~tä¸ €ÀÆÌÀ–÷”™eòûóáÈÍ~Ø €HÄ$0€ @À ÃRXÀÁ£÷g­®(@ä ÀU€NzhÀDP00c‚7þîâ®,øÃRŸ¨:`cn÷-@€˜Ô0ÀÀ ÊèGÃF9¬ùÂõ––Û·z/ß`@D0!ÿh%X'½â€.Ë<Ð ›€ÜÈKJ!©`¿f¥‰`T°Üß‘«AYõÉ‹(0šRC ¥ 4¢ó% Ͼ--¨¿nx à ªy`ï€éÁCw,§^ä´a97s‚€3vÄÐ ¸°2Äòß,ƒû•! FcÄÚòb=ýÀ€DÑ»€œ2bnˆIiâ·/°–â/GøÐ@ ˆ@6`ÇÈoXi|©"fØÍeãXhË,ÿ,‘c÷´Ä Bi(á…”5œ`Ô|ìùØsêŠ[»w³¿ð!ÿh%P'½ã>À €2&ƒ@-ÉD§~ä©`»,K¥†æþ¼VGUÊR–ô\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊRG‘)JD\¥)r”¤EÊR‘#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JGR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".RG”ˆ¹JR"å)H‹”ºÀ€€ÁX°“qNHËéH ‘—Äkx^ðÉ``„M`Ó G))S«ˆÝé%'çØ{Mó³ßì€7J † `7pÝú HHguá÷úX ~!ÿÐ@ŽdÒ:,À¡X4¼Ž,QiŸ_™ ~¨  À¨`&VK NB†mŸã}毷ô`ÿô‚=ðôŸìÀbLA3ᎼlÃGÓ»ÛR”º¬îR”ˆ¹JR"äŧ„§œÿ¥­ †ÄÐG4‘¥³ýêAòÀ7üH`MÿÛÏ€<~Br ð(K% è Ã;æ1øûï·ÆÁ Á ÿôFEÄ@tPaOÕnPoOkó¥.ë ”¥".]à @4`Äìî¿A)I î¼>ã_KÂ?úÈÀ šGEˆ+†äs–F¬´ô!õùê€G:Ì †B`d°Ôä hfÙøþ7Þjûp0!ÿ@ÿH#ßIþ€“Løc‡Ì1=;½µ)K¦Îå)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ€#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥G".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹úø ~jI¼ªqn31ƒ8à÷½( ’Pɉ&tâñh0÷u3_r ¥!1ÉBJÁ43ä‡1{ï¸ï½¬° X€D<½É ;&¡ero@¸BŒ±}Å^`` JÁ›³5ÑÃ8ÛóÉßužË}4?Gÿè G2iÌÓß½ôÀ@ü Cÿ  ɤt] &?úÁäj  8¿FLЀ#ÿÒ/‡¤ÿ}À˜ÿ Gÿ¤_IþÈJTöÔ¥.û ”¥".R”ˆ¹\°Cbh#€HÕ5À;0&‚8¤$¢ÿBß30@#ÿÐiÙ/‚‚ ÿè4Œ‹Ê!€/º‰„›ó¥/Zå¹JR"åô°@ü CÿG  ɤt_4¾–„ô#€4Ž‹˜‡ÿX¯¨å6¨ef€° cvGW#^¬°)x©h@N|ÑÔœ©@ e Řs8ùòkvøž/àt˜ Ò‰¥WrƒQ‹G“ŸKuüÖ7‹áúú0 ~@·äÀ àÿdÖP«Ýd`Ð @bLÐft“KÈÁüñ!0²†ôŒqNEÖÉ&·fpûüýJЀ˜p&è˜H&%â]éÀ À ÐÉF,%çZÐLÀOãxìt G3–XÄ.Ë¥³ûó0*BÒ dÐÐÂb™iAX-?k~RÛ¤`˜ œÿè¦ v'ßoˆ@¨¡¼šI¥“K槸v3aYV‹‹a™iáÚÜÑWùآЌ”% G9(ûî#åAðûjÐ4– ÞŒÊë ,RQÔ~ªVí @Bz‚¸`ÒŠÉGîÉÇ·:°N5†¨{@æ:þúÖA3€5àŽÅß&ºGdÀ%ÚȤÎu—j>¾”†ô#€4Ž‹Òg^–oúAÈ  %3öaÁöœšÉf'ßÄ/¥‚áýdàM#¢ùŸ?ßLÂ?úÈÀ šGE@ ?úÁäi@qïÑ€ô`ÿô‹áé?ßp&?èÀÿéÃұĒC½µ&JPR:SöÛ?üí±·Õ@‚êP–(¡i&Lû–G…Mç¡¶_6ê&’Mê8ßfYyóP*ì q„0€è˜$Y4¬¿rtÀP¸À'ù €è5<ä šWHNäëï‡Òâ2ÌIáV Š×ùÒ/‡ëì@€Àbbh wÒHE†$¤?rÃ?;O_@8uê-0_þéaÊw'é[‡_çJÐ*` MpIï‚àB’†‘î0&‚8¤u%¢ÆÞGÉÝ¡¯‚ ÿè4Œ‹ì——€8¸¢26á¼4²Ë!©öK6+-j_çy@T®PÌ?]E$g{ù(À30°ˆNp A_ˆÉûûI0x¢P`&ÿ€nVüFÿ=÷bÃK&§–ZRZSߥ?ÿø¿ç·ÀcSÜE˜¢¯ó¥/¶./Ô‘hؾMŽBO|Æ’¿Ç¡úøè@€€è DG(¼ŽjŒúë!D…áöE“yo¥‚áýdàM#¢ù¥ô°@ü Cÿ  ɤtRCÿ¬F¨š~Œÿ  Gÿ¤_Iþû€ !ÿ@@ÿH¾“ýd”¨„w¶¥ à'&dB, Ò0 Ìÿ‘0¾eõð à€7-(BRBÑ„ÄvéÃÃ~$ñG[€¢Hg+³,¼Uüœ†Ôð¿A4Pœz9G4¡¸Nñ!3|~@` 0-<äbiCxŒï}î— ’Ÿ µ·Ž¿Î”¾Ô¸¬P…¡RCŽBO|ÀÖŽ!Cõñà BBÄA€;!$iA¹ðü=^6ë!D…áöE“y©J[Ñr”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".RG”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹ZA ‰ Ži#UVPCbh#€HÒAú|‚‚ ÿè4Œ‹ì—ÆÁ Á ÿôFEå„À‰×Q0“~bö€øà†DÀGÿœ4MâïhŽ`$LùÀDÝà:?û@›œ4‘ïêdÀ ÊZ÷çPÓïÑDÀ ÊZ÷çPÓîP N@}©ÛGõ`ùà†$0GÿÒ`%ÿî¾Ç|p?<Àd†ÿúL¿ýרìÀ40à+ämQ4“(..Р Ä$"€©4†ü1»$¢ŠÝœ•ÕÓù¿vÌ× \¹DÐÀ´|Ë&øGgÂsV\ŒpEctB'•¿'Ù®Òi ¾__±AY¯íÀ  Šdü°(àcìëù u~k}îx ©†1(£ ¡¥$9Gq?k ~./ó×BÝP@ÀCþ` HÓÞ~ä°(üÔ{ âÔ>þ1} ? ÚF“0+ý˜á¢Ü‘ˆü*ù²O¾ÜFÃ@€‡¹ÉB0­ŠÄ[´Ü7ð%žÀ‡Ùo¬@3¡€P˜¡¡©ÈFÈ—Å€:dLA,˜p°&“Q‹ÛŽ B]ØÎÃ}î@¢ zM&§?!D¥ºSFþùgïì@NCèGã2«&ºýè >:9D0 `^àŒ¥o„'lœ婢€`  €ë¥ 0 í·ZI‰_›¹œ.ùØ1ˆØ JJÆ9xeâ~·€U(/oßz +5ýÎø(ÀCP ‘}êø(ÀCP ‘r€fŒ&Ô„µjr€dC‚O-W^Z8]÷ÐÄ“ HaxbJOBpï»}~w¾ª–àð(G X1$ŽÄÜ1Ëö ·å:‚j ¿8hìì$€˜¾á 0ZòbxÉ$}y0R€`B !—ÙˆéOµöÀ@ø`ä" ”‡”•p£ð»Ää€;Á€: bwàUƒKø@'iÀtä<Ç%d(°-Å_Ñ€1 `€Äš²Ï /¤F3e_?<lÀ7z‚C“N?à.œ#(?ßB0 @5G¤À(œ²ix¤aµð˜0ð ˆ@& $ Èqü¤?¿¹ÀbX(f4Xf~÷h '@tCÚN&’µ÷°€ì4$0ÒorÃSÓÃÌŽ×ÈôCx`âvÄ󓯲V’0Ĥ`©ûý¯Ä€ÕÀB¸%VíÈiÇç?#òùÚùx`€é¢`€0)6&±=Ÿñ~¼Á &p‘G0¬Û@ÎZòöK¤ T¥=ºµ™Em¯Ñ/)|䘔B`` €w³¡!ˆÅž8²ÈXýžû! „X‰¥“QÐXbz¹Ÿ{óÉ××ó¢ € úPŸöL(¾µ£“¶° )ã:ԪɨÙwœèÿ­ Žåß(÷ÕÁúÒà]òj˜pŠD‹ú` ~!ÿÐ@ŽdÒ:/FLÐ#ÿÒ÷œGÃ?úÈÀ šGEèÀ ú2úAä&a‹l ïáé?ßMÂ?úÈÀ šGEó$Ÿï¦‚áýdàM#¢í0!ÿÖ#X“@qïÑ€ó€`ÿô‚=ðôŸï¸ó€`ÿô‚=ðôŸì€1$ A¢ÞýÈ ~X´€èŘ®ÉÛø@àþØ^¾¤QI JÒ”ý¶Æÿy@ü Þù¢ˆGE(wý/i0Òv¬sàÂXhyHéÄý®p)°a Å ´,$»ð  @0tB(4Ra@1ŠvÿìÂcìWt'ãSÜUçC@L  Ð `”Ü„ÁÁ ©-/æ½Èe¥.þçÅmŽ¿§ë€0+€j–ø„ìLwÑúÆ ç½íùð$$ì2akAa…£‡ëôÍþyà&&ðÔ,ô]¨ïâà€GÀ†`Pÿô4pÀv` MpIÝÀ@àC°(ÿúG¸`;0&‚8¤îò!ÿ×Yç@¯ô-æ€ € N¾7ðÀ“KǬâÔ3^–ø°  :TLNË¥–ZxxÌF¼À*à ÿ]% o¾0 8¸¬PÐ !€úJAeð–ÓÂí À8nÐXƒA¬C&!'qc6ÉÂ’÷&—ªGinã}ÊJ×÷Ð`ˆ`N +«˜”s“…{Ë‚;H×€?€î3€Ô/pü« ~@ÐP?ña‰ãÙ¾ ]í@òð» !†po/|C!?7î¾–†ô#€4j‹æEæMôÐ@ü0Cÿ  É T^€ þ°yÄš€«ô`€‡ý?ý"øzO÷Ü ú2úEGðôŸì€3$ ED#½ý4?úRLÉŒpѾF_ ½¨@€Ä˜cÉ©ÈÎvsx¬mÌ# á  ÀCÜä¡F)`@;!€˜7Bid"ó±a‰èN|ݾn½q0˜g µOt÷ x\Øb€tI­†ÈebÓÒhÌñXvC ªÌp`¡œ¢[óƒC @`j8ü”mú¯´‚ò€5G_ñ$ÿÈhÆ€ƒü  Áü@B ?ò1·¨†îHôÐÌ2Èð€2Ô4 ãrJH+Èœ]äÀ/J© $÷@jÉB‹Aì%ˆ×¸Ø@väRi ;6Hii/ì9Óú®0 PhZ Kø‹s“P4™÷=‰ú´vJ¯â´‡>7·qÜ¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”G¤EÊR‘)JD@#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹XCÎL ÃÊI®ŒêæªXø2ÿEß5/»à$°Ü^úx ‹|ˆÀ¢s1ièÊOt|q€€ P¸4°À+’(Cg¾œØÜÇì»È!  “mÖW•ßÇïnŠ^ÀDÀ©G¤ÜnF³K7)‡dˆ”4}(¬8 ÿ8Ð2PB&oŠÉ=?ž_Æ9˜Ë´ÂÀÎÿ}°üÖA¥áŒ÷Þ˜i43cKAüêM$ßq&¹ À€À¬‡AEàÐÑØ¢»ð³°»áå÷O²Ç’4ÈFß«Ï0!‚?þ“/ÿuö,~¾:ž`0Mý&_þëìXýd !€/ÈÚ²i&ÿ=€˜À,ÀŽ KDGTטÀ,ÀŽ KMSzE’x››QÅ?ô€#€7Ýp@ÀCþ`­ OrñAý`à À·\°ÿ˜+HÓÞX`!€@½Ô Ãïâ©>ûX ~© €€ÅóbÆ÷¾*“ïz’Ñ$2``$Ä?&bQ5€$1"È÷`07înknt¾Ø È Ð–žÀ’RW¾N f¾QG~‡&K¥†'¡%|”'¾;ß+lœ C€ xñféù0¾?tn0^ù…Ù„„”ñ¨ÏY0½•ïÆ]РÀ OÿXi\1KRˆóPQ h €Ì’ÿ ̓þ¾–„h²ndpÀ(À°c¯ð&YƒHÖÀP ’÷û퇪‚ËÛ»ô7Á@ `à ‹ïWÁ@ €`à ‹”Pa6„#ïGtÀ€>@p ˆ`:ì7ᡜqh^ {™KÒBF'|eÏóëý”$¤ô'2QþûŸ¾WÕ`TdÐô$š_/ ¤¿1Ͱy@@üÐÀÀà•˜0!*;âN<.õ`:…€Ä†B ÃK N)ÓÛ^!IÅ£&íù»_ÏÁ ,šô7(1ÃNi§Bƒïœþþ¼@ t aÄÄlžÒÒÞ¦õ€vK/Ü… Gf¿F¨Bä0À;eò‰E‡!;òuö‹óÁ „Pɤ"ó 4¤”œ)9¯¼€=ÀšèäÐwܤ«4äá_\€%ÑÐ-íHyoXtjà@Ôs‰…Å$3 î÷:û `Y` ÃPÐ÷J1$®)N¡8Û瀠 ‰¨€5 @¢òPœ)ºÏtP(Z í¿Üuïká_bÐ:bÔ¼Žø˜QAœNGÈíyp ù 0&$0Èa©Ìz: †íÓÇ)…ßO-)-)JJSÿÿŸÿ?ûœ$£òӘͬš^ê×ãAúÒà ]ò}`èÿ¯‚8‘/“ûP @s„RB$_Óðþ€2p&‘Ñz0`Cþ€ þG¼à ~!ÿÐ@ŽdÒ:/FLÐ#ÿÒ÷!Àä[RÀ'×ðôŸ}4? ÿèG G2iÌ’¾š„ô#€4Ž‹´À‡ÿXnŽí`Aô˜3€vM`ŒŒœVãÒŸ¶`=êâoì3…\Ä´1úû ø 'BC@`­ß•’‘N¤oZ¨…Àvì@Íœi  ¡¹øu° '&€fK¤G4,7¿äL+¯tÉ)!–ô5¹D'åüÉø~B þó6°„ÜÌOº@r]üÔ4“ï§áýdàM#¢ùŸïï¦áýdàM#¢î0!ÿÖ#X@qïÑ€ô`ÿô‚=ðôŸ}À˜ÿ Gÿ¤ÿf™%*‡{û` ~±3“€óbú Â9X‹½P ` €0ÄîÐdÀ”XGÌK )‹Øiá…£¾kÍä6HiDÀ Ãù+‚€<‘«‰¾ŽB!†€è4¢hbz NJ>3ë™ÀÉ37[0~µNZïâ@‚`ÀŠÀ•ÿ'ßú  Xp"€p%È Á7þ®  @üð €NŒt€Ø%÷á‰ãДnÂÌ.È@ý`0+§ïþ8¢féü=²0»¿ŽìÉö8 3ªìÌP XÄ€GÁÌZF#ð*ü8›Ô?®x$…“b` j>,05T –_95(á^úðð$0à1äÐЄ!A†‚7Þpؘô†~bie˜1`Wu”žb6êÉãó}®rÃpcðÞì½ú«ÉGI#_Ë:üiKÓ¹®R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥" #óô¥/ ¸.R”Gˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"û  @ @ É™¾&ì3 5•ð…²úsõõ À=pŸ€vÔ#'þ#Éœ^-€îÜUðš´R‹„t†fùõ©dÌ•ßèûŠèÀÈtìtXÎy4½Ê&l<––ÜBоKÎ䢜xÌámDÒ“lže Šñ]ö@G&Ð r‘ðh ?û!³89ž¹t>—yeðÞþŵú @ý`ÀbКB&Ëå†1A…$´ö/äoïª`À ߀^ Cо»U€Ý#ì@1²3®´† ïz€tŽP `„(Lß|ß|V}ñŸUC÷Òžÿû=šþŒšø0 @B ì ìLûòa047nç~R=Ò$hô À`GCÈ$‘û–¢iHÁô¥kä¨/ éxj}Ê€Œ % 1žÓ†:]íқ䎄ì”'|”uï¹û—[­ì¯é€ A ©1) 0¤Î¾’…!ÀrØ’&÷D0(MÑ|¢hadÄãÐZ:ƒ“·¿ñh6Ø€ì`1ÉHÉG@„À0!9i<²VïÀx‡ï•[ölÛʬ%÷y$>fhÄ!w÷AÀ`Š ‚HPM;âÀ  !:Ð05 (´’„î„£Žû¯\À¦³ÿíH`;·35% ïf”¥Õe}p °pÄ2À)F%“8¥¸›Ø‚4å€ìš‰5 €tá›àDÿ¾xX+ý|Þb```+”R Ý)/ìjSÝ)âÿ¹Ã¯@GbJh’·Nö‰ïÞ4¥Ñgrí)D äÍ¿°+ š2/‚~2âÒ‚‹åwÓNß_Ü€€ vÙ)¬Eò°"Ù[–Løy/fÂÜUÙ¿8 5(€Î4b{g ¸°jZõ¸ƒ½ý° H©ß’ †È{”†o†–,Ãý@@€h¨€˜P“Q@ „^I`¹HèÇ_I5)Ž-: G^ç(t€,Uý4ÈÐ wË  8(ÂðÒi41Ìt£g¾iäá©õ—A št»5™Hšþ€–p “@AÀt\‚ƒ\ÄÀÐÖZ%#µÞ0`ì 5Ð4š€¡… šŽ’ËÑ5FúQ¶×ÇОƒ¥äÔólŠˆÀÂSÕðÇK½²O÷ÐòÀ.ÔRh8€`°+PhÐ gè<”Ž×ÏåGBz¶&‚ƳŸf” Í`0`ì 5Ð4š€¡… šŽ’ËÑ5FÓÊÛ_Iþ^MO6²’ ÿ)še2Æí} ’@©iˆ̇K¤°~ËLýK_áW€†íQ0š’g}$•“¡b€hY(d"i H4¤•À!Ùç!BhËŃ &—ÎAHéOFþüæ~Í×…ÓFfFȳ\@¸ Àå°‚ïêG€ ÀbY4`ä“1) ÒC-,¡»8Ì(“Å^¤@p˜"€ˆ ’@T@ø//øÝ:ÓgÖùäf¿BD`0`B !“HEâËrƒJIIÏÍBv÷‡¿&íŸò’ÛÕP”ôŸ5ÔYcKéÞËfÍwgÁ@1  šwš€ ˜À5l‚  ²ò@ ÐÂYY™†íÑÏ=\UòœMNG/û—€kÛ6kP 0ûý €Bqd Bi ¸ Qöà*ç' ßë@`adÔä„–žrº³ûó–&¥˜ýF`„!6Ô` ó àr` ¿­*5ÔT šš`)»ô%D2ðìWZ¥…o|¬ Â`‰…@(V &aˆF;`ódI}'ÏtÀªI¢,Ê È¹}?,à @5&€ƒ€è;¹äÂaa¬ý’‘ÚGùô¨OAÕ“@l^K=% nkû€`P¨¤Ð 5 )Ôt–X‰¨B0þ”£m¯¤ÿ/&§›YH!€ßîÍ2J²”„”Z2J/t%{î~÷Ó‚€ì˜”À` ɇ€Xà”)œ9cE{æPßã¦L!¤™ÔpéVMþ† :!€À²Q ˜LH )%$);yÊ ,7±HI|r7ü~r¿ùºð¸bÌÈÙvÍrGà$O–À ¿±02zý(H) CK&¡‹øPÙ!ýµòp€€tP `Q(0 ´¤Ô§šŸPÔ¤Ùî‚hÒM¬Ð‘r”¥Ógr”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HG‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HˆG#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HG‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JRG"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”Gˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥G".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”Gˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥G".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)GH‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JGR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".RG”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JGR"å)H‹”¥".R”ˆ¹JR"å)Hˆ!#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".RG”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ"#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”G=@ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HˆGPà¶„€!Z'aAÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®G¼pÝõ×]u×]u×]u×/~ú뮺뮺뮺뮺ë®E "ºë®ºë®ºë®ºë®ºë®¼pÝõ×]u×]u×]u×/~ú뮺뮺뮺뮺ë®E "ºë®ºë®ºë®ºë®ºùÃv€íû÷[½ûÿ§­û÷ïß¿~ýû÷ÿÐ}oß.\¹råË—.\¹råË—.\¹`"ºë®ºë®ºë®ºë®ºñÃwÿ°x[÷ïßG¿~ýû÷î·{÷ïßþ×ÿÅk~ú뮺뮺뮺뮺ë®X"ºë®ºë®ºë®ºë®ºñÃÐ0€Ï·ïß¿ò#É÷íûô úýÿÖ›_^ýÿë·ïß]u×]u×]u×]u×]uË"ºë®ºë®ºë®ºë®ºñÃwïß¿~ýû÷ïÿ@Ñÿî*ß¿ú~»~ýû÷ïß]u×]u×]u×]u×]uË"ºë®ºë®ºë®ºë®ºë®Gºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¯?~úë®GÅè+/a}ò뮺뮺뮺뮰"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¯?}råË—¾ºô½ô£Ò×]u×]u×]uÖ"ºë®ºë®ºë®ºåâ‡ïß¿þ§¿è9û‰¶l·×¿~ÿøAð ­Gû÷ïß¿ßmwïßÿ@<OÿÖ¿Cz?~ùråË—.\¹råË‘À"ºë®ºë®ºë®ºåâ‡ùkM¿~Ÿ¿óÁÜO:€g­õïÿ ˆ6ýû÷þ ?Ð [÷ïýÃ_ÿ€6ÿ@> ~ýÿè¿ü_·ïß¿ý@hÁ¶ýõ×]u×]u×]`"ºë®ºë®ºë®ºåâ‡ïÿ€»~ýÖï~ý~¦ö—øGÿ„ÀÛÿáGíÿô@[÷ïÿxµú½ÿðÀí^¿þƒ7ÿ“íÿï·ïß¿}u×]u×]u×X"ºë®ºë®ºë®ºëå xÿõ[ÿÐ3ÿø þŸ[÷êõû÷ÐoÃíVÑí–ÿö áooß¿ûöýû÷ïÿ`Ì wÛ÷ïßþÁÏÿÍ2ÚË—.\¹råË—.”"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®Gºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºëG8+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G · DŽ|~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPàÌ„€!Z'}a_ÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®G¼]õ×]u×]u×]u×/~ú뮺뮺뮺뮺뮎 "ºë®ºë®ºë®ºë®ºë®¼]õ×]u×]u×]u×/~ú뮺뮺뮺뮺뮎 "ºë®ºë®ºë®ºë®ºù™uñbÅÌÛ{÷ï߯ÕïþœÀáæÛÿÓ_ðÀ- À5íû÷ïß¿~ùråË—.\¹råË—.\¹råË"ºë®ºë®ºë®ºë®ºðywGï×ê÷ïß¿~ÿÕLçoÕë½õïßþÔEû~ú뮺뮺뮺뮺뮎"ºë®ºë®ºë®ºë®ºðyÐ È,¿Ø3€:®½ûÿ†€l(ÿ€x}¨oß¿~¿}uê÷ÿ®ß¿}u×]u×]u×]u×]u×G"ºë®ºë®ºë®ºë®ºðÑs~ýû÷ïßþÀ>"Ë~ýû÷ÿO×oß¿~ýû뮺뮺뮺뮺뮹`G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¯Ÿ~úë®A|èY{}u×]u×]u×]u×X"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¯†Ÿ0o/o®\¹r>/.^ÿéÇ‘)råË—.\¹råË—.]"ºë®ºë®ºë®GºåàÓïß¿þ°jÿó/ú€/[½Öú÷ïß¿~ýÿÓåÛ÷ïß¿~ýÿô@ƒ½¿úqÁäK~ýô,¹råË—.\¹réÀ"ºë®ºë®ºë®ºåàÈþôŠ­û÷ïß¿ýƒOÿN:¯~ýþêÄ€øpö«ßë€"Àh‹o××þ°uú€ÌWÿ@=$Kòì<Û<>Õï×ÿ°q uÿýW]u×]u×]uÖ"ºë®Gºë®ºë®ºåàÓï߸Ü ïÝïÿ éÿáZ×Z¯ø ˆ¡Ð:ûÛ÷ïß¿ýö¯_¿þÌ¢u«×ïßþú½û÷äë~ýû÷ïß¿~ýôL"ºë®ºë®ºë®ºëá§ zoÿ@Åÿà½þ€EŠ·ïÕ^í8;oßEÙ÷ïß¿~ýû÷ïß¿~ÿö Œ·ïß¿ýƒp‘·Ë—.\¹råË—.Š"ºë®ºë®ºë®ºë®ºë®Gºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®G3ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬GPà g„À 1Z'íáZ'™Wÿû€µóA€"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ "pÎ "pJ°iÿý¯0D@ìæ˜Ã \ž EÈ ¡À"3€ "pH„þp‰Â$ G3Á( #@h ˆšÎ "pVÐ0Ÿ~ޝÿñÀlÁÇËÿ{âóßààðÀ‹ãù<ËÏùÌãÀÏÿâ–æ^HÒ xào±‘ç{Þ览 (XópØYÀÚݯ˜y<ˆ<9ØØ½À<âo#¶~ú¢x ®Ä|ú¾.`Y;r7ÆÀ‘‚±×¼ðxü8Ñaø_€G¼¶;oz}îf“€ÐŽß@À D±8žF#˜"óƒ pV‡8,I§ß ëÿë|«ù„õ·è×ÚœO½à À,fÀ}G¨~o~sˆƒ¯h}¡À""h8"pV° ,Y`¯ƒlÂwØ ‡2¿4ˆcïOñu׋#…´÷Û(íwàr$.ºâÀ}³b8`8çvšGz« ‰oþL%ì ¯G‡áBqø€r‹8œDPx¡@/¾ A#L` ¯§ÃÀ[¦çÓú80fxX ýÙáWÄ â3…Àl| èÜ^tÃ…œûì|às¾€„w'^(ˆÐ#XÀ‰Hh(p"pVˆóGâsƇb8 {ÜFQâÌp;õh“Uÿõˆ_cµñˆGý0øGOñ ?‰§øxˆ@¼Dä}‚Õû­ApæŽFs´¿üæ€ÃÈ&ß0b:)¢ 1ø_¾h(õ‰?ÝzxØ*ñG>sá@+"ßÀéùÄmÒ-óˆÚøÂ 7Á€8˜‹˜¤¾£p Ѳ?§åʼnö<±>Ç€²ø…È$X°ÂúQ{¼G#™Èäèl²,SBÀßíïåJ"Û¾WxüŠ/AÆÔuGð  8tã¸õ>?e+׊‹E…ˆ"ÀìF¤ ¡À"pT„þƒÂÀfsר  ÷'_`Ýÿ⎧û D2ú`Ù£¯²0ñgœ]ôð9}úˆ¬f3}¢rÃÇ>ù l:" Oôð×С@pŒO¥=ª ®”-Ž€; Íÿ½öapqœ<>‘‹äàâ à8EÀØ8"pÎ"pG3æ+ž ¼ï~¹‹|  9ΡsCÈ·ÀÐê.p"p4B?ÀZµx¸yÀmk"þ©‚À8Î|  ˜Ÿ×|\™À9¾h‹¢,pŒsÈ–`yÂÆ€ˆ‹XÐ`\à"pxGr ?ë/ÁáwÍÀ9ðr „½ðŸÿh@kæ @5†Ù ":3¾¿@à5ëj˜2€ –gˆ4 uáþüºýGðr”"6KZs¨q8ÄãÀáê8 }ó"“€|è€pá+}ƒ½øø¡ߘ×àä{ôXuñs@_ç4þç4E€Ñå0ðƒ×ÿà¡ì¥Óþÿ‹¡×Ä‘ :D¼ëÀÁÿàLìxR†úœ7ോãè@ÏOð± ""Ö4D[æ'‡অ™G耰•Sþnø‘ €8;8³8[ÿû^ð9¢pýDqñ €q| ;ì Þ?ð"ÎD"ø\D§ôüÛΜ98ˆA9G³p?{˜ÑG@lЍ8Ž$ñï˜q8lÇÆ€¼Œ( _á7Øà€à*׸žøŒ¿€ÙÀ2h–ñ¹õô8w s0_6ñu¨œö?öÑ8 žD÷À Aë'…°ðüoèî÷ÀHå€~:0à³=b/¡byø°˜ÛõÍ"Ó.|<  ðàM{ö: ƒ'ÿãx¸ Ô@;@Ãÿü^qÇA\EìÌ<ò#p|ç@ËÿGàugûô‘/ˆ„ p‰øæN×Ìp€>QŠs3H°àø®"ò1€2s¾.h g4<‹x#0ó' µïc@BŒd`jÿót ö {æÐ"(À;Å,ýyÀhžaë˜dfæ¶§ 8"phFƒ‚€Ì!Â2/²01ÿû圓©þ@p ‡å8˜£¾ýGµ-iر ,¾Â€haÆßDðœFרá.G8Àñúsh §È(B‚ñ¢"(ùD}Oöà Ö§úcÀæcŒ°Åz±$~ûˆæ buö-Dqêáøã/ 4·È<?ý¢8 ¶ÂyàÃÿäCN€XE¾DPÉ›ŠSÎOò™ Â'ØèH¦¾€\Dg¾@ $ï²¾˜EkìXÜËè È}P¯yà?ôÂ=õ Ï1ú;-ó¢8"pG2ZÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ!"pÎ""pÎG · DœŒ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPà°„€!Z'µ¡ßÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®Gº ®ºë®ºë®ºë®ºë®ýjºë®ºë®ºë®ºë®ºë– "ºë®ºë®ºë®ºë®ºë®º ®ºë®ºë®ºë®ºë¯·ïß¿~ýû÷ïß¿~ýû÷ïß"€ "ºë®ºë®ºë®ºë®ºè7Ÿ8€€=JóÅ oöµzûðް…Uß  x8‚ ÿW¾}ƒGÿ¨}_ùÿ€   aõøkäøðpÙ¿è fGÀ °Ãëô|º»ôê`;W¾ºë®ºë®ºë®ºë®ºë‘@"ºë®ºë®ºë®ºë®ºñÃwß`Áÿín÷[ÿØ ßìf‡´ó«éïô€íþêÈ™AÖ«×G}€üëuW]u×]u×]u×]u×]u×]uÈ"ºë®ºë®ºë®ºë®ºè6»ñ·ÿòŒj¼ô¹ .Õ{÷ïßý p‹­û½ÿ¤¹WÈ€t˃ÉõõÔÓG«æx5 ¢àëú\ o®ºë®ºë®ºë®ºë®ºäP"ºë®ºë®ºë®ºë®ºä{ p@hÈâ þð:W}[÷×þÁ‡ÿÀˆ»ýƒwÿ®ß¾½õ×¾¿ö÷"jºë®ºë®ºë®ºë®ºë®ºäP"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºëG®ºë®ºë®ºë®ÃôÀé–ÀÑß]u×]uϰ4A·×]u×]u×]u×]u€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë—aø _þö"½ûê«Ó¹r÷ïþ—"}.\¹råË—.\¹rå˪"ºë®ºë®ºë®ºè>Eß¿}u×}ƒ½¾_ü ðY?5×]{÷ïß~‘€h?¥ï—ÿ@ê N³¯WÀa4kÒÿ¥À9õGsìÿüžÕúà Õu×]u×]u×]`"ºë®ºë®ºë®ºäY{¥î{¯ö ²!8ãÈWûÏÿ'.¾À9Öÿú$ü(êüP]¿}èÏoþu¿UëªëÝþ¬,¤a¯õ‘­û÷Wtà°8*殮×]u×]u×]u€"ºë®ºë®ºë®ºñC«¼ñä{üD}Wÿ¶¥ï®¿ç4G2¾°Cž¼ˆ üœG;œm.»ð(foß}@ݾ¿ô,´½÷¶ÁGÀÄj½û÷×yl)AqL&”µÕÛ8\²0˜€*¿€nÚùJ\¹råË—.\¹r8"ºë®ºë®ºë®ºëÅ®ú€0RØû~NY©×ÿ@XE«ß]r•uùôÇ€zhº½û÷ß`[}ô௢*€öA‘äkºÈâ<"µ½€8}ײ8 @gGoßmäðX€aĺ뮺뮺뮰"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºëG®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®Gºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG?¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬GPàÆ„€!Z'ÑÁÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®G»)1Aön#zºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®¹` "ºë®ºë®ºë®ºë®ºë®¼Z뮺뮺뮺뮺÷×]u×]u×]u×]u×]tp "ºë®ºë®ºë®ºë®ºìº7'‘ªï³@ÑÁ×]ñ"€°*4ÕwÙu]öO#Þûð&Õï®ó€à?£ÿò«ÚEÑ07€ @¿تïÐ`G°ö¯Üauu×]u×]u×]u×]u×]tp"ºë®ºë®ºë®ºë®ºðyk¯]]à"ÚºïÓüïC¡‹«¾Ö ÿ„U_ê&D›9¶î»ì@êïÈ}}Ò0¯ ‘@ÕwÐá e¾žK]u×]u×]u×]u×X"ºë®ºë®ºë®ºë®ºèµðüñ@>Ð6ÿùúß\ºï$èî̧«½8íoþœp}¾¿Þµ·´G¡U}ˆ:®ý úú+ °U¾ºë®ºë®ºë®ºë®ºë£€"ºë®ºë®ºë®ºë®ºä|rßyË4œu¾úaà-o®ûðU×¾»íDpî¯}5´ò}“ˆÄ=}wÿ®¦©:뮺뮺뮺뮺뮎"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®Gºë®ºë®ºë®ºë®ºë®]u×\ƒe×^ú뮺뮺뮺뮺À"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëÙ» Òpâ F@/:ÕUÕW]x6å˪—»—.\¹råË—.\¹råÕ"ºë®ºë®ºë®ºði÷×^úë®»Î#“È1äû}ø¸#ÔÂí`4ÿû‡U×~Ø¿þß¿}{å׿þ€v¡ /³­¾ "’ï¯G+Ò×]u×]u×]uÖ"ºë®ºë®ºë®ºä.¿Þ·?Õþ¨<]vDªcD*¿Ê«Ðß;Ú‰¯,¿þ¼ðjÿó‚èU]ô‡ƒÿÛ÷ïߢºªï¢"À:ú¼ƒ ñ®ºåwÀž=G‘ý]óèW]u×]u×]uÖ"ºë®ºë®ºë®ºè÷‹‘€æD`/‘jømæa8§ïãc´?ÓŸÀ]måGÚG4${ƒoÿ×ÀЇǀ__yÁØ‘ïøõwáÁUWБõú÷¯€‚HÕ|À~;'@> «ý$"߹ݬðUÞHÀ-² ßìXu]w‹ :"lযH±]nW1@ ™P‘îð¬ñVúåË—.\¹råË—.Š"ºë®ºë®ºë®ºëÁ§®½ú½}Î À,"×Ðè=]uÊU×}‡Î”÷×¾û 4 G¿Ø0û×ÐçÕÿ°8õwÙÚûp°cºÿØäjûÕu×]u×]u×]`"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®Gºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºëG®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºG<‹ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬G@°Áàá$¬H„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGA°Áðð HDMVˆÿüüððÿ¸ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG · Dªœ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPà Á„À 1Z)BAZ'íáÿû€µóA€"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ "pÎ "pH„¾Œ±‚ç ÊÄŒ"O8.ùó ð- À}ë˜Fô¨(p "pH„ý;Y˜<‰GXíf`ò$žh˜„¨\Àò7®`yÚ<Ç@¡À "pVÐóµ 4x1ÿúä Ž,€Fs¬HU?Œx홃äÞÄŒ#¬ìcf$`ë÷ž¢0“€ ïϸ0ýúÀ &ú UíØq8q0|A ,½ØÎF°‘&¿³väñ%«<àð ýñ dýb¯q@J€~ѳžÂÁ›ÿïËš"ö:˜,XGî8EÈfX2øpHÿ|áàDÇ/€€|¡OOîÿlYœþÐG‹ä}ñÿ8,qËñ'€Õ€\Ëásk˜$ƒk uŽC€"pVÀð³ñ´nÀ<ä|/?æÀt )føa%qŸÊFë¯ÿ“z$0u˜'°V~D¤0 ¡ØJHÚù·ÅÌôŒúà=|~¥¤ûýÜã@¬a@?£@##àG9 ? ¾±C‚ÜIÀ¿{G(?ÿVZŃ«^1€<‰`$"I½ ‘ýà?Î3‰ÎG :Gö¸œFä÷Æçê uÎ÷2*8V#*ù‚o…ÎH9ÜG¹C; "(Žáxuð< ÿ¿À|œ&?¼G‘̘“¯Š9‚@7 ?€X/ùD^q° @Ñ:û€ˆÄQÈÍ{YAÄù¿×ϰr€Þ|.`’'®`’'¥AC€"pVG¸Ü8b-üyøS¬ŽªÀDxgK/ÿ¿@| ŸþÛ=ðà>¤àö³z$€]úvt8ë÷Æà=\‹¯Ïâg?ß¶x @?|>zŽÿ€Ò]¯a€p}`@ðX€eÆ3Yf²õâ–8?‘ëÈòyÁD}|o^øã€Uc€U|.wCï‡Î@ŽG÷Î@ŽG÷¡ÃÀ[ Ýl;Þ+-ÜŒqÀsÊP>`=ïGÍâÖ!gz#–R ²ØEó|H ‰€~ ?þï|68 ìX9Do|.„‘\ "&ø|‹ï‘| "pR8Ø`Î>ÞûPP Ä_K ÎO¼ZÊPìxP]™°ç'Š"“¬óIÚŸíoïµ±ï ï0€´`ðßKSxE¼Y”ü8ÎG"aäí}Ža÷Û‘)þ·Vx°üOšgÀŠR–þ@/ë#‘­Fƒ@GßK¾aT¨(p"pÎ"p5 [ãÇ V öG‘ÀÄ!Lmä³8 æ"±à-¿–މ<*ÒxQø,‚ÛQ ""éB$¼h õXûð h8"p5Ç0<£íØ€ÛîÄåì À9zpâ$ð°éàyø,"XDd#ðP†)ãCˆúñ¡À]x‹ÈÚšÎ"pxG\ðâ&¿ >"-øÀG¥ób cïð¹”p`E_§üŽPð!Ç‘:¯Ü<€À‘÷É@Áÿð Ï#=øaœÀ,¾vòL„‚F'1·í‡ÊýN@köÃþ<Œf#ß0Ø,ÓüÇ7¡¢8:¹·ïŽà©ÿÚùÓ/yàyø,"XEóIr0³´÷éærÏçÐ"Ñùûí€ ‡üà€¬ KB¯‰ßl!?çÔeXGz`å *"ë˜ ¬#à""ѤAj`)çñO5×ëAL ð3™Àpp®×œð5*üXX `ƒ€"pxDU<ð¢4žxQÍâºø €ˆ‹ €ˆ‹|º‚Ùc–E®hvï,ìOY:ÌÂ{“€íqÂÉÃVN¾PX€gÿGøÀÞâ*ø¡à>0Ã!âV“CÈ÷À°ogÉÇ೨î%\pG³ñ?œŒyŒ£ï=<Ìù¸•Í#ö½Ñìkiãëð#c¯p÷µÇ-Jb9 ¿þ&±ü;ˆ·ØS‘Àjy÷÷ÀÎ4¼8GÄ÷ j¼U8î5ÒqÜ8k  EñŒ£/ñ¢@˜f@¿Ø‘bÁ‹ÿᄈp~'{~ãèò °bëG«_~ΣLÅ3¶ëÏ@"ÃÜxHYäûâä6œ€F×±Èà±á'ƒoÿÐ0‹â£p`/±à5ÀqA÷œàÐ3{Åz/À^‹ ò6½LptÃÁ”Cæ;ˆ.?“|œˆ ŸÿBMÇ@:6ù2 ˜²  4½Î÷xÞ+‘•`Ò8G(×KS²ÀèP“ƒõêc„ÿÉþñ'@qpÂN½|lÄÖâ@Ç3Ùž÷9 .œØP‹Ù˜!Ax × ïç ÎÌ×ÀÀê8„uìòÔp¾O¢'ïÿÿ…°‡ß%}CÃˆÞøÿ,IÄð5%ÜN'ãB•Å/ÞÐ#Ä€Ò¸áäliB˜öÆÈë¶)uóï…{Cádì@'ëëXóÀV$ã¼øàð b<>ü<@3ýèÀðG~Øòusƒç'‘I:õâ©Æ‡ Q'ðàª!Buñ±QØx'ŽáÀ]V>`™ÿ„hp2þ€–¯ÔBï÷8lDšÎ`Œ8à4Û÷p³ Ø^ãñƒŒ¾0£Cˆ·Šüð¢5ò$ºøF€Õ¸‘oŽ,8`žåçØì ÿÿ\ ø…ˆ¼ƇôÈ·|Ä^F×ö0E™„ò{0]„^Èùȉø>óœâxGDwŒQaÁÆ•|À\>–XœMYí|äZäóƒÌX Ž]8IÀ"pxFûëQ„``ÿö¾Å„‘xà4ÖÕÜî"Ó#b*€=s¯ß`ý}`_yà3?Î?N¬Â%ô À¢5ôÀ¯µµð“ŒÀ|ŒÖñ˜8ÓüˆøpÀwÄp^DŠ €,’;äE0ÓY\€="/¿,â-÷„_BÀ_}FaÖñG;Ô³Ïuçž`Y€BH×Ò˜ŠvmõæXpxMõ„_X³G¼ú¡&œ³ …A"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ!"pÎ""pÎGPà „€!Z) Ÿÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®Gº Ç뮺뮺뮺뮺?ËK¨õ×]u×]u×]u×]u×, "ºë®ºë®ºë®ºë®ºë®¼pÚ뮺뮺뮺뮹{äòYråË—.\¹råË—.\¹rÀ "ºë®ºë®ºë®ºë®ºñÃè€2·î÷WØ Ný_ûð°Ëü€Yoÿdq@úò`ÕÿááVò ~0«ÿ0qÿñâã$~ý÷Þù8{~ù<–\G¹råË—.\¹råË—.\°"ºë®ºë®ºë®ºë®ºñÃwÿ°Û÷ï×-Sß^ýûõ{õû÷߀Õÿúß¿w.\¹råË—.\¹råË—.\¹`"ºë®ºë®ºë®ºë®ºñÃw׿~¯]]†€Èàe|Öa;ë~ýû÷_ÒË_¿}^¯þ……Û÷ÒË—.\¹råË—.\¹råË—,"ºë®ºë®ºë®ºë®ºë°Û<*ëGÇï°uL·×]{÷ïÿ@.p){÷ï¯}{åË—.\¹råË—.\¹råË—,"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë—ŠþÀ>öúë¯~úëÿ`zºë®ºë®ºë®ºë®°"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë þ]:G¯ðb-Û©råÏHäkw]{뮺뮺뮺뮺ë"ºë®ºë®ºë®ºè?ßý8Ïoêö0;gZë¿jA·ß¢goß\º÷×ÿÝ]é“íû÷ïêúQÕ® ¨Û?^ú÷×]u×]u×]uÖ"ºë®ºë®ºë®ºñC÷=û÷-þ­?"Úê½õßb¯äš[÷×þÞßý9œM¿]z½ÖÿéÈþ‘Aäooß¿~ÿôGG° *ߪåråË—.\¹råË‘À"ºë®ºë®ºë®ºñCÿépøoßý9[÷ß¡Ä`fÿú»Ïh,ÿü}^ýûÿÐ4ÿûÛ÷ïþŸ€ êÿ¦÷ôºÈöÿéÅ öÿú<×·ïß¿ý…A˜jÿØèê뮺뮺뮺À"ºë®ºë®ºë®ºä]‡ï¯~ûää­õß"0äD–ú>Ë/~ú÷ïß¿þ×ü©¡uôÀÑGÀ_ìàÁÿöþëk(¿YVÿòa  ê럑zý0rËù t¿oþœádJû#¯Õî¥Ë—.\¹råË—.\¹råËG—,"ºë®ºë®ºë®ºë®ºðywïß¿Ž€ö8>ÑCﯮÀ|Eµû÷ïß¾ü öÿó ÐqŸnåË—.\¹råË—.\¹råË—,"ºë®ºë®ºë®ºë®ºðy§ [÷ïß¾ð` {¢tx׈Äjü]¿}¤Âmûêÿ§¤[þ׿§ûëú ·ï®ºë®ºë®ºë®ºë®¹`"ºë®ºë®ºG뮺뮺èög…]x?—¾»Ó¸‹ýzð]¿~ùöçÒ÷﮽ûïN¼ºë®ºë®ºë®ºë®ºë–"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¡ªOû뮽ûë¯}u×]u×]u×]u×]`"ºë®ºë®ºë®ºë®ºë®ºG뮺뮺ëÁ§ÿ¦ÿ€¶Ñz:—.\½Ýu×zE‰õu×]u×]u×]u×X"ºë®ºë®ºë®ºði÷ÿN ô½ýÔˆ È–-ezë¿ ÄKúLáKÛúoßþl ÿÿt¿éÈ ,·ïŸŒD´ëÊÓ‹vÿéâžß¿«é~¤ô·¤XŸo®ºë®ºë®ºë®ºÀ"ºë®ºë®ºë®ºìØ­Ss¬Öæ‘-û—û^G¾E¿G§ØŽN·ïÜ®ið÷ü`rÿûúýND#Ûÿ§Àr¯}w¤‚’-¿ôà ~ú÷×ÿpkÿû}Ò;z\¹råË—.\¹rè "ºë®ºë®ºë®ºði÷ÿNÿ`@>þXž"ÕNFj¿ú@×ûõý?"½¿ûG "ƒ7ÿÛ÷×]u×]u×]uÖ"ºë®ºë®ºë®ºèø7¯1y—þÚ®º÷ãø½¿ùžÃ¦P]¿úký­ûë®^ÿökW¾û8uWÐ À]u×]u×]u×X"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"G3Xÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬GPà K„À 1Z)–¡Z)BA×ÿû€µóA€"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ "pÎ "pH~~”¥ô„Å€Ž'ÞYóãhLœLhqòY—àPà "pJuú×Â$,G8‹xˆD§á1QÚ¦48‹x¢nü  "pT~~”¥ô„ÏX 8-dkÙ‡ò2ïž%DqÂp~€üpÚú(Q<}{)§_ ‘Uâ›(ì÷Rá }j¾ >ôxƒA”o8€B(Ÿ£ð«Uñ9Æx¼ðëé—y ÀWÍ#ûذñf€úÿQ# yØ OqCï­aÜ?üßxªÉÄu:GÝ—1¢H‘œOá ?‹>Y€Û'¾Ÿß€Òœlp‚)> …‡/™ ø€4¾â>€¾ñQB!B!aÀ;Å;¿‡"pT„üTqKâ„ZR\»nŒ—¿|A'»äi Aáø¤{²*"ßá×L-G Îmð3 p7Í(ñ“€Ý⬥¶Ú‡¨CÅz~“â Ý”u˜«÷î’E¼ Q_G uw¤X|GÀ:œëÁTŵÀ1Ï:ù·ÙÜ}x(剅8øžõó½é3¼S2Ì¿‡"pV²ùw‚4h!K¿E ‘޶xy;ߘ Æ^(@Ë6`häKÅSˆ2qr5?’kà|8¯,€}7P²)3€¬Ø-Å5â9÷fp¸zÜ|x lñ!@1:ñVðÜÈÀñ‚o¾G |ÇÞ+ãï ¥wÌög³E¬ÐûÉ‹D˜dE׊à/‡xxv¾…ˆ¼cç`ò=ó°yõý€:³äwjŽôp_ägj¬€dKöX /E¾ @dûñœ`¿•ñØÂ) ›}CÈ"oKðàðrB'$""pR¹˜àˆ Oô…2¯³ÓÿÇQùî|iKè. ɱ„A /³ÂÈàÇÿô¥·@Ãÿä¾GG ­dx{ó0Ð ÅÕwÈ,àl”Üs ¦‡Q“À2ÉàÙ‡‘¯³ ?€¼Q`€Ÿ®eó ýs,Àâ%G§¾Î)—Ål¶P ˆÇµûñ‹Óò-ÍÙ‰cÄ@írƒL¥¬_0@XìלqäP#Dv@mïÃ/¹èw®z]àqŸðŒGâ\~Àð7ਠà"pxC€ðîF‡‡r5ÒGñ7ˆ d(–`YÎxQøàrÀåù{ÁA XAß2ñ¸Uðˆðýzq\P‚ƒâ/;AâÀ:‡€¾IØFG'»ïP½ 8 ,^Ç…€uF²ñ¯¼P×x;—ÿëãð’ '52Ü 0þÌPx¾pPò D—ްëÃáà3°8xáѼQð@ÅQâÖhlç{ä{ìÕ:ÁÈoà&fr5?Š@t葽óð ˆ7üp‚/£p ¬p‚/¡À.¼TpÃï€pæóÃøq€@?‡ÂƒÀ÷ïî ŠŽÕŽ×È·ÃG¤[Ä-Áj ‹áïnñ`Ï9œ8Àø¡î Ÿÿ9ú÷г4äã¤pZÀå¤þhà޾€üëÎôீ7b=î,ëäuÓ„œ"pròQÂàà"$È4uàÂáL¦ÕòðX`4³°É÷1\BȰ {‘ 9äKÈŠ‡€ˆ‹¯„n£BÈ—‚¼¯ÑboúnÀ·ïß~í÷§#r=_ú"ú¿@«²˜¿úÕ{÷*뮺뮺뮺뮺ë–G"ºë®ºë®ºë®ºë®ºè7ŸÎß¿ú¡ªý§À;~ýû÷ꪹ]wœ$>cmõ﮺뮺뮺뮺뮺ë–"ºë®ºë®ºë®ºë®ºè7ŸÃ5¿úýo®¿ô,«}{÷ï××¢ï öA Z~ýÿè=@Ëÿöýõ×]u×]u×]u×]u×,"ºë®ºë®ºë®ºë®ºèøáè@Û÷׿ôïW}`Û}è,<Ë~ýGû÷×¾ºë®ºë®ºë®ºë®ºë®X"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë‘g§ï‡ÝRRå˦ÿÐ<}]ÈÓj’—.\¹råË—.\¹råÈà"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëÅß¿}u׿}u綾.\¹råË—G.\¹råÒ€"ºë®ºë®ºë®ºñCëß¾_WN-RçëÿŒØ0ý]uïßÿAÜ}]{÷äe§ü_ÒÈ5{÷ï¯}ñvýõ×]u×]u×]u€"ºë®ºë®ºë®ºñC»¥ŽÁöýóìÀ ^ÿöõëWý9áä{~ýõÿ!ر^ßë^<:߯ÿmoþŸ›oß¾ô‰¯éñ–ýû÷×]u×]u×]uÖ"ºë®ºëG®ºë®ºè>¼_~ÿú,Öýÿð"ÿ€Ð>ß¿}ðPBmû÷þIp<D¿4ã€_6ƺý¿« <>ù¡Ö”>Ž¿~¿W¾¿éøÖýû÷ïß¿~ýû÷Ñ@"ºë®ºë®ºë®ºä]‡ï¯~ý÷Ð4«ß}¢6g«—E£×^ýûåß¿ý ­õïߪ®èáªë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"Gºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG;ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ뮺뮺뮺ë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬GPà‚„€!Z)zŸÿû¸µ„AA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®Gºì¡€ÛÄ>”FÕu×]u×]u×]u×]u×]u×]u×]u×]u×] "ºë®ºë®ºë®ºë®ºë®ºì©,F«®ºë®ºë®ºë®ºë͟뮺뮺뮺뮺ë®X "ºë®ºë®ºë®ºë®ºë²á¤ûµ÷Oÿ"Wà૱ôBoø àmÿúý˜*ßÿ ·ïÿCÅ׿På_û`ÀàU?CÀ7B«ìIç.—ý)Gõzp9¯B÷¾ºë®ºë®ºë®ºë®ºèà"ºë®ºë®ºë®ºë®ºì±pgÿùëèà/«ÍÿûÕß®½º»Zjåÿ<‡Cý¾û0ín§ŒáAà2¹4ú ×b‚@h¡B0¼‹_c…úûFp¯‹ƒ/ÿÀÂ< Z ÿ}u×]u×]u×]u×]uË"ºë®ºë®ºë®ºë®ºè·à W}0ÿ»~#¼;ÒGë¾F˜ ¬ Õ×¾½ÕOw^ýÊúý~€x*¯ü{A_×]u×]u×]u×]u×\°"ºë®ºë®ºë®ºë®ºèô]wаªëÍÿéÆÕÿ®ß¥úôÿ\½õ×_ú}W]u×]u×]u×]u×]rÀ"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºëG®ºë®ºë£É=éÀ7õ'.\ºjºë®’—.\¹råË—.\¹råÒ`"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëéÏb€~<ðUß]]u×^úëß¾ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºòs˯|»Òjºë®ºëß]ö²}\½õäïNãkèx DUæ÷×¾ø‡Òï°º½õ×]u×]u×]u€"ºë®ºG뮺뮺òsËß¿ýÄc€= «þŸ‘+ȼK×ÙWËðM^TXUŽ_¤W~‘N«½i¯‡ m.½Õ]öÕëMèiýû5"Øàúª½cÝ]‘¨ɈÙïö£A I÷ý'€°>ýV(< —.\¹råË—.\º°"ºë®ºë®ºë®ºäž}¹£ïn·®ÎhpU~Žm]ðÀ~ßÿ =]w¯ jòŒ a’jëôóØâ9G:pëÖ›|½ÖîºïZk¤§œz1ãk2¯~ÿöˆúøEÿ\œ½]u×]u×]u×]`"ºë®ºë®ºë®ºè÷Ò€€WÈ8*PðÄêIë¯}{ë¾€Ùä \ºï’Á›ÿà5\ñ`8GW¦*È Oµ‘ùß}Ò1ö¤Ý¥B@;W^µ×þÖ @o®^ú뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºëG®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºG뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG7ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G · DÔÌ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPàX÷„À 1Z)ëZ)–¡³<3Ü!Àµj¸*€ÿøµÿóA€#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".RG”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”G¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"åG)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”G¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"åG)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹GJR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".GR”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥G/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".GR”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹G”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Gå)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆG¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Gå)Hˆ #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¾Èˆ¤0À€¨À§È ( 7û'†¡]G{é ƒùà ÁþÃ$J ^?LÀlâH@—ÿE_h¼ÐÏú7 çë ›þJ¹—ùðBÒM0ƒKGZCHA…§œ´•¿P›=¤àCð H@–ˆ³]åæO`ƒµÊR•Êå)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".^ø„à 1(„¢ÊAI! ¿¹HHOIxÿ‡mxêàøÀ‡ý¤ÀG’/ÿn`#$5¾Ý\ûRod_4¨´Ø°dÀPÒ’”ÿ°aHá—G°ûçWØ ù@ #€ À7ǹô€„¤!9¶Ê2dÏþZìÒ”ºìnR”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR" #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆG¹JR"å)H‹”¥".R”ˆ¿F¦`4q$ Kÿ¢¯´_Ó08’%ÿÑWÚ/( C^¾F×I “„_çÐ À4p !X"Íi¸À<@G’%€",פ”‰¹Ðv¹JR¹\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EËêàøÀ‡ý¤ÀG’/ÿo”_GWÆ?í&8” ør€höíHd‹ÒhÊÈ`–‰¾=ϾÂhÊÈ`–‰¾=Ϥ DÈGY¥)vXÜ¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤D #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HG‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"åxÀb@É T4¢aXô—öÂñÛ.¸øä @0,d>È+JyÈ@¾oµ5bd>COlà`3à3ØxôŸîp(9 RÚ^(Mø‚ãdLÿè @vÀ}?Ä>-!h×D5Á ŠaÀ÷ KØ>`xTô€GEØ’œÈ)+-?¸§{†X À’7 …ð$‚`ÒØŸqé ì•Û’ø¿( ~Pàü€*€Ð~j@¸`h Áå0»Ç#äì÷ß>øï¹ºýP y0 “ ! ò‹GG'™Ìç{à:Ì8Xë¤àP Íº öa…ô«ßx?LÀhâH@—ÿE_h¾.¦`4q$ Kÿ¢¯´\ÀGðò6¬†IÂ/âä0 2¸DËé&ðOˆA˜il¾½‘€Wó™zBÁð’àX 0¤5ð ÆÄûÚ`ðdÞba`T½‚G#4´ü„aÏð«„M7NPÜ lýÃ:B¿ÏÅoüTBÜ'ïøþÐK,Ëòàä€h´â€bL,ÎW!ÿ! À{Å¡(-(ù(Nß'}÷ÜÝò¾¿C–RC’‹BGJJ?ÉBwß|~û¯{ç`€ KJI ¥Ð3“HN¾ø–Œ+¸Ý‡ïj°# iF"‰½ÛßΩK¬¬¨` © O&Ëç8¬®ônžØÿaû]`@€hТX I¹’ Á!¥€©aý°»ØP@ü2²~!h”ãMÈà ¤€ o~À1!¤ Røhi}ÿämŽÛ²µˆÐ`  ÿ:ÒCQ»pßñAG˜Q,¿â³ñW˜Pœµñ-®žMOê¿@üBbS°À@Xfa¸°‚”;É‚ôh @3&€ZL& jpcóî„ôt$RZúX5RB(hEYJé ÿ~#?½`1ËÉ›†¹häÂgß>5£›…çÞ|ÄÂÀqØGy”ãïæ`ƒøÀÀ5&oý^L ”ˆ €1+%P5-’GÂÛüO¿A_ 00¸Àý¨ @tPb7CŸH`jS×xN´€ @©{ô HjrþF~Ïöpû×ã:PÔ@ ˜ ¿õyÀà†`‚8Á,=÷™€À MߥÕÇÈ4¾šþ!À À. À˜˜jRL(‡“ð Ò1?}„óqîØß¯RCÃÙ „À~ƒ8i5¿öÞèÀ&²i@P GKf(¬±ˆw7ŒB¯ÿ³ûÎ$ä: bà`*4Ÿò!°À0!Iî9ûVKç_ø :-91d-ÀJQ`ga} ì!ø«Äèd “C!€ÐÂó¡(êä?uëïà;Ñ ÄÔˆe$04®É)9¾à2ç}y0@0%€˜¤€¾cMÙМ9Øg¡ÕÀLPÎ’”˼ ›Ý½üšê€3fDGÈe–„†à̓2?~Ü%(R®UíAñ € #ÿº,nÒaX°Ô#ì ížÂñÀ'ì`WØÃA#þ®P0° rQiäÒ"€(ctàGÿÞ슾ٻ,uÈx°Ø’ËH‰…“V’iiÈ@Þ°’ËùÒkgH«Ïà &oºöÇ®èÄÔß“H ~cB0@Ád>à–„KŽð?4 KÁ€T¤€)Véø°ÇGKÛ|'£aw²8 °$7DPŒé°j NÀŽo‹H·½IÔ€BðA;Ì —¿Î”½° °’ÀBh ©éH pÏϲ\ œ+íx›Ò&†pÄô\ÈHÜ÷.˜°à4C€ì›Ÿˆ H„Û ®JÍ €4I \5 X˜ŽiÀxƒøQ·ÚÀvI¥Èe¤44¾éO4‰°í•¬@t ¯©GzÃCF}üø ‚á•“ñ$§ÒnG‰$k10? xà(ÞQ `$1`ëÖ:.nÕ°é<0ð¾€Âƒ’_ÃEŒv²f\´"¸i`0% þB-¿ ŽKaück evp÷#ÛË<‰2pŒàj!Œ P d‡gù "ü]Æ¿D–L-”žRQ÷BQþèøÝñß_&Z?ÐG§ ‡ÿQMë’v0kw¹—H€ÃPqÈ04j¹÷ço«‚ãöŠ¿ü ¾Q}\?ÿ°˜àP%ÿàm@ý‡yɤÐÿ” 8Á,|{Ÿ}„Ðÿ” 8Á,|{ŸH 9@‰Ž³JRì±¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"åG)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"þ ŽzC@NL‰ˆÅ—ÿ 9ÄÌ¿zp€’Ìò ·èÅ÷- H¤-Ãa‡˜ `JTY¯@†ŸËâlJÁþ¬Ž¤; &£0d$$±e£ô8YH´¾P {ÃQÃɅ눆ð #€)`[¾@Ì€#ÿç°Mæ†E.Eº¢Ãïâ\ûêàùòhåëp€gÀПÀ"|'ßlÖpAþ` \ †ئ']€ Ø ñ[ÙÉMëLã€1G~`ÿ!ï€fH–Mád2ýúÀvŸÃR&Ĭ¯è€ø Q€h ø4˜ž?!’€§MîÀh^À;!pJÿÄ_>Ä0 #ÿÑ`Kè úÀÿä˜ û¯<]ÈX>è Íþ},ûÛG‚ã ýÐ `xpÒMîñ ˆ@þȰ »À !ÿÖs–Ž"þ­~|pd:|²ËcCSœ´‡§ûôfZ0ôìO¿9†ŸrgÙÃÞÔ…Ÿû8¿¯µ‚êé:ZVdôXYhÝ ½ñ{ëÀù`‡ý)p&­À4O? ¤‡‚.€@²Æ5-Ü’¹ùEõ @Cþ€HrhGÊù'€ @r"Eýd?$<šô )¸@ƒ2€!¡?‡ `Ué@`Ð @¢B`Üš–OËèÛ¥ÒÃe=ÌÖpAþ` \ †ئ']˜`–JÑšKØi(˜Ô¶gìVý——p6ÄÄc‚1>Ý<'‰¿Œê& B €!(¢ŠÙB „=Œ­¶±Ú8?LvOóÀ’ T@úÈ €èEG Á$€¨&€A@‚( ^ A4íø ƒ?rZBñ€3ÇkÈR„Ð ÒC¸5†ÐK-Aebƒ\'lZ®IRŸû ˜ ø€†ì€”Y1#‰P >ë‚€1P¼@( ‚hÜ€ €è¸A¡ fR©])HˆhBëý<­¶aö)Ø t;¨Ö«^þ;ï¬ãö“Š¿üG ¾L“ýõ@ü`CþÒ`#€Q@—ÿ·xþý4¨Ðÿ” 8Á,|wŸ}ˆÐÿ” 8Á,|wŸH`9@‰ŽâlÒ”»lnR”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆG¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"þ®§!=({q€1 BÀ!˜gÁÈÈá÷d¸Îdô˜R7pÂh#€gõ.ÉcZù€ À4H‹ããI…€HŽq\䊾ܘ@;|K€; á…•ÎæãŽwG3å^H‹ÄÐÁœý˜:ê GB^ÿ?ä ½’’„ì”G'wßs¾æè_mlRü’Àah &(“wJ0 ¾ù(» ¸E‚âkЀL¤$å§:÷Z@4 ÝMð›,CC.þ|ìèlP*–ÙH@-&!'eû!°“Y‰e!,8nv¾òx°€9&€Ü!¼7å#„aÈFV"›|@† :p °ÕÀtaHÿ¿çÈ¢Æþ:ûÀú`†@'L¿ú*ûGEñp@ý0C ‰&_ý}¢äÈÀ€¯‘µ© “„_çÐ À2p !X"Íi¸À< G’%€",×¢ž'Üè;_ÓAðÁþ4p,kwÀù€0üà–i¸ø`‡ÿ8–5»à‡üÀ?þpK4ÞYÀ«‘n¤€ä>þ"“ï­‚䀃€  ·²b;˜4¬Jø;dpûä‰>îG!a€€d’flC ä²àM€qÅp–æ]àP°0ü¼5õPÀhhì„C-Aà ¢Š-N.ɾ ù;%'uï»ï¹ß|eúšL © )%Wù(NdïŒúà€6#~ЬL+”C&cƒ »ü€G4ï’𫈠Pì”G· ,a÷ñkÕ‚é9( ÅMÀ)>%!â€Jž)‚þ*õ0@üP ËCGè p'Ée°½Ÿ`·½xÀb° É©&Ë,†ßôõ«aÙY•µ± ÉÉ-¶Æ¡$Üʽ7Â@  @.pÄ}ÚøH€!€ÈÀŽØì€5› ¬„IºÀ‚ €bàC°÷Þ¯‚€/0ÄÀ$† ` ï½T!"dC?_ÃÀ 0Ph%ÿÙwí€` ÐKÿ²î%Ú@'HŸ`Q#¿vˆG`Gÿ¤‚XßE¸ÿÐÿ$ÀKÿÝ|è?À,ÿI°¾Šp!ÿ  þI€—ÿºó€L` €Gt“@rŸI7¸Æ0!?û À6ðᤛÜã ýÐ `wþ&ç,×õ"`å­{ó i÷è²`å­{ó i÷(' >Ô v_^Ë?éH#€)0|†úð ~X!ÿJGAI„k` 'à*ôÉX È!ÿFp&€ ¯’{ë`€ ‡ýÀš2¾Iä˜p‰‰õÀ@ü rp LÙ0¤¹ŽV#pû¤Lí @*_ø3 ã^g„²x­|¼´p ÿ8D¢›Rå¿7²Ã?3¥ÚûXhad"ÒPjQhÿ% ßt|gÜïré8šLnÍíCpĽþqµ={¾çqñµG#ïµ8Õ~è3€°&!HA5ÿF„ï» ï±—<`øà†•ÐB!€§à%Yi„£Ýi14j™‡½Ž&¡¯È‚ë$w &BPhÿ$´%ú ßq©0vXê€@ú`5Ò|z€lÔžÀZ²EnÉ} šM ¡© JK,¾éJ{ÿÇÿ|àÈ©(ì% Ìà0 N_pDÿ¯‡H<’:À°(QGDÀŸß.Ñþ•_Ïï«‚ãö“Š¿ü ¾Oï¬ãö“Š¿ü º@4?ûödÒEê4?倎d0KDßçßb4?倎d0KDßçИP"d#¸›4¥.Û”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ€G#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å°ð@5 Á€!&bÙÉEà€Òœ ',;¾æë)Bz;îÓùïè€'A-ÿÐ0Äã´$¯°#ÿèf,o€E¿€3v¸L<ᬠ` äëåŽÐîl¨ní@l~è@G(ò@3&°" Ĥq!©tü!âï È+ ¢³!!vÙ¶]ãlCI4úVA×Ñjð¬"hÈ€d”ÆØay$¨wf>õ ‚…/ö‚P‚wûÞ’ ¥†fGPt$¬•ûr3è ˆY$°5˜i);?gcŸÉJZþ7¿§_£NM€†‹à'>²:À2ïÝÁþÊk`€@b€jBG%¸‰é%†«æZXñÞò°@ÃP›¨:®ÞÇ>4¥ÑEõÀ€ ¸^r8af@ REdã‹ÂV;ëÛP@ PžP ÀLMAœ°2L,,€ÔC|ÊîpÀ–™ÞÑ!ˆMý0€ ¥8üà0&h%“K è @7Ž&>À;ÐQ`; ᅀļC{Štm€x˜}Ä$á©5£G¯ß`@BûA(Á;ýð€PØ4à0–0`Õž1ÒÁ~ÍJË¥†æòAYõè€@`@t4”i0°Á¬4a-;>vsŸ^ß"À‡ý ”`þ÷€¤Ãe“ ñ’²O½`0À0€ Á €Y“‰c C]=$©cÇû%)ZSÓÿæÓ³kí€'M€“ „ΰà0_K€2–S]à(~G€(M &€F‚Ð[3Œû³€övxjY²Ê@ÍÔW+~ö¥÷÷hHÌœEN@†phÐ0]”3Êg½Ç¥ªБ¸ú~ß5ûÄ!RPAþ×o»ø¼}üô 4†’k 2¤uËÕ€/-À ÀCÀcÀ3©ÊB @’FVCG !³`*¤¨ì^áá+c¾¸ô©¤®û´¾Þþ˜A@3Ü€ 0& ¿ð–LHY¸ÀÀ@)ÈÀ2+?þ†§…bcï—?£û˜Ü4U¨ˆ¿RÐÐàÄâh Kà“P½’„$pG7I/€¯°/&Y}"+)lMHiþÍd\½@°@¬œGè¼Pá„Ì0À2ì”÷p”ÎkËÒ¢‹HgtBQ“›ßª\`€€”0 ÉX¼J>%8Ôt@-,çyN|i ÐÔ†÷LŒƒ®R”´•ÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD@#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆG¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Gå)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)z0‚ê€0Ñ7“9—÷nÂ’Y[€¯'¥$²FüDÿØÿ~rG?¶ürë@t²Iˆ!@Ô†rQÔ8ýתË$$G#M–ÞF_¬Ëdßð 7ÿn  P¨¬ ÉD¾PÃ;í¿Sñ÷ß/ ðGÿrhЫ„ €è Â†çq6åô¥¯ÊÒ”»ì.R”ˆ¹JR"å)H‹ì5NÜ™€v@)ÐJFI!ׇëp õjI€P0²Y4¼R3lüz @üGH¨&%ê€ ú.ø Ü€:)$Â_woÏöé NK_Ãi*Ošï°¹JR"ämøåÂbÉ ÈÒÙü_¬Êdßð 7ÿn  P¨¬ ÉD¾PÃ;í¿Sñ÷ß/`BHÿrhЫ„ €À ÀÇÎnPjR–¿+JRï°¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥G".R”ˆ¹JR"å)H‹”¥".R”ˆ€#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"úÀÒM( ©&9/’qûÿ„!ïºßn|n÷« € €vGMᨠØB{ðÂ’WFpRzÿq˜†Pfù*~öÁ¥tõ_Pÿ“RLÅÀlŽLès±ì/íœF¼d„ˆäiÀ@  €é00` BúÝ)O=)üôð9•!d„€«‘­‰¥âɯ©+2ÿDß60àþäСWØo ðGÿrhЫÏ!€(~·&oÊÒ”½{’å)H‹”¥".R”ˆ¿¤à’@.GHá—©,?è¸ÿà0ky`@üH©2õ €‡ý?ü o „`€UÈ·Y`…_à ?Í)gù¯^å¹JR%rbÉ ÈÒÌY!"9Xýú&øð °!€Ð$¹4hUöãÀ€À†@‘þäСW”C^u 7åiJ^µËr”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥G)r”¤EÊR‘)JD\¥)#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ²ûQðûèàø@9¸@TŽz ìà @.Àÿ€[ à cLý˜p}¯&²Y‰÷ðÚA9¼n»+/‡è=÷p ‡ý€‚?üA/ÿ}âÁsà ™ÿw`&Kêݘx}²G ®–b}üò/‡ÂûP ~°!ÿ0¢C,J¶„ ÎÍœç"ê ,•Ž{ø³êð€„@ Ã@© ˜BÜîZ q~{íÀ Àp*XÈ$Ò` ±}`aӸݎýJu º0*MØjCI¥¤4´ž’ÿÿ‡û›aÝiP…‘í9 Uü00h‚jF˜ ?;`•¿ÿ=Ì>ýy  ;dM( Ô¤4Éûß’·(`ï‡G˜,&΄¸¯!¿^¿ŒÒ;äì”}оøïº÷лì.VHdÀ(‚Y44 Ä2Ò„ -?kÒ€€ @°—Ÿn´7éø@¾²p @v˜o&€ìšY4¾jy¶9VÛ\¤ $7?ã1?Ú–MÈQ÷ñœ·HÀ08#ÿÑLìO¹¥Pj2JJ G9(ûî#å_¢nxÀà!l@`Må2ºÊ,RQÕÄŸŒö)GÁA Xºñ ~¿‚¾G×Ü€€9@àâ¸gä”;ì”;Œã‡\p@|à Ðà M#jҠºzW³³^œC~ÌO¿’Eðýkz€`°À`YÁ¨ûp$œ´$9-ï½ÈE€èšL à JJN”vö€P bá-ñŒäYY(ËüóKÝ‚€=¸&€`_ !RLpO À"OpÞÔ43†'£ÐŽ7=Ⱦ«€bG°ÀBh ìQ0¤–‘/™}ìP†€fhÃI$Òúx§;a[+ Ö`P\†ëm…9TXi(Ç¿ÏÏ¡}ìÞCz”S“NþéÂ0FÇ^†C ÐadÐÔ⊠GJSÎÛVM %3q¡ÌA’7;5Õo  À.‡è&€„A‰Ç¡$Ò†à;“¯©'!ˆ²ÒBJ@  ÈÝ‹ ÃÃ~·aïz«˜  ¿ÎGžÂµ§!Ž×ð=È=€  @¡7"ƒJJ@"ÝÉÖ;ôVÿ/vøï¯0B#Š@Ä ô\Lè à9+™“Àúõè,/‰ q1ˆcõüuðý ô]ð €\,…ˆþІ ¸×Xæ"úJ %ó˜>ù1|?D°$\~‰¨ è× fc‹¤J1ïó¤É$$G#^¨Û 8#ÀhЫʤ‘hYD¢ÆGÞß=þ‰¾<l`3ÁýÉ B¯°ß60àþäСW˜CPýt 7åiKº”90PÉø Ã_±éHä`¾uê¡¿¶_÷?ûg÷Å,4¢b:KJ F=)ûl'õ]¤¶K€€诂÷kí €;°Ð2jCy˜â)ÊÄqöë…f HU°¢¯óÁ0†L¨%“J&£ò“’€´¤v¿@G€0€\MÄÐK&GWœrp¯¾¹` @‚óàYD¢i0¤”Ä„ÿ÷ÉA¹ÍÆUÀ2ãI*Ç<€-ÌuüMô/·gZ#ÿÙßçÛRŸgwÄ_fQcqÍIÂ$€\ ‘Ã/TXÐp#ÿÀ`Öò øD „R8eí„  1€ KÉJA¨/ä3ñÛ=çLàSät?¿ý¿ýG[Ç]BÀ€8)#ˆ ·û+°–ýƒï®€/F¨ðßÉ¥ò‰ŽåDp,Œc€J¤9®Ý²25)ÔrížÀ  Àt|àP†L!áá… ¶‹ú‹ô90† Á¤ÂÒZ’Ñð¯˜ëð R€kð½A„ÕlMâvV,wÊIÇŸjMC3£ÄúJ&ä¨ëðóHHŽF–bÉ È×^>ÆÿDß60÷G&€ ¾Ã|xØÀh?Üš4*ò€B` î¢a&ü­)zМÓF,)Îýh&nwøÔð<€ÿzeÞÚæéÈÏïË“HdÀ(‚Y44¢b™iBŸµÐähìf`Iÿ²˜-Úûp @B@5 äÐ*M,š_å÷Æl+*Ñp` 1©áÚßÇküôBˆŠ‰¤ÂZ Áhþ¦ý B¤ÐƒI¥†ƒ’GRz>×ËÀ øôà‡ìXªØšÀy;+9”‘'ÛÀ@Ìèãq>’‰¹*:üM)K²Æå)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¿¤à’@.P#†^¨°ÿ GàGÿ‚`Öò ø$ €THá—ª,?è¸ÿà˜5¼‚!€>’?ºËÍü,³üÒ–šõù÷-ýØ8!ÿ` ÿÐKÿßx @@ÐH€Lÿ»Ú€'?ìÄÿàš ûï‚Hz  Ÿ÷yÐCpíu 7óëí@úÀ‡üÀ‰ °*ø­ö @ý`Cþ` D†Xud”ˆ"ë"ØMìTë€3G~Lý/þZp)j~ÙBÚøx€<¸3 ¢³? BKH´–Òž'ßK?+p`T°$bØO Äg¾[èjrFnÓ&#|÷ëÀ` `1€P0 P(W rbV-ZqhFÙv¿0H\à;O JC`BnM/ÿ80§üÞ±˜:ù€:À¬4Ò6SðÄ$¾²ÓºRîÈ q :L®ŒÜ†’hibù/•€ F¼ý`;©åý»m ³=õÀ€6n”$ è5‚d"Rwœ†Åáù!ß_gzq À É 0!àÎ~9(ëɾY:ø ô@ü (ŒMÈ âIe†'Š+£ Gké =$¯ÝæM+l÷éù€0û"{â ?ßo"?æÀÿì‰ïˆ$ÿ0 I(#½ý(?’p€*G ¾‡³|ð?’p€*G ½0  œøä¶7-¸ …ÜÀ:ã¦ã·#ûBÖ_¿ž€ /D"€¨òb¨ËÙ 6/8a À÷AÅ–ƾÇl§¼²@`‘h%$0å.B `¡R‘©GóÞ‰d2Ò“ît¶¿£ë‚€tLH #”QK!EüŒ¿øS¯lÐvËÊ×ÑžRrQþûï¾WßõùÙ% 4¤†† ´t'òs|~†!†ØšXaä¢Ò€»\&&ðÔ}ÖÄ[pÔdu_Ã^?Úð ǀ研ÿøR“ÀFIîjI ïhzÒp Ã$¹8?ô­€W‹I!"=ÞMA(›ð»» :ÿDßG60÷&€ ¾Ã|xØÀh?Üš4*óÀB` íɄ›ó !Š@¢I ˜’þ3~Áç_|ˆÃ@NC !†ñ¥†§¥<_älv||?L7†*‹véäÄ“Páyï³Ú`€-Ò?´ˆ}{_‚.$!;B@3×~žPa3~€§ÓórV9G÷Z¯šà .)a›° n' ¾îBfôGAˆ&5ˆ`baEKB3÷ìÛ?ÿÕ‚ò€7_ñ$ÿÈhÆÌ4˜M/¾/l4%Ëð`úà€&< Ì Ä‹&:I¤Â”RJ5(AÅtömóßM ,˜Z +ô$¤ä£ã÷Ý÷Â= @–Ž„€b~„ï¾ä0ß¾ç{¥d„¡ ž6´ýûå_çðÀ!À€d æÀ†dýŽÉ9;NúÉzp@"É` ƒ0„2Gj0¥ä€ ï1zäÔ -8]ÈŽû\¥)iMÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤D#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¿£àå€]Å\ ` zðA¸0˜Éç°Y{_:ËÁ 1x‚YÒÑ© ÌžGÆ~)ï­!<¤ä£ý÷ß|~øÛÈ€I a:ë Qwù̲Ošõ ôœ„PØhàÛbòrIEý–Z„6ÜöK0¹À‚è€`(^hù ;ä ÉÅØ)JP݇gqW¡À i-†sÇ(.æ%¡×ôåàÐ`§ÀbC¿üMဩ¬ ÷}+þŸÿïúÿæß4Á dró$á¼7dÆGü+ëÏßBaé ZoËßjÖ?æÔH`%€1WÅoµëój$0À«¨ ¤D]dC; ¾ !ÿ Áx%ÿÙWÌo§ ù„À'‚_þ|Æ  @'‘0‘z@50  Ž¡ –~ý~}ÔÀ$ ‚8†‚Xûôˆ'VC?_Æ  È@ÿ„ЭP À‡!} ÐâƒP”€AG½h €!€áÿðš5¼ðhaD0ÂÃpÒƒP’“‡¡9¾ ºR0 þ9$[4g)…_è‹á N€ @dZ9 „Q1"’LÄ®âYÃï³7|Ml©4»n Jä‚ðœÕr€ € C@’‹G&€è7¹ebJq,§SÀ}WÃ- ÃÏÂíÃ1+¿ŒÒî“ @J€BR’Rp¦øŒ÷h˜ ~hA‰(GY7æÁ½ ·O¶aw¤‚j{ áùW?-~ ?4èØ^„w¨˜Q3€­Ò_ ÁÕ@€ ‡ýÀšFׯ,´†–’ËOJSúRž¿ÿ_ÿþò€ ‡ýÀšF×–”ˆ]DºwrÜ¿’sãÙ÷ýP?(ÀàP©X ÅE±ØšŒ°б&ö$ “@¦ Á…ò€nW -€ù_ïÑÅv×À<@PG ˆ`0ì7 i3Ž BÐwý÷t¡%'¡;££ý÷?|~÷’Ð2Üô ¨5hA 1&†ƒÒXih(¤cRžÛߟÀ2È0À€PŒÄ™?òúÒô¿'_D<lp†€? ÀX@X˜æ“S—Á ÑÂÓ½óD÷öà†¿Œ>‚ ³}”?H…É€ @wùÁ¸0´ Àaü4{ãW¸Êh€è02b?HGÄ¢koß$AIwŸÌµcVnj ¹Ð"ý ¸ Рd¤ö?!LÀ+t‚Æ6|—ߢK&€Ò“Ð’¾J•÷ËßqWÊÀ怀!ˆ@|ø‡³rÆ~L,^¿G¾aÞÀ$$§ä£8ý´&²½ø»²bt€ Kýi&$˜i ĬÁn\C#\B@Þ‹àfIiáY°×Ò@ @ C@†¡G&èG3¹E:ÿ8–[)ÇlH×@…¥;ýöÝ×fYy{ôw €\à ‚?¾ï| !€ÈÀŽØî@ À&ÂH–Ä"O¾jI È×è›ó²I È×èšÀ0(q*`}üxØÀh?Üš4*òå€á"9õ€À†@‘þäСW—,‘tPCÿ®&Ì0‘¯ôMñà@`C HÿrhЫì7Ç #ýÉ BG®‚‡ëba&ø` È\`„˜Œé,DÔ |®Äûï·ç=}¼¬¢@^VGÄ ßÃH\ÂWä%pçsm€0I%ôñÞþn`tìa03pœhJy{…%ƒ¯3}Ä0² ’±,0¶A41Û‡áÉÆr òðë€0ÙY ¸™Í(›ºƒÛ£‡j°(^/ý¿Ürè /3~zúh ~ ÐXG0·Y0¢ËH 3öÛ‡!ÃîÐ@üðÀ& Hâ@É {#'n=)û>‡¾ªp“@5¡ T†‘¡¡©žDÃ¶ÊØÍfbrIiÌÇ=DÒ÷ͯ’DÌ€#ÿØËßIþûx!ÿ0ÿ`/|A'øÌ’B;ßÒAðI ¤pËÖ5І_Ù›ŸÎÈ-Êü;%ï&‚I¸@#†_D¹€uœ„GŒ?r?µ Ï¿ÎIÍü×Ñç†B(@ÆîVÈ@öétc°nΗÀOn漺@ @!xdÆ‹é‹ i:ô‹¨K üF¹±høý|€*C(ÀÒhobƒ Iiã²3ûô47“CK/žZRž'÷¼€X ÿj8 M’Pp.”©$Ö;1…:Øþk^´ @ГJ!Ë NBÿÜ&&pÄ~•~NÖá©Û+;G!r€ì›ðà;l/VXZ}ãÒHHŽF¯|‚` !`6( ð&_Y|GOì* ²BDr5ÜMHÒoâìJÌ‹ý|xØÀh?Üš4*û ñà@`CžÿîMyà'0 ¶&æóë9 `FgèÅ€Ô~ßj¿<HEì˜B/9DÒ’Rp›“½÷  @œšnû†'íÀšòp¤åÚ€dGœ3 [ÒCË{ù€`€/l†€h44²˜7€V¼å•úÙ=³üí¶Ë¹@‚`ÀŠÀ•ÿ 'ßú¾P[À$²a5 Ñ7¿È$†$Tn®ùIϲÕ|è pÅ”7j°äâк²e%C~1žE¾2Ð@¬¸@8¿äà›ÿW@ €5!†B ,šLOBJ?>K ñŽCÃv7¡õØJGžLäÄ@Ý)Iy’[£#sÀÆì‘¦ û1—ÑŠIx½ÊéÉ}ÑÑþK˜Ì·³&ÒÒZP9dz’’·VÞÿ?˜ ûŸ¾7{éÀ Á vB,°*ñ »þBÀ‡ÿa‚‘¿J0H®}ódüu‰†’gQëIX»ýM!@¢IDÒ‹ N=£¡!_oBašRJ&MO9#¥<9ûóŸ&Ì“‡}¼1 fdlGŒ+5Æk€‘<Z€X.þ ˆØ “K( €;@„$|œ?¤š)-ÀPîccï™'æÈFÈB6B³m²¶Û+mŽÔåôŸ=ÖM!¤›×dQY/­€€4z ' !diIრ„ÒÑØ˜VRPºï’I‹J™šbg|ÐZëú( ¸à À4Ô)Ø €bÀtÙ$Òhfü •ÛrÑ·÷Ïdá©Ió̆tG¹ÒBf»ÀNŽ\ÿäÀݶ_ÿ£«a÷ÜðD A$€¨&€ðмMN  P 7S½E”K¿FR¢ €©04„^ &þPiI);t«ô'n»*SÒ|Ö¡©%§¤}6kì+H ä!…ð0C+pÇñ8•ÂñúúÈÐ` ’ @t_+'ýnY3áä½”!-Å_«@jPm) Í×­ É¿GÑ÷h@äªpÂ@¡0ÒrŠ`>rø ·õñ2±£4{g ¢I©M‚@3R‘^! ¿±€'"Ø@!Ä €`¨ C10§& „^Hoq«)Xëšbàð5Á T'…X‰dÒhbågJ6]ó _Ðá©öœ=%t|aôâcw{~|iK¶Æåõ`@ýÅ“†@¡]8æF_ù}’€¾Nÿ¾SG:Cxg,¬_&C·Ù8[bB&€Ù.Yh®à€Ð(›„tà>•–þp¦Öh~þ6‰HÔÿNÍ®Q·ß'n›î½÷?|:”¨é_Ò@‚“JJ@¨¬pξ§ICÉN”Î4ÅÞô†`0/”C &AhIIÁÉÛßž7ú¬ÿæíð0_³'8»nL¢t`€„°0DÒ`H0¤—ÀG ݯL6Ùð @b|žq3ð(b,hòÆnüqE8¾eò° ~ͶØvU`ß$€kùÙ§ˆW÷AÀ`Š ‚HPM;ã ‰¤ €”ÂÐBÙ%Ž„£¿WGo¸›”tÏûÚÀvt35%¹öÉZ#‘¯»` ø"ˆ ’@T@øE^&§T¨ާv‘eïÓ‚À €€¤"i°GðÞJ&”Ä·AKdíØ]çR´$G‘%ôŸ5 icKéNÍšþï€3P¼@( ‚hß+.€ 0HDÐ(Xøo%JHb[ ¦ì»^cS¦JzO°&€Ä ”1š´ ïmt€6€ðp(¼Ì°ÀÔC?Ã÷W×>—JÊï¬þ}ir@äÂä$Raø†BG- ݰ҅Ì;ûÑ~qA}ð×ïÐGñßíø]€ Ô´[òïwt€Ø4ì Jà‰ÿEîQ aä¿›ˆCñW8 `y€L` @5-%'PÒa0²ÐK|ÈØ¤q›c|ûä)!§Ï‹ú®ŸueŠ¿¯€2v€hMÀPÂé,°P„fëéI[käI?ÉÉ©æÖ[È`ý̢ٚ†_½ÊÀ ¤ àP*3ƀؘXhÇ Gä¤vvì÷«p\‰ 0œà C¡a¨@i| JÈ+õñ¼¦Cê¾*„ô/&§Ùœ”VCmi& K½ýˆx xðE¥$"’(á“7IhÀÿ™þâó ^½gݾoÜý~rÅôJ_¿B?öþÍ©hru\„;ß߀.`x”ì`I»ö%ä|€Vجï“€€` È}0ýðÔà™¹è)GÙÿ5?e+÷˜ä4úßÞК^m›R‚c\ýüé΄ˆòÒë{+û¸ €à>€"x$€PоV\*@` ‰ P° Ãy(šRCÝ7»^cS™)é>å&€Ä  c5¢w{k´¤€“0Þ`*¾&A0ËÆ•øzÆÜZ]Ã;ë>Œœ»ûˆðà À-i+'ý“7 &|^0 ÇíïÀªyµ¿½ hR^lªPLØû HÞóR—mÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘#óô¥/ ¸.R”ˆ¹JR"å)HG‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥"G.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HG‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JRG"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”Gˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ G¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”Gˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥G".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)GH‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JGR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)GHˆ #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JGR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ!#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".RG”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ"#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”G3"ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HˆGPàþ„€!Z)²Áÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®GºñÃvÅ.\¹råË—.\¹råïÚú뮺뮺뮺뮺ë– "ºë®ºë®ºë®ºë®ºë®ºñÃw×]u×]u×]u×]{÷×]u×]u×]u×]u×\° "ºë®ºë®ºë®ºë®ºë™âà Œ8l7~ýûåÿ®ÿ€Û~ýû÷ïß¿~ýû÷×]u×]u×]u×]u×\°"ºë®ºë®ºë®ºë®ºä†‘@ÕÿûGƵõ®ûÐÀ€.¿~ÿö×úÁôoöÀ­û÷ïß¿¿;W¿~ýõ×]u×]u×]u×]u×,"ºë®ºë®ºë®ºë®ºëç <€»@çÿç·ï®½ûÿÐ=ûµ¿}{÷èO¡ýWî°¦oÿ@Íÿà>öýõ×]u×]u×]u×]u×,"ºë®ºë®ºë®ºë®ºëÇ ß¿|½õ-Ï~ýû¯Ý€t°Ý¿ûU¿~Gýû÷×]u×]u×]u×]u×\°"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëÅß¾‚´zZö¾¹ ­–ºë®ºë®ºë®ºÀ"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëåЀû›Á`×ÿçoß]uïß\½õ×]u×]u×G]u×]u€"ºë®ºë®ºë®ºñCëß¿þƒëù0a—&ßÿôu¿~ýû÷ÿÀnÿü«þƒÿ€·oþŸ[÷ïÿ€ò:ß¿u»ÿ¤@lÿó-û÷ÿÀlEû~ú뮺뮺뮺À"ºë®ºë®ºë®ºñC÷ïßþÈ ×ÿïoßþ@/¿Ø»[ÿÐ; oß¿ûàÊ»ýƒgÿâ3Ÿn·éz?Uÿ :;:ÿ`Gø>Ýn{­û÷ÿ°eò¿ýÔn8u¾ºë®ºë®ºë®°"ºë®ºë®ºë®ºñC÷ÿ°6öç¹oÝþ°Ö¿à<€·ïÿY?þß¿ý/ÿ<ãmÞýû÷_èÿýaVýÖÿÞïÿëõúßÿAàNöýûå×]u×]u×]u€"ºë®ºë®ºë®ºùCìüx—·ïß¿~ýûÿÐø,ש-·¾^ýû÷ïß´¶ßûG¯ÿS[÷ïÿ`Áÿà>SÐ÷ïß¾ºë®ºë®ºë®°"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®Gºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºëG?›ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G@°Áàá$¬H„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGA°Áðð HDMVˆÿüüððÿ¸ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@ðÿÿÁð cÁZ®ÿÿÿÿÿ€4çNÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG · DâÜ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPàZ„€!Z)Îá_ÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®GºðyzUŸ·ïß¿~ýû÷ïß¿~ú¼ß¾ºë®ºë®ºë®ºë®ºå€ "ºë®ºë®ºë®ºë®ºë®ºðyd•u×]u×]u×]u×›÷×]u×]u×]u×]u×\° "ºë®ºë®ºë®ºë®ºë²¼ÀS~l oÚ#ƒ/ÿ¥v÷ëõ{ÿèñÈàqžßý ?À5·ïßþÁßÿõ¿ü@9'ÎËÛ÷ïß¿_¾ºë®ºë®ºëG®ºë®ºå`"ºë®ºë®ºë®ºë®ºëÁåÿ]þˆ£À,Nö¿W¿~ýú^ý?ôŠw·ï÷’à9ˆ×¯@j  u¿~…{뮺뮺뮺뮺ë®V"ºë®ºë®ºë®ºë®ºëáå°gdföýúºõÿì½þçÿõÿÀ}_ôÒ&«×ê÷ï×~«ïÿÛ_ðŽ þâoú9ävµu×]u×]u×]u×]u×\¬G"ºë®ºë®ºë®ºë®ºëÁåß¿|—?^ýû÷ϯßì|ÖýÿíVýû÷ïß]u×]u×]u×]u×]rÀ"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëÁ§—¾…—.ŸgÑuÐ'Ñ‚Z\¹råË—.\¹råË—N"ºë®ºë®ºë®ºë®ºG뮺뮺뮺ëá§Ò0€ðPû~ú뮽}uʽéù /«®ºë®ºë®ºë®ºë"ºë®ºë®ºë®ºèõàßüà4Áöýÿðr9úß¿~ýû÷ÿÒ Vâíû÷ïÿ è"Õíû÷þÈwŒ¿X ÿþ ·× gð3è>ÿÿÖÿúŸþ=~®ºë®ºë®ºë®°"ºë®ºë®ºë®ºøiÓê½ûÿÙ@Uü†Ø ú•àG4Áïoÿ ´6=¿ý€Ì]þÁìu¿þƒ°½þÌÿ×û 7ký€~áÚþ—4N·ïõ¤X õ¯ÿ@lxûýƒp‘=¿~ýûÿ§äR-¿ýü~N[}oß]u×]u×]u×X"ºë®ºë®ºë®ºødo6k¯ö¶ýþ ëÇÚ _ºÀv>·ïÕûë ÿ°hû~ýû­ÿÒçð^ò=eªÿÐ5G íú½üÐöýþ´¹ /׿@| ¿þwÖýû뮺뮺뮺ë"ºë®ºë®ºë®ºði÷ïß¿~ýÿìý¯ôG<À¶©vÿèl4¥§ïß¿~ýûÿØ>ÿûÛ÷ïÿ`ÏÿàAêbÚýû÷×]u×]u×]uÖ"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºG뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG;?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ뮺뮺뮺뮺뮺뮺ë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬GPà Y„À 1Z+?aZ)ëWÿû€µóA€"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ "pÎ "pG Ý|\D³ ^ðpŠä\G… ÄzpPà "pFB~)˜f@h ^¹Gë‘qÇ Ä{ãûð(p "pR1‹ûÛ-ÈüÉ0Á¼ VPkÍ@°Ìw_üYᄚ4YÆ(~ûÐàþf¼ðéݹ¦@œŽ`¯OñPù­¡DcÂÀè‹øÙ|@€Ó˜¶SåÀ3üzhŽÿYÇêoT ç1ÿ¨ŸÕ¸i|À˜4¡©±\@Aa¡dÄ †¬âFfÀOàDÿÎh#€’fOMíÓÆ!iGçl¾ —é`pu´@“»@€¼YšðÁ;³ ÿÓø)*`ðábHšb!^à°€ºPýG™ ðŒa÷¼„QÇŸ·oô@'µ8ö‰àß‚„N½«Ç¬Î`‘cã-±}äÅCÀF3¾?¿‡"pRx²x ‡<B€] ¦#8€þo÷ÀáænXÍx€!…+½€ì;D\WX Ägñ¶a\Ê??¯½€3?îÄÿØ ‚_ý¦ø&¾öÌÿ¸Gÿ`* ö›ÒGÀ’XsÎÖ Àp}˜=OÁf9‘dqâ§2þ À4œx€Ð¥;£´îk²™AìÐŒ8œE˾ Ú&Ž\h^àÜÍOâ°ñ$MCÄ‘59Ãûú†8>ÇÞˆÌ"XM„@K ¾zDÓø«Ï`k΀4TAÇ qkØgG½ÂC…¸îD »Db{€¸O^xŒBŒ¿ƒ/ÿ¸ÿŽF€h³CÅ ›ÿÈáÜnG½,`œG¾?0×Ìt "pR¬Žáûáß÷K`Â$SÇÿ}ƒˆ¸í}×ÿ½ô7`;©þ@HÁð ÞOPRÀèÒña`ãÿ똀N\8kä ?þ*ïÿ÷Ðÿ ûì€ýòÃÿÅ@A¯ à:A·F§ûz¢88@¾X0ÿp¥K¿ÿ¾ÀÐgy§_@à>C€"pÎ"p5ìàpGÕ–-·§œ¡c€äø ‘`‡í©ÙúCwc€"p5ƒÐñpB²Žæ¹Ð‚ˆ¡{’=½î@54|? AþéÊC‘}Èþr/£xqØúŒà±À"pxGÿ~øÑè¡|Àç#BÁÏÿο~ìcc°Á]Ô–×èõÈ€ç#_ȡȩüd¬NB”íøÐµ$‚!äíy"H‚G¹ý°ícœ]ñ ‹0 hrwo¢#b)‚¯ ú–:hÁ»9ÎbIw´IÈÀuÍ€~Ü?ø’=Æf*õñ± ,¡à,½£Á€Ti‡Ç°Äç4¶søF;_È+sð;ŽÍGùþ@ØÀ©ÅBÅ«}¹çî"ö8£ €n£¸Ç$ÄB1¤c…^Ã@:T@8„_ù°± Þ -‰Íˆý¹ùÏÏ´ ‡‡vðxx­|€€âv'ÐIÐÙF­éý>2ôØÀ_ ×½˜€"<8y3õ,ÓôÈ„kå Ã\œ`÷8¨@W‡Ð:Î9öVåŸ9÷Ŧ¿æðøÿüŽdÆ;ß >€Úyþ…0¾"_x°"p{€ Ewé§ùר(È -:úåòøâÌ…‡ûŠÂsºÕ¯ „)JuçË2'‹G; ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ|¿ÿÔF€=âøQ­Åï±Á÷Ó»_ —ƒ€‚…€ †"ŸäC‚ˆÆÀ5ørÉßzpƒ€"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ!"pÎ""pÎG · Dðì~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPà f„€!Z+!ßÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®Gºä†ÐãÀ\"®ºë®ºë®ºë®ºÿØ «®ºë®ºë®ºë®ºë®¹` "ºë®ºë®ºë®ºë®ºë®ºä{ …Uu×]u×]u×]u×¾]u×]u×]u×]u×]uÈ  "ºë®ºë®ºë®ºë®ºë™Þ €±g@4{œ|FñäC^ønˆç¿Àò!8ñ0j¿óÿN€|à>¯Õ°¥€ê÷ï¯ý/ÿž*ÿ@°G8êú €tN«ÿÅ8 "?"5`WØ4 <ÍW_ù¢( j;WÀF_þXåU﮺뮺뮺뮺뮹"ºë®ºë®ºë®ºë®ºëç Ððþß}x¨Ê^ÿäHÀ5 :ñ€/öÿ瀼t"½]uï¾€84ŒN·{­úêî³ÿõë ¿“ 1¬k´^ú뮺뮺뮺뮺ë ð"ºë®Gºë®ºë®ºë®ºëç Àmÿñ W^àgp3.½÷éáàq­Öý÷iÈ$ u»¾"€_ }º»‘ø?üžN·Þ*F"4€æ €jDÕ{­û÷ïß¿~ýû÷ïß¿~ýûäP"ºë®ºë®ºë®ºë®ºëÇ ¾€Ð»ýšOUu×.»ì€[ï l·ß °Pè €Ì>¯ýÔ:¯|û8n?[ï ÅHè°:ê뮺뮺뮺G뮺ë–"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëåг)øÞF^¯°4`óȵu×_û9—]wØ0yäZ]u×]u×]u×]u×X"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë°ýðƒW]u×^/¾ºë®ºë®ºë®ºë®Gºë¬"ºë®ºë®ºë®ºè>P|@Þúï8œ0¨äRpâ%^ÿúÀ^Å^ÿø€Öÿø @pU]råï®»à ÿ‚ ˆW_ô€ ˆ•wè>ÿûÒë®»ônø}.\¹råË—.\¹räp"ºë®ºë®ºë®ºñC÷ÿOé{ï[‘õÿá¼â!ž" ]_ôüºøœ DCïé"œa¼˜lŒ: ýý pŸÀå|G `5|H‚;6ðž—R¯uQßËÀÕÿþÿ`Ýÿã”m¿ù06ÅŽ ¿Ñx[l*¾€d ªüª·ß€€ü_Å@ÁaB+ðà,À Ž «®ºë®ºë®ºë"ºë®ºë®ºë®ºñCïÐH‚ïí"`6Ähx{R÷ïÿC°ŠøƒWÿ¬*_„pfÿñJ«ÏXä=P“ÈѶûéïô€¿@hGK®ô€ ȵèqºü½|ÁHƒà €ã…ÿK®¿ø?ÿÏ_lÿñ lຽ÷¸H4ÿø¿°ú ­yà… =ã@6«®ºë®ºë®ºë¬"ºë®ºë®ºë®ºè?®û‡˜e¾ºëÿ`3ø ªö»{éu{ÿØäq©öàÉÿõèp8»ýƒ0Ÿ¸Š¿ô%€…ª¯úCí÷Ù€»~ûìàÄ!G÷úÂkèâ}.ºë®ºë®ºë®°"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºG뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG9£ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ뮺뮺뮺뮺뮺뮺ë¬GPà G„€!Z+#Aÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®Gºðyo¡Ç¡u×]u×]u×]u×}Ð5^:ó˜ÂÌ“W]u×]u×]u×]u×\° "ºë®ºë®ºë®ºë®ºë®ºäE®ºë®ºë®ºë®º÷Ë®ºë®ºë®ºë®ºë®¹` "ºë®ºë®ºë®ºë®ºë²ÌŠ* Ú»àùޱDñÔƒï¡ÀÏÿäCëõlyÜoW¿üC¤N|:oß|€7 Q²Àe^œÖ¾ G×,¸{üEÕ€lža:¿Ãÿĵ~5]ôâëàa°Çu‡ëG﮺뮺뮺뮺뮹X"ºë®ºë®ºë®ºë®ºë²ƒ@åÿõh`w‘+è¾¼Vmƒêʼˆpw'&½,¿€dõôPkìŠ= ·{î $÷K®½õ×þ°`±Öýò뮺뮺뮺뮺ë®X"ºë®ºë®ºë®ºë®ºG벜ÀëBE“ÀfW^zå«¿H‚kôŠ@gJ n·ïÝïß»º<Ðà «àðX«ôˆ°:F¥ï®ºë®ºë®ºë®ºë®¹`"ºë®ºë®ºë®ºë®ºëÁå®û4ÿüÕß@ãÿïW]ô@ WÙêº÷˯|½õ×]u×]u×]u×]u×]u×\°"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®Gºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë£×}€¸Êºë®óÀÙ8 Ý]r ¾À\e.ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë£Þ(±<è`cÿøP²ñmu×]ðî—_ø÷K®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºìúx7ß]ôNª¦ö–ýõ×]øAG‰¯Àxÿ÷«—/~ûÖšñ`cÿý l,Ð:=:ßxf>'ê,F¯ *¼â }§Çº]ú# _DູråË—.\¹råË—E"ºë®ºë®ºë®ºìéȯ†éù—}'׿g¯DXp $Õß bÿ÷·À6 Õöq«É„…ל @\À-N#®¾À€¡ÂW|L‘ƒ¡Ë™—>߯qGà/±à/¿h¯ÇD…^ÕwÄЇ‡Yœë·¡~ðÖ8E}Ìjå߬eêèpåð¡Ç½u 5ÐôX}~tAyÖWoß¿~ýû÷ïß¿}X"ºë®ºë®ºë®ºìúF~€üÍ_ú éˆôƒo¦âß¾ù€|`aœc[ë®ôàDM|«ÿÚ8W~wÿ®¿@=Ô¹ðì}>8ðØú]ô8úùGÓÀÐ8Ðk µÿç¿×W~€ þõ`øùÀ9±ðü&ÑÊî€Þ¯Á@ãëâÈáS‘Âê뮺뮺뮺ë"ºë®ºë®ºë®ºèõ×Ã{ „eÛÿÐÀ3_«®½ûïK(õôººï°4Ço«—þ€+ÛëŸ@-ÿ¬ƒW¾ºëß}_`l,{þ‡_ cÀÈ tU.ºë®ºë®ºë®°"ºë®ºG뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG6 ÿÿÿÿÿÿÿÿÿ뮺뮺뮺뮺뮺뮺뮺ë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G · Dþü~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPà y„À 1Z+“ÁZ+?aÿû€µóA€"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ "pÎ "pG Ä÷z4:øf˜NÓä ðJ‹9â^Ì@6`x—Ù€à¸8 "pG ŠÀG|:€øtÈÞø ‡…À¹¹ ¡À "pRØ/ ¯ÒñÃÀ€}í``ÿû`‘ˆ¶€СDÅchØPxÓÞÝÄ€Ír€< …_‚ çß›¹žíáàu¸ hA€޵^ðaÿò2 ÀãÐ oÀtÿ÷SÞp D\ð²=ñÀtáàG…´£NÛì˜G"/Ìü?¶½ƒøÀk ¢+éüà‘ß?ÿ~ÇGP3 î?ÿÀrùPq>÷‘€yÔ*Е‘3D@SÇõÀ ‡ýà‚?ûPKÿÄß>@0 ¼ÿð„F.úPCþð ÁýÀ¨%ÿâoŸ €^ÿøB#tPCpífP`Pà"pR>Ë€®uìÅÄP „Øà€[}˜Eb#.Q£nyãÂï««}x6ˆË°< ;βqð[-¤˜FGÀíŽïÿ´«j]§Œ~àõÏ@x2€ ã7?¶¹è¾mïY€cç¾(A¬v„×pÁ¤otö£aÜAû½Ù À8¾mÈüðæÁJÄéûgœ*îBÀ[ÀÜp )þàÊ!pà·¿ÈæzDð(p"pR‹N •À7'‰{²!Ë<@ :À~h÷‹€æ'n;¢oA‡‡`[/|<ÄÀG^+b b ›îpÀð}àû$Žû"¨î8lŠx›Ü8¨?ý€=” ÿþ&ñHþà?Pâ¢#€¤ßÐÑ -¼PxQEœÀ‘/âH”oD€ç"_6coIœAIœAÃéÿØàáAäZÇ "ÞÓUXxäêf®kݘ D`7`È7žËÜXï@Ì7–νÌçj@3 Pà"pP…­ºGŽb0}ö`“8 ¾@Ò:„I÷×”.ûb-ôÝ@_jü”ÿxëíKÜp3€ Sý¨ðeÿûë"¸rðwÉGƒpØØU?É@ÀtnOôF" 7_`ÒÖ˜²˜X3ÿü8=À€f·FC€"pÎ"p5Í@çÿæ@ëÉü‰Â.¾.ú€þŽß_#éúw“ù ‹¯€‚ ÔÐÇG"p5÷®dEêÜÀöºüäM ˆºîÔôpˆ¯¯@wïˆàþG‡ò=!®ùù„]| >€úèc€"pˆG}~È;SþI8?_™Wàkæ=0ƒ0°ûô@1þ¿uú9€9¾w#Íx¾E"Աǀu(XŒ>”°i⫎/ÿ8óuëH}?ᇠUù|þD¡×ˆü‰|‰ ˆºýð€þ ?¯.óÈ$AÒoG1ÿÿ€~÷à “ÿÇÞ6Uâ (N#Þ×"RÁäy”Ûpßf€Öüºˆ׊ü‰|‰ EEð€úè >ý<‹¾€^÷á‚È€¨à"pˆF>½ÚÇC€[Xëâƒà$|/^ìS0>Àð|Ç‘ýÔ¦·Xë½{à?%'Èá×Çã³t?ÞŘù:#¬MbHQø¸Ñ¡ËÚŸÝž`~Fœ~×™`ÎGkÃÇQÉqç‘_#®aáÀmVG:óìµÈã»ÿÇßü< ¸1ü;]˜ÐõȗȈàÀµç$YÃÀ诟x¤mcÀ]z>D >P}ò%òƒà9ˆ×ŠþüäB.£õà€à‡þ@'p Ïü*ù…ôð@ðCÿ ‚8‚gþ|Âõ@5œ:å!," àåÿ÷È€–`† ¾”?ÿx H¢oÀoÌOv÷™c¯V:Gñ¸&øÇÀ@‚$Í1À/X o¶oõË `F幊þüºð¨ >€úà —zåÜq€t*…ÐP·Ïâ`d<}òb4QÀ/¾0ýF€¸…Òp"pˆF>½|lEäxðá׿Øs“àeÿ÷€8]ð¹ÁëâY‹äKј\à¬Àúä‹Ç‘ý/¯r%ðâ/œ‰@|8‹ïÜX€fÿûÝþ!À8Xpý\GŒ7€?"Êøæ à·pyÏ×Û,N'œp€Þ*h‘fW#±Mð±¼8,p§˜x#H€v¹×…Ì$â-ù@á¯`5ûOxOA¾6½0Eòƒï˜"€ùAð»/JL|ÁðuÊ(>€ùW?úáÌB¬ðãÄ 'Î `~ƒp¸v¼SÀp@ÿàÙÿ÷ˆ·¡‘„^"HÄŒ"õ„‘oŽª"žÑGý÷ ¿Þ ×?ð‘ëà-þÈ x¯Ì|‰Â.¸™ôÊ'ª7\ôk€Ç ±Äðbv#‡“ï˜ Ä@¡ >þþÃá$ñ$â,,Éþ8œ"’„"pxFƒÀ8ôÛíܰßQÂ@g|³‹ÿÌqÜu$àmX6åðCÍ‘/µßAÁ@3'ß ˆ€5T,xà`ÿûä`¸v8F^^âcG;b(GÔÿdQ÷Ù8Œåò–¸· Yæë6¾£x€|¾D£p1 ï¿€ï¨î ÿÚû4€hp£„^œ`rúM‡ð _+xŸ}‘\ã€å?Ôx€ ,Uö÷Ônhì|›“Ì?ÿ`ßÿáÔÿ)b€È< B §8"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pG4ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÎ"pÎ "pÎ!"pÎ""pÎGPౄ€!Z+[Ÿÿû¸µ‚!A€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®GºûÃRº®ºë®ºë®ºë®ºëßýxYÕu×]u×]u×]u×]uË "ºë®ºë®ºë®ºë®ºë®ºóÃk®ºë®ºë®ºë®º÷×]u×]u×]u×]u×]rX "ºë®ºë®ºë®ºë®ºëÏ ¯~¼µg¾»æC´à-÷ï·ß >÷ûëÖ“kæ?ÀÖ:¿|úú?ÿ­ûïÀnê«®ºë®ºë®ºë®ºë®ƒÀG"ºë®ºë®ºë®ºë®ºëÏ ¯¤’º•¿4úß¾½ûëßü‡\Û~ý[ׯõ‘@6ÿù™o®ºë®ºë®ºë®ºë®¹,"ºë®ºë®ºë®ºë®ºëÏ ß¿~㨷ÿŽ<‡¨ª½û÷ïÝoß¿w¾ýBN«ß]u×]u×]u×]u×]rX"ºë®ºë®ºë®ºë®ºë°¥}žÝ{÷ï¯}u﮽ûëß_úN«¯}u×]u×]uG×]u×]uË"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë úòúë¯7éèžu.]{뮺뮺뮺뮺ë"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë úò¥ïßU^µÑ*èû뮺뮺뮺뮺ë"ºë®ºë®ºë®º®ýGÛ/þ–Öýû#Ù•{÷ï¯|½û÷ê{õ¾ÕNF©ëéôœ+}ú9Õ{÷﮺뮺뮺뮺À"ºë®ºë®ºë®ºëÓómÝUø÷ú_ÿ]¿üžÀå¿ý00€ ÚÑTwÖÚžýûåî·ïýÀÓg·ïßý)° ×ЗW©wB‚ ˜ˆOë«®ºë®ºë®ºë®ºÀ"ºë®ºë®ºë®¹/áø,8–ýõïGßzXðæ¿èâ«ð¤M’?øk~ýõËÝî[ŸëA°^¯õøË~ýújߤ¿øºý9šÊu×]u×]u×]`"ºë®ºë®ºë®ºòÃ÷ï®úý¾»è€cR÷Éýz|:ܪuïßþÀ6]¿}uïÿL `oß¾½ûëß.\¹råË—.\¹räð"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®Gºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºG?0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G · E ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPàB„€!Z+w¡ßÿû¸µ‚!A€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®Gºñ弓Î`‚/«®ºë®ºë®ºë®º÷×]u×]u×]u×]u×\° "ºë®ºë®ºë®ºë®ºë®ºñå—]u×]u×]u×]uï—]u×]u×]u×]u×]tp "ºë®ºë®ºë®ºë®ºëÇ–û<·ôàÃÿïjA®bÈ7·€Ø:¯üÜ¿þðöû÷Öý÷‘Â̰bÿÿWý9Rï Ar+DB7·ïÿAdà €å¿@Ë®ºë®Gºë®ºë®ºë®º8"ºë®ºë®ºë®ºë®ºëç—®½%ÎlõºßüˆÀ.² Uï½,~z½û½Öú÷ÿ¬ª¿å‡þñ—ôü‹W]u×]u×]u×]u×]"ºë®ºë®ºë®ºë®ºëÇ—}øi¶›þ‘áÄ_W¤ÿŠðp¨Ðòw«ß=æßz}Kß¿ú~E¿é [ÿ§À/¯ÀTD·×]u×]u×]u×]u×]G"ºë®ºë®ºë®ºë®ºëµ¾µ àbÿñk6®ú €yW]uÈýÿÓœu.½ûåï¯ýžû}u×]u×]u×]u×]u×\°"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë£âýõ×]éêëß¾ºë®ºë®ºë®ºë®°"ºë®ºë®ºëG®ºë®ºë®ºë®ºë®ºë³§ b¥K˜ ƒoßW^·]{ÿ§äB/«®ºë®ºë®ºë®ºë"ºë®ºë®ºë®¹³Ëß.^ûôâ&·ïþ]C¯_Ó…$KÓ“³7/úp!íÿÓ˜öÿésjò^—7ÿ¤Pö·ß€.'*ÿ§ç‡}ÿÒÈú뮺뮺뮺ë¬"ºë®ºë®ºë®¹ó§çmûõ½Oøö>ßý,NêGµ¢¸èŠEâ¯Sþœ‹ÉØÛï!Þ­û©ñù—Ì·þèvoßý9‹ˆqDÀÉÿ÷û ¥ÿ@е/AWb„ýßbÇÕè"r\¹råË—.\¹råÑ@"ºë®ºë®ºë®¹ó’)`ÙÄßô£Âíû÷î¿zðjÿõÛ÷é¥SòzN·ÿND#_ðP·Ï„@«úpÝN8Aý§Qš߿~ù{÷ô€ ˆ6ãÿG‹¯ÝMIråË—.\¹råË—!à"ºë®ºë®ºë®ºñgß}`D€7·Úuûí' 5/~úè¿:q@>¥×/þsÛÿ§ 5¿~úÿ§Öýòÿ¯U/~ù{åË—.\¹råË—.]"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®Gºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!G;Wÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬GPà „À 1Z+è!Z+“Á×ÿû€µóA€"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ "pÎ "pG Æ®EÄ{Ä9ûBA›‰hL4â=ˆ°?Ó‚§ "pG Äâ<qñW GN@¾E"x/¨ÂÈ*!‘Ã/RTÐp#ÿÀaòÀø@9ÀD28eê@ ú.ø #Ý@PÀ#äfXáúᅟ攳ü׫îH8 "pP„üù`F"…^Dà€p`/ ß;ˆðÄ{Å\€D'@5 » ½?Ãà‡,þø¿ ò<~Ãâ'7‹¥ xDçyÍ9N.ý<Þ僑 Go sÿý|ÿüØÒ!^œ‚D×ÁÏ%Àk­byáãÅõ¯8,XQ €åúâqâ/'…0PöÌKäùÄÐ7~$õ‹XðŸx ÿFøPyÑùÒÏóJYþkß÷ œ"pRˆñž¨Þ Ÿÿ{¨ƒ ð}OípñðÄxâ=ñùØ,.r%ñä‚ÐðêtWÑH šò<È„W½@ðŠçqÒG`ŠçW6ñ\ì$ _2ÒmäÜCð›éx£˜$ˆ˜‚yÌE""ø|pp6üçߨ?þŠ ?ï#‘/Û$‰|™vyå_pƒ•À;½Ùy ŠžÔáäàR8eê@ ú.ø #ÞX? ¨ ‘Ã/RTÐp#ÿÀaé!a #û"À'áÔ ,ÿ4¥Ÿæ½orÀ©À"pRŒ°ˆ¦G^<±àÄP ¹–G#ëâ°Ž ”.÷Ü‹ˆ÷Ï®EÄ{âæ€²so„Cð‰ #z?Ç€¼hŠàÛð-WшB5æi0D;€ºÒ`ˆwusdã/ù‚/˜"ùþñQà,‡€²Í×£ÐðÿzïÞ)p<$‰ëá$OÒ")ý6N"zÆÉÄOf`r-ö?‹@‹ÃÀXÄhP3 : ^'ßphUða„ë8œÀÞüF"ÀlG1üF"ÀlfFGôà©À"pP‚“®<@Eò Ö ÿþx¾N°rNËOö%éþáfƒgÿÞDñúóGñ< £„cŽ"Xàò%ðr,äYB"ž<*ñáWˆ·ÂCàXà"pˆG@Ùò@t‹~òn|‰î@¿€x¸ûCãÿìžÛÏ'ð°¨H ¿#–E`ˆ—é;“ï·P  ¯™`/Äð;,€òÃõ˜D¿XÐGBˆï¼\ÀCÄ×c×|ñ@¹cœ@ŸÉ2œ@ À…“»ß6;L~¼œA _"µðÍ ˜ÀëÍ'‘áÁÚò]“µä–P5|ÍØPè]r-ñs€#"Xà^ ˆð ç#ˆˆÄhx¦ ßk¿Â@Z÷Šxð«Ç…^»H±>ë3„“° ÍOù ¯ÿ#Àç"pˆF l‰²%â‚„‘aBH·È„Å@ï€ï˜ÐàâOˆÄG>#üçûÆ^sžÈ{ѵ÷å‡.êÜÞ< Ý’ñÀ5\Ä~F7²5Œ#À“Èð¦A'Þ޾eáÁûÜ*¨£Pp¶j⇉ ø8 kð ¯x0øP¡àvï€épð<Àñw @O XOdLOwÈ ˆ X8 â˜ÿ˜ /^"µññáW ¼Ð:D÷€Tx‚ bàC°÷Þ¯‚€10ÄÀ$† ` Gï½] &Ć~°Œ‰…‰¿çƒP*¦'ß eÿõÀä>öƒHâ$(L? ¼T ‘,ƒìx‹ÁÇRùõÖÂx Ø ûâ§"°à…Ì{ªø›¨Þ㯇‰8—‰8—†€üð¼‹|²)ƒãC‰ëv#ßxY À?`«Î©Ó&œ à"pˆGXh°aásα@›Ïdÿxn¥_ÐVÿê ª ½ñ³€q^Gøúõú,Mä3Üó¹;߀ìaÀD,}ç¸èŽ(ƒ|#QFáøçŠP0 À˜òuñ0LhpÚŸÑ ­AJÑ¡Dà8Aƒìðºô³ Á÷Œþö±Ö,^kœA¼D¿<@¼‹,Þ²-àâð°øàuÿõÂOê?ÿµéþƒà ÿßp|; äKÈD`ØÄ[íp½{D‰…€~Eˆ ?¾¡W½#ø#ÿéGø±Àˆ­q¤r0¯~±<(y{ 20.é(AÀ"pˆF×}`>¾ÍOâ…=µX»LŠ€8±úŸíˆ7Þ8)ÅÞúP7 ô0a-}BÏò18±ùï¦Wÿ}Ò—Þ!adbqäõSø°ì1Tû0:û;õò‡ ”ðˆ´óG8:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿù ׄÞ"½?ÈG•ÁƒÿÈ”ÿJ4Ó„"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ!"pÎ""pÎG@°Áàá$¬H„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGA°Áðð HDMVˆÿüüððÿ¸ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG · E~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPàØ„€!Z+¯á_ÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®GºùÃm`Ð7û¡uu×]u×]u×]u×/}ºë®ºë®ºë®ºë®¹ "ºë®ºë®ºë®ºë®ºë®ºäz ®ºë®ºë®ºë®ºåï’×]u×]u×]u×]u×% "ºë®ºë®ºë®ºë®ºë‘ö^‡ïˆ ÂÁƒÿ‽]uÞV†ÿÙ€Ø*·ÿNò ¾½ûëÿ¢O¯NN#Û÷Ë®ºë®ºë®ºë®ºë®X"ºë®Gºë®ºë®ºë®ºëç K o½;ÚïUHðâ.´¯N·×þy³_â€~+«ÝoÝïþœxŠº÷ï—]u×]u×]u×]u×\°"ºë®ºë®ºë®ºë®ºëÇ ÿf™[ô_ž—ÁäK~©éʺëß¾½ûõú¿úäðlÿûù0ÖÄ…mû¹råË—.\¹råË—.\¹rå€"ºë®ºë®ºë®ºë®ºë¥¡kÇë®ú “G­û÷×þÁ£ÿĨ]¾½ùå–yn«?¾ûÜsQk®ºë®ºë®ºë®ºë‘@"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºåâ‡ïß]u﮺÷﮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºä]‡î*Ž]uïÝK—»þGœµ]u×]u×]u×]u×X"ºë®ºë®ºë®¹aûåïß]úpç[÷×ÿ K®ô€üv¿Ùêü#Îþ¼ö·îª÷ïþœñVª÷zè«~ýõï¯}u×]u×]u×]u€"ºë®ºë®ºë®¼Pï~ýªÇ¿­"­û÷ïÒüôäB5_úíÿèÐ[ÿ¦öýòÿÈ| ¢Avùôø­ûÿÓhÛ÷÷ Ð ïVœ@«G®ºë®ºë®ºë®ºÀ"ºë®ºë®ºë®ºåÉÕc…9>ßþµƒ0ÓéïZÒm¸MB5ò÷ïß¿}å…Ûà5·î·ï÷§ö«ÿoß}zß¿GZ]^¯úqíòåË—.\¹råË—#€"ºë®ºë®ºë®¹ƒ÷ï¯\§Iÿ{s¯~úÿÒÉÕu×¾½û÷ï¯~ý÷à_@4 Ûï jÿó[÷﮺뮺뮺뮰"ºë®Gºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®G3 ÿÿÿÿÿÿÿÿºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬GPà„€!Z+ÌŸÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®Gºøymuu×]u×]u×]u×\¿öªR®ºë®ºë®ºë®ºë®X "ºë®ºë®ºë®ºë®ºë®ºðvZ뮺뮺뮺뮺?¢§RZ뮺뮺뮺뮺äà "ºë®ºë®ºë®ºë®ºëË%Àu[ýÙE¨{œD ¾D®¬Ž@‘)Ñç‰@Ú$ãëÖšý0 .—}=|œ@1b/öàÆ Bú‹àÈ1‡Éy·G,Dàòkè‚P7W]wáÀ3¯Å€Î¯ú@Öú뮺뮺뮺뮺å€"ºë®ºë®ºë®ºë®ºëÁå®]é'ê÷ùÅX4ÿýåÒrÀå]øHº®ûåÀ9«×è½>úð]> @€F¬EäzüO#{W|€×DáË«—]u×]u×]u×]u×\°"ºë®ºë®ºë®ºë®ºëÁå¿H[ï5ˆ¸fW¤i‚jGå×?C”G¿à n«Ýo¯|¿ëÛë¼™ÀÒ2DÕ×.ºë®ºë®ºë®ºë®¹`"ºë®ºë®ºë®ºë®ºë¥¥¯ò뾌'×Ùžâ5}v@ «¯}öãéuî[œˆ«®»ìs0ÔZ뮺뮺뮺뮺å0"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®Gºë®ºë®ºë®ºë®ºë®ºåÑë¾…Š<•u×^ 뮿ù*뮺뮺뮺뮺À"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºèõàêºë¯E[åËÝîåË—.\¹råË—.\¹rê€"ºë®ºë®ºë®º=ø÷ ÷ô¿ú$Ž;ü/ÿ W]ú9­ÿñÀ–úë—~zu]{뮽úý\ù9,€¸>ß«®¹]u×]u×]Gu×]uÖ"ºë®ºë®ºë®»:Xð²7«½2¯†öôûe¨Šú—y`8Ã_«¾*€ÈŠG«½>àÒÿF€¾¾Û(‘+ñ­ÿá°å]> 5¹nõOÝV=¿Øy Ùÿ÷ø`-‚Ž·×ýi>¿ ö×^S¬€5kªÿW¥Ë—.\¹råË—.]X"ºë®ºë®ºë®¼kösƒGÿÀ@Õ›oÿ»uvŸ‘u~¸ú¿ GWºÝ×>¬@·ß0ñàx¿ýëÏk¼¼jô¤ÛwçFþõ\ü`Û÷×ü¹‡né5rõÕ]úp ­] G¥®ºë®ºë®ºÀ"ºë®ºë®ºë®º=x7É÷„0WzSȵw§§–kß^ùïЫ®]öÑ:¯ú ¯¸À¾ÔÐ íûåËß.»Ó¨mW]u×]u×]u×]`"ºë®ºë®ºë®ºë®ºë®ºë®ºëG®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºG뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G · E),~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPàX „À 1Z-<Z+è!³<3Ü!Àµj¸DÿøµÿóA€#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".RG”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”G¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"åG)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”G¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"åG)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹GJR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".GR”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥G/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".GR”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹G”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Gå)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆG¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Gå)Hˆ #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"þšœ”È@v¢iX01(ÈÜ0¯Û”ŽÎ¹€€ À1f°*P K)( & à B7c5í€AùÀ5Y@–¥^xÿÔPG€GLÿÄ^ZI…Tãã2Ùf]9<–>þiJRõ.k”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"÷€7¡ &¸ä0ÎÅ“ …–ŽÎ½Ÿ+ßSÏ^¿ö QùPCP A  O}ÚóÀ4(¤”‘¨Ýfë †Ÿ¾oïàÀ €vMÔà vCû–M+ôý¶ÄŸŽÊ2æGÝpàC  8%ÿânEØMÛ”¿bƒµÊR–”Ü¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥) #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".RG”ˆ¹JR"þØBΨ ʰ*óÀ€‡þ !pÏüEè@AùÀ5Y@–¥^xÿÔ Ž™ÿˆ¼‚Á  ñëÀ‡ûù¥)K×¹.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹ê€'0ÄÀ š4÷ݯ„€'0ÄÀ š4÷ݯ0 $GMÒC?_ÂÀ €0pà—ÿ‰¹\¸ÀhGN ø›‘wÀ'HŸ`‚F¹JRÒ›”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥"  #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹G”¥".R”ˆ¹JR"å)H‹— vNèÇåÉ¡¸ðœ¾ùûн ~°9d$¤ œ¢5àA\xøãµôt!%§!§§¶ÙþfÆÿp@ðÒÕŒÖå“YZþx…߀ <²(/ÈðÊý€¨IFa„ÜžP€­Þ€ ˜•‹>Ä-×€- (¤€Dý8{[€€5l‚XÀ`G0hi]¥`ò¿6¹À,ÑÍœ|ƒY,4ò%üŒÐ €•Òѽ9); ´8ýÈûýs/£‚ g&€fàPÖùÅèPÌL-±Ö‰—l!?çÔeXpÁˆa€: †“K@aHÓ¥)í¶(6î‚ó€j², »Ûó·ë?yy²fÃш×WìŸÅûùp`øà &' P°²‰iH ŠGâ Oȶ“ð¸Ð€e˜yD5àä”°½w@@b¬!˜7ëœè´´Ÿÿ%àý®°ÀtN’H/tW4¯öâ»qV˜@:9_‰]d³È—ñðÀ @2bWà:,%ÒL, 5Ëß Gúå_ @4 4†ì„‘…†'|,~ã÷ÊøÝ|U!Ñ ”H&”‚ð§Çu] ;Ð —ŽäëÀÑG·LRœÒŸ¶ÙÿêÛc…õ`@ýPÀ5!– OÀP3Œ ø?ì½Ö$±½c­ „ÎMK`ÿIižüÐð@üÀ €L””XSGÅ'ÿ{þ'#áwcá5`!‡WÜ,ÌN½ø`adÒÐPbZSÙFéOüͲýåH@€À I¥ àP0˜ùòI¥d…oØ=¯<ð ‚Bÿb-ÐKç¯Ã€6Ö|í83þ¢oG8¢k O‚÷n)Æ~f€ Ç€è†LÚKÛ%Ê@gCp†£“¯¨€=Tü—À`:,3~ؼÉ+ðGÿÒ¿CŠÿ{pÀbC:P’i JŠÉIãvüÖPÀgï» s‘dtìÆßÇ€€hÄ`Ä"`Б.€Ì†À* O'^rúÀ È!ÿP$8iù?ºÀbLA1,ÖA‰éË¿FÔ”@;À:!†Gí)åbÜ1t7ÿðÔwPéÀë€dÜ8DÀÀ”ž„¤hj26B:{üžv{P@üCþ´8 K½r IN1=¾íÙ÷WÝŒøýs˜0°ÍÖÿµI59>þNô?4'†B’ãú>(˜àÿ¿Ñð»®P ~n‚Q¹<0zÀ€€ @“C ˜ Ä­“KÁƒpý¸OøÆãëÀ€9dGPˆ`Ç`2RPS‹ÿ@¡»=žÐÊWâúÈó᥈¿—2+À%t“`Š¡­“ØñŸ>IUÁ¿D–L-”ž„£ä¡;·ßõ𠀂ö€>€1à9NÿúŽÜ,ðû¨`:ÄÀ”F² éW¾eì`ù`€¡44˜’zC I_äÑþìäÝÙW¾üìÿÄ ÿ0KÿÄÌÄÄzF™Ôô3_ÇGÀ.+ÀðPp(:1i!ä ’ìà Kœqã®øAñ@tž€À²À%,°1¸¼Œ„ö3ßI(á¬B(–’Zs!øÒÎÌŒzVØÕÞ\˜n¤šKä ÀÇÏŠ &•‹ ß°„ýr€Šîž£7ö d¿•|P(‡ºv!€eöM~JμXÀ nL 0 %³ GQe~bP`“¹žûXðÀ€4 ÄÀG’LOÎ…ä¡8‰GèâÛ¨Ù= l©0 •ûnÅ ÂÊä”r î¹–`Ä¡ÊW1»é š×¥'d£º·Ü~ëÞ—§Õs[ZÒ”ä!þŸÛmÿ¯`ˆ ~XÀ0O( X ÓGÅßñ9 ½H ~¸À1¥€˜„_À:&$g`Dÿ²Ñ×øônHÇz (¢ ÃPL!M JQHéOלBøif˜A·,G›ÎEø0Aü ×0C¯¸X"\° ò@0ÚrvL ‡ü’øš„ýœ z”€'å àP1NC& '' /Þ„À!xM° ÈE‹3')"МèNõ˜ð’¬Î+¬X/«ø`iD2ZJNt%% ùR_b$FX` ˜MOà&&ö-àÏÔP9€û…µñΫ¼ ¹ Üë‹%áwÖGN`*ˆ#€A4iï»_ N`*ˆ#€A4iï»\@á"mˆgëøXp!€ÐŽœÿñ7"ë€ `à Á/ÿr.òéìH×)JZSr”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤D#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JGR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"åÐj¨˜€ìÐÀÏÐàO©?®}éÁô?¬idÇPEj0ÒчýR{ob,´–”–ŸÒ”þŸùÿþÿß&4TL ô†VH!¸ƒp!€(fPÜ9)ZÀ›ëwçÀ ›>Ë àÀ(À’ˆ¼À—Ê+lj®’fxÒG”óâ5÷BvNù¾ëßs>óÒõ_Ü·×x¨ 6Ô TL‚`ÊÀ(’ü`8ã\ŠRI/–¿_ÛAùÀ5Y@–…XÁ €2(P!œ7d”’G;ô)ýí€ ‡üà€¬ KB¯> üÀCÁ¿ð«Éý€£€ 1êË,>þ\Xj>ì%!  €BL/ ¡% Qea¨á{\ËP †`;Gp {Õ)<—„Üß*ÿ@ß)/– €ÊƒRÄ{í·Å t²h%ÿï¼Ð€L®‚a&ñ)Àà @®ì”|Ž8´„ Ÿõ÷n»ã€ú 2C` IŽ â+_c˜X ~?Ȇ}ü€Ðp`@ ðÔn@w¸ÿ,0˜p@îYÿ&Ãï!ÃS͵€\À@ 2:Œ ‹=ÜC/¤¿bVÛkbG`` É…ˆe`ÐÀÜ1(J÷ÄÞû¨Ðœ°$0?èGr¿4¤­ì®/_¾®ŒÀƒý¤ÎoN ?ú[\àÉc ú²SÛõpGpÛäÞúÈ Ð!ÿWp ¾Mæ˜pˆ![É?ë@#€@`Ô»°`’€70/9I ܼ<¢‚Sƒö÷?$ÿ­Ž€Rë p!) Ž(† ` ›®ÀGSqȵHCïãE–fVÊÛ…Z@vRb ¤ Ü4 Ò’RpýõZOós¸‹ÕÆ»›r²¯ôAh%%(ç£ýýòp@¢ú@ÑÀðÓðÊAú Áþ`ÿe€ }ó@ÀC‚?üàK=y`1Y3‡]A€9¿}øÈ!ÿˆ ÿ0KÿÄß¾üäÿÄPGÿ‚%ÿân€ H‹2Úüp ð…@3 '/n|±GNaa½·FMò䆧óï~˜@ñ剨6ð– !O?¤™‚/Ò‚è°ÀS󤄒ƒJã‚và}šø€H!€¸ Ž„]}¾åÓ¸gíHgßÀ€@`žh‰˜(­ˆ–€à!à:9 “ƒ:Ç$°„p¿T°ÀXGr®¸ ~{‚ ØRcˆ%â-ØÎXRE±à8¿±ß6,v pœG4†²ä°ÿ(3p‚Ÿt-†öë|ç_I¹¥,nM)”ø2Ð’„ >„îwßßs>¼¢Ñ’†ýµÕ»{ùÓ]Áüð$€(л@@€&bpi0ì®M+rÀ¢@lC|^1À²Næ_@b $x$€PР €èE Á$€¨&€Ѐ#¾-!xgÃ3_RøX€ x  €@ûG§=Ã?Bö÷Ø@‚( ^ A4@€À’vL&‹Ä0Ö(šRJHÎ1c·gy€…¸aŠðBRopCP A  O}ÚøHpCP A  O}Ú`á"dC?_ÂÀ €0pà—ÿ©¹\¸ÀhGN ú›‘wÀ'HŸ`‚F¹JRÒ›”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹GJR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥" #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"åÕN§¼Ð ÈHΞPÔaé(%?ë• J8Äî;¼þ}£/Ž‚€5(ðÅë§ZlJè5!€y8V$GqÌ.õ ú€…€˜šX 0GH ý$Ôl` _?¨‰=Ìê½ bC50(ÀÔ”uÜ?u{É/ !ŠàsÝhpÄßçº_T€øÀ”‰ P ~øi_‰Ûômo~¤ìò¸fåè¤æN&o’œ;—ÿøMvà ®Êö¢þ^` P0 @¨ ˆ@\ù–^ábVÆñê¹—ÑÁþÀ3p(Gk|âÐ †bac0ªJHÜ÷öÀCþp @VP%€!Wž@?õ#€8&ê/BBΨ ʰ*óÀ€‡þ !pÏýEç¤À .Œ8¿šZÀ10 Ø#€0hÓÙ-`‚€ìÀ4iïUœ'\¼ï /‹èdÐKÿß}¦ø° p!€à€VM¿ý÷–CPû¨˜I¼€ÀAÀ3Gl3¤ ѱý%r^Áÿ_t¿:këàúà pRb?€OJ>Ê /¯†qÃÐ)F[€h³£‰Öd4~°É@€<(…Ò_ôlƒy@$NÁ¾¼ÅúÀ! PCÐjI¨98ñßswUãÉ€ø ¡ ('¹e8œÿ4ˆ`&JRå2Ì™DݲïåéJ GJ~ÛoÿêÛc}÷ p¤2@Gf(0À ‡÷áõ À À€5G -(&9á„ÍöH ÿýspýdrcôž;T5Züx Ð!ÿWp ¾Kï­õpGpÛä¾éÌ8E™0ëúà ~H!ÿZ¥ÎlÌLp!‚X&@@üCþ´8 KœØÿ˜˜àC°MÈ€CŒàDµOü¿sâgáωGœG½snKýCÿ‚#ÿØh×ß/<0ˆ#ÿÈ&¾ Cÿ‚#ÿØh×ß/<0ˆ#ÿÈ&¼€‚pë¬07ã/¿9?ñ#ÿÁ ÿñ7Ào¿9?ñ#ÿÁ ÿñ7@–#YÌ¿‚ €^ÿøB#x[Ý €^ÿøB#x[p‚ýðPL$kî‚ €jàE×ÛïˆG‚ €jàE×Ûî@ €p‘-Hgëø( C` Ê´€›€jÐ!›:@Á/l៶ÍgT`,€#€9W:í/Œ&þ9$[×ú.ø¨ h<¨`ÂfH &À`´sÆ?å' e ×ЀÀÐ<41€À†ž’“²ŠüðÎ9€ðü#ÝÀ /ˆÂ!€À7†”¥äáÉÝ_ ÷˜ŒCÅë§d®ÿG=€Z‘õÀ;Å !C&—Š(¤~ŸÀf;}@ @ü@ r 0ÒR÷-'ä{Ð5FˆÄ2ò7|L à Ü_éâv ÄÞžØM&¡•~(@@ü T´œ„0…ÓÀÁaÒR %£ð‘ÿ£¨w¼@Ô„ˆf&Bj ¥s’ŽáÜÝÅußulØ @bP€¢õ¥ x1–žfÄó²ï†€hpp` ˆX G3-&–žIOøQÒ8`a[3î:ŸïhPCP A  O}ÚøHPCP A  O}ÚÈ $Md3õü,¸ÀhGN ú›‘uÀ €0pà—ÿ©¹y t‰ö$k”¥-)¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"#óô¥G/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹™óß^´è ¨À SÃ@`_Ⱦ~B dÏÅú:D–ï'K2‰© êõ%'ßÔCA£òPÐ7ÃQÃ÷&6 õ :BÍ<¿à 0& ÒQ,š®€Ì ó7ôs€†GŠ´±Õdˆ Å€¢CCCCvņ—Ïc23#gÅܺRé,¾_e‘‘~Äè ¢€jC?¼ÀýÉ@ıŒŒ‚Hhs‡kœ‘‰¤0Üð†˜À0Á;»€Ü·:óô³? 1ÔÌv¨ !Þåi ˜Y041ÆÊJ†æv|õT·sh¿ÁûA(;ýïØÖ``14²WO%’‰N7G¹ ila¥ˆhË- úƒ«Á›w×& ¡‰&J@hay’Rs便®íK_º¼ô„CO,€Xç{¤¬ 79{ Bx»° ~ÌkZ“0“XÀÉ×Ë`ü}Ì€†ìÊöœ˜~ÄÀ Ѐ N Ćvœ¼L+r‰›€÷¸ÒðX~©Z\PЀà p J(3` ÈÅÌC+0¦Uåi>×w ‘~G˜@ bœôÔ°,’‰@‚I£@-,yŸJZ††¤›Ý4¡_©ZY€€Ÿï€j|Áˆ(`@d‘ÿw¹CÎj,/@À J˜cZ @ÀaÆ£âH¥œã¯-J0Ãr:™ŽÓýîzR–ô_¼,0ÒÃ@# iJXéÙû³€ëÌ€&U€ÀšBÀ;?%’Æ€0Êf`2[…ÜšX$aG©@ÏÔ^+n÷/rAPp*C!𤠆–0ñØ–ŸÙÀó³žÚðÔ¬0š’cŒ6IFI÷ÙH‰‰€T¬ð RWpƒ7oü-ÝÅ\jRe—Ã{óå°Ì×´è@0À`@lt %Œ1gŒ‡ ×±D@"ÿh%X'½àifK&fG©%dŸw€€ @bÀÈ…b‰c cYÒÂÔR–Éý=ýG;5¹4˜LØbHD2^d”œûàs/lˆ ð!¥%€d âarѸ ÝÆì% âï K0ÂdüҌ›ú˜ ø7`€eðð†°%€3“®p‹¸@3 ÈÇ  !)üVHn+a#8‹çèþÀj*ÐÄ]à` "€ &`ÄrJO,¾<´ŸÈØÍR})u$¾_ì¶Úõf`PPÀÀ¡‰ %°ÑGƒs;>vúö˜‹ý ”@þ÷¥„2ÉŠG©%dŸz@.Ó<È ƒ€ÜÄtƆº$ K?Ù©JÒ‘½ù´ìÚå)J¥r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤D#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".RG”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JGR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹J[@1z`DÀ€Ä›ƒÕéO„gü8ãe·ý¶y»^*]Ð € À; ±0›ðo$ŽWHG ¿WâÅ\(JŽß|&7Þúà À€€p €ÀÈ#F‘’Hguá÷@ú@NC !VK&§‡ Û?ퟻ øG` ô € {€‡ý`?ü u‹& îíͶHjrZþIK$ù®û”¥"W)JD\¥)gªõœ?,¦ì_ð 7ÿo'Îâ=ú ²JDû$Fu5¨i} ÆßÁ€9€ @G§ :%’²y@_ ï¶ç?sï\p`,ÿðXÑ‘¶&£_ØÊßor”¥­7)JD_\¸°.°ø¤hÂR2I î¼>èÀ?HÀ Èa„ À ÉdÔâá›gý—ÆÝÐ@ü#€0úÀ½`CþÀ þ·`Š,˜7»·4uºCS’×ðšJY'ÍwØÜ¥)¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥G".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ€#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹}d?%$Ð —%b@cÝ߀FáWÉ®ˆG°À/&`À¡.€•Æ”ç·ûï¹»ï¬tƒ hºþî’Ê,¤† ÅäÆî¦c\ëó¾É¤‘ˆq,»Ð€:.là†€¹4a¥w(ý¢¾99Ftãük^q{ÖçÜ·)JNW)JD\¥)gÄ{ôAd”‰ä{ó¿;ˆ÷è‚É)È÷žŇn€*`}üàÀ\4ÿà°¢/#zà@€CpÐGÿ‚Àˆ¼Ò° Ò&È0‘®R”·¢å)H‹ú ~ÀGý`ÞÈ0!ÿXÿ€]xÐ@ü#€0úÀ½`Cþ° þºò !€>Èþë,7GðrÉ>iK$ù¯[ŸrÜ¥)9\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD@#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".EðýD¯qýY%"}Π®ÌÆ9ZY)”ï¥ëÁ0!¨ooø,h‹GÈZ†”Ð{RŽùîÃõëAòÁ #þC…ß]¹È@0¹CF°s‘k,š3³ïó¥"ŒÅ¤¯Bª`4pH@Kÿ´](iyj?lâ¯Ï>¡~‹¸€€%`P„¼˜ …‚¿bÆf_î8íqð ;æ-Ç©ˆ¶ Š¿‘€-pLHÂÀ3†ù_ܯð–ê²è :>p(C&ö?†‚ØHÏÚýGTB!“@tƒI…¤0´’¿GÁúž†eÜDÀ-ã¯óÍ/R@• HI !°ù a¿( £œ[ÌK(Óo-w–W)=Ë Æç¹JÂi4 (XhjqEºRžvÚúØp@ýp€=-$À% PG6ìXn_Ën·aïfB!$‡Ô¬o™eä_ËÀ¨p €aú  !ÐbqèI4¬ÉÒ€èè@!ã  À¡5 H Ôt€E»“¯G¿S)yW ’“ÜE°¢¯ó¤_ר€`F@€d~*Pi3 07÷ )&?ëJ¯^¢´eûºXrÉú\‡‡_çH¾v ³,ÈÀ‹ïbØ †^”‚h¢öà#F`[”BÉ&’ºXöìä[>[!Úþlúè €BXÀ'!ì£É…ä°üjóàûàd"@1&Ã;”M)£ŠNyP)ÈL·ÜSfQdG±W])}? Ù(0˜]e€RMV$ ?¿øV´&riy.”¤f{ð‡è_¡@` ÐàfrÉ¥ ¤aiì>ø€:1‡·àM }<_ë²!LBØ%ÜÆb/¨ ÒYŒy« ¤0À(‚Y4²ƒIiÈFOÚô` ¥. ÁŒX Cs£r@f•#Àx€»ë@!Ì`†òhÉ¥“Kæ§œ+c¶¶Ò!G™!¹ÿ‰þ &äv>þ$?ÊØhÀ08#ÿÑLìO¹Å”MF,¤ ´s’“¸•~ˆ°>r dÔ”ÐyEŠJ:¹b žâí1 ~¿‚>GÃï¸'n€ 1(x®ÀlR AøjÆqÜǹ €™À†8‘«à|WOJövb+Ó‰¯Ù‰÷ò»KϾŠ„p‘ÿ@˜wI00åä;9¶iHÌ÷óÇGоì›8p þ·ÁÓ›ú¨³å»Šb/¨¢Én¦¿£àœ€$Ð&%ì€õ€`ÿðLÞ4?à #þ0/dÿ¬Gÿ‚`ÖóÀ !€FÈþܰ ¯àÅ’|òIõŸíŸ«cÞõ¹÷-‹`À€dnÀT P™À‘a¥!!_¹:ú(ˆ ~¡4e–  á„ÌèI5 ,4\ô s/“¯sÿýÿGÇÜa€tçO(ÛTÛ©wðP(Ôð SL‹O9šPÞ!ü*çߢï.ÀŒà#@*”P$¤ gîXcæÜ¤ó0ý‡5! 1!.+ÏÇëøëáú访ï‚ €cpFÿ Ò=dÐÙF¸¦b-(&ìÄûòÜî#ߢ $¤O#ßùÜG¿DIHžG³À¡ÄZÀ©÷ò0@€C`ÐGÿ‚Àˆ¼ÐÀ5€G ¶àT ˆNp AN oÏ}t’€É 0ÂidÔ–’nJGÛ1Ya=çz"i44†_,4´†¥=úSÿÿ‹þ„€›†–”þÙÌž&ŒFÌ÷ð À  ¼a@€›÷m€nVüCü÷4ûô]Äd„0à0_,„á Q=ÊøÖ<•Åà÷´,&Á ôâý¥´ðàPÈ Ø¹$¤ãМ?ÛÝ÷ݽý?Gà #þ0ïdÿ¬Gÿ€À®¼h ~ÀGý`ÞÈ !ÿXÿ€]y PÀäu›ø9dŸ4¥’}  PÀ !“SŠ(1)ü͈£±¾õ¾~×-Ón  À.‡è&€„A‰Ç¡$Ò²@"w'_UVB)Ha1)€:;ŽÉ/ N=À–ã0»Ô\Eeþt¥…k^CZ³ßÁI€ ÀþÅjGþv¹OÿÞç_¢î ÀŒ‚øi Â@¡|#ãF;’¸¼¼‹ÉA óÄ5¯_Äil¸Ðì…Ü¢ñÜôsP‘{Øîï¾íì¹JRqr”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤D#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"åG)H‹”¥",ó¸~ˆ,’‘<~wçqýY%"yóÀ08°â-ÐL¿’ †‚?ü4Eäo\p`.ÿðXÑ‘º@bö‘6a„~¸?,ÀX?ä0h]õÛä@ù`†À‘ÿ!€Bï®Ü‡ûbhB¯ó˜(H#^ˆ?TÀh €—ÿe^t¤¯Dª`4H@Kÿ²¯@ Cÿ¤G¯ìŽ"þÕ|¼ĸ ~bªCSÀ,(7 )Ga½]?»>홯¨_`V hr0"€I3ñ<­ù>ó€N_(¥nLCûÈMÀU Ð `ZnB V¡9zû( Àøa ÀlV ß¿FïºÖNìëf¾-}0?ü€ƒ‚0§$Ý@ O-¿}ìɨÙ}@ò!-Ö0›‹ HŽWIGøÏ>û€0!ÿ@@ÿ`/|9'ùg‚pˆ!ïè`ùRQD ÿð ɬn€½ÿÂ/¢@(iD"b9e†§!ÆÿÕyð@ý Þ´kR0b0¦ C“ÞÂtMbKN0!ZWúFO¹IŒL›€ñíR]øP€@À©00 ;ûrË FIHムK£lþî1 @ €v‚Q4@dG”#ìøNõ ïæ½$Ëéw÷>+1×õ€@ýpd4`€™ø HÎß’fsú9Ÿ¯ïg|y ;t¨bsà ‹NYX–‚~×Þ¯8Þ…Ÿ•t gUü,°ÀdGR/±€^‘@@@C1gQöàI'¡!É`ë``!€Ð@Ž„_r/D›ÆSÇ'Üû:0‹ý HE€èšY07 ,1)BpîŽÞù À° À`G‘|$ pÁa‰ëÀ"I]P@ü€6¡€•‚¨ cQ•ÀF‚~÷ª\ý 1€;Ç!,^•' Rð½¯5;ì„â‰÷Fä¤ßÂɤ҈A…†—Æ ¤t§ŽÈÏï¼9̰ ÀvDÿÄÿ°äe!Ùµó€@üÐè!d¢b_€…“þàˆÙ`öaúˆ!²ha03 ,58¤aý=µ¨„¤rù¤mI5/ö¿GxØ–M&€? Á' !9¡¿¤HìïžœhÑ0šC,RKâ¿ œ ŠlG '2úÒþ÷`?\7†,;véÅ ,5N{¤5 ö1ö³FŽ"þ˜C@1‰4 †÷HjzDØVÊÚòà€@ØzR°@ ‰›)$Ô-ÌFÿ,Í{+à  ˆH0 ™ÈEÀV^’¸@vbG”£-ŠÃzï0À&(”BÐ#f0+þ¿÷ÿ‹ÿÝ`@€†$ LX “ŠGãƒJC!;›Øh»ƒKÓÄ2ÑÝýÏÊGÇ_è@€Àšh& aa‰èN€iy@PCþpÀGRi ? 0Ø`n<†”€­(#m^lÐà M#^_I,…Ò=NÌ[ ¿sá€$Ð&ó®}ôGP@ü#€0úÀ½ý`ò7¹É¤‹ö@ úÀ0ø ëàåŸï¼$?ëÀÿà0k¯ƒ–±ÄôVB6þŒ‚p‘ÿ@˜—²HÖ€#ÿÀ`×^4?à #þ0/dÿ¬Gÿ€À®¹À !€>Èþа ¯àå’}ìó€¤@  ÿÑþ01 47Ø^{Æ–I÷Õñƒ~G u YBùiXS]À:@Ò»ÞÅ_¶Û§í·ÿ«lo¾>ˆ¸Š!€^L@Àv^Éá¡„Çà Hÿß¾‚R¤Äh…¾XyHéÀí|D7ºnP“yLŒm©0§]ÜX 0 A(° `’€—!|2ú( ~¸ IÄÄ€fr:öBñ[ð•ÿqƒÐ¶?*ù¼Á¡ˆ¡…“ ZJIIœÞë&GRÊIê7X¤­õþ‰¾:h`3þƒH÷×ÃPJ-(þ ÷È  p#ÿÐià8!€(U¹0“~_Ä{ôAd”‰ä{ó¿;ˆ÷è‚É)Èöà”8‹H0>ø € @€Ÿ”ü0„É!†ãöç! Kv3/ß0 À Å@E”²±a©ËNé'µß6! „¸ âH!†§ðrVÂyjÀNR4fíµ!…f{Gé?LØÈg@h  ø šLBQǺ6…%õöp`` BX «²‹ÇW98Š;ªø5ïÁðÀ¢90Tä–øýöNÁË ˆi‘ûïÒ³=÷A €¤ð“ø €NÆ`Ü´$<¯‘ß @0 ä €è7+”C HQzüø“à4lÇÌ…ß{ú0 ~ÀGý`ÞÄ !ÿXÿ€]xà@ü#G€0úÀ½ˆ@Cþ° þºæ€†øG#ûBÀs,“ï£ã€?J,É·À7 cWñH'ð‹ç%’}ö€@ý ÞXЭHÁˆÂ˜1W»L¤Ñûod ¾è €`¨&虜²ix¤ æñXþ*ø˜€€ ‰ˆÜ ĆؖC&•‹ !/ŠÃ™cýöð(I 0 A4„Y0´8ÂÊOBsæíó|¥XGù@ðDÿ A'þC@74¢Ë$$e¹]ü÷ñ@€4py\¢€Q`%(¤…âÊÙ$ö}œ8$€,̰~K)E†pÒ¹Î/ÅêÀAþPà‹þ !Ÿù ÚÀb¨ @5û€ì†M½· -%ý‡nŸÕQ040’‘¸t‹JvkñÀ€ ò`C@4OÀU(ÃJ%â5òëî …ðÀ pFÿ¬€Ý[áG‰?Ý€¡‹Ü~²!u[R”»,nR”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ€#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".3¨}ú 71iÈ÷çm}Ð |ìdΆG/–;†'º>WpaÖœ"Ü ™=:/$±  Gi'”W¼uöP@xP/rR{bò+ã‹ØÑß)ð‹çƒû D°r˜pÀÑ †“­bL, ÿ‘þã³Òœ0ûéä—Ф”NAwÖ¶~ØÕ^dœ^C)Ì”BŒ®Zyåüb¶Ûu…Ý€üØ HCà2‚ËWt¸r„ýqDpÂ`JöÁ¼joá?6@ F½ ~¨!€Ð Á /þʼÙGgÞ?TÀhà€—ÿe^bÈh^#ÜéÇj¿?€:0ÈÀ ˜ `¯Ðçð@† 8,õĘ&Ø„¼—ÒÁðÁþ€4p,k|ÒúX ~!ÿÐ€Ž…€ n ýaÈšH¿HLÎ#ÿØËßIþû€0!ÿ8@ÿ`/|='û É(YïdÏ!r`òjL (0´ Ä­G¸;Õ‚0f„'¶¡…“35' >òÀù` p©1–­Ð±ü™û¸$'̾¨Qi J +ô%%+ï—¾®rcHL)­]þuçÆöÀ ó@LCP<¢ÛpÑŸ†,!ú8÷Ì.ãÀÀ7€„¢Å’ZxRפ’jÃ8v¹ñhcõçJt€ÀKOg&$3 Hn˜-ïºÞhGļ4ih(¤pÀwA\’ž)l§Œ½-æ€À™É…,ÿt¤o¿…€ €`à E÷"ë€ dà ˆþä^™ t‰÷1DŒ"÷9¹@2!€™'–€-À‘yhágŠ{ïA¡‰!Â÷BJOBw3îß_ï©‚å8> 5+1@1ˉ¨Ë7ÞåÐ5¿(yÖ¤4~Ȇ²hÉ@d¾X)…8)# ׆G;lh C@/ ÀXAŽi59|HàÞð˜Y ²ƒ ÃRZr±ÿ§¶ÁwÀ@\P@ € ÎR¿€ùiZxY®`†’Šaöˆï"{ûºNBàTp¨F‚ÃZ?ƒ{‡1aˆ&¡!…çAhå'Bs|z…$bw÷¹SŸ}¢o†!`¢QÖ‰‰ÀŽâYï°€3xØRhƒwîR@%+’G„஫œ`b 5(èá : ø †n½À%)Ôãñ·”J´0 NºŠI)+¿‹Òï @ÊrQ@< É)8S|°çºà Aó@4‰(.~Mù±c> + Û§ã6Ì.ôñ7öÃõÍËÌ}úp@ü°  €9ÁˆîQ1œôð¡­ÄLlÐP#€)4z ÐÒÈe¤²ÓÒ’ÿJS×ÿëÿÞTØÿ  GRiò’G‚Q  r.­Ü½ÅßÈ9÷ÑAðŽÀ?èù×>ú( ~ÀGý`^ˆ þ°yç&€ãß²HÖ€#ÿÀ`×_,ÿ}à !ÿXÿ€]|³ýˆ'¢²ÞþŒ‚p‘ÿ@˜—²HÖ€#ÿÀ`×^4?à #þ0/dÿ¬Gÿ€À®¹À !€>Èþа ¯àå’}õ0@üB@ G0&°A`Pc€õ¥Éß_,,“ïL®Ñ @~¤0~VÇ¥%F›‹×p’J&áj ¹Ãs•L*:4fj{ ’’8;”üGKßçߣ¾l˜?8™‰…@ý(IXb®Ý9;vtîÝ͹BBIl”-¶&²½üö¼ ;@¡4 —ÙÂ’_v:ê–N¸¤ à“8¤d¥ d~N½ðhGn€Àd†éÝ=*,›ñÏ·R1û×îÂ`,´çGØ×Íb’öǽúòÒ5)ãÿá~øø  !€Îú #ßb¾:h`3þƒH÷ Á CõÐL$ß—çqýY%"}ùßÄ{ôAd”‰ä{` JE  ™%7:` ’ „Ô¾4aa;‡÷Á׾츘\C&îú‹@á_îeòÀê€29[Gð*RM(›º>Ü®íb Åôíþã© /3_œ¾ˆˆt0 €a¸K¤šœ;3¸À‚è€81\ÂÀÃ@ò ß!Àz_Û0 ŸßUÄ2ð–²F–_~;c‡m•©0NI-9˜ç6 ¥æl»PD.° @LLÙù`T3 ÎN¿?{¾¢rÉ Té¼5À:|ùÉ&§2‡ŒGX¿¯˜~þ3-þà…G•EÂ8Hÿ L;Ø€$?ëÀÿà0k¯„p‘ÿ@˜w±HÖ€#ÿÀ`×\ÀPÀäjXoá’}öP@ýg ^CìØ5… XÛ€C½ñ’É>÷€ù@ ’°fŽ”@,M`EOß$Bû€®ì1c «5VÜè¿d@ €Bܘ3&Ü0š‚ѱ,²˜¶»†%ϙ;\ V\G  _òpMÿ«íÁ©&‚ÊOBJù(N?}ß|"ùH`@üà €b„jÂÛ'üž_º7ã’Ì?Ü 1ÄÜܧcv¶ wkã‚€(Wü€œêؘ€@ ˜4 &ÁˆJq[ð*¾+:¨`úà tWHî&ür ˆIiâ;d`ÿ¯¨)VCZ²Zq(0¥HÃøôóxu© PÞÒŒAG|¤e7¿”€‚90 &‚?Gņ”°*Z/|ä4£‡ïq?}hȘü†›èšX`Š Ù¡Ÿœ –“>^Ïï’óíÀc’„·HÒ%Ÿ|¬ÖiJ]6w)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD@#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥"G.R”ˆ¹JR"å)H‹”¥".]   p)Ÿ‰€T0À†ÎÀ„›Êá{¯\ZRQ|®øùý“›ßÜÀ€"vá?P3M+ÉŸ%¡ö–â®ÅùÁ©A°%¡Ü”Sœ-®f¥ ‹~Bïï ;n€tÞŽŸøœJ&l?––@v~*ù@@P ¯@b€RMfÛHQ¹/õû„’yµß½±4ü5GYZ„2.]Ðr4` bB ,šZ@ÃŽZ{£©ßõ\(n×IIÇ}ìþ}õýà@p˜"€ˆà’@T@øˆÅ$0à - @&d¡;äïŠÏ¾ëßX€n‘óþ÷9 `7Û3VPa*Íô@üÀ €5Ô†n ì ä'~L&ÜiÜ”Ž×Ï¥Bzµ&€Ù#Yé-s_Ø ;€ @4 &€`¨aHG t–X‰¨B3uô¤­µñôŸåäÔúÊd0 ~ìÓ(¡—ß}¾êû¯}Ïß}( ¡7% TÖ%u¤NÊI@§bïœC«&ÒLê8tVMþ† :!€À¾Q ˜L/àÔ$¤…'oÀ €„²P!Òƒ I|)߀oþo·Ãºáˆ}‘¶Ã²®0\Ä‚}¨‚ïê€:6Ø`;ˆr@-ÄÄð(b`G/–a,c‡‡̽H €à0E Á$€¨&€ðn_ò€Ý5à úß<¹]ö@   ¥Z%Ž„£¹Ý o®\?é>7bR5?±ÙµË¤¼æjq ᡜpj dŽ+û›HBF}ÇGϯéÀ€à 940ÐÐÈ¡àDÿ®£@$Ëõòô÷ïXL(0…‹Á…b‰e¤5,ËOt§‹òÙÉ 7KÔRkG”¥-辸Ð:R A¼ JpöZ'ôqÆ}`Ø`ÉH ÀtZJÀ‰ÿDÍË&|;´iu›e~èÄÄä´€ÄðÄ—á :üfOú·àK¶卵@€d’PÀ¡4„‘Á¥%!òð½~|ݪñ ,ÇÜA€!èÌœöÉ!:ò¯ôa0˜KÅ ,5<䎔ñûÃ07‰ ®@/É…d%(!`CGÿ ÞÊß,•œÀ˜Úù^&ŒÌ#1~_ô¤7;4ñ}ýç€&jý€bÀŽ T@ù` h ¨`À*L&‹¹|”M)%%¿¯‡{ýQI NAHéO;#ø¯°Ì ҀС ëp3†ËÊ+çÀ+KaÏ|…Ñ„„!6Ó¤5)6E€f ŒÑˆCî h ЊÁ„ÀÌÈF#óçÿ×ü)K¿ÿûûšýØ ~P@!×d| *FZ4ÄÂÃF9)œ”ŽÎeGê@.rLv¡a fQH¡)HˆhB6Iÿò¶ØMñ”' éy5>å(ä ÂPÁöœ1ÒïlY'ÌÛî„ì”'|×¾çï‡}J]N·²¿¤€)5&¡) ° ëà:ü%Å~¢Ð;~4ÅÞì €À €˜²P!HIA¥$®¯Ï[üuP½›¯ ¸ƒ5û2sÛ¤„çv¿Ñè)%öBž;où:òÀ €=NHhb@@GB44†Ž„ü( 씊ý.øÊ ¤¬ÈÙvÛ¦HjRm ÍA£‡ûÔ€0hÀÈŒ´§’KI¥§›ù8쪚RïJz{ûšå)J¥r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤D#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹G”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HˆG#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹G”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Gå)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆG¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥"G.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆG¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥"G.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HG‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JRG"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”Gˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JRG"å)H‹”¥".R”ˆ¹JR"å)Hˆ!#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”Gˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ"#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥G:Aÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HˆGPà„€!Z-Aÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®Gºñ°Ý]u×]u×]u×]u×A}…ÿK—.\¹råË—.\¹råË– "ºë®ºë®ºë®ºë®ºë®ºè7®ºë®ºë®ºë®ºåïß]u×]u×]u×]u×\° "ºë®ºë®ºë®ºë®ºëÔÓÈXÞØnýÿÒþA¿àçM·ÿÀoÿõ[÷ïßÿÌ}¿ýz>U¿~ýÿðÀúß¾ºë®ºë®ºë®ºë®¹`"ºG뮺뮺뮺뮺ëÇ ÿ`÷ÿït»Åz;åë7ÿOíû½ÖýûÀÎýú½ôàtO·ïþŸÛå×]u×]u×]u×]u×,"ºë®ºë®ºë®ºë®ºëÇ ß¿ºOȶý_í>·ï×ê÷ïß¿_«ß¾^ýõ×]u×]u×]u×]uË"ºë®ºë®ºë®ºë®ºë¯7~ýû÷ïß¿~ýû÷ïß$ó^ýûõ'¿~ýû÷ïß¿~Gýû÷ïß¾V"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºñYìe¿}u׿|º÷﮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºñC÷þký¹K®½^úë×ï—]u×]u×]u×]uÖ"ºë®ºë®ºë®¼PýûÿG¥Ôâ­ûÿà2ÿø E[÷ÿÀÛ~ýû÷ÿJ@eoß¿}@Îàg~ý¯¤@ã[÷ïÜ î·Ë—]u×]u×]u×X"ºë®ºë®ºë®ºäZýyëý¿û€Úß¿ý0‘Ì ØÚÝ~Ó‘Toß¿~ÿZñáöýúýû÷ïß¿~ýû÷﮺뮺뮺뮰"ºë®ºë®ºë®¼Pýû÷ïÕï×ïß¿~üËÈýû÷ïþŸGmû÷ï¯þƒÏÿû~ýû÷ÿÐwÿþe¿|¹råË—.\¹råÈà"ºë®ºë®ºë®¹aÿì@e¶¶žýóìÄ[~ýû÷׿ú€Úß¿~ýû÷ïß¿~ýû÷ï—]u×]u×]u×X"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºG뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG5Rÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G · E7<~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPà©„€!Z- a_ÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®GºëÁ宺뮺뮺뮺è}‹¾ºë®ºë®ºë®ºë®¹` "ºë®ºë®ºë®ºë®ºë®ºë¢×]u×]u×]u×]uàÿ}u×]u×]u×]u×]rÀ "ºë®ºë®ºë®ºë®ºë¯—ô¹ºßý /ä~ýû÷ïß¿úoÿöüæ«ü¿ÿŠ·ï®ºë®ºë®ºë®ºë®X"ºë®ºë®ºë®ºë®ºëÁåÿ`íÿîeG}‘â9Ÿ[ÿ§æßÒ(N·¤ä_¬P;€ ¿~ýþ¬‡|‹o×[÷ïß¿|ºë®ºë®ºë®ºë®ºå€"ºë®ºë®ºë®ºë®ºëÁåß¿ºOÍ~·ê÷{÷ë÷ïß¾½/_ÿ ;ôà>2ß¾ºë®ºë®ºë®ºë®¹`"ºë®ºë®ºë®ºë®ºë¯—~ýû÷ïß¿~ú÷ïß¾^ýû÷﮺뮺뮺뮺ë®XG"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºú#ëý7š ÷ïß¿~ýû÷ÿNE#ëô¸Öýû÷ïß¿ýƒ×ÿ½þÁ“ÿÄ€Öõèàú½~ýûÿ¥ˆË·ÿ¢ –ú뮺뮺뮺ë"ºë®ºë®ºë®¼éÀáþHÀto^߫߿_¿~ÿéÀG;ºßºýè÷ü"€zG·ïßçIõ¥{ÿè4€ }¿~ýû÷ïßÿAïÿÞß¾\¹råË—.\¹rè "ºë®ºë®ºë®¹ìÿìüm>ü}¿~ù{÷ïß¾‹óÖ¿ÿ­û÷ïß“ó^ýû÷ïß¿ñ_n=û뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"Gºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®G08ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬GPà q„À 1Z-áZ-<Wÿû€µóA€"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ "pÎ "pE ½`>…‘&¦@¼&F lºú`gS€ "pE ñAäHP˜Py&œ„ÒG,AS‚§ "pNÁä§‚xŒzR­—Ŷ†‡l?1¤©?>FÌr ‹B>Â-¬›€Ìö:úøZ…‘¯`ý ‡ëÜůü‹Ö;ÄP°bÿûÜñ"ˆ„jÉ<*ph‰×è5ø÷¸ŽÁàšñÌr¥ˆÝ¿ƒoÿŽT<(Dõ€þ' ßþ³/ Ë^œ‚D×ÀãˆÄS"( ]@B÷‰âG°y¡bðt?YFXúi(ŽO>#€É`uoŸ}À9ÙOõñ"ˆ'cÜ߀èâz/ÀðSÿìF½à2#‘…šÐ6y¹Qnu瀸x&0 “õçȆ…¯@Óÿî°¥^‘bºœ8"pPž ZA8x ‚ ‡pŽ\8€l‰}Ô *ù ñdcØàxÿõÞá@,…²b>úqÀÞ'kÅʼn¸Ü"%ø;Gá‹úˆÄæöf¾ÇŠ#(ò(¾,kß÷€Þò Ò/ Èšú@pŠoàíxˆF¨r%â£Ãˆ0ðèPŽF¾Â“ÿÍë§Ÿô@;‘¾@ B€_OÉ p‹©ÁS€"pPÞ y<øÂ@~ET7ç§‚€à,÷ÌÕe4ÿ|àWÐhµü~˜Ó)üW2Ì€ÄKÎdR ò  ëÎð;ú·°GÅ}x¨YÄs Ç  Íbù¦øHàõß÷˜zr Sü¤j†ýAøpuøÉÜʘ DÐsáð‡ jú¯˜ HXò h^p0€ ÁÀ°½ó` ]SÏü}¡à-€ÚÛô°ážNð…ÌžaÊ{ô ªž$D"ø'8Yo~‡ÈÓÌÚî0 'wà,‡€²ñ@8@€áp>F×ðö‡‡ ö‡‡.Z À+s]½ÂÎYþO\§pˆÀË^ð@X(“º”ÝÛÄ@冖>¿=ÁÄô#"óþx¤xŽ  ï 8Gvb-â£ÃˆhtˆúöàF¹ñà-fú÷ÇGƒÿÀÂ&›ñž@¼‹À†4œµ®yÀnG~<÷ØÅ®üÿäHà"pˆF@Þ+ APŠ”Nÿ¼è€€=Ço±@ '®úr(4 ÷óiþ@ ,Îl ¡ÇÞx€vaùàm§iWí» ¢‡}p>||ᨲp·"}‘Ž€çPÖ%}½ô ?þo¾þü˜ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿpÎ "pÎ!"pÎ""pÎG · EEL~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPà €„€!Z-X¡ßÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®Gºëç àˆ¨?[뮺뮺뮺뮻ä(* 'jºë®ºë®ºë®ºë®ºå€ "ºë®ºë®ºë®ºë®ºë®ºëÇ ®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºå€ "ºë®ºë®ºë®ºë®ºë¯œ7ô^¿A MR«¯þ€¼Á!Uð'…¸‹túûÕöèZ¼ó‹ÿÀiOÿ¨M]ñ>‡ÿÉâG¯àÀÏ€XF4q: üñ;5}xOüêò ©ÈãÂà8EÕôÆßWžÀ1þœtä«}ø(àöûðÿ»zºë®ºë®ºë®ºë®ºë–"ºë®ºë®ºë®ºë®ºë ÛÈ€|&ÃÉÕµk©<~¿×_¿Ð9ÿþ«¯|½õß@¼_ 6A£ÿ×_…¨Öƒ€àBÿaàÇÿøÃ¿¥Öý]ðhG}ªë®ºë®ºë®ºë®ºå€"ºë®ºë®ºë®ºë®ºë ÛÏoÿÐå@Uóô  <Ó)ñžž¯}ç@/ˆLý}@tЀåþ@Š€`pkª½Ô«_*«×WvŸÿõ]uþ¨}ªºë®ºë®ºë®ºë®¹P"ºë®ºë®ºë®ºë®ºë®ƒk¯Ÿ°—S[N½÷Ø£±¸ÕÛÿØ Àü t(}‹íe˧ß]u×]u×]u×]u×]u×]`"ºë®ºë®ºë®¼PúïH'v«ÿ 9mÈ™UðpÄaç½ÿ@|À8U¾¿úF# ±ÕwèùøUwàr8 Õðÿÿ=]{þGqGÖË ä•W¾¿øñ¼Ó™—^â3=^®»ðÿýV¾ºë®ºë®ºë®ºë"ºë®ºë®ºë®ºꫯG—°ç8jo®ú_ÿõòq€¥ÀÃÿär}}Wÿî° Ïb u}ƒŸÿ³ßô€‰¯€±`Î.l @ïöðâ8Qõô ßÿ‰Â­û÷ÿHàï_¤( ßÏ`€5ÈÄr­W¯Ò«¸°pp5û«××}‡µ]ú‚µ¾ºë®ºë®ºë®ºÀ"ºë®ºë®ºë®»Ð ˜½_€W“" ¢YÅå×»ýG`@A‚…WààÀ"êåßAÀ?¯ˆßmû}ö ¿ÿŒjòg€Ò#µ¿~ùéëôÜ«ùÁáp9€…UËÝÝ`°:Àhßæà¤@€ ëð p÷øü?õwÐÄR9:¿@ч´M]u×]u×]u×]u€"ºë®ºë®ºë®»°4N8(<*¯—°:Fþß>À<;¨ë}{ëß]wÐyAÃê뮽Gûï°pÿõÒë¾ÁèWW_ú8 Ï_ pñæÕ×]u﮺뮺뮺뮰"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®Gºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"G<‰ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬GPà ,„€!Z-tÁÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®Gºëáå±äî,e}û÷ïß¿~ýû÷ïß¿~u®ºë®ºë®ºë®ºë®¹` "ºë®ºë®ºë®ºë®ºë®ºë²§ÄOW]u×]u×]u×]u× ú뮺뮺뮺뮺å€ "ºë®ºë®ºë®ºë®ºë¯–ú {îúë@^ þ>¾‰á@/ ·ÿ gÿð"ÕïøÀÒ+l ¿ÿޝÁà-¯ 6N]|<è*Á—ÿëÎGÿ öT8€œ"Ÿ`5'WÙ( _ÏèýaÁõøD=~@€U߀¸œÕr뮺뮺뮺뮺ë–"ºë®ºë®ºë®ºë®ºë¢ÞDzè‹Â.–×[ÐblŽªëýcUß@Ú>¯ÖLÞ«ß]rýO^¹DgnGÐ:ÿþ¯°°X¯}ƒ0ªÝK«®ºë®ºë®ºë®ºë–"ºë®ºë®ºë®ºëG®ºë¢WsÁ‹ÿâ_™>¯‡ñͳj÷ÿÒµu×/u»—^ý9\Óž+K¾À8P1 £©EW]u×]u×]u×]u×,"ºë®ºë®ºë®ºë®ºë®‹]wÛT×M8’5]ôÀqÀ4:¾@Åÿà-‰äë}ö áöë÷c€>¯°" @Õu×]wÐ:«®ºë®ºë®ºë®ºë®¹`"ºë®ºë®ºë®ºë®ºë®ºë®Gºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºèõßW]u×}¸Õußf…¶®ºë®ºë®ºë®ºë®°"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºìñ_ÿTh £ˆ5¯°kÒ.Ö»ë¯)÷×/üE¶ں뮺뮺뮺뮺À"ºë®ºë®ºë®º=r ß|GA¤WŒª»ð’нõ×]ú#šü °a:®¿ø@…\»Ò.×Ó܃ýMWÿm~x5JºõwçW~¾  W]u×]u×]u×]`"ºë®ºë®ºë®¼y{å×^¹\쀀í}wÿ‡‹¯€@5ЀÕ×ëÑ@+à ÿþs´ _ÿ«ìÿü?Uû–Öî®ôŽ«®½Wî€á¸àD$ þxšýGðX«Õú»sÄ(‚AUÕ€uÈõú$wk뮺뮺뮺ë¬"ºë®ºë®ºë®»>€@:õw°p°äó€lûåWI]¼X6|>혀ú®ú'  ¯¡B+é‡W¸`-'ÄBxø«ì¬=uñ ˆ1êü ý^¾»Ò8Z¾ h‚@€6>õè  À?sëìué~­`êëè°…jù˜ GˆGaøþ½{à45]ô_ÿªë®ºë®ºë®ºë®°"ºë®ºë®ºë®º=ußdSHÀר4¯²>¯ e¯²pæ®ú`Õuß /X2ª®ºðo^ûè?üQõwРvÿ`lÐÕï¾€dc*év÷Ùں뮺뮺뮺뮰"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®Gºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ G9%ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G@°Áàá$¬H„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGA°Áðð HDMVˆÿüüððÿ¸ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG · ES\~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPà Í„À 1Z-åAZ-áÿû€µóA€"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ "pÎ "pE ±Îâ<8b}$‘ï€ …¨‹ðœG°3ý„p•ðÏWÐ*p "pE ÂGI#ÒIø|À_0P/ Å«‘$ü®D¾Öƒô œ "pNÙ8`4«Þ<ˈÑÀtÛÉã„F`ðëás¸ŽF®wÈ׳I‚ñKPÚóˆÀ 2ÅüÐ߯|?&Â]`.0÷à4ÿø…Þ. Àpë1äK÷ÆÝNLj ì#^ÇPž €Ô ÌØW Gð9ÿûv @Ãÿ÷‡&ý¹ïG9äGèÁ|žèûÅÀdHʘtÖò ù˜Â”@eó[SðÚôà3÷ƒÿÙøAâ¢)û^ôü®Dš@À*äJpTà"pNB9ìÄ`áòRÿˆ·ˆ68?ß_'AXq:ù 'À"A¸@¤’Gé'qÀáá0ÌÊ=`p| ßãp·'Çá:@àùEЪʼnè‰@ˆÄRÌø×licŽ€Êœï·Gì _ÿwŇÉ#Ö^ÜQ>IÝ È;¬HÁÐËá £ï’ùƒ|.„·9_Çúä\G¾}r.#먩cMV< ß" ®Å`?ÀZFÔȰüë¸1ƒxû¡HáXŽq:â3‡`Þ0°ØY¤?ÿK÷Ê4@x«Ç“‚Àevôü#‘/æOÇ2X á‰t@©À"pNñ .]š@¡Q/ߨ`¬d°±G=¯ß‘/¹ÜG#W;ˆäiðàˆ‚/÷=ðü&¹è‡á7ŒÇ$L÷ïBÚl;0Mn Ÿÿ,x 2û¿P2 ø§˜"̾6;V;_Ø<‰ÁäKà(L(Mÿç×8?õó뜈úñW" 9iÌA¼VáÄZáÄ[4—Á˜ûèxœÀõðRÈÀÉÿð À92ðb( æhÄØyÖÀ«øx©á‰ÐhG$„r%éä œ"pL„þ×ÿý÷¸§ú̾ˆPcÿú’´Ná`jû='_M”G}²…“ˆ¡×ÒÔ })ØW{ä<:\+ß ÂœLàæ7Ü.úξÜ(ÀŸä @¡ â+¾Ç¸pX 7Ó+À©À"pÎ"p6B>OÆ€«‘¼r„ëõˆ$Np‹Å $‹¯˜ ƒFàS7ïˆ$kõާŽG"p7‡xîH;°Qƒˆšýí±¢TN#/Úâ= þ#ßRG¬EI’œ#þ`ŽGõÏÀ.¾`ŽGõÏÀ.§pˆ¯ˆžñ„â=üx &"ò?‡€²b/#úpXà"pˆFÂ(Ü €~øüG¼€ø ñpµß1BoŸÄûÏŸÿQÐþ.óƒý Üxš`gœÀ‰ nŸöá×燷cïÄcpPö÷ÏÄ`°dÿøˆ¾qG¿‹' ü 66¿P ^pXTÆãΠ«ðpœG¿ÑðëG¼D€î#ß^G yýx H¢éçü¹ø—£æä\üëæäÃ`°†#SüÀ|E:öñ_=â'… Ä{âÇLuó?ÿTpx FŸðàeúJp"p’\7ŠUsÐ$‰ UsÐ$‰||}ãï,xŒUcË^#|tŸÄûIG'‰"ÞË™ƒÜP‹ˆÀÅÿáðþôÞÌp5#ØñvþÆqúñ1ÐîEwõO£ÜqX¢=s¿¡4½ .  ,ñ\rÐ5¼xuóä|xÏÇ"Ùê4þMç\x¸aÐŇ|y¸‚D_þ8?×^À‘ˆ¸ëYe‘!wÇx‹IüO½—'€üˆD60@Tô|ÁãÿÂŽ¾`ŽGônHVÀÀE¯ óÀdƼP@W@kÇ€&žé¼xw€éñÀò-ŇC¸\®sWIáFÊê¡*:ñaÖmw<öpd×ä` •œ"pˆGüÁÏ@y6` €ÛÆ‘ÈGÂ}ñcð–p’p λ°"B ÷Ï'_"ÝGç…ß<.øXô‡HÇß//èÄŒ"Ì8 ,"b8Ä[Ûs˜|jÇÑÁàÆ-|Mh¬àcÿû¶š@%€>ˆô×¹)3©`iDy9oƒÀ:… Øäp“¡«à.÷é?‰ðØŸï¯9¦‘÷@|?ÿ«®"€zÝñÌ'Hb¬ö¾ h¢5âž4G¼Dð±$M±×àG*äjÇ^?€«‘¯‹M|1âº[D(€Áâ‰ÁDèÑ'àìOþ¼ý& Äu‘c„òpßßÜD£p}è ‹ëž€ c‡ SƒWÿàûb5ó€âÉÜ0<|ÖÚœ@ ë‘Tܰë°(± q¯¯xÐxâ==ÔlÌÈþö ¤Hr…Þ ¼PQÇð°øL¡$þ÷ÌÀ> ×þ.œà"pˆFGñ-§úSƒHšÏ|ˆ€t8w´’CÁo¨Ÿy8¡s^ùXè Ûä_€6¾åÐaÿñÞù8ª4:’ç%Š5òŽÇŽ9Ls(öÛ­«Þú"_bÀ=P¾Ní }ΰ°;|˜‚G²H×È y1Ád}çGiþ àeuõpîù|ÁT‘(М÷¾³@~/S€üP hù@‘÷߈žûG7<ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿrÏYûÀ~A¡·Ò¬o³ds…Óƒœ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ!"pÎ""pÎGPàè„€!Z-­Ÿÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®Gºëç 'ÙW]u×]u×]u×]u﮺뮺뮺뮺뮹` "ºë®ºë®ºë®ºë®ºë®ºëç IñT뮺뮺뮺뮽Þúªë®ºë®ºë®ºë®¹` "ºë®ºë®ºë®ºë®ºë¯7~ÿ'Ä^Dªë¿ÿýí¿~ýÿõ¨mÿèŸo¯üoÿÕzú뮺뮺뮺뮺ë•"ºë®ºë®ºë®ºG뮺ë¯6½þôøŠ@µ{õ^ºÿ`úÕ{‹\ÿ§Ä~ýúý^ÿä{?ZêîûW]u×]u×]u×]u×*"ºë®ºë®ºë®ºë®ºë¯œ6Ä×ü˜¶ýû÷ÿÐ6mûÿýnU’qÁöç¿~ú—ü¡öýuW]u×]u×]u×]u×\¨"ºë®ºë®ºë®ºë®ºë®g±àÉÿà?¶¾ºë—^ú÷׿~ýû÷ÿ ¹G¯~ú뮺뮺뮺뮺å€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºä]‡ÿJmòåïÿnÚÕ×·Öµ×]u×]u×]u×]uÖ"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºè?þœx›b׿ÆÒÈþ—/~ùråË—.\¹råË—.G\¹r8"ºë®ºë®ºë®¼Púžå¿~úë¯~ýû÷ï¯}Óû}ú$( _ð½~ˆ/ÿ#Õþôpûõ`¯ôE'€é7‘UÞáuöFö®ºë®ºë®ºë®ºë"ºë®ºë®ºë®]‡¤ ‘ý"ïþ8EÖýû÷ÿ°ñÇ€mûÿÐ>ÿ®Ý¿~ý(ÿ­ÎÖâþŸ‘kì€D´ýû­~«ÿ¢È·õúÐ5zëý€È~Öýõ×]u×]uG×]uÖ"ºë®ºë®ºë®¾L:ÁÀÞ>«ýW]¤\EÖëöœxuª¿z(Àë~ü…cCÄ[÷ÿ°·î·ÿ_­ÿ½{~ýÖïþŸÿõéc^߫ӫ¼.½z}xµ]u×]u×]u×]`"ºë®ºë®ºë®¾Pû4€mû÷ï¯ý ¤Z½ûëß¾½òÿØ­oßü‡n*ßý8 Õþ€€·ï¯~ÚÚ{÷﮺ë®Gºë®ºë®ºÀ"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®Gºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºëG®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®G3±ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿºë®ºë¬G · Eal~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPà1„€!Z-É!ßÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®GºëÁå½"Äúºë®ºë®ºë®ºëß}€lq:®ºë®ºë®ºë®ºë®X "ºë®ºë®ºë®ºë®ºë®ºëÁäW4ây®ºë®ºë®ºë®º÷﮺뮺뮺뮺ë®X "ºë®ºë®ºë®ºë®ºë¯—ý/ÿ2ÿ@.6‹®ôæ 'UøôçÒß^ú÷Þ‘Bþ·ÿ rX]¿}úàÛÿ÷ý€øNµrºë®ºë®ºë®ºë®Gºå€"ºë®ºë®ºë®ºë®ºë¯‡”j"‡Ûÿ§0U¯ÕïõkÓ{¤ã°}¿Õ¥Àvâ©ùÈ€  °:׈¶ýS߯Õ×ü˜ämg‘¯qÇàYœ8‡¯[÷ïß¿~ýû÷ïß¿~ýûå@"ºë®ºë®ºë®ºë®ºë£ððÒdB5¾^ýû÷ÿN÷Õ{úþA"U¤ø‹~×oß¿ðÉÈ„jü «º^g#ßáëÕ]u×]Gu×]u×]u×\¨"ºë®ºë®ºë®ºë®ºë®‹]r¯úu ¿ô¿þf¯K­Uu׿}éý¿}ènDö®ºë®ºë®ºë®ºë®ºë–"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºä³ÿ  A6—]uïß^ýõ×]u×]u×]u×]GuÖ"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºði÷ÿN1"T-–½š¦rö•éùß¿~ýû÷ïß¿~ýû÷ïßE"ºë®ºë®ºë®¼zcÚýÿÓˆµuÏÒ0"íû÷Þœ<Û÷ïß¿~úåËß^ýû«´ü‹W^ú뮺뮺뮺ë¬"ºë®ºë®ºë®^ 5/w¿ükùf±b­ûÿ’ȃµ¿~ýû÷ë‹õä%G*÷;<Špv®Å€\>0ûK«Wý.~W¿õ¤j\U×ú_éråË—.\¹råË—V"ºë®ºë®ºë®¾rdp xìŠõê½Ò\íûÿilj W¦4w¯@Æ€Ößî«"RA³ïÿ@¿oþ’&•¿wù/ /éù‰ïy0ðLOwµ_ôøx #K˜ ƒoßy`Ãÿç^<:ß«ó¢dÄnNµ_ýÜŽGE«®ºë®ºë®ºë®°"ºë®ºë®ºë®»=š@7«¯û뮺÷Ñv}õïß¿~ÿõÛåïß¾úöýÿèWo¯|ºë®ºë®ºë®ºë"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºG?hÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬GPà—„À 1Z/9¡Z-åA×ÿû€µóA€"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ "pÎ "pE Å–F€Úø #‡g’g| Â]¹ÁÜ.èDP°ÕŽ}üÎ$Uè8 "pDB_B™Gœög}ò!á1—8;Îpw½x¨_ðö“DÀ©À "pNÕß ebà…ÞxÁàB” xN¦xݯ "CÁÈGKàÒ-à`ÿûóñóàjBèóŽ8‚Ëã‡Ä``÷°{€¶lð÷¥äE€}2À>¼á- Gš 9óöøƒBoÌp²9·‹N €'aÁDð» `^à€¼àyabB¯vGÄ@ÄÍ „ü_¶X€¨°³¯88,ëâìO€:r1.ÖûËŽ ½xªx b?“ÀH#ý¤Ñ0*p"pNÀ;ˆ÷ÁdðH‡9¯"ÊØW„‰§ø° ô,—›Â-ó/v8zÃŒ…¾u¯Ž` ϬäKíÁ—ÿØ.ôƒÿÜ<*áÁÜœúñ‘áDZiæù1øþ_^sÌuä3Àìç…¯û3€¶GÀ}x®¶±Á×Î ßžò˜8œG]µä¦±w‡^¥€s§8;Ù‚–GçBÃï^*ž„IàxDžES€"pNØ#“‡ÞqG…]ᬷã€6'Ê"ð ¸XŽ ;Oâ‰É#ÀYÂ7§Àݳø —|ÀÝ©X(ªT¦PŸ€€à#g€Ëß .à:÷(Þ*‘T,Wˆ‹"ÂȳF’<÷Á8G‰8‹ÅlA¬A±â´þ)ýý1øŽðïhPtРëÎq@2õ‚@0ޝ¯¬Š~°8ÿýàîwœŒdçz#xªR„IH'‘`Tà"pL…­º˜r…1ëìY_s, /£àßjð0ýõ‘/¸?üÛìá<œO¾Øˆ×Øþ`}2…Óýfd^,Ù°{ƒ'ÿÀwp«1ƒŽÇ_jPûï"Ò±dñvGÝw€òìŽÖàê7VëÜ^»aÄHP¬À,¾°!§"pÎ"p7§#kìsß@uµ:!"Íç"±ÀP–ÂhéÁc€"p7ƒÌ<Kç~pØ(j”þ‘B¾8F,~˜ý|E€ºêvB>(æ œÁ0¡_§"p”˜A @/p Ø%€*o/ía&ýÇÓÏç˜x GE¬+¿=X2ý?’Xëö Ëõ”-L"ýŒU<þ.`xì*po,Ð5Oøi÷Ìx°K'ïÈÝx¸àºä\G³Sßp µ™ƒÈÚñK‘ur.…"û÷8âP_DüËñ‚>æq{Å €ï… ¼™Ž8B,㯸ãBÀ]y âxàvÈÃï^`}â—"êä]9øAÞ/àiÿûþÈÃï°¼ |án5`ÀÇG"p˜F>? Ä{Çá8z\gx®<8‹cȰüïzp:G¼°ëÆ ÷‚x2t±à/˜íuÝ"Flß»Ç~Æü¸pQèÜ$‰f‰îâAWÀà—žàPQ¬ ÿ|p" ¹9xŸ¯Œf˜ëà ?ÂÖˆë1Qä]x€èæ… ‡Kú õ˜.þE#Fñ&‡y5䀀áPÂ?'`#~5â¦ÿìX¢-àG;x¢9'Ž€úÈÓ‘5ès¨pœGœê'ìa|@ï#hò6¼Qg¤pž‡àoò°‘f(ƒ A¡ÂIàm¡B…ßPŒÆ€úñNiˆÞñBaBaüIñû‚¯µƒXÞ…J4€|óš*Ï ¦}@ëi€3°8OÖr…ï’‡¬– `ëÁljPP‚ÇPàè‡êS8"p˜B°;®ÅÔÐ4@G£dð;x®<O8°“3/ƒÄyCÅׄ³Þ(90äÚ ]ð°¡йÕ̬ÀH2%ñr>Üg‰ÎÂ6{”p6ÿÿ‡ÿÇŽƒÉ˧ûÛì pûÅEóN¥€üé*¾£øPbƒˆ÷ÀŒ;àðа¾cÛÁðÀŒÝ¥Äm|#p}ƒïàt #èP (pœG§ñK‘ur.œÁÁ0 ð²=ìê8ØG@Î*ü ÞKôwˆþþÆÌ|ÆÌx o&$‰ÎØפ(œÄûÃ3‘€å€qf0§ðJzðÒ!ô`1€9y:"â7b55‡Ÿ‰ôþ€BˆÂ|xÇý<=²‡ˆï<ÅÒPs€"pˆFX !*ûXX÷Õ€|D¾€Ñê‡k¹9ÀÙÿð¡ _{µôpì>¾BÜFË(Õ];„NóÄÓý‡…›Oò„ÀG;ÿ8X¨]õ·m÷r.¾Ç¾úC/¼ððá“0X ÀåôËëêp/¡bo"#ö®ºë®ºë®ºë®ºë®ºè<"ºë®ºG뮺뮺뮺ë®GØmzqiG} õû_η[÷ÿH"ëý€z² =>4MîKN2õ;3ÕïßzIáz¯þÓ—­õ×]u×]u×]u×]uË"ºë®ºë®ºë®ºë®ºë£ó„hv·ïÝU×þñ5ôÖÿéÌöÿÒG‡kw<Ѧ‡Éoߺý§Ãƒõ~r`¿Ð^ºë®ºë ­EØõ×]u×]u×]u×]uÖ"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºñC뮺ë—úKšGÔ‹.¯®ºëG®ºë®ºë®ºë®°"ºë®ºë®ºë®\‹= wj\½‡ÿN Û}¯ý'€ÌÛ÷×¾üÅÛëß¿u»ß^ýû÷×^ê¯oµ—.\¹råË—.\¹räp"ºë®ºë®ºë®_(zóBêë¯~ÿëù¶ú÷_»„ ~ú÷ßn ¿ÿn{÷-ûÿÐÄ­õïß]z;º¥ªü^‘G‘ju×]u×]u×]u€"ºë®ºë®ºë®KAù}Gû½×ôúþ¿›Ñc¯äÀÐàg~Ýî·ïÿ £É÷ý]^ù{ôúëÒ÷ï¯þƒÇÿŸ­õï¿à‘ïéðPÖú뮺뮺뮺ë"ºë®ºë®ºë®»¶»ß¿ýÈÄ ½ÅQï¯}tœ»kHà[ÿÒžßþžß¾º÷ï—¾½÷Ð6þ«®\¹råË—.\¹råË¢€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G6#ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬GPà‘„€!Z/Ÿÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®Gºë²§Æˆ«®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®º8 "ºë®ºë®ºë®ºë®ºë®ºëwE®ºë®ºë®ºë®º÷﮺뮺뮺뮺ë®V "ºë®ºë®ºë®ºë®ºë®Aö]UÿGÚjíi«®ñPHÞ \½yÄATò},žÕwØò-]wÄH€| ª»Ü$ý…Ì|:jºô ûJºë®ºë®ºë®ºG뮹`"ºë®ºë®ºë®ºë®ºë¯DîŠ8;ÿüšú`v•תÿ–ÇYÕUuëõ´øÐëÇ%§ZW^•ÊwT6¿þ8 À;«®ºë®ºë®ºë®ºë®X"ºë®ºë®ºë®ºë®ºë£Øm¯ƒƒhÀ—Ø?—\½õ(°â=™ÄUî·ËÝËÝþ“áÁú®ù

®üÁ·ÿϯ8œ¼ßW~=ïZ@7µwéW^úú¹ëˆ¤úÖ`ð>k¿š×Z¯«Pù 2­püDe'—.\¹råË—.\¹tP"ºG뮺뮺ë®A´zå×]uï¾È3âÕWv,¶¾ò›UÎòÄéi·ï¼Ö?‘¼›«¬Š eÿúê‡B€í¯ß¿ýÔûý8Ú¯N^®JðévÿúF6©×]u×]u×]u×X"ºë®ºë®ºë®Bv{b&jºï_È•uÞ<ÓÒkÂ\¹páàp:ðêIkº¯YäB èšü…ßèëÎ,>X1€ }ŽÕwŠ4׌m=iG«÷PìxóñU×êÖœeu`¢¾üMh£¨«¿—ÿÄ‘+à$°6:Ðýu×]u×]u×]u€"ºë®ºë®ºë®º=uðÞ€f.ÿL‰Ä}}¸2€ Û×½Òë¿Û,@úzSoÿdE@hŒª]uß"Z`pºúP•þß¿ý86ý^W¥›Ðþ,>ÿDæ' «®^ùöð Rï¥ÒåË—.\¹råË—.]"ºëG®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®Gºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºëG2ÿÿÿÿÿÿÿ®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G · E}Œ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPàUç„À 1Z/ŽZ/9¡³<3Ü!Àµj¸JÿøµÿóA€#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".RG”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”G¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"åG)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”G¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"åG)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹GJR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".GR”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥G/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".GR”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹G”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Gå)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆG¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Gå)Hˆ #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"åÞ+¼`€$ €é9âÊÏÑ“›öêê¸7ªÎ0 ü& lÈ[pÔn>¢ÉýºóÀÿ€) <@¢ò )ÒY„ZO,0¤ñ=ûôG* 8N¿=@C8,õÆÂ‘ÈØFµ&'þ¿îºR—¡ar”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD_ÐÀ À À€8À ƒJA@`¤· B{÷7é@€ @€7€ ÃJID¢ÒØ1ﳟ³ÝÐ@üÀCþ®à E«8?éÀŽ¡ K˱@8ÌGãk§§’ÏçßÉi|oRæ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR" #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"åêó AGÿ €[ÊÞ¨?8À`4ÿð˜5²€‡ÿe ÕHâ/ëè$á:üô @tà L°×èTp~z€† :p&Xë„BÛ÷])KÓ¹îR”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹úð ~`!ÿWp "Õ‚ôàGPÐ¥` ~`!ÿWpG "Õ‚ôàGPÐ¥ä`C€H2%×À'¿’sã|o^ä¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR" #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HG‹”¥Ðrì„ЀìšbƒKO9[Û-àë à€è ÎI¥Og±ÿŠË½ˆ Áñ@@þЉ T©N&#ˆQi Úú°à1jy4 —ø…â°äb??Èð`ð¿€è²nÇ–¤„–Ÿâï8 Œá½ÃÛ])&ð=~GáºÀ0)‡[Ü, .(ù NœQ5 &O`\0õ G F×® 7R¸„L,…ÊOùïJXˆ`0¸˜C ,˜Zœ¢ÑМ±ÞÏ€è ”NLÉeà5Ÿ·ßo—º÷z@üàC€ÐGÿÂ`Öòᙉ„ÀGB€šõùÀ† ÿ„À­è3Ñ€{`_r¸‹úú 8N¾.˜hÀ €t¢ƒKá¤Ð €7H1%Ùî*ûUÍ|Øð!¼ ‹!§Rû!+G,¿‘…?¼²i1¬7¶×JÐuøâÁð’4 `€=!÷'6'Ü Àù`œ¼Pà 7ç'ð2œ ½`5R å€TPkgø0šWNÿÅ!ïV”$¤ô't}Ûï›î;ïhx Ê'H/·ÉÛï¾ù÷Ý÷ÜÝô/~pä²j  ¥ÀÆ$Ç38J»»À^‘43“Ð}ÎRFç¹u€-È¢Ga¬žH @HjD p¾Ø]xP%. W , ˜éÅcýö€ÄšjHd2ùe—ß§€Èv°Ð€n¾¤ë £oçä0@ü4?Ä ¿Æ$4šÜ$Ø?T`@ü@(ZvØ ‹&`&^ ()B?½  @À¬À:IenÜ5?€F_ÛñYýÌØ  Ë©Ý—ñ04¤¤'߇orðë+¶à+YÔ–G_Wó@Р À1 ,²Yøn‘ èn+µèñ€(€j Lßú¾š€*°bi $°Ì‰DÐΧcŽn Ö˜@‹wã£Òb¯óØ €v€@À*VNA5;%¸öÿçÌ%`hËÉJ ˆéù 7ì9þÄúІ`8"Ô^`,˜#€2o@•€Èõƒ„=÷ñ€(€j LßúG¸Ä0ð €t¡0$Ô¤¬C@ÐÂcnMJØð{°»íöh˜Rj@: ¥ìÛ:Œ?§ŒB0¿µÁÀ4 ƒíñ57â  øa dè3–MoÃWØ/Ù4Æ1591Ñ`QÀJR@nŒ' Bpv÷¡,àIE ±0¾"aƒIÿ +Þ¨†B ÐjI„Ò’Y]’„æûˆðJ³'¹Éx _çÒ 0aˆG&“ @iEçBQßz»ê@€ÀK!‡€dZ@(»ô`$±€+:ùmÞC&Ù,~2À¤××b´@ @©DÒðjF`1‘û³¬jQvÉ€ù@ ¥”V!…ËNFtø$ݤ?À,Àÿ\ÀßOߣï¿ß/|~¹@ Š ÉîýÍ´,7¡-¯âà À @.hžŸÈd0çÆõîK”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆG¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥" #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹—ÕÁòÀ1àTÃ$ DgÀ”žˆ÷Ê/¸ÿÀ€jç–¹4F῎֤>lˆ§by0OñDÔã Bø;_G A0€ ŠÁ™„+±üÛéÀ€ rhY'ÿQ|ÏЩ|hÃ&LÊ{¾>ë€-\ d͋آK !²ów“z9¸*åRìAiG}ì¾ÞæÃ )ô!‡m¯Tœ`.ÿøLÞVõ@ùÀ†á ÿ„À­™ ¹4®ÝRIþÃ|¸ÈxÈ#lÒ±4¾jykÄæ¾î…ü&üô˜p&GXë„>Åa~Ø…ŸÞr_}€?0E€òјÐÄÀVwäkäWÔÁñü€ #€)éÓð2A7^à@"ù@ H@=@j8y^øï>û0 x!ÿ8 #ÿ@žøÏ> Às„Aï^Í×P|„á:FCõ+Ié4é~L‰PfäÞ(Bþ;LZàƒý ¹àde¯2€À !æ€U˜A- GÀQñˆÖÇ–0Ä (RD$ 00¬1B¶Ú8´ãg¥ëtÿÞäÛk÷ù` ƒ`:†# šö&¶É\Þ-Ç_S¾¸@ Üà ‹#_v¼ÀÒRÌ÷I72oà`  2pE¤ÄÀX0GdÙ€ dà ‹Hˆ!€°`ŽÉ»þA#ÿH¶ $¿¹ß5@Ë]°ŠzzM…l÷Ùo…GfX†`à—ÿ©¸Cþ ·&gMñ‰i}8? #ìÀW`’ÊIEñã:‰ßß4¾„†0€+,v€›ðàXpG¿h¾Ü$ã©D{àå«ûï€ ûÀ@ÿôQøi'Ø€b«!~ø?À,Àÿ\ÀßN)´äûß1Ä0 0#ÿ×°÷ÑÀ4Ã@b0#á@]s€˜ÀÚ@sGÈH| €`†`ÀÄn-,ÃýF/ïi'Ö^¡iý¶Bz¿“`@ý0˜?Ñ’ T@ú 2@/ ¸5ƒ@»!£ ¾IÌZ7ck@‚( ^ A4è :Ä@HðI *  0ÂaDÎù_Â7ûïv$@×S|=ìq ßGÎrP 2à&Bp Àv¦üIÚúÍœ†C “K&“RY4¾”õö"l­ž €0þmÐZF÷¿€00ÈÀ C` Á“e``(#€2-@ †À‚8&õþ#ÿH·( ¯îWÂ@ `à 3M÷ká  0p¦âÔl&Ü„I¾Uô @ü0 €4Ydkç·ÐðÀ&GÐe‘®Àý À=YÛ÷Àø€†`&úà–~ú0‡þÀPÿì ®¾rˆ``Gÿ® `ï£`ìþÊë`úÃ@rž‰¤ŸYVM$úËÕçÜÚþʤÒCQDkœxÜMpI]@ý Cþ’ GŠ#\à@ÀCþâh#€:HúòA î DÿÀûùW¾Æ n a¥˜P€ÝÌvoƒšøç½ (®Ä þ@£¤0S(<Áwp Ŭî«Üè¿¢€9(ÀÂÃxÀÀÝÃ ã†ø­Ûûâ\†‘÷èòÊHbzºŽÝ7ß÷:óô€€> A1$ †!HÄ׌;¾ì·q€ì„Öèë#Û¯Gµ#ï^^¦DÐÂÅI®äÜ—d +æO'^´àùÈet@:pç,¼ o½‰e–M-%–žZSßÿßÿÍþ² îp礰ܯâ` õ€4fÅbÀ,!ðDPß—À 9$î*áÞäÄ«€ë` !@Äü@œ½¸"çÆ8 ¼7º€v„ ¶GöAŸü»úð ~X!ÿWp Õ‚ôàGGRhÒ°?,ÿ«‚8 êÁúp#€)4ip @‘.€DÿÀûù'=/^ä¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)GH‹”¥".R”ˆ¹JR"å)H‹”¥"/xЀ1+r`߉¨ãJ‘»áW¶8  5Ü“ ÀH ¡!Ÿ`•‹Ü-|êŽ×8`Ë ;Ú$1 ¿©à@ð·&€e°¸k‰ŽN¸@À '˜ ùå‚%!Å—Ý?ȼ@ßGz8¡¼vž!"çlÙ¶ÛaZê€1l?Ѐ˜à JK%ÉÉJG#ܺ]9?$i¶m™¯Þà@B³pAþÐJ°Nÿ{Á ¬ã@ÁH)Ùœfge³Â”Ë Û&¤uËÓ+ À À©DÞâQCÀ2ë=ÀnQó4¨¢ÒÝý“›ß¬dd€@“N'´ 8>%;æ$€V– ¼—>4i5$ÒLÐŒƒ®] `€-Ề«6¡‡ðGÿÔu'qw“(´•ßv—ÛŸN!‚G €^À,ˆ ‰¨0—ÃCÀDJ-Õ˜)Nà'‰…bY4±( Fþù«ú?s€†±–€"û|˜âÂ&¡$4d²ÐCR%e(›íz@ABû(Á;ýïJð CPë>@6EÜ`` `BÖ, €Ø¬Q-† cYûúà À4€˜†X¹\¢XÁ£Ñއ Ö:[ ãFš} ¦¿|G ˆP"ÿh%X'½â@2|(lp 0–0`Õþã¥ìô³ ¥†æO#UƒŽ«—x8†KˆHà1>·ýÀl]Á#ÿ kƒKB‹åwÇê~|×í€@xP€;&P,Å ±€ƒ¹ÎØ*ðéïüÔ 4†’k 2hFA×ÛN“%& œ`À`¾[€2êfbYLwˆ@€ƒJ %'%€G™Û»8ÿ#^””²Ê@ÍÔ4•“ÞоéyéKj/×51@–ˆ„½±(ø–Í€˜¥¬  ˜)¸Pñ¥r†T5À-,yºX†Œê8Ë@1îSR—EöÀ€>Zå†îB¬À†ÁÿQÂNâïbA@1G 8 ‰¨0–C(7C|ÎîpÀ†•™ß ´HbP&G €;Hà;Ð3 Hi|( lO¼ @@€ “‰¤4€мKFA1Pc÷øzy§ñ¥ ! Nc„O­ /¦zRéw²¿VÄ·+ÿÌ ,‚†TI·´¡ãªÀ @@@ @+b’‚P@`“™Æ€ZYó±À;/ c¨ã-ÂîR”·³¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Gå)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Gå)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆG¹JR"å)H‹”¥".R”ˆ¹KÑœ?\  ¼˜’-;²xa\´#‹NW{Š`@ Ɉ!@ÔJIÉAã÷×O)(ÏÑöÓßso9׬H ~hD'£€¾ÿMŒý¼§;ˆ¿BPCÿ°ÐGÿÔ‘î`M5ÔÇZ—Êf¿…8n d$ÀtK„Œä´ îîuìA È`ÿ<i¯lC+_ØíB8ݽÊRG–´Ü¥)r”¤EˬÜh €`ΰ2‘¹¤d’Ýx}ɾ‚†0@+&‘‘d Á¡¹î@¬¾1|p(¢àdÐÂa@ NB3lüç ¼µ÷À‡ýà?ü† o–Iö@'! ™ðÇXúƒ éÝíéJ]VW)JD\:õ©Ìh„ôp÷Ý€&ÆGþÞOÄ{ô(?û ýIÜ 0! š4k©Ž´ /¡šþG฀’CÑ,b3’Ð3¸_¹×±:À„d0Gÿž4׎µ!•Š/ìe(ï·¹JRÖ›”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥" #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"åG)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".]i& ð ù1Éx˜–cÎY9î}$ŽßqÞ>¿ÑgŸ|èû“y`¡`6È+ŠÅ¿8[p€bjÐä>MA`TC{¤ ÎW(CPž‡ð«Ï`pëèÅ (ôÿÝ%¤ §›ÉלCØaaŸeþN·(¯“ts½ú†öGÿú’=ùëÄ{ô(?û ýIÔ€ C¤C0>þRt`&CùàMxûØ ÁþxÓ^>éˆ!ÿÚh $k”¥-ìîR”ˆ¹JR"åô@ü €2Y4Œ‹ç×ÐAð€&ÈdÒ2.pý øÀ`j ¥W‚Ñ’Ž?{¨†Bë^ç{"‹ÅÚR—¥/1(pf(­‹GØnÈ瀚HšÔ¢¹}±ôÿ‘Ÿßž &†‘Ë , ÄcÒZrƒÿÚèò60ÌÎÿôS»ï¶„€^É ;&–MOÕ…#°­k¸†5<;[€Z*ÿ;†”MF,0´ŽrQòwò¥|>ûàÀBè4 €ÀšÎn= ”õŒ8<¼†L¤ 0œLÈ/†ãP+‹¬Ó$¨{@æ:þø|¾ÆGaœyE‘¯’€f ` :!€è4އÌáÝväÒ&' k¹¬lÐXÜíyßпA€œE€€ †@ÜÉ OG÷Ï@A4úð$Á`õ‡Ù€˜”PÜ‘¡ÌEõ šý™ƒïç´¥i †P‰…“Kì€Ät§ŠÚìÙìn·Ãõ_}z©`€„†²Ï /ü+ƒµã@VC ¼7b&9¥ü¾ˆ÷@@GJ(o,ÆÛlM~ÌO¿šRrhiD"’Zr +t¥<íµõ úÀ;¼´“`”@¥-?/n·lL!$›Ôq¾Ì²ñWó*äq„0€è18ô$šVHNäèèØ!ã@'Ñ5 I¥t€DîN¾ýC޹ À9î"ØÞ:ÿ:Eðý}ˆ@0”*ôPÀÐÄ”RrÃ9‹ëJ¯^¢¼’{ºXrÉGú\‡‡_çJ]ÀL@2ÎG¸œî#Ýe bzv±ÝóÜ|?BýC?û ýIùP Ö !ðFÿž4×0h €ÁCF¸p´@hÞÌO¿Îâ/РTÿì4ÿõ$~zçqèP*öÿú’?³À¡ÕÌ¿• ÁþxÓ^:ö €@†d0Gÿž4׎º@böš äÅ–€Ät¥9Çôý¶ú®ÀGd €:%§ÃK|L |Œmöà À5rKÙ5)ER!XIò!Á$Õ’0ø,7!GûøÊ@€6Gnˆ œÿ诂÷k €v‚Y40š€&”‚Ñþ¿CY€L€dMÄÐ(M,˜^5ñß ê¹xÄ÷­1 ~¿ÏÎÔ}}¨ht€-&À ”0šLÉÅüH-ÎNÆ Ö YÀ€hÿô‹@n3þ–øGÆ"½ ¬ëøUô@ü €2Y4Œ‹ç‰Íï¡‚áL ɤdZ€ÀÿéäjC@qïÜ.?îÐÿä0k|5_ß €.¨0@¡ ;ô ¿±ÿ#º®XÐð @†¤jxa ÂHá4á©î NCJØ}±Eâ·¿“€-pLHÄ€fmݘåvÝAö@(Ÿ~©‡±à`5°‘Ÿµú@ÀÒÈIGņ%%% ÉGèøGË´2̤÷¤h«üïKßë$% §pÔ¨˜CVÀ‘f8îi·»ƒCÛØ!99õÎw~‡!‚ý†‚?þ¤~xçqèr!ÿØh#ÿêH÷%"ÚS/å €@†„0Gÿž4׎½ˆ Ð!€¡ ÿç€ 5㮂ý¦€ÂF¹XM&†K , ÄcÒZrþ×¥--@ؘŀÄG¼ùÉ›ôã°¾² @vˆo Ù4²jy©ç Øí…j@&I7?ã1?̲nB¿‰pà 7`0Oý•ð^ía€1€'ÃHD2a -à?¿BU“ ¡ P¼ZC BòQú>òî~†e'‡êÀ+ã¯óÅ/vL® K@3øýA„5bX fÃGso w††$3·±Brs딥+¦å)H‹”¥".R”ˆ¹JR"å)GH‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥" #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹—ÐAðÁ @2Y4Œ‹ç×ÐAðÁ @2Y4Œ‹œÀ‡ÿh#Z’=û€À‡ýà ù ß $ûï€ ûÀ@ÿò5¾IöžŠÈFÛßp+?éGÔÿí7Ã︂ô€jÿöš€0ÊDdC;_—@?úÄÀ0j›æ÷Òþ€1p ¦ù½@!ŸÈ˜H¿²è‚óPXë®Ðä€9Ì ™€Ê[ð$Œ¿ÂŽrôAùÀ¨ ƒ,õè¬#x¿ ¸P‘„-LjÖÿ9|Mü¸À €< ÄÀ(blÜ´”„–‘i-;§…ÝGÐÐ@f‘ šL€P ŠIhI1(hÅü^FÙ*výbï3ϯÞp(CÃà {ÒA ²^ïϹ¹Y¯ô-ñ`@  tç†rÑÔN¾Ì”‰ä{ä@€ †à‘ÿE‘îç&ëra&üÉ š€(L &¤„—Ä#=÷ à†€^rhÃ{ðÔþ#°­¯Ž€†ðÀ!û·èÈÁéÄKíÖ !IH¶¤‡×µù@G€AþrÒCßI@&&v줓R&æaü;_(!`ø‚€:)•ÿZ~éH÷@¸„€,Ф(hf- +-~å[ì ¥)ûujJ+m}РÀ€†$”B 0XÂi1¬à”!Íì÷Ù€Bbh@T4 P0°Äô| p¡×çËê`øÄ$y›&°Ñ}â6Ö@&!¥½À€@‡üäG F¾;ϾÄdÎBQdkã¼úÀ5Î""þ”Žàaa€•”[@W‰?¯jð2À„„² NÿA¸?_ ¼B€€€†Î GÛŽHáÞûÐÀ¡`0!†“ ÌÄô}Çî×8 ‹!ƒ9Š´&á‰{üúL&”²aD0Îå£%W×´Ëv|b€@W ¡%‚8#œÈÑ4o‰ @LMGKp9hü@ЉÚ÷À Àð À¨0¬8¤+[€£ûœ…(,·(MôD"À¨iD³¤59Âÿkà@€0(°P‘ Ø †¼¤§8 ƒ Â’­ˆþç&10…¸§´HIwàÀ€>lLB@vL 8 ~Ý) Ù%À‘EwB€ŸÏq`\´‰ À´ܘR„qƒªßù¯M$2ÓÝýÏŠFÇ_ÕAõÀ pÀ'€'²Jýù1<åõôsxÛÛ_nB@À„˜•îB/‡£ Äý}÷Þh ¼4¥Ÿ­ÃP3ßÃÀ  €4W#ÜG^wv€  €4W#Ü^wz$0Cÿ´‰ö0‹ý C?û ýIß*:0!‚?ü𦾪C?û ýIß*:0!‚?üð¦¼à‚pë 07ãùÜEú ‚ý†‚?þ¤ïÏ\î"ý AþÃAÿRGöà”:̆`}ü¨èÀL†ÿóÀšñÇ^ÄèÀL†ÿóÀšó`Kœ³¾!G·3±>èÞrÂè)E_Ù@€=H° ɤßù+~PfR ?‹³€",8 z?á€P˜É&†ãØÄ ¼zµß4! ,A{ÃKJxöí‰Ú󉩰1B5ÐŒKMð€LØÀâ°`Ì¡©)––ÓÂí`@6r”ÂaHE ¢ÑÌücdáI¹t½@ KÝÆû˜•™šþôÜÑ4 C@`GM_BМqhç' ©DÖ #ÿÒ·Ã! `€TpÏÅføïd€ÿ¬@Gÿ¤o(¢ÀÉ0h¯tü1,.þY&ú ~À¬šFEó²É7Ñð€&ÈdÒ2/D‡ÿX¾o®ÐÀ*Z»Ø$­õþŠß£ï»}ß|¯¸ûáÀøD"@'@ @V…8y÷Ú@5&T`©@W¾t|ø€5 ubмÄK€èÉ&8ërgdµø>w~…!‚ý†‚?þ¤ïÏ\î"ý C?û GýIÛ`Pâ-TËùH Ð!€¡ ÿç€ 5å@vC@ˆA¤ÔœRKà"ÎÁ÷ª:0!‚?ü𦹠¡¼0p~íú€´â%¹ Ûú”(1Å_ØÀ38h`;&PÞé OH‡;×’-& j4à!pàÎ3¿ÜšXœ±˜Ö_÷·°€€?€f&€B`fŠ(šZœöFì»ÌJÐÈítïk¿ƒ” GâbÁ@™3ƒ‰X}ì€À€@ЀdL@&“7,°Â³Z1ì‚B>=[o¯ ‚ò€7_ñ$ÿÈhÆ<X”ï¸ !ûæûÃ[î~á7BDÒ’ä¼O³å£âEôP””œ”’¾øýñÞø0 À èf–S$hW'ß{>ù ±d°I@„4൑dª1ÇA ·¿%JRõn[”¥".R”ˆ¹JR"Gå)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ€#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹—Ððð!0\RM#"ùýêô0H@rÊÃR¤’ØÒWRX`®ÄÔZ’=ýL±``ð$p&_þëóùkMú7¾ù_/q×ÉÀè€`G@tQ@! ¨†VÈý9<¢ÙCrQ¾Âòn0 C¾ß°ëRbvW¿}Ì x° ü¿ôYùȰ@ýÀ0!$ðš~Cûäb²F#˜”¥(öï­†–ÒÒZ{¥?ÿÇÿP‰Cÿ˜ÅÈšÛkùð R`&`S|âõà€$@vZ€ì°,,¤f'÷úò@ û“}™3_ÙôAùÀ¨ ƒ,õ€Gðÿ´4À²>·‚è‚óPXë à!ÿhh#€9d}p ŠÜ?ð>þUë@¨!€14À°§ª­ †ÄÐGBÀžõ±÷':ÿA†€å"yù ¨!€¸$Ñw×C@rò=ò @`CpHÿ¢ï(à†¡WPa&ù ä.@j„gà`nwäç¾å~uIH BJNtº>¾o¯º€-tÐ2h/Gvq¡‰1%s¾¶É9’€úHy{ßÉ €N€€07Ýù16H®R—q/µ BMTMï¸h `2ëp&‡PÒ=óBâY8%=¹%' ^ný°À¡x¿öÿqË ¢÷ÇßúÀ ~H PC~Pb;€XLÈH”þ’-æÀ‚æ€h Ä N~Mù²F||nÝ"6awÔÈd2À¨ia¡©é,¿ÒŸÏÿÙ€ %–œÊSŸGY4½ókó@€@‡üä F¾9ϾÄdÎBQdkã¼úÀ5ÎI‘fúh ~@€Ã1+ÂXÀÜw'½ó+p v¡  *·EâG Pn@ÀnæAh¯îä “@uÓÉ…ò¹hå'ãP“ð8`bI¥ 0¬é-9Ãÿí´ ¤ÄƒK /2JOBpï¯pÐìT€jœ0Ü›ò€"˼GrÓŠGM׳ö¿œ€8¹ .€&AèC†ñå¥iáv9SÆ÷š÷ OJ¸¶m_Í!pÀe¤ÀÐÀÄál†äý8 ˆ Ð`!ƒ{biE“:[â5ãÁó@$P äÄt†€Áñ{ÉœÐu‡ßWBRRrQþèûïßï(…ñ4„šêHAwùןÜ€0Í41€þB&£0 Æt”X¾3~Ž=L.â@ @ÓÀ5 GH¢²Rž)²ízI!£°ÏÄk›¾?Þ@ 1@œ5<(Âùxf#ßx¼Àxi` ÓƒÃtWt#’KàL¶PŒeéï4ÄÎRÏëºR7ßÃÀ €@®G¸¼î"í €\qyÜEèÁþÒ$‹`Q#¿Ð Tÿì4ÿõ${å@€@†`Tÿäe}T ‚ý†‚?þ¤|¨èÀL†ÿò2×GœCntæü;ˆ¿BÁþÃAÿRG¿<ó¸‹ô1 ÿì4ÿõ${p J@×ò @ C2#ÿÏkË€fÈ`&Øf_I7a=‰÷¨:0!‚?üð¦¼i¶à;ìCü]™K*ÿE§t¹û°Uò @P †ÐÇ ©ßÉ ÜEî€@$Àåô!ˆD?Ë æ,ô G·,b@ÄÐÀ”$ 43Gõ‚3™yäÔVLQ«×B9)+¿…Rô@&Öd²xñ &”MÝ·Gö àú€LW¨¾pÓVN)Àz_Û0 ŸÞ ®Ãr’ÐÇëí‚âÅ &Öá(‘C[b5ë@õ€hÿô‹h`À/Øh!¤ie÷ã°í‡leˆ!ÿX€ÿH¼¢ŠÁƒ·º¿—¿„–I÷Ñð€&ÈdÒ2/–GI÷ÐÁð€&ÈdÒ2/D‡ÿ8Æþ«$†í¿^rhG`;&†€JZRº4 7å‘…Œ@¾žL&C-ˆå–_ÈB1ÿó/ƒ2}€>€&è@ÐÞ<´­$û€éÈ >Ø™/x¹ÜEú†öÿú’=ùëÄ_¡H`‡ÿa ÿ©#Û`Pê@©—ò @ C2#ÿÏk’VLä0¡þ+'‰;òsÝP@ CB#ÿÏkÈ–‚iE†´„¡8GRs{rAYÊ¿Ñ7Ê &zØ Rh1dÕ 5 €ï:QÛöA7lâ¶¾ŠÌðh€ I :/|1<•ÌI\äàë˜XbDÔ ´$4DÖ%£Ž*N?yÄÑ¥†9]g¨Ût6ë¿™‚€(Wü€œꀂ`ÀŠÀ•ÿ 'ßúœ0”piCp¡ˆ^JƒºÏz`ùàQÄ€.ü4´Gæä1+JÉéÛk¹)ìð—Ö< leòÈ@ €v°Ð@ÎC ì’€ÀO»ãÆ9 %÷À: äÀ,))ÐK -ø÷ Jy>ý’’XÝÒ5ß|îãß-"!^L|Là†¤4šXNÉa¥²yÿuـĤ”€ÿ‡zƒ>ü×Ç¥)z=ÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊGR‘)JD\¥)r”¤EÊR‘)JD@#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”Wß}¾ù¾ëßs÷éH‹úHP@2 Hx€†ÿ˜%%8P;DÞô†`:O(šY18ŽŽ½ù㎫»æNÉþ{„0_³'=ºHC½þŒ &ÓŠ (°ÔóR:ÛGûÀ&5ˆ KA ú8€¦n8!ÿØh¦<¬=Ö*ùV&ŒÌ#1t—Ò|‹Õó#4bû,QH@`b1E²Œ­¶;m5)w~ë±f¿«ë€6~p¤0Ò€'!•ÐņBihìV;¡XA Àb¥–°Ä Äá¤Òhbòœ´l÷ÍZPu8jy÷ è L™í@Ã%ÞÞ°‡¿&íŸò“¶ÇðWKG¯vöF_Ý P×–Ÿ€cóó€`Cà|¼¸T ‰@T„M!røÂiI),=“·¼¾&§L”ôŸr“@bJÍh€ÁÞÚê€/X  P @°iNbn=wŽn ¹TºPžW}×góæ¿·;*vá) Q!¡˜?虹aŒ?ý#ÚîßœP”(Xшqíœ.á@cÐO·ä!w÷ ÀÀ@§€(GÀÎy ›¹AŒ?œ±{œœ€`Ra0@„(¶á¤ÒˆA¥îY¬JGÛ ¾<’jS6/ê€ {œ¡Ò³_Õ À?0R`hÐ$"² rÃ@¡4¤gÀM(Úù_>NMO¬·!“@oݚ̤ Ír”¥½õ@üÐI Ô0ä$>?Èû/ýœ âoŸ0|€@@0Ä–Ç–•𣵌4˜L&Œ%bÉIÅ¡ÌGN;‡=ZxÞ÷9`W¤3:ÓÉþÍ)K¢ÎâŽû}Õ÷^û™ï¢€%4 éHÀl”u¤NÉÜ€õ'ó÷÷Ρ¿ÖDÂjIAUVMþ† 0 &,”C&“€ðiI+…'j@P–J!Heð<RKáHßß@oÙ»|;®›Ñ™# V'\@¹‰ -À,T °Ð Ø¹87È@0 JYD±ŽG½H €à0E Á$€¨&€ðn_ýåºm0¿;积¶`B&€è ƒ ¡…“ B;”Z9IË5 Ûë“Í“§¦k­)ž‘oe³f¿¹“@5Hi>ÇîZ{àù ŽwÍA €L°{PÒÀÊzGҌٯhð€0j® å‚ñ$¤4r>;ßYnTìÒÄĀĘ¿‰¤$rÔ)FÃJù…ß‘ôY€v’bÕ“£¾n»’è0ЩØ@:/£‚'ý§t0’þ`ìüUð^7ïÐñßíüCO¹G¸y”‚}¦! ¿®€--  €0@‰€;ÔšœžCI˜YHæ#d#¶×í€ €9!;a jQH&£¥)Ñ Øü­µñœ_кyµ€ñŸ} .سýîòÀ28¥ƒè@T ô$4h ƒ gÈg%nÏxyrzºƒ@Áy6I@Ü×öà ? 8( €>ÅĆ£§€è†‘úøÞSfîpÐ@G @’À`„€„ ?û†g FYYj‡Â/Ý3bþïr€÷8:ÔÌÇßèÄ££ü÷Êûæø:À` @§ À0&“VÃPŽJÀ+/„ ?ߟøk’P„±¿nG‡©ôp ó àr`q÷ë  ƒüÇ †v²ˆNœôHUæÆ÷§ï´45!½ýŠ‘pÎ"û™4@T†—ðÀ ~éJð cÁï†UâGju˜!€Xêw¨²‰wëA @L°<&”²4 'ÿÈ&†$1,3-“·kËJ”ôŸ5¨i`e=#éFl××Z  HY (!•¸ ‰¸ôñ8ÔqƯ«€=(né) :,4¬ŸôLÜ41‡ÿ³ {_‘©A¶À¤37^¬²fH«ýb0  À1N@€`C!þŠOØ_K Ø_û_ŸË÷èGãþß…ËÀª}ÏÀ3ÀGHž+°]ûà@>JNy(4†…†°IAœÄ§œ”ã6Vx¢Ò7ÍÿçÆí&“Rߨ¡)JZÓr”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥G".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)GH‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥G".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)GH‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JGR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".RG”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/G ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".RG”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”G¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"åG)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹GJR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"åG)Hˆ!#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹GJR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ"#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".G:RÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿR”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HˆGPà8„€!Z/UÁÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®GºëÇ ß]u×]u×]u×]uÑöZ뮺뮺뮺뮺äP "ºë®ºë®ºë®ºë®ºë®ºëÇ ××]u×]u×]u×]tyT¹råË—.\¹råË—.\¹` "ºë®ºë®ºë®ºë®ºë¯7ûÈàØ6ýû÷ïß¿~ýû÷ïß¿~ýûä-ºë®ºë®ºë®ºë“€"ºë®ºë®ºë®ºë®ºë¯7ûø1ø]«ýÞyG@ë]{ó½{Ý.»7ïß¿~ÿëM»Ýoß¿|…¢×]u×]u×]u×]rp"ºë®ºë®ºë®ºë®ºë¯7~ý^ý~¯ßx<ÿý¿~ý~®½û÷ïß¿~ù E®ºë®ºë®ºë®ºäà"ºë®ºë®ºë®ºë®ºë¯bã®ýû÷ïß¿~ýû÷ïÍy>½ûôGÑ–ºë®ºë®ºë®ºë®¹"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºñC÷﮺÷ï—^ýõ×]u×]u×]u×]uÖ"ºë®ºë®ºë®ºë®ºë®ºë®ºë®¹|¡úÁ¬U]X±$}]u׫¢×G××]u×]u×]u×]u×X"ºë®ºë®ºë¯?~ýû÷ïß¿~ýù¿%ïß¿~ýõïß¿~ýû÷ïß¿}uG×]u×]u×]uÖ"ºë®ºë®ºë¯×ïß¿~ýû÷éz~ýû÷ÿ_íû÷î{–ýû÷ïß«Óõ{÷ÐV\¹råË—.\¹råÓ€"ºë®ºë®ºë¯?~ýû÷ïß¿~ýû÷ïß¿W¯þ8EÖëw¿~ýû÷îõzë~ú Ë—.\¹råË—.\ºp"ºë®ºë®ºë®^(~ýûòW›®—`ûÿúÍû÷×¾ƒv¿~ýû÷ïß¿~ýûG÷ïß¿}u×]u×]u×]uÖ"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG5©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ뮺뮺뮺뮺ë¬G@°Áàá$¬H„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGA°Áðð HDMVˆÿüüððÿ¸ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@ðÿÿÁð cÁZ®ÿÿÿÿÿ€4çNÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG · E‹œ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPàg„€!Z/qá_ÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®GºëÁåþ—0<‰W]u×]u×]u×]t>Å¢×]u×]u×]u×]uÐx "ºë®ºë®ºë®ºë®ºë®ºëÁåß]u×]u×]u×]uÐû\¹råË—.\¹råË—.\° "ºë®ºë®ºë®ºë®ºë®aú Ûeß¿~ýû÷ïß¿~ýû÷ïß¿~ù\¹råË—.\¹råË—.X"ºë®ºë®ºë®ºë®ºë¯—~ýþ®ò68ŠkG¯ynñõ“ì㌾ÕvÓßÿ{úG‡{~«×[÷ïßý.GÖù\¹råË—.\¹råË—.X"ºë®ºë®ºë®ºë®ºë¯—~ýû÷éVïß¿_¾ôä/µ{÷ïß¿~ùråË—.\¹råË—.\¹rÀ"ºë®ºë®ºë®ºë®ºë®¾ZÁ»ÿηïß¿~ýû÷ïß¿}Ks¯~üד뮺뮺뮺뮺룀"ºë®ºë®ºG뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºði÷﮺÷﮽û뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®¹üúþº½ ªºë¯W]u﮺뮺뮺뮺뮰"ºë®ºë®ºë¯Ÿ~ýÿñíû÷ïß¿~/¿~ýû÷ûÅG;¿j÷ï½6¿è¡d ~úôô÷﮺뮺뮺뮺À"ºë®ºë®ºë¯Ÿ~ýû÷ê½u¿~—§ïß¿~ýûëßþ€sÛ÷ÞC@JßþˆÁÖúõ_ºN [÷вåË—.\¹råË—.œ"ºë®ºë®ºë¯Ÿþ‡A‹ÿíûõû÷ê÷ïß¿~ÿéÌ'{~ý^¸¯p7»ß¾½û÷ïÕë÷ï¡hôµ×]u×]u×]`"ºG뮺뮺ë®^ >ýÿè?ýª`ß@ôïoß¿}{è»>ýû÷ïß¿~ýû÷ïÿn@#[÷ïß]u×]u×]u×]u€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"Gºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG0zÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ뮺뮺뮺ë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬GPàj„À 1Z/âaZ/ŽWÿû€µóA€"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ "pÎ "pDAW‰‰"³Tæ˜p¨„ÒÀ28,p "pDA|”„à(L(M8,p "pLGƒ­3΀Qÿê` Âο@9`ò;ž¥^Àµ 0Näø ‘®ûüœG=óxƒÀgãDßèQÜóÙ^OΠÈëöYÎ:üðH¬N¾ÙÿêPð8+ÓúG(õ ½À8âq„èl9ÉáWÀþS³èp?_kðQ·÷P7€|0#VÀpŽÇ‡ÿµú ßþ{o§þ àá DŸÿØy!þÆÀG/P}ñ8,`Ä÷×à9€ Œ»áC„Ó‚Ç"pNˆ¡Â̇àðýïù<Žyx g¾Àf?¾B„8«€áýÈ<œ÷‘<Èx~¿{®8<*Ò*ï¢y€hVÐ,p"pNG°:NO¼?ý¿ÜਉŽàhŠx\÷úÀ€¼™áñ„^tx€÷'SÏ?Ç Îx}öÖ}|ŽO`¿Å…Öm?§ b%ñs§:ñ_‘/‘/‘H7§|ªªyý?õPè‰à¹ÈÐ Ùøû<wƒƒÿ€Ìt'ÁøŽ(œO¼P¬A¸Õ.þ2üs/§ À±À"pJ°àHû–WGÐÂOâ ÷‘ \‚ë<Ò5<ÿ`ËÿúŸè €Ìƒ…¾È“©çŸìe <ßK:ŸèX›ä ?þ`tzúù'ÿ´øÄSý)À6§Ž"pÎ"p9lèÇýK¨Œ»áÀËÿâ/<=€o©Îˆ°à‹œˆD¿ÙPˆ ÿb?а^­8*p"p9Ä‚OY¢ iÿöyìM‰á`98#ß tBÀGYNpŒ\Ñš"ô¢6”#d‘à,¼Û_S€"p˜G@æ"Sú܈÷ãoÓ0‘#Çž$Ó×òµö<Ž @~@;€r¼÷èpàSüÀÐáØÌÐ@ný5Èôÿ @X C×~È…ÿ~ê0u~…:¹àkˆjßúŸà,°Sþg ÈG=úÿ¾¿k„ÅÈ„IÏeÂ8"À¶€7à>à`v¥úG '_€€=¼SÆ€¿^4úñ‚oÐxÿõ_€ÃÿàiǶOøþ¸à"p’ôæ…µé/CÛÇéŽmãô?‰¾ ãD(î+Ä2ˆ´‚(eBX¿þÂÂéüXãÀ;^ˆ‚À=brì ð/0ø¼,é”p uï! Ùg>R´ÆŠ"ÓùãÈd ¡> A ?ˆ×¼Îieœò0{¬Èäp»Å‚Îx¥GP5ÿüi^Dp¡l¯ì@}€Èð:+7Ïï$;Šàï|qà,±à,¾#‚¡ÁWÀX !`,¾ ¢?Â#Û‹'¯c€#DvFéí-WØ ✎¬1ϾcÀXAx}ñùùáW°}ÀØp|O˜Œ¸¸Hã¸ç|D‘H¦‘Âà8 ¼D¾¢!w ¾ðXð_Øë;³€{48.ö‹'Ðå@‘'žÜÕ‡ÞÐgÿGñÆÀ²O€„p«ápákEêœèà"p˜GH€Â#¾÷ÌâOÆ´Ox§€;ƒÿÇ­k„Ì,{ˆ{@Ùñúñúòllà;È‹#ÃùŸæp^"(í¥àÜ7àP2þkð¹À<”ÿÿø(8‚x»ìÀ"ºD€9ð³¹°õÈý¹–õâà/Ø*¨ñø¬|±ÞúÙøãÀ_G¬x õ?ÃôLh Ñx©ùfuŒ½Ã€[¸qÁÆà߸€bÿü-Î|ø»ïä ÜÜ8ßß`‚zšŸì†ž8P«èÞûìÁkèÝAwÈ u¨Žµž­ÛÀpÛèXÞŸàÜBȧö€ÐùÂ2ÀËvqáP €jD§ú"ƒ7ÿŠ:ûÀ7Àß%HÓ/–<èäHŽpò3]SnäP óœŠo€? "_`59ÂȪuô?Ž9@>¾Àj`[*ù1áÀ:P Bÿ¡wÈG˜D[뮽÷ž  ÀXu~0 ;WþÀ,*ë¿@~:¿"‘+Gè‡WèQ®ûñËeÿd?ÂÕoË×]u×]u×]u×]uÉ@"ºë®ºë®ºë®ºë®ºë¯7ùàÜ&‡@GUïß^œ^QÈÀè:®òN£ÄƒÞß¾û"G·{ê·ï¿ÎpŠûñ‰×ò@DžìpU^~ºë®ºë®ºë®ºë®J"ºë®ºë®ºë®ºë®ºë¯œ7@пÐùdZû€Ëÿꯡ B®G½ÿè‚€<¯˜ Ç€xÍuøEU]{÷[÷Ë«ß}€¼Ž(WÑ hE.ºë®ºë®ºë®ºë®¹`"ºë®ºë®ºë®ºë®ºë®º ®ûèXU]u×}€vA'=}!W]wÐ8‡«®¼5N:åמ·ïß¿~ýû÷ïß¿~ýûä "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®½&t2Ä}u×^ÿôhg‡U×¾úÛµ]u×]u×]u×]u×]`"ºë®ºë®ºë®ºë®ºë®ºë®ºë®º¾À7Xö-K—.\ººëßzK®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®E—Aû뮺ï²põÒ=gºþ’ú®¿ú +[ïÀ·ÿK‘Xq®¿ö ÿªGÿïo¯þ³‰÷ü?ÿ<åk~îë_ 2X•øG`V«®ºë®ºë®ºë®°"ºë®ºë®ºë®E ýû­Ýzê¯W}*®øxø kó«®úp1ÿÿöýûª¿t‘bùõrP Y:¾‚€Yo—þÁßÿÕ_`Î$aç_Òä÷#ÛÿÄn@D¯8ðÀe¿ýÀ׫®ºë®ºë®ºë®°"ºë®ºë®ºGë®Ãô ˆ¯8<äHðµ9¯—ƒ@Ñÿë·ïß¾ñ@4 ,üŽOŒ ±ÿ`þ¾€Ñ¿A€H×ýñKW]{ÿÁ€8˜нûïä@5àj‰àpƒ  cÿð9Wþ Uo¾€fN·ÿ<…°\ à«~ûô@<}y0ù+À53WØýê뮺뮺뮺ë¬"ºë®ºë®ºë®ƒë¾ÀàØ YX­@€GÐ÷^ÁÌu}€ÐƒW]öàÛë¾. 'ÀG  u^ùè?üáõ{÷ï¾Ï¿ØÀ,–úëß}7ÿZß]ò"@³4@zû‘¡÷ú€ç½]u×]u×]u×]u€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®Gºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºëG®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G9Sÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬GPàe„€!Z/ÆAÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®GºëÁÙk®ºë®ºë®ºë®ºë¯R)råË—.\¹råË—.\¹` "ºë®ºë®ºë®ºë®ºë®ºë¢È>ºë®ºë®ºë®ºë¯|ºë®ºë®ºë®ºë®¹` "ºë®ºë®ºë®ºë®ºë¯¢ôüððaýˆäÆUÿ±@?«¿0mêïÀ€s_Œ@×­5w‘ûw­Bkè‚G¯ À?jü<êºÿØAÚ¾`ËÿúçWGà'Áf[ö²åË—.\¹råË—.\¹rÀ"ºë®ºë®ºë®ºë®ºë¯–º÷ï¯EŽ*çÑ€ûës“ÿïS±B­|úrU>ØËuwn( UÞŸ™W]u×]u×]u×]u×\°"ºë®ºë®ºë®ºë®ºë®‹}È{×éîÄpt8´¹{÷×]uï¯w¾\½×üp«ß¾ºë®ºë®ºë®ºë®X"ºë®Gºë®ºë®ºë®ºë®º-wÖ=u]u×}03 ]uß`áÿú¾Þ®ºð|·:ë¯]oß¿~ýû÷ïß¿~ýû÷Ê€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®¼ŠìÖÿ¨êºë®»ì…Õ×]u×]u×]u×]u×]u×X"ºë®ºëG®ºë®ºë®ºë®ºë®ºë®º> ï ׈¤ ]u×.ºë×﮺뮺뮺뮺뮰"ºë®ºë®ºë®]u×]ø0Ußdâ1¿j\7ÜqÐÁ8W]ú. þ:¯}{ë—þÁÿõ}xoИê+ô@-«®®êÈ Wè€*¿8o Õ×]u×]u×]u×X"ºë®ºë®ºë®a±ÿ ¨òë¾ÄGFð.ßúÑAÕ]wè4ÿÿ¿¥À8Õí E€<Ð'Ûë¾”Uȵ{ë݇vçu#V@ÜGXX ªýÖbÀo«¾@.èn<‚j÷û¬jîÐ:{W¾ºë®ºë®ºë®ºë"ºë®ºë®ºë®ÎLDìß žG¿ÓUïÑÅqêÀXjô\½ÿô €^WY•ÑäPfˆ¤5^Ÿ¾]{«¼ì‚W¿þŠWþÀÞ—Gü¯ÿU¾»Ïz …€_  —ý u]u×]u×]u×]u€"ºë®ºë®ºë®]tÕ']u×}{êë¾N0ˆè€:»ì8 U×zÓWƒ}÷ÙäPý]uï®úüßo®ú'à€¾®úâŽjºë®ºë®ºë®ºë"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®Gºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºëG54ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G · E§¼~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPà G„À 1Z16ÁZ/âaÿû€µóA€"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ "pÎ "pC øÖ˜ƒFñÈœ„âÆr «|68<ß8?À±À "pDA~T Þ#^4GoG¯#ÎDäZp^£Q—Pù ?ß8?À±À "pL~~”¥ô„怸)@2øUí0ˆÂÀç‡ÿÕ| ÃÀBΘÑ[ÁoxÑâ5ŽÈ·€6¸À;ÀíóèqÄkæ Y~š `ï~¨Ž+ähûœ8{(ÓþFá Á€9å΢0ðÕ¨ãï˜ ˆ–,,«âkŠ£R$‰¯!Âï<?ü ™Gÿ“Ï"Óù(ð:FƒÃµì ÷À.ôE”˜p ½éLJ_œïœàXà"pNÛÞ gp±b Æñs˜ ‹ïš­lðÛÐä@ï¿À|;f >ˆ³Ûèq®àFÅb-Ñà5þ’uð3Iæ ß)AB(Ü!$Káãï{ðŽD€ç"^$àëék#‰÷b›ºÍV4~uàk±X ‰"jbG@V@ \¡ãE¼D"ëäàhLH×»|ìGœëŬqŽG™¶ ð»æ…_`À*¼ÐгðXQàÙœ£ÖG¾h]ñ±#¬uðÈ<¤˜’$ "pL„¾,ëY9€6"а­s¬WÍüO<€ø0¢8ìï@^ˆÞ#^4G£xxÑ W"Óø%ˆ°¬E¾@"_ÄP\³nAÂñ—œ ÞXY¬ G¿þ÷Ø®A¾>ñ÷ûŸ„r%ãõsðŽD¼~½>ø1b ñ±üIV?‰"ká±÷ŠØ‰X‰cÈ·Ãç`ò=ó°yðF0@4³¿ÿ蟀DNµ#Óû˜ÀHø÷N9Ž?Ëã ‘„b%c°ŒD¾˜Jd˜\ "pJ² Á‹ÿΧúÀ9¾CÏ0-˜ˆ=©bÐä ð;p`pùQàhîA¾Dr ãà ¯£G ¾Ng¬béOjñáÀÓÿ÷ÙP /¡bÀçØ #SÏô×Ð<þ¾ÇUõ°¸8"pÎ"p8B3úÿ÷§œÀѸ<sͧ8E€lƒO€ç¿,t¡¬žó˜FàS‚§"p9ÇàhEž(ã…‘ïdG}±8ו€\ ÀûÐæ¶ÁäkæèÜëR§pb'˜‰È×pc€?˜àåHø~Gt(þ€]` l8"p˜D—gŠX ïÆ ‘ýóÌ£ÐD¿@yß;ƒGÿÙãÖûäOdÈôÿ«?ÿ'ß ÈÐ ¼\†Ùï.ýøè‹~\xX‡<Œ~â‚ïÈêˆÀ2×á€2_ €_°qTÿ‘¸IÞ˜ø~@÷Ì|? {Søh¤ÀðaÅžûõ h.ó‚ð\Ç`ò=ÎÄyˆG$k”àùŽ#ðlÿûÎ\à@Âr§øÜô‘«ž€ò5<ÿ±ÄDnþôàÇ"p˜DS $d‘¦8<‰¯…€9õ€9÷üp}ˆúÇÐá8¯Hüëϰò:” `\àâ í ?þ½Ã¯Àpƒu8л Ý·/‘«˜Nÿ‡ˆe‰u_"( ˆ½èQ®w±áÄv#=s¯‡ß~h€òuàŽ ßÿ@h||Û&ôGx‰W`ëŽ7Ž˜Ž°ëÛe‘°1€ â2Àâ,ÀïàtÑâ髚ꡯ¿,Hà2½ð Ø#P¾.` ç0÷ÂàxµÀð oGÌ#Ãð*¾`qP½€ /Ž( xXïcïeÀ€ðØŽF]2Ü<ëãˆàxˆF]ñc&¼Qˆœ²7˜Ñ$ á,‚ç#Xí{N€øO:h ï˜x¡œ‚5sG€â{Ðæ¿Ðàò4æ¿Ñ¨#@ëÅNQ<( .ÇÙ¢·±Èà?òP5€ <äKØÀ.@¬P Âï€[èpäHXwŽ"p˜EÞ"$°¨ÀëÝaâùÑÀ2aÎÔà5DÕÌ#é`h 00ýô÷ÂäŠ2øü‰|Áø@Cð}èùôh–'»P Àî"Yáä{ôáàÄ&¼lâÂÏÄå§:s¯SGùØ ð‘|xòpööpâ Eà‘:øæqψY€à2 üp÷"Ž„ŒÜˆ…‘¬oÕ…‘îÚºáÒøuÛÜÀÏ8÷Â7Q¸·£æ¶Áäo|ÀѸ<ìarȘo`À«Î…„€m,`tûÞêÕðÇß:c¯ÈW#@t‰¯pâ âÛÀ?âq³Þ~;¤F€|ÃÁƒÿï„nÃÈ÷GÀYp áø<çÞÁäo|tŸìq>ÿ‚‰ôN`5@ãÿ÷Ìž0a`-¾@-«õ‰Æ€„@Ç"p˜Fðß@‘¯ €Øuö8[â-õ$îùûr%õ-ð0ý<ÿBÞŸïp5|#ù8<|Ñ‚§Ð{Žÿ¾Ïç€Ìâ¯Àáo}¹€5×Ð¥x°¡,GРó 8>È i^ìFaVÙØ FG2 ÿÿÿÿÿÿÿÿÿbo¶èêûc€[y ˆ ¬ãßDS@äMˆ$aaVöÕ{LYÌhžÀ.ö@kìð€Ýô 6}šA?;Sƒ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ!"pÎ""pÎGPà„€!Z/þŸÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®Gºë®Ãs¤´Z뮺뮺뮺ë£×]u×]u×]u×]u×!À "ºë®ºë®ºë®ºë®ºë®ºëÇöE®ºë®ºë®ºë®ºþtø‹o®ºë®ºë®ºë®ºë– "ºë®ºë®ºë®ºë®ºë®º ®¼~óÁ¼V&0HÄû}uÿ®ÿ`‘‰õÜ$ \ }}oßý8Äû_yä@¨À^¾@ÉÿúU~``9W«®ºë®ºë®ºë®Gºë–"ºë®ºë®ºë®ºë®ºë®ƒyû'|í^ÿZ@æ"Zý~¯ýü€åý>·ïß]{ïÇ"ëúl»}÷ß¹nu×]u×]u×]u×]rÀ"ºë®ºë®ºë®ºë®ºë¯6û°mõ﮽÷ãŽ{÷éû÷ïߪµ]è<.ß¾ºë®ºë®ºë®ºë®X"ºë®ºë®ºë®ºë®ºë®º ¾€ZªºëçÒë4Y–ûèGÀ=¿È‚tðÕ׫¼€œë4Œ@µõï®û˜­ò뮺뮺뮺뮺ë®X"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®¹~Ôûaúúë¯W¾º÷î9råË—.\¹råË—.\¹u@"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºGÅ뮺ëþ–48‹o®½Ï}u×]u×]u×]u×]u€"ºë®ºë®ºë¯?~ûñíù^×ÀZ:¯ÜŽÈ. þe~€°_dáUö6a7ò h‹m_`?U]u×G]{ë¯}ußOoÜ¿; ‘*ë®ú"5þÈ!Výõß.ªÈ¶ûèpÍW]u×]u×]u×]`"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºG뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG>„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G · EµÌ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPà^„€!Z1¡ßÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®Gºë®‹]u×]u×]u×]u×]u×]u×]u×]u×]tp "ºë®ºë®ºë®ºë®ºë®ºëÇèµ×]u×]u×]u×]w§Æ‡U×]u×]u×]u×]uÑÀ "ºë®ºë®ºë®ºë®ºë®»-‘u~+ƒ`××W|ƒ€ÜÀ5W]ô à«ò¯À9êï<)€ !W_à ˆ´hQï2  "pJÑ< ¼Ûæ¡À²ø˜Aäkù<>æàØ3’}ÊE@×WînsÃŽ8<²`Ê1@ëÜpŽé>e!g‰ uÅkõÉæox( ï¨n~‡³€i{ÝA×.cqœQ—ÅDõß0WÁÎp¸wïî¦@Ô8 ®þØ¡s¨ƒFþaÀ2¾ çGtnuñ1ðîó=·ÜMá¡ad@5± qÈ7æ~™göyë8|p3€ ´þí‡GÿÂ\@kç8wý`jÏßOÄ?ö0#€*@·Ì/§‚âû˜À [×!ÿÞ¹I¤Š>Ø P!ÿ8€ÿ¤Kâi>û` P!ÿ8€ÿ¤Kâi>È2Jj!àXà"pL‚>ì¾ À7™|u1õGôN„ êø±WÁÈJä]u `¾ÁGâ%¤ðìF×h€¤K@Q$i¼xYIäûâ<œÏ€éöyj0þE3AáÂ…Lh‚ñ¸ñk1ð¸9ÜE⢄B„_"ß;ÒN÷BŠ[Š“Ì–¾vÐ9ÉÀZ@uãð›œnE"W"‘..ó)Ÿ:ÍœÑ>î6= 3Ïäô€ˆs„ ÄJ4:äÈÿžG¼`àLh’&§ö£)F(~mGã@k°ØxPûãþX‡o¯"Ž"pL‚|7à?ùD ÂÀ~gÁxó,ÿüx§÷9ÀÝÿñÁó€q¯r*õÀ{׌||ù7øÐëÄ5xû⃓À\Ä ÏÿyÞ'up â;ÚóÑÇ `5·ÅÀð ´àxF¾:¹×ÃÛÛ—øú0Î÷£€qáüðü$‰p3<,9ád{âÄ”‡¦$¤8G|küjpŽ%LD ˜\@pö„Ž– `|ñB˜[¹b¢0v Õ…`øŒÐÌ¥À¶p“^*<(‹0ðü|ňšŽ"pJµ9€o¨HX§úS°ñWÑ« ¼„kŠ"Øy˜nWÏÇö\ @G¤A¯ˆ–?YàËÜÁòƒ‰Ô _þ|X½`€q}±ñF?^0LƉר1úè’ÆI¾Å‰½¬GuD@5Öá7ºÃ„H¤êç¸(§{}æ0Gy‚¯¹‚usß"]0vÀRŸŽ³ù]áâD.÷h0ÆË3|"ºˆ‚À|O½±¼Y¦? ˜ýp˜ØÚ&àÓºðº+¹>î rÏ"ï Ë~g 0P ¿â ð1À"p’ôà3—ÔÀx ßÿ}ÿ‘A¾‡€·_M}Þ«ä Áàà©WØ‚xúù(FïIsÅÇ€ÿHññ? ¾Œ#ƒ(Óýp8ÿýò¡³€fGKîÇ_^?_+$5÷`zìrÀÕô¡Ëýö8{ßPâ—Èp'´x{â80ÿý?ÔO¿ÿ¾Øûí”â@޾ð Îo;'ˆpbÿùÁ„o¸ÓÎ.éÁŽ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ!"pÎG9±ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ""pÎG@°Áàá$¬H„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGA°Áðð HDMVˆÿüüððÿ¸ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG · EÃÜ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPàÚ„€!Z1Rá_ÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®Gºë¯7T{÷ïß¿~ýû÷ïß¿~ýqo®ºë®ºë®ºë®ºë– "ºë®ºë®ºë®ºë®ºë®ºë¯œ58àÒ뮺뮺뮺뮿écDj뮺뮺뮺뮺å€ "ºë®ºë®ºë®ºë®ºë®¾pÝ[~ýû÷×]wÛƒpÛyY‘·úôo®ºïÀ"D_Ы߾ºë®ºë®ºë®ºë®X"ºë®ºëG®ºë®ºë®ºë®Cy Ýÿè,·ôãƒïëMêìX múë}~£N`}®-û—æk™¤Õë¯WÀ5‹ë~íÜÜU·Ò÷×]u×]u×]u×]uË"ºë®ºë®ºë®ºë®ºë®¼pÚÿЃíûë¯û@Ø„Ë>¯TõûëÐ3øÓŽEµò÷-ÿï·{”¹råË—.\¹råË—.\°"ºë®ºë®ºë®ºë®ºë®º çZêzò}tÖGi=û÷׿~ýõï—^ýõ×]u×]u×]u×]rÀ"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®¾Pýäp›?——.]gß\¿ôª\¹råË—.\¹råË—.\¹"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºÅ÷)råÈzž®_ôàp‰W]Gu×]u×]u×]u×]`"ºë®ºë®ºë¯>¿éÌpÛ÷ï¯ûx«ß¾½÷§ñ r¯}{÷׿|¿SN8>¹X2ørªó6t‹%×^ú뮺뮺뮺ë¬"ºë®ºë®ºë¯;ߺÝn÷ÿÖ·ïß¿ú:ÿ`>·ÿ¦#ŠÞÕë(Õøô1ßþÜÛ@Õh½~ýûÿæÝþÈ -·ï®ºë®ºë®ºë®ºÀG"ºë®ºë®ºë¯õÖýû÷ê½u¾º÷×^ÿåÉëóZªÿïnZúž®ù°:ÿü@ý^«÷S3Àmû÷ïß¾ú,|úºë®ºë®ºë®ºë"ºë®ºë®ºë®e²(2€šƒÿØ1oíò÷×]wÖcƒgÿÛ•O}wÈÕÝ]{÷ßB˜ÌE¿}ôE`6ß¾»ì± Ûë®»ìð€‰Õu×]u×]u×]u×X"ºG뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºG4ÿÿÿÿÿÿ뮺뮺뮺뮺뮺뮺뮺뮺ë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬GPàn„€!Z1oŸÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®Gºë¯—J÷ïß¿~ýû÷ïß¿~ýúu¾ºë®ºë®ºë®ºë®X "ºë®ºë®ºë®ºë®ºë®ºë®AÞ¢9råË—.\¹råË—._äoäK0>—]u×]u×]u×]u×, "ºë®ºë®ºë®ºë®ºë®¼[ÒÒ·ïÿ]¿~ý÷Ø@t.þ@<‚x ÚÌ«þŸ€°6N«¾È¤¿öEÕâꎑŸÃì(žA«ß¾ºë®ºëG®ºë®ºë®X"ºë®ºë®ºë®ºë®ºë®¾Y‡€ÖïôAKóÓŽÈ–—|€>õý>"[÷׿ò~½n[~ê‚×z¸¬ø€ƒ„ׯ#ßô=@v߹˗.\¹råË—.\¹råË"ºë®ºë®ºë®ºë®ºë®¼YôÀ.·ïß¾»à Fœ,jýi£Àkoß¾ôøìG÷6½8«” ï¯ý©DCmw*—.\¹rGåË—.\¹råË–"ºë®ºë®ºë®ºë®ºë®º,ƒå׿}1Z#Õïß_ò+/ÿ]˜yoÿLmõßdcGœ!tº÷﮺뮺뮺뮺ë–"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®¾túÛíe×]×ú]{}¬¹råË—.G\¹råË—.\¹tP"ºë®ºë®ºë®ºë®ºë®ºë®ºë®¾uüËþÑÀÓÿöùråÑ~s|`ysˆ–úå=ò뮺뮺뮺뮺ë¬"ºë®ºë®ºë¯žSÒ÷ï¾ÉÀpM]äˆø±ïöN ¾¯~ûÓ‘±ß¿~ÿú?Û÷×þÀ=öùÓŽ#ßìÒ-zT9b€gI»¤üÐë¥z8寲(¤z¹u×]u×]uG×]u×X"ºë®ºë®ºë¯†š[žD¥î÷_²' à¿oõisØ]®·ïß¿þ‘í¿ý€üÐa~ãý¯Ë~¯\7ôüu¿@Õx™õ®¿ÖG·î9ßì?ýíû뮺뮺뮺뮰"ºë®ºë®ºë¯†FÓã°}î–ûþ5¿|½û÷×]w‘aö;úôæ“­ÿÖvo¯rüôxv«ß¿w«÷EŒp"=³Ç_×ûúGüe¿ôäc+ÒÁDq")øÂ@^~«®ºë®ºë®ºë®°"ºë®ºë®ºë®Ïf€ø UÞœŒ:Á¼¹{ï7ñÔWx¶ €¸(xg[ïÑÍoÝUßP ß¾ó]oyWú6>®º÷ïŸ@ÐÛ÷ÿ W¿ùOöÞ®ºë®ºë®ºë®ºë"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®Gºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºëG0+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G · EÑì~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPàU„À 1Z1ßZ1‹!³<3Ü!Àµj¸c€ÿøµÿóA€#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".RG”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”G¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"åG)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”G¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"åG)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹GJR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".GR”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥G/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".GR”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹G”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Gå)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆG¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Gå)Hˆ #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹—Ô@‚ë€7à1„ÂiX ÀÞ„nWPŸ¯—_s1?êÌÿë‘.@!¥#vê4M©7ý³v]üø°x` KމhN B:G„/ñW¾Š€ ÁÊ#ß:¬èÈ ûm„H™Ý)J]w)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)rê+94 À;¤Ï±a…:?ÛçqÞåÝÀCp Aº€Ìå£qú|î"þŒ?œ¼ì0@¢ò 0Ѐ`oܰÐÌ”ý›8}úø(ÀCP GE¸@BR ß#e™­É‰ÿ÷ÿß:”¥èÜ÷)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘ #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)GH‹—ÜÀ Aú€3ú÷Ã/¹€‚õfÿõî r‘[rØMù@€fàQùÕôP@€fàQùÕ`!?ûô )J]Vw)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)rî‚ €jàE×î‚ €jàEÔåq¤Ä_Ûï‚€,0ÈGÀ[ïWÁ@ €dà ‚-çfŒ$‰nB?ß:”¥ê\×)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘ #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".GR—ÒõÀ Ë%–…ŒÙD0ÔøˆæaÿY“ ‰&¥°RS‘žüȰ@Êåð*(„É`§üŒ!ÿzPÐ@ü.à(Ã0òÈnNÁ™‚ýô"Š,šœ‚’ÒžÙß§ñ[/ûË@@P T¡ È&n½‰¡¥! ?NÚó° E`•‰ìFº8i|å_ á†~ÀTD•‡†âÀ J Þ<àP •Ë€hÑG„”}ÐZîGϯ°=0rÓ Ø Š_ü+àÒƒÒWãF×?ÊÌІ¢f+–ƒwÔ”—o=¾æbÔ˜#ÿÒo†_s1?êÌÿé6€å"²!„ß—8ÙØòi ´‚Šý)í²ÀisÀ5Æ€bz`¢À®À%- 6G°ÂÓð¯§a¼#?•|Å^\€` @bƒ@Lß>GÄÐÔŸ€Tý8{\¡¤ Ä–4¾íh‚Ó³ká“ð‚@)È ÞQ5x9%mÂõã@1Иg,A¯ñ$¤á… N"ç×Ù@€.¼’rB4—Ae$BJý)Þ¸à$Ѐ' Ù3ýÊùñ‰A¨ã÷Õ–ÂÐå+Šï©ÄÔî»ø + „ÔR`a5€Ôdàüõw§ó\ÖÅ–€Ät–œ„lý?¶Ø_÷±Ä?,'”G ?À|P`r~Oà5ê@À–ü†“ðƒ;vPN?ñCµêÉ„ Ð*Z …$4´öBºSø­—p€A¾É Ý“L@]ø „XÕ€`†{…‚%怀>rœ“À¡7œMl7€ »q â¯vL7RPÞB uŒ,šVHVýƒÚí?`ü’pØ,˜°‚Ô’¸‚Êý)ÞÏ€è %Hûq]Èõ’ñGë¿—€=ÕÈÀ K4˜–S?) Xj9: HÒB!í B¸j Ù€DžN¾Æ°ÀNX!—ÃKm†óÛãÄÞ4ðÿÀ†à ÈõbúßaôàßÒ*þ[zP úà4Š@tM&í)FGrаÔru毰‚çô†‚8®  4¶IÍfžŒúü€ €ù0 *GñI/¤›ƒVÈ=þ MÐ~– ‹åè0°§ýÉAÉù?‡!…ßUAiCŒOÃsvÿ>ÇëÍ€`\¼òb ¥LRs¡$2ÐPÜ?#„°¿šã:!#¿êý° Ë÷Á(? .À0ÌÂrxaò` @0bLO(›³ò`j’% ù8GqWÕÀ€;e²@b: ý°j‚Êq}Œ]B 4A¥CÐY_G%ô’bax!B÷}58ûüóKp` @ @šV‡'+ØoO££ýÌísn÷ìÃAò@’¹.„ôvA1•ØêåhZ€ &&€ŸòÀ¡0˜‘‰ä<ÿùÙ¤–â¾ÌpCÿ‚#ÿá`_ÄÀ¯A3_JBýÓÔ¤co4à3å>÷@ Ò*þtp@üBIø@&,7JXqÈO úp(†Ž€G¨Ô†Fð’„ nÐ` À’Ê%ò0®ÎJ,šV,þÁÿ^€ð€!pM° ɉ&ϾøzМ#Ó€t®¥~¾äyðÒÀ…ü@à &rL¸ qh98䣎J:÷°ßrHì4À$ÀÔp,”âƒPbQù¢×ÃUÛåïŸ÷pÀ Ÿ1ÜëÂÉx]ÉÃCJ&’ÃR‚Œý)ûm…ÿ/ì¿}€”h°*’Gb~Ðgm²‰iÀ}#ÅjˆD.CKel‘i¯Éf”p“Ð@Oðßq û§€D×T5Á À-î—»€ €¨¤Ô¡0²ii9oøuæ0 ¸~PÐ ƒ7“Ƀ@£ ÷ð(òàrÜ —Î#_”À?(à§J 7à±a˜JvÉÀ’mxò‹(šŒYIAhN|”}÷Ã÷ʾþ €Gbq7“bB,„^18ñ{ð½þ¼Ð P2Àí0!§ð{7X/œœ;su¡440Kâ)A7»&þGw A À5p"ë‡w A À5p"ë¸0(ˆö);ˆ¿·ßX`*#€2·Þ¯‚€,0ÈÀ[ÎÌIÜ„¾u)KÔ¹®R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JGR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥" #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥"/ª¤00À÷dä (iV¾ê”ôÿÿûþ?ûä`ù‚ ö8ÐǾ¹×––GãýÒC$‡_ÇÁ .@G“Q’°+à ƒ ØwæûÈðÔúð(Ø:Øà @IwÃR’ý‰HÛZÿ‹GA{„æJŸ|;ïv,!4Ø Ë‰€U¾ 43ãöàá×&•âӷή}-®_r1?êÌÿï‘/†ßr1?êÌÿï‘.P €r‘[RØMñÁ À2(à@É{%:+†·g#‡{ä) OçßJ@À€gÁ Àß9˜G©àe‡mÌ}’ ¡9ùH% J ¾å|˜!€€A’F¾÷`—ü¤‰¬†~¿†ËX—ëø1‚¿œ´^`†£²R‚R8²ÔFz €\tÁòÜ@TP¥9>鏨RE²@¿®ß/`è€NZ7ØÐ5þYAœäaÎmö\~¿<˜ø[`cHë%ô£m‰™GýÓÃ6¸ P˜˜,@U°Âó}̇|~òRôò~î÷3_ÞÀ€`€Àt•„ý¸ô¯,xàCpä{X ~^Àƒý]°c…Yü`ŽÜy)ã@£EÕ³Âïå·ØAóúCA×ǯ°‚çô†‚8®À €'â,Hd€ûÖH’/fÂó•’S‡â–×ÃK îÙXuõð@œG_ÒãˆA¤kä¼ú@5O°ªˆYOz€† àì„XJ &¡{>'ß S†‡v¿<@& pIýC?û,ÿõ$z0ê,:d”c |òWoyàAýG0œ?ÏHÁ4/­ PRÑ’€À¥ Ûï€`Cûînø¦úPAÐ Š@‚HPM:K…÷åð¼@š èÌÚü(X0 @0J’CH\ ÷sPü0î.úvírÁ@‚( ^ A4è :Ä@HðI *  d„fÉq?TŸÓݯã@ €cÀ5tbïÒ²D¡DKXH!€¸ Ž„G]"Ð`&‹BKÁ¥$¤ìêNÞ †à‚8ué³UJE¹p¯í÷Á@ €dà ‚-÷«à   @2pAãÌIÜ„}ó©J^¥Ër”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)#óô¥/ ¸.R”ˆ¹JR"å)H‹”G¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥"/¶Z§Ì°Ã(Àe)wÜ/ÎwÖAõÀ ¸š€é : î–Îdó÷ç3Üvr¹«Öä4~(ˆ©@ÀÒ_ô­Š-ý‰ ò¯9~‚0@¨DÔÀ jC AÝngº¯ BÅGÅ`Ð@ÞðÒœNßংÓùLÜÈ(›¶o,º`5€€Äd (ð›$7pŽžb¾¤ì?TèÒ¸c”:’‚fû§éÿ¥…f¼Ø ùÀ‚@×ÀMÊ JRy›Rwûkùõ÷ Cþ  Áþùøm÷ Cþ  Áþù@å"³!„ß’@È`Že o_E@È`Že oVG¨!ÿ߈ԓ Ðf` pGTß{¾ÌÀ@àŽ©¾÷s€`HH›RúþH`4r<Àà à€2Ú6t•°j67•( !€ÐUÈ÷]÷^êâ=Ö‘„?Ç$‹bŒå0«ý|P¹@À h S`ÀÔ£’#ëè à ‹dYHüDßÒ[)žWãñƒõÛЀ>!âƒxaxÜwþ;á^óGƒJÀ; ÍÅït! a7ùþpÐÒˆE$²Ó„oÓùÛkéÁ€ø€ä1`0…¤ îZ9ù:î7+¼ž%R€Â`"€)3t#€­ÿJCû]¨Ð7õ¶ÃÞÇÐרhà À¨Ä„¥ŠVV¼Ø à!ÿy À‘ïoД3ïyó(}âûÈ`ŽÜppÂgØÍn…§_Ë/°‚çô†‚8¯_aÎ?é Gp #]ÀOÄXÉ÷˜èÿ¯‚8ß&çßY:?ëàŽÁ·É¹ð˜p‰‰a4`ÐG4‘½ú†ö´‘ïÏdÐ ƒAÒF÷èB!ÿØh ÒG³À¡ÄZˆf_ÉA KúMä¯Zp`*X#ÿÒo%t€ìÿí"lƒ ÿA€„ÿà†ÿöX×ß0<0ˆ#ÿÖ_O!ÿÁ ÿì°G¯¾`x` Gÿ¬4¼ð‚pë 07âïDª`0°ï;z @ýPC€€ˆzD Ê®d’8‹ûMùüà!€xŠ#_ /Ïà À@à QáÌM¹ÿ}Pp€2ÞËå ÛJ÷ÚïΟo¾ù÷ß|?{í   ƒ@Ÿý¿„ßÒL-”°~sâ5@æåéÐmüĈž¼Á G )›ã_Ä}yð¤}úà`'pM¸ yI;ãМ9(êúòHÄÔ`H €uÒ?rö‰ùd0ôþR÷t 57×ó0 @”€, ËQYø±Û ÷·¸?MJ5&‚ºy(41øÌa- ü_@Uî@€'ÌŠpeìVî€Â°Â°rÿâÿó.d°à1@!eX A¿ò66Ì0p3ߊçMG!¯ðËøiäÀ C14„‚iI9(ï€ç}Ø)0ÔÀ‹®H 4€€ ` ¦bƒ3 üÔñ~ë‚ €jàE×rèc†â=€â/í÷Á@ €dà ‚-÷«à   @2pAáÌIè!|êR—©rÜ¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EGÊR‘)JD@#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".A_t'd¡9º>}ðï£HÊ‹õÀÁ À.Õ<°¤DóÐÀd™ø¤tä ;°«Ñ–€ßp,@4/?þ†£…raùtܨj‰µäÄ{úP €G5O/ø ˆ`%“RЉ÷‡h @‰(\4´–IJÃzûFdlOs_ƠЖ›$mrö€‚ ø È`1àÀlrúI@ƒF9ƒ@+C…kÅÒÐ0š’gtJQ’}÷€ !§„üèÙ€,¸"ÿÙnN¸4¤ÃKá½ùð„df× à:9Ñ4 %’º°ÖsYó…Þß"#‚'ö‚P‚wGûÞ”†Ë&8Î|$¬“ïXÀ 0€ €&Á €Û|KJu!©`»%)ZSÓÿæËf·!ˆ@'&$„CM -] 8qß^äð@àÀÔòÀ0> s‰€W~Œ 5–ÅÞ–a„2ÃáÕ$¬“ïêX¯ìhLÀÉ5,œy À€à`œMÔ4ä¼¼·(™¸µô–ØUäFññ²HCS˜ê±1ýh0@G€€jX @ p²r6 À:‘‘™\ÒˆÖPÀ€(H²À¨¸øÒ¹C* æ¸ Ë#^r•€—Ð1ÔÌd€Âî^°˜ z€… 1à€T5A( 2HÀL҈ד¥ `jC;¢”£$ûôÀ   à  àY%€*š4ÒÈ×™ô¤†¤7ºaÈ:Ù(ŽƒŸ|¯wÁP”¤µ†ÿØéÏàÿG‚¤ƒi&8Ãa(É>ú` ` à:ÀTýËå`ó–YæR•–_-#yòÙ³_¼,2Ë Œ%¥)`§gîί2 Bè4…€v~KÉÃ)™€Énrid–Z~ âX3n÷.€pÀƒý€ 0±-€¸Â[0¡Âî}-‘ú>øÊ:ïß"¿Ú @ ßïxB À Y$°ŠGÌìk?`¹)dK ÌšÐVA×+`P„bH@T1ÐÂÏBH†î/.®–»ü½A÷ï1>&þX@'q0 î„¡l%‹ºà‚à Ý€n“¸kX9:ùdû•! Âíy þ‚@/“¸ ”3PGÿ‚Gþ†Œ`I?x0h,@LÁ…jSÇ¥'§Õ? hË Wô 1¹mzŒ0GÝ cŒX‡ Ö*[nß|eß¾D(°€,¿Þðà&†ÈÀPX°2b±D¶5gKúšYRÃs$‰Z È:å)Kj.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥" #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".RG”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JGR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".Rؘà0xL¸ I¨ AŽ¿øä#?üFº@€8~MÄÀÂA|€Ôr†ˆýN)ÞŒR~|ðö›áúGø7T¸ð0@b@vX7ü‚Rœ®UïÁðÁ 4ü,iI¬‘Îó/ŒCß(„ Ø †”€ Æ–œŒá™Ÿ€Žò·ßùÀÿè ®¾Iö@1! ˜Ãu†'¤ûzR—U•ÊR‘)JD\¥)~°°@üЉJ8û£ýÀQÝ€%¸ €À˜aa :%Œ)#9-;…ûî '?ø!‚?ý–5÷ÌGÁ vÿõ€— 7;¨ÛrƒzRݯÅÒ”»ì.R”ˆ¹u@€/0$`eƒÈ% iÃ×®UïÁðÁ À4ü,idB+†äs½EñˆþùD @ýÀT4 ÄV4´äg Ìüw•¾øØÿÈÿE uðÒO²‰ Æë¬1='ÛÒ”º¬®R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹GJR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥"/ê`øÉ&€—6r±Žë½±](Nè|÷Cæ5ðPG  4bL° Ñû,¢ÑÆW»|÷×Tð ˆ@Ä4^’ RWrMè%ngèB3ü/°«Í!ì¤mÏÄû °ÏÓ|À€§,<˜WH‘˜ûÜ‚á‚hÿøXÒùúR7ß@Ã0#ÿádk¤K¨#Y†€ãß¿pä`Gÿ¢€ºüþI÷è‡þ@&ú(k~ $û @ð}d#méJ]öG)JD\¥)r”¤h¿Ð€'?ø!‚?þ5÷ËÁ bÿõ€—ÔNðCü,kï—‚Äÿë /  †Ü:ë&æü])K×¹.R”ˆ¹{ð@ü0C€?þ4¼ïÁðÁ @ÿøXÒç€!ÿÚ]hMÇ¿|àÿÈÀÿE uùü4“ïÐü€LÿôP×_ŸÃI>À<YÛzGR—}…ÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD@#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)wˆ¸ø~ ÷è@‚üÁÿ ûæ€x€<|¿ë .Bh €ÁCF¸¦¶¨&ìÄûñT:—¨GÐ0 ü #û ¤Ósö³ý·÷æпEßžÀM˜À0p °Ö T@mÆ»Šb/¬ ÒYtEðývÀ Á À5p"ëíò€0µe±ÎE‚ÃI]™ïó¥Ò&€/t04P!8üt>·P}õð€% @LBÉ„"aX¢Q_€¤Y}N ëµd€ šB«ä1Úÿ>€èP‡8¤"#€ j aG#?k5ú˜M !‹ -%…ä£ýð¯“#,¨b@ þàT™·É_ü(î6Іn†î7?RQ7'±×äiIÃKA0¤–_ÈB7ÿó¶×]•¥¸ €9ÀÜa à: HI4¬É×Ó‚ëìÒB2RBÖSå/ü½…`ûØÜ!€tç/°¬}ºHlrïà@PØ'ã@'Ñ5 I¥t€Dïa¿EÞ\G0€`C z@©0°Ä”RzË ÿ)}i@¯Ôd‹ËâB\Lbý|?Bý|P©„ 0à+#ÚÀLd ëi(4—Ùšø‡àº>} ? ²ƒ/ à  $‘/~–*L¥vHbrptƒLJÉŇ1£šI£;1>ÿ>R¼À1(PvÝÒ²H8;Ô]7k-r/‡ëÜ‚å;°EhW !„G–àŽÁþúi˜X (˜Vt–œ„a~å&€ ”7¤`s‘u¢I£;3ßçŠ[<(°„  òøòùü.뀀! XL‹Ùx Ä` R(v6ßt–1  kgê¾i40„ŽXie#’ÓŒ'ö×@”³°˜ œÿè¦ v'ßlÌð€? á ;&¤5"ú°¤#+a»‰f -b­¹ v ¿Îá„ÐÂ1a…”GŽrJNJ8¿Ò¾}ô 'xƒ@`MHg7e¡"’ޝ„Ø@€1À ÃHD> @fAxtãP+‹¯€eÆ’T=ˆ TuüAðø_f.δ@##_÷A „ggu9ÌEöe7Ößµ×¾Ã0#ÿá`Kß8X 0ú(k¬ƒLJ%cÔÃêI4bY‰÷ð+ßá‚€ÿð°¥óòó{èGø`† ü,iX þFh=ûð‡þ@0ú(k~ $ûô€Cÿ ?ý5¿?†’}€ x>²¶ôí},¼?PšYi€òŠC ²$—ÍÅpžCïóü/bqÃx#×#^:ê, 0_C»{4q¹ïô Áþ¨#ÿÙ`_|¼ìÀ@`ÿXi}@à‡ÿTÿì°¯¸ € I  @t¤1 š4 öø¤3cR%ZòHerÃcZê+ŒKßÈ@¨ ÀtlàGT†L!nw -8¿ZÊVà7²37ã€nVqóßs!É ;-!¤ÒÒZWÒŸÿáþ¶éÀfZ{ˆ³·Ž¿Î»ïŸwÜÝ î` €jȽɅþá$$÷)8@âõñÀÀ P ¸¤•É%$ r'6é!€é$%Ÿ‡Ù”’&ù÷¿Ã0#ÿá`KÀ^ü? À ÿ…€ ‡ÿht@qïß8?òG0#ÿÑ@]~ $ûô€Cÿ ?ý5×çðÒO°ÄÖB6Þ•„Òi@P0°ÐÔäVéOæm}h8 ~° @–’`’(£™ ,7OËn²‡Ý$"H}JÆû2ËÅ_ËÀ¨° aÆÀN Äà<’iY ;“« € ÀþÅfoùØåoÿÞûÍ.0$K­@-ã¯ó¡ô¾âÐ` ‹À`¾Y1ÂHIîW€G—¯Ž:~Bn€vB9*J9å$ÔpÝd0$„/²(¼]á¥)oEÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹ýCÿ‚#ÿÙ`_|ÀðÀ@`ÿXi}<G ‡ÿ0Gÿ²À¾ù€ à!€€Áþ°Òòb` î°À…ß‹½@ ~€!€¹4ÿô0ï/z€@ýCrh#ÿèaÞœ¡:æ,‘Ä_ØïÏ 00 €#€0`Ó_¡¯Ï 00 €#€0`Ó\@’lB?ßX¤À`0GB.¾á|<¤À`0GB.¾áH@p̆I¿š‚˜ NxCCtôG ÎPAéJ:’)ß^4ÀPJ,@% ä σ‚t€ ƒa±¤Çâ÷*ë¤4òúÎê³(¬3_Ùõ€g°|B! –R?q‹oœs^@x^f8´’¸„ëÍáå€iʼn÷¯HØ #ÿÒ.“ËÍG·NZ‡ßÂS›Þð?$ÚH@P˜¡_îCå°›œïYþû ~ho,™yÔPGa[ UÜdd“V—s“{ Múr`ad2ÐVéI!ýñ @€€8&X É…œ?:@Îņp$‚¸B€ŸßÞôÐ €/&tç±E†àì«ãÉÿûœ$>S#*Ô˜S¯ÝäÐ\PJ Рw!Nã_M×" x€ ¯Ø°Î°~s~¾Ž,ëå¶À¤$ì “Ÿ$˜Y;>'뤄K)9ÿûõGë"Êß_ß Àd{íŸ7¾&R`4‘î €LlB$ß$ &(@tH&£ G3‡{ï`!`Rh ÌÄôpâ ùòú@ ~@…†^”X  +ÄŽuРhÄò¹§ ³!¡ó޼ €Éa„Ð ë($Àü}àË-ˆIiì„nŸÇl}÷ –ðRÑÀpœâÐn ¾h¦ÌG¢`¢BJÀ5ÛæçøyÒØé&æ/s -‘ÜËú8ð Òìçt±BŠÊו:h~rÀ3 @ÒŠsCy^è01$ÒÐQYÒ_ÈØþø@ Èð2 9Ç–•òÎKÄÀÁ˜ÕkB°ÔÞP*MÁ…“ŠBSÄl÷ÞÀ€fXð“@v_~Z{ A˜;_- äÀ@!û· ƒþ¾ãl’”‹j|Gí~H€¨˜š’hé(Îò’ Ìï“@À4+4ÑHÀŒˆéà+JwO÷D „€*˜–Ž‘iO¹À;©åý»m@aY¯¶Ü Àpı06&“ŠX¥lœ=O}˜P@0Øhˆy‹ OÜX¼+ߟ¯¨‚âP P›²ÃI"ú;buié%~êUdҶϯ¦^ÎG ‘¯$ûì €à‡üà:øÒO¬0Ꮏ~†`GÿÂÀ—¿päGÿ¢€·€Ã0#ÿá`K߀8?ò€#ÿÑ@[˜†øÁkú( ~"`$íì@öhÿô‹Çá‚ GþÞÄ !ÿ`€ÿH¼À(`„{¤°…_Á‹$ûëàùd.Ô–`i0¯ƒ•É÷È $ûÙç€4H` aˆ}áœð£îÐ' š³Ubí G€N€1!rû`ÜÇœ«ã<ûôZÑòwûîûã÷×ËÀæ€è4˜‚`ÿ“Q¶¾GIE‹HÇèHõ5ÎKd£8ümdÂöW¿ t€Å ¸$ÔöbbvÓ›[‰   ‰ˆéà†$QY)ü; Ž×Ñ À Ë_ñ0˜„†è®ûrI| ¥”#t€¡iN}öÝÙ–^Øûõ'ß)0€È÷Ûo‰‚ ÀGd{ŒP ƒíˆD›àÚÀ/Рà&!€À³ƒQöã’g ²RõÆ}ñ—7Ï¡@v  4„™!‰èø^¡4dÒ_N& ”VàyµáÁò؆P% šÆŽáøŸ{ŠHjP„géûl?þ«Ä /Œ›±8gkñ€ À5H¡¸0$á¼à£ï•§÷DpÄ2xBÐ X–Ç–“ÂŽ°^  CIeŠÊG¹ƒÚúàÈ\ €4Ô¤/€Ûü²5÷Kó¯F/t%y;£áû«ßsRà°€“HIÜ”ý!œÄ•Îa\À™(´!ã½ü¤€è8à7~Bܘœ-àßlDŒš¨‡ûpÒkÇ…=Äûæ@P„p+$íƒÐ’Rp¥æáßÛì ‹ÿo÷Z—@a{æýwÀ¾¬@1&ÜÀÆH”÷¼à@üà Gt”ƒ€“~Wðb8ÿÓ·HŒ}L†C Ù4²hjzK/ô§ó² (I-9‡n}DÒ÷Í—~t¼ÿœ@##_çße/?çÐÈׯ¹õ€fœ ‹"Þýø ~!€@ÿ ^ø°!ÿ þŠÞ? À ÿ…€ /|ØÿÈÀÿE nP`ûPÐßÀI>ú ~!€@ÿ _G> $ûè ø`† ü,iwèÿéäkÐ{÷À ü€LÿôPÖøi'ßlä`Gÿ¢€·ÀI>À<YÛúp ~! €˜†¹I({¹õ` c€4vN(š‡ÔE¾PNÛ€7|Z ÎM&¤0cÑ„ëítº¾0Ýb‹& ú°Õ%ïó§n¼½×èàôD€`xÝŠÙG]ºTf/gJŒû{Ê$¤r4Ô™ð¬_àd9:ô ¨OÃ?³ØbÑ;9 š€(Y5=±Héî+=ú †€Ü†)iH_¼xh ~°Œ®d”Bà9-*Hh¦1Wïkp˜™ÃúUù‚­É©Éê2þFp`(ÿõÈ×2õà€† ÿ\y=Ú°Cÿ¤‰° $kýpCÿ‚#ÿá`_|Àèè ¸G €éÂI£XÑ…š}<à‡ÿ0GÿÂÀ¾ÈиdRÌI\Z G"s/4šP t¡#÷ðj^”ú€ NVåÀ‹4¢nêº>œ@ý À +òa4ô4»8²þÈØCñWª`k±)!W)-õõñ@NŒt§ Jyó+p»è€ ä0ŠÙúCJÀê  À€ì°øJNØäcG…kË2H@39-À/~rCLÂØÿye ¢ÌÄû§òZoå=¬„$l¯ á‚€hÿøXÒùú{ûèø`†à?þ4½ý <`~ü°!ÿ þŠëóøi'ß ù˜ÿè ®¿?†’}Έ¬„mý„?0™ÊkËe†ð¶Íîa1r@†Ü˜ùC–GRþWRQÉ÷‚Íl @@P ÃÒXœnÇŽhw¾¬„ò“’÷Gß|~øÛœ $–LÍÖÌ"е&þÁ À °"p%À Á7þ¢ V\  _ðpMÿ«¶À?8T˜P`iàP†·/îÂź7èü×Ì.åPP®´ó’”ñYMƒþ»ÀbŽÀ_ˆ{,>u] €$)|L¸ÀMƒ }ŸPõGñX›ý˜ÀI;€ K|’ƒP°—ŸGý|ï©%NMZwû”B)ÀÀcœÔ€÷Ø ‰€À¨è@ ‰¥“ ˜$ óÊ;£„tó±¶04 ? û›B+­«øú{÷Œ:¼oNæ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥" #óô¥/ ¸.R”ˆG¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹ë-T  P ÀÁ4 CRk?GÇ£›¯­=.vá<à:-%c‰¡›–ðñ¨q‚Þø}ZR‹”„“3­ É¿Ñ÷(à@§`À4½ÀKðÀÌ/––A=ï‚ÐîJCœ. !§Üüg[ÖX`Þï}0A…€hPjQh&#% Ý GZ¾ëÞÃÿÐZF§ñö{5û°@üÀ €B¨Ðð€¨5ÀlL,5„’‘Úõ €9&=1a fRMGJR¢°ÿùG[kã(OAÒòjy·(` ÉE˜}§ ~ïlYñ½Õ÷7F—]•ý ( ™e–€:Ûî~ÉÜÐ1ú¾çî:úÀL@@Y( “HIA¥$®¯Ï[ýV~Íׇ{ˆ0^ŒÉÎ,Ûd“å_è (¢ K%‰¤Òø BKHR7÷ˆÀÜ D0€g’Rpby0“R–Q,c° ³ñÊñ4fdlŒ+5g/ódXnGviâÿyf "x$€PоBTB&€è€ƒa…“ @×(5 )9f¡;}p@n?OIö„0€Ý—IAƒ9öÔ¥.»+Üä;І€•qx‘Â*I ÙdÐ*€,—ï¾W&°q÷Ë& !øaX®’Yô÷90 ðÂ’ç ­% ûŽºËã|Ô¥ÑE˨Äp @@±hpGqåqcÑÍ×.”¡<®øùü÷öÐ À'’À¢CC2ñ ™¹aŒ?ý#Úï_œP”([ŒGãÛ8]€ Ô´íÀ,slTìªp €¢J çÉ»”°¯ðH„=ÌNR@.&‰€@€„†“CA¥£–(”¶}ñô“R“fÅýWÏ9C¤f¿¬€4z P4†I…a®Xh&”Œ£R”m|G§Ÿ' O¬·!À-û³*̤µû`@ü° N©Ø@P†z /üL ,7åŠÝ¯hð`pÀ @t’Àf„ šWéH {lçÿÊm|M è:@¤}˜` ÀÁC¤† îöÁ¤Ÿ{@ü° N©Ø@P†z /üL ,7åŠÝ¯*Ðu¸`h/$u @Ü×öÀ€ †j¤–ø4#Jý)mœÿùMµñ ÒGO”éZ}˜ ²™ª(¡cv½°ˆ v½)ˆ !÷å¿dñås‘]^ñPÝ­ ©&wÔ¥9wúà„Œˆ&¸¤®Ä›ázÐY58 Â’ZyÈFéO³ûó–&§*š0‘²f¸°x ,H¶³¿«€.6 A þ€1É3oð`"Èo3 &±W£ Hßœ€€ôdö ½NG¥’¯„rúa‰©Æ×€3ïÔò³_«00À@ð4 ‰ Q<›øÂiI K1ì½æ%I}'Íu–K/¦ÉfkûˆÀ5, “zbÃKûàþøo4•p€€ì𠉥–Q4'(4 e€Ô1Ì”o–óëäø5:<´ón^¯efö¸…‡ßßÀ1l˜Âúb ÒbØoG%p‚íÈBKùÝ?¶GÄm~pÄÔè š0„ FÚŒž5ù€X.þ¸Èøô °”L´¤›ºS‡WXz[_'Ð tø J (áÿš”ó7Ô$5)¬ºH`;I5Gk2ƒ2.^Ø?0@€jB6Ð!^€ÒÿÄÀÂÃ~Q¤­Úñ2äôhL, ’:” nkû`À€ Ã5ÒRø4!Ò¿J@`CÛg?þSkâE’| 7MiöG`T €ZÊf¨¢†:î){çß7Ü﹞ú(p@PÞ”€ìÖÉGt¤_²w`ý_ ýð»çPßêÉ„4“:‚©IY7ú` ØJ¤"i #ƒJI\«„—Ù§ŽÙù:üáˆifë¢ ¤¬ÈÙ3® \‰àrØÎ>þÒдȴ£¤˜&÷)@‚»%"”Âï’€>x`À0À:†Y|’&’&;X’”GÖ]$0¤5Gj‘r”¥Óer”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD@#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"åG)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹GJR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.GR”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹GJR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".GR”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹G”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Gå)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HˆG#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Gå)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆG¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥"G.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ!#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HG‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥"G.R”ˆ¹JR"å)Hˆ"#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HG7zÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HˆGPà!„€!Z1§Aÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®Gºë¯7}u×]u×]u×]uËß¾ºë®ºë®ºë®ºë®X "ºë®ºë®ºë®ºë®ºë®ºë¯6ºë®ºë®ºë®ºë¯Cû뮺뮺뮺뮺å€ "ºë®ºë®ºë®ºë®ºë®¼pÝû÷[½û÷ïß¿~ýû÷ïß¿~ýõ×]u×]u×]u×]r("ºë®ºë®ºë®ºë®ºë®¼pÝûëß¿~ýû½û­û÷ïÕZï~ýÞŸ¾G\¹råË—.\¹råË—,"ºë®ºë®ºë®ºë®ºë®¼pßøx[÷ïß¿~ýÞýû÷ïß¹n÷ïÝoß.\¹råË—.\¹råË–"ºë®ºë®ºë®ºë®ºë®¹a»÷ïߺÝïß¿~ýû÷ïß¿~ýõ×]u×]u×]u×]rÀ"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®¼Pýû뮺÷×^ýõ×]u×]u×]u×]u×X"ºë®ºë®ºë®ºë®ºë®ºë®ºë®¼Pýû뮺÷×^ùu×]u×]u×]u×]u×X"ºë®ºë®ºë—Š¿}{÷Ô îwïß¿~ýû÷ïß¿~ýû÷ïß®÷ê­ûè+.\¹råË—.\¹råÓ€"ºë®ºë®ºë¯>^¨>ýpGoéñß¿~ýû÷ïß¿Ý'yiðÌkô úo~ý/Oß¿ýÍ·ïß¾ºë®ºë®ºë®ºë"ºë®ºë®ºë¯?~ýûëß¿~¿S{Kûíû÷ïÐ3ïÐ3ïß¿~ýû÷ïß¿}u×]u×]u×]uÖ"ºë®ºë®ºë¯?~ýû÷ïÿ@ãÿïoß/~ýû÷ïß¿~ýû÷ïßþÚß¿~ýôœ¹råË—.\¹råË—#€"ºëG®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®Gºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºëG1ÿÿÿÿÿÿÿ®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G · Eßü~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPàG„€!Z1Ãa_ÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®Gºë¯—}u×]u×]u×]uËß¾ºë®ºë®ºë®ºë®X "ºë®ºë®ºë®ºë®ºë®ºë¯–ºë®ºë®ºë®ºë®½×]u×]u×]u×]uË "ºë®ºë®ºë®ºë®ºë®».ƒ8¿`ÿ~ÿõƒ¿ÿÛ÷ÿ°€í¿~ýûõþº€_oß¿~ú÷×]u×]u×]u×]uË"ºë®ºë®ºë®ºë®ºë®¾]íûëß¿Gu»ß¾½ûõú½ú®«ß€Æ*·ï®ºë®ºë®ºë®ºë®Ž"ºë®ºë®ºë®ºë®ºë®¼]û÷׿~ýÿï·×¾ºë¯~ýû뮺뮺뮺뮺ë–"ºë®ºë®ºë®ºë®ºë®¹ì»÷ïßþ»~ýû÷ïß¿~ýû÷ïß]u×]u×]u×]u×,"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®¼}û뮺ÿÐ'Õ׿}u×]u×]u×]u×]uÖ"ºë®ºë®ºë®ºë®ºë®ºë®ºë®¾túÿ@3¶ú\¹>Që¯~ú\¹råË—.\¹råË—.]8"ºë®ºë®ºë—ƒO¾º÷ÿÐrÿóRØ·ïß¿~ýû÷ïß¿~ýû÷ï߫߯߾…—.\¹råË—G.\¹réÀ"ºë®ºë®ºë¯Ÿ~ýûÿ§Öýû÷ïß¿~ýÿ´üËú|`ŸoÐ3ø¤úß¿~ýÿó·ïßþ”:ß]u×]u×]u×]uÖ"ºë®ºë®ºë¯Ÿ~ú÷׿~ú÷ÿÌ€ÿN8þß¿~ý}uúóÖýûÿÐ#[÷ïß¿~ú뮺뮺뮺뮰"ºë®ºë®ºë¯Ÿ~ýûÿщn¿uÛ÷Ñv}ûÿ×oß¿ýGãÀ=·ïßþû~ýû÷ïß¿}'.\¹råË—.\¹råÒ@"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºG<šÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬GPà p„À 1Z33áZ1ßWÿû€µóA€"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ "pÎ "pC Ä ž*€UÈúø00€³ïƒˆ.@ϰ¼X‹Èð,p "pC Äx{áãGïä ðJ)b/#Ö"ò=ó`Xà "pJÒÀk|À?ðã" ¡Ãïx  –a‡Ý%Œ#]ËÇÄsÀÐs]½ìø‚áZš e8u?¼ãˆÀ4<ÖòÌÇš(à®°@o€àjÈ ‡°}øO`ó/y‹~$‰ïàhŸ¡€´ãÄó Šçádyâ€ç'ž~q:üóÀæ3|FûܱÀN|yÐGÁ@>@?oÿ½Ø˜v9Û´ðc€k€ÕúãfýɈ÷ƒÿ“—ÿÀÏ•ÀhNX U|C‰ÀmAûfbñœO×à/¼ÞG¾l "pJŒx DsüƺöaÄ™8:€ 8O÷Ø÷ÀËÿç™x¨ü#Ãð1ï?àhDÆ^Ñ`5¬ÆäzÄ[¼Ì÷]Ž'Ù<ÿþ±–fí©kòí8G(×0GIøÃ„hp’ ñqÁcÿœðûã«—ÖŸ¹±Ö`}ÔlE¬v¿‡ž:ûˆ7ÀrÌ8BÎ'û3ƒÿß"¤1$x8"pJ‹X8ÂsBpx°;›_0‘HÖ$…Ì]ïÀ@H ¯1àê-|Gá„{àÆL`uñ±¢Hš±¢Hš™s…ˆÀ@œÔ œÜjšù€Ôî×âàeÿòpUì…Gh¨WÿÐá$ô8IŸãcÀ>¬x×Áˆ“/„hUOñîý0ãBÔGm¶aÆ_¤p Ä[âD—³ ì+àó‚Àêìå¨åõžø1¢yÌhžGð,p"pHƒ½)‰äl(N´Œ»ì‡b§úÈ ßm}0;ÿýòð\Ø Ì<ç¾@/ Ø,Ð/¡A턇¯ž¾qšž±àpŽ)tóËRœ~~´i}GÁa:#Ô(Eö Àê>–´è…®Ž"pÎ"p9Ì<Ì¢$@0m|Dù×À8¿#@>Žˆr1„T^àóú°ì#Jˆƒ@?¾x /ÈРPà"p:BH 4áôAcN_yÂán;ðkUÂcóÀY|‹à"ÇÇ f‹ fŠuÅ<‰<‹à @¡À"p¨Gs8G Ñ~Š~üÁ[ò$‰ïžf… ¼ðò0ðx`Ͼ`?8 Ÿ–÷è`ióŠ{ð,€íúP‹§ùôñ¤s©Ÿ)€v<Êàx¦ZƒÙwîG8‘ÿ†ð‚uù¾<”@ SÏó¯ÿ`ý‘»‡_@Éÿì|À|<¯F_þ€úøŠˆ€> ]ò`Ð ò#v9Kâ̾)àIà_8@€áýG"“ý½7k‘ƲZEó \à"p¨F pŠˆQ|E…¾?çßçßp*hp*nà;ð}Ôˆ£Á„DÁáãÄÎè<}ÓÈSïŸF€Šìñ.#æ"ÞÈ~Ge gT €À2……^Ò8zÂÀÜે—ãÞpâxr†g#€l«ýˆÇ€~}à áâVGPÉþ ýﱌ`Q5ðóÇ h‚€=½ÄGU`±B¡AäIÈÿ`»ä$(G‘ŠQð €Ø ¯;<À³«)²¡á÷ÂÆÖ6ø9à,œðSÏÿ"À:ÐBŸÚOôϾ@ñ |?•ó9–œ9ÁÞþÀ^9 ©ÿÚ`/Tÿí{ÂÔðrÎao9±Š}áäç¤{ùñÀ. 2ý z??}ȼÿ¨0Gÿ¾F×Ão¹‚õfÿ÷ÈÚôÀ2$¤EÌC;XGC€ @pu ˆ'ø‡  ã×{@èxñÄý|XÜ8,<."ôàÇ"p¨F>7€Ï^ͣƒÿ€§ã¯x¡_`Š'xŒ@…ð èóAžá¹‚q˜GüÚ4:Í£C¯ˆyä[KÜ,,ZÈŠ€=[©ƒøƒà:<àð6#^üÁ$l<>ÿ8ðè¡Úø\^ûÀh8{€|$|=G]Ž ,-¯«F3_óç¡K"Xqç1 ¸Uø ¿ÿÃŽ;ß›° ³w﯅¬mÿæ‚ Q‹|ÐT* oÍ@¾h*Ê‹Â-Ϲ¦g"Ìx¶8{ÁwÇ…ð­‚ë…q`2¾`•¨Ÿ£€XËåî`^äIξ#¸ Ñ1Üè¿c„piÿý~´ŒïîÕr ¸ÑtöÝ~ôÂv¯¡ÂÀ? °°ZëUÿҷ﮿ô?f†Õ×øÞ¨ÿ@g<‚.ß¡~úô+ÿD@#o®ºë®ºë®ºë®ºÀ"ºë®ºë®ºëÅ¿øHñÕ{÷å¸_ýË[ÿØ€>j^ÿ瀘 Că7ÿÛÿÐ#×ÐÉÊâíòÿ¤pw¥î¿vFÂí÷Ÿ@Î$áuøÕä@8æ“ÕcÇ×èx¡ßè …[G÷«S_ô_ð¼ÚR—.\¹råË—.\¹rê@"ºë®ºë®ºë¯?þ~D¿Ðá€=·×}=]ì€Ö·×|@$q0ýÈô¥]ú$Ûϲ"€dë}uï¾Ô±A@o®»è¡ùªë¯~üëÕè ˜?«®ºë®ºë®ºë®ºÀ"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®Gºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºG60ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬GPà1„€!Z3Áÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®Gºë¯—}u×]u×]u×]uׂ~õ×]u×]u×]u×]tp "ºë®ºë®ºë®ºë®ºë®ºë¯–]u×]u×]u×]uׂéù¢j뮺뮺뮺뮺8 "ºë®ºë®ºë®ºë®ºë®º-öDqªëáþƒŠ_j'“Èà.¿à 4·ÞD_°Û~úÿà=«ÿ j<«®ý€4‰W}¼Äk}uG×]u×]u×]u×]tp"ºë®ºë®ºë®ºë®ºë®º/ð8ßìÿýwº·"Z¯~ÿú‚ͫ߾½û¿ÊÀh"ÿc– @kõ^ÿô_þ÷ú#«}u×]u×]u×]u×]"ºë®ºë®ºë®ºë®ºë®¾]:½ú¯rþœx í?Õà8x«¿ G·Ï€ B€Yo—¿|»Î ¨S'ÂA»ÿÞ¯þµdð9oÝU×]Gu×]u×]u×]tp"ºë®ºë®ºë®ºë®ºë®ºZZ뮺뮺ï¡\®¹×}€nÀ5«®û©¶~ºë®ºë®ºë®ºë®º8"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®º? ì)u×^ýõ×þÀ‰—]u×]u×]u×]u×]Gu€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®]~å\ª^¹Ê«¯_¾ºë®ºë®ºë®ºë®ºë"ºë®ºë®ºëÁ§ß¿~úëß_ýoÿ'¥ïÜÿ, 0oW^ù{åË¿@€ªÿàa"À9·×_ü0A¡Öý÷áÖuÊõ×]u×]u×]u×]`"ºë®ºë®ºëÁ¦÷ïÝKßî¤,Pú"Õuß@È$Vëw¾ûGíuW~ÿj÷ï—þK"~Dƒ«ßøƪÿØåíúèGzqZýûåË—.\¹råË—.\º("ºë®ºë®ºëÁ‘ï²Zûð [Š^ãß¾¹uÿdOp ë#-ÿè€/ôNu¾^ùzïÕ`6ÿù˜ÛþÕ¯ôïøÇWÙBªïI5¿uûNx¢ ¿üüÀD(K—.\¹råË—.\¹rèˆ"ºë®Gºë®ºë¯žûïÿõ{é;hç»éZÀZÚÛÐi{ëþw|*¢Ñëß¾ôáÆ5¿}ö Ò ¾½÷Ù à7W]u×i뮺뮺뮺뮺À"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºG2hÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G@°Áàá$¬H„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGA°Áðð HDMVˆÿüüððÿ¸ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG · Eü~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPà„À 1Z3ˆAZ33áÿû€µóA€"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ "pÎ "pC Ûï" øRÇ@´& ,8€æ>Ðx}©Aôà¹À "pC ŒÜêç^¼TPyGG¾h’ B\th<>šÎ "pH„ýäPªxðÝÈ÷à²5ïs¼äIÎ÷ÄQ8žN ]ñ;ŠöÎmð¨2 i"€~@—í€@3|– àƒ?ÿо7 Æ‘ˆ8+“ï†ÁF²x!܉øºÇ_À3¾dç ôAŽq—Á@.ãšÍ1;˜Oð)È r4ƒÎ _£˜Ëõï ïz‡@2 AGaàqwæ,püzüûAúsð íèPyÓ‚ç"pJŒh2ÿü?€µï=fPÞ4œ&û4P¯¡Bˆ—ÄÁ)~«"û ‘Úo¡áúñv<ÿþlþú"cˆD¼W ƒc„m'‡iþ#ø aü÷ƒlA"J " ?ÿ¬ˆF¾ `a·À‹À’€àñÈ·Š|ÀûHœߨÀëØO"L`uì'‘/'B„ë7 Ä{âçÎ}èr.€Gér.€éñÁä áóñùáØzhˆ·hˆ·¼pYøqäCˆü*ÿ¿²½õ`HÀBðï|(x3ø|E‚ÀÁJ§ôÏh? €ç´„Þ0 §ŸÅùðþE¾mö8ìzÀ=UÔVþkŸ»˜yÔóm³c„€ø Ïu#DðvdÀãÿ÷‘Àh¯9…å“îUÄ\Á2p4ÿü=Ös.Åv˜X€;x9$’|ø q¾b2“ÿïÈÐcÿûÑŽÁaô @N†Ÿ@Gò+YÇ}¬²ä±â›‘/Oñ±À-õŽo£¤´À\0G_}Æøph!€¸`޾ûØÜM‰ “„XCìp gTǶrÓMpˆ”x¦ ¨ f;_z€hï< á‰fnÂ%ðdX ‘oe(@€8"„ªŸâÓ³@÷§Ä[ããE7³?¾åð³…ß"0 ,}Hªœà"p¨F"„b.èMî¿8<‹GC€€þ¸ú÷xg‡Gð@-¼…âHðû˜#Ÿ žù·Šø‰x‰ ©ùfp²=s Þ'ÌFä{òð±@BóÜnÂ@dDOû‘Ï}íDç Æ£Ï@?ÔÿÞŽáĈðáà ”€Äëô<€Ð…ÞC3…Ñ^2ôŠ©çþÇYc¥µü8,Ÿ[€x¼PÀ€×ï«ÿõà®` €”n ?ƒì€×ŠæG`Ù˜D<;ßW3‰Ádšøøx¯ $·žypÝð"ÇÞæ8úǶȷ´Ã€q9tC/ÜVN:þÃñ*e@DCµ! Ç"p¨F÷kè~² öhqƒÄ#ru±SÚ|þ$—ߎ÷Û}çž` N ß ,×Ê_ÿ#X‹ê4:Ÿä5Fq)ž0(O÷ˆ¸ŽÍ?Ó þ@:ûœm}ÚùÎD¤@ôÇG_" å‹WØ7€ ¾N`… 4-`/¾ñÀ/¯|ˆ‹p àën8€ûXæúbyà`ëÀ¶•ôÇ_%€Àä 6eøNbôÒˆ°.p"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ!"pÎ""pG?´ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÎGPàÇ„€!Z3PŸÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®Gºë®ƒk®ºë®ºë®ºë®ºä}ù_~ýû÷ïß¿~ýû÷ïß% "ºë®ºë®ºë®ºë®ºë®ºë®ƒqú뮺뮺뮺ë®_ñNàqÊû÷ïß¿~ýû÷ïß¿~ù( "ºë®ºë®ºë®ºë®ºë®º çôüóoúñVïu¿~ÿéÀfE{~ýûÿàå„“ª÷ï¯}uïÊû÷ïß¿~ýû÷ïß¿~ù("ºë®ºë®ºë®ºG뮺뮾pÛ<ÖýúëUïß¿~ýûÿßk‹Ê4øÀò?µõïß¿~êKW]u×]u×]u×]rP"ºë®ºë®ºë®ºë®ºë®¼pÝÿ쀮×-\ôähëŵ¿~ýûçû~ýû÷ᅢk•n¤µu×]u×]u×]u×%"ºë®ºë®ºë®ºë®ºë®ºì6€:<•u×]|ý€xmûëß¿}{]¼¥]ö0U×]u×]uG×]u×]u×)€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®\‹°ú뮽ûë¯ý€øêºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ƒù|b€:´uºß*—/Ju×^ê\¹råË—.\¹råË—.\º°"ºë®Gºë®ºë‘v^ýûëß¾½ûëþœx G_ôð€qý¾übp1ÿù®ôüW¿~ÿøð[÷p—m]{ö»z뮺뮺뮺뮰"ºë®ºë®ºëÅ®ô"ëu»¯öœx›u¿ìÂ/·_ðbmû÷ï¯ú~hqÐ5è¿tÐ`ÿýÔ$Ÿoß^ýûëÕzë~ú뮺뮺뮺뮰"ºë®ºë®ºëÅßÿhGÀnß}5¾¿ú ?þG Ç¿Ûsoß¿ýƒH½ý q½ÿj+}uÞ–48‹j¿tœŠ½oß¾ý «ßý,hqþ‘üM^ýô£Ò×]u×]u×]uÖ"ºë®ºë®ºë ü_}{ëß} ê½ûëß.ûz½õïß¾û¤{þ‰Õuï¯~úÿÈzA÷W}(wW]u×]u×]u×]u€"ºë®ºë®ºë®ºë®ºë®ºë®ºëG®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºG뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G · F ,~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPàP„€!Z3l!ßÿû¸µA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®Gºë®Ë`@ Õ×]u×]u×]u×]r¼ý 8A³®ýû÷ïß¿~ýû÷ïß¿c€ "ºë®ºë®ºë®ºë®ºë®ºë¯‘×]u×]u×]u×]u˽ s‘lë¿~ýû÷ïß¿~ýû÷ï’€ "ºë®ºë®ºë®ºë®ºë®º-ú0ú¯‡Þ~Ý#À- úºï ¨ cÀi€7°Úüìójÿé ‡U×>… ¯q*¨ ÄÂÅzGW_ýÏÿÕôò ]y×~ýû÷ïß¿~ýû÷ïß%"ºë®ºë®ºë®ºë®ºë®º.÷껫{ߣÀ[o¾D70·ÿ à5®¾ÇÕ×£–†»»í}uÿ o×ãW-û÷ïß¿~ýû÷ïß¿|”"ºë®ºë®ºë®ºë®ºë®¼[òu¾½Ô½ îïÕù×ÈP '«½:HµzÝUݤ]jª÷Ï€3ù†@‘ÀÝ\ºë®ºG뮺뮺ë®X"ºë®ºë®ºë®ºë®ºë®ºì´âp‚êë®»èP kìíW}‚ªð¿ûBÀd>¯~â¨÷×>€ÑË×]u×]u×]u×]rp"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®†°jwè°Óèµ]u×¾ºëŸ@uªG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®}€y°`x´#•Ë—/Tu×]u×]u×]u×]u×]u×X"ºë®ºë®ºë£×~æÕ߀hH6üG«ûã .—~ïu~ˆ`=]ø,(€].]u﮽/O—]uÿÁD½õ×]u×]u×]u×]`"ºë®ºë®ºë£×0ØæÙ¶ïuzÓÐ6G¿¥Gˆ­W_º¡ø>õx^A«ÿ`r}}Ž W\¿éù¯~ý÷§ {üz]éM/wtDˆ<©"+ìxàÛ뮺뮺뮺뮺À"ºë®ºë®ºë³èp¸oOOªë½i¯dx ‘ïœ^pýàÀ—_@C×ÛOÀ9íÕØ¨´ÉìÙ4¿W1Î"ç]` G×ëR¹ñcf6Ÿað°û\®d¬\Ÿ$ ê½]uߦGA›ÿοseß'SàÇÞ·[ï^ªèZ=-u×]u×]u×]`"ºë®ºë®ºë£×]u׃z뮽ÝÕdéu×zSWý)¯°HÖúÿàð5W^þ¯aËiÕ-u×÷²8>¥®ºë®ºë®ºë®ºë"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºëG®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºG뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG6Iÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬GPà%G„À 1Z3Ü¡Z3ˆA×ÿû€µƒ?óA€"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ "pÎ "pBGdXüýí€ À€fರ‹B7=ÊBH÷‰¾š–ö"öu²Cvùî0ÞÈ£`GÀ @NrƒCC:ÖÁ…b6¾dŽû_nHâL¯ˆ”HÖ@!)ù¶Â+ ÿè‚ÿœJ ý'ãöñ0†1`*äj?p˜ ~ 2ÃJ(š„ý€(+‘/(LÄ J/€í(KBF×ÓÀ‚úÁÿyð € ݤ2aX˜ùu-¬PžK?ÀÇ "pBCù>ôÀ@ü°Cÿ°ÁÌï¦å‚ý†½GpýëšHô~Œ !ÿ‰0N¾"‚F¾ÜÿĘ'_A#X€f~¬„wˆ/ðIĘC˜°r4L!€LX ¹ë€ÁýH`ÿ¼x@P ƒo|ìÿÔ†ÿûÈ÷5˜6é †ÁÚÌ ÀÇ "pHÌü|€Ä.xLÎ_ðYÀ<%åöÕûX#hÂðbXiتqÒ4Ry4…0ÞW Á¸GšM&¤5=%ò6ÍDÂÊ&ð,YJ=#vA<ð<Ûš-V èBJ_ðPÀOÀpjJlå~Z·ÉÂP°¼ö€Êr Ï9'ˆ3ˆË#DWÀC /1(I?} ì°íˆ£,Ë’=ˆ[@¨á¨&d #ø¤´‘ä‹É€T0  » %eÒ ×Í£údäbLÿ¶{ç`‚è€` B@v^“ŸwÜØ^ظÊ@v97¿(çx¯{¥pÄô{‰ žÃÎ0 €hGÁ 6ˆ %³d¸XÒDhäÑ­À4>FÎ’k’Œ?’ˆiäè ~¸P@TÏ &f¥ŽÄÔ8pûßïÂs(Ü,~ÿB?Æ_?Ø#UÆ,ü3ì5ŒV"ýj!€ó—²IG§¶Øf y BR3ärB8q‰÷¹Â@HÏ ÊäH´vW;«áï0jI†nûŠöÕiD"Æ–’Ì ê›Kdô¯e4¾ÜA¤IG+ò hX`$²yÜ.ÿžw 8/93²pÏÉâ9ÞAA¥Ûp%ßp®xtY'‚θñWCÉ€TdˆóâQ|3˜wŒ‰€Tdˆ÷Z<0`#€!Dh *8pMà ƒ #EP À #€a†Ž"pHù‚þ`1r‰¼a]2 …ƒ0HJx¿@*Hè#ÉI$*ö$²À*+ ?ú Q@<Æ¥¢Žzéçþ|L!G‚ú”9,ÁwD¯²tQHåHG†‚ åq@<t6Ù´L„‰D TJ/éqˆ,° ŸÀÈd ëé üJâX!€8pñ0„„×ð(±a‰áG@aù0™øÎ&(°$G¢`!€8`‹£€œaà^(7Œ@5 'èJ`(C쀠kv!=X¢‡ žlNà(!e’ÀT8>-$˜0 àBÿlà TÄG'ÝbÃG¶ÈFmö GBWº½½Íà`°£ä€NOAž/AÒF‰€‡ÿàF^G‹Å‚8¤t  è(˜ðX#€)!@h0˜îX#€)@¿–ƒÖ/…@0ÐJCI½|´þd€>¤‘ ˜`ßÊ-Q÷^ƒt`€:+› `Gÿßs\NRˆDÓP0;Ȉ!€>ûÔeÓÃt` X#ÿÚ`*GL/±d>€ †à™ÀÀ°Gÿ´À‚‹IXŸh'†è¬L&R›D +œ sPM) + ÀÓV‚=°þM&à/Ç;èE”J ‚/þdñ6ähA( ‚ü“.¾CH¿øŸEJ&OÄø R@ÐG‹Iþèb¨Þ‚ƒKÀ)ã8ýÖ*B36:²»?0Ò¾@P†7:ZŒà-·|Ô[a¸YG£ïèª,˜X¸gƒ  ¯ „”BÙ“ ÂhÉW#]` ƒÊ#Eìp8ù€& p(° Àtàë"pH<‚ :ÐÂnW¸¿Æ¡4`½Aœ` wÇ‘Á÷G­rx’£íÆ, ©‡9›¨+‘/y(  4°0JGñÈ1Ïê€~F€È!€I7Øë£Ùz „G*%A€8Ð`$Q(½°Cp*àEƒ €8@Á À¨#€LÂh ‘5ÛÊ ÂDP`!€0`ˆ Ð$E»Yìà­10›‚7a  ‚ ­7OOãPR@š4µ‚iì’(tg`Bn°À„è3š~º:Þ[,t $(ü~ i O|Œ ·ò€¦œ‡ÀJ¢„ÃâÌ,À $ks8qЉG Ži#\®B€h00ÿà°GR,L€a``!ÿÁ`ޤ[¿†”PG4À:€0|€>à\ ã]è"@ ð#ÿêHð±t` ú’=2»Ð€‚Gýê3P A 0#ÿÞ£4‘×O €!€)`ÿi°C”‚?þ†àÀ–ÿö™;0 àÿ¡„{B½Žƒ 0ÿô ­c ÂÌýG(kl ¾qB4AþI€Ž‘|â„h0 ‚ü“+mv4„C$qQnãÑ (óòÊ(tr€bS‚ BDF^ÿþSºÉ÷û–2%à „øA» ¸ä³¿ æ Éa«J±¼Æ×÷‚I§$Îê¯Á KW#DÁ¼ §0!€1@8ï_ü A„0CRÀUÈ×G`8 ° ÀtàGæÀ`#€Ñ@;œ@Ž~8"pF@Û–—¬ùHŒ1ñec` ‹Á8Y=Dàûä¦Í!%pÞy-…0WÉø,  PÎ:B3lî×Êønh`AH@6ú¸ IF¹çÚQ'Fà5Š/úÅ¡ ÿ›þ­¬S(ÏÀ–Î=& h^¾D ÀÎQ4²jCxjK@ÉákvÝðG]ò(¤ C;ÈBòÜô f"ß-ž£÷ÁqA€c3½òz+ %WøÞú%âX`8'%Ä_$`0އwOHã̉x–Ãvî"Ñ’™Tœ4/p«dYm˜r¨¼K,¢À$Ì<Ÿaäk`›}“™;'s÷´ f%¡OƒP`Õ€Fµ Áð0ÿø×È)À òtRF†©?€$Ê p‘­(±#–md™Y[`ª/žÎ„ÀÇ"pGÎ"pË- €0!p*F’&Ÿ@@`†DÙ%GgNÃýs¨ö`@üП°!À$€&Þh@; 8bJq‰ÏŸ7¾þPp›áÀ  I€*צ°(Pb7Ïs_O]!.@ñÏÞˆ00Ày0šhÜŠ|6óÜëìÀ`‡þ·° ÄS÷q–žŒª?š€>/ÀÉd¢ Ü¥ û…}\ÄÿÕ"/”@&`ÂÛ@bzsúA ‰‚‡"p>Øa5ÀÂXöôGXfÔ€jM%þã}„˜°Ô^JuŸ|Ôèàå’Ëá¤ÂÀ˜gBÄîft\ø’ÈD²Ë”¿¿'m®î¹1fk1ÆÙC @€ ‹ Ð ÀNX N ˜™¸ÌÃýx+КtM(˜°(059P?<W/9(u%´ÀÀ €4"€–ˆCpa[Ü™û³š°p#À.!J!€ì £nG“ŠCŸþT„:Ké zQ”‚0¤vˆ€‚ `€0C"lLœ¡4“½ÙÊÎ|4p!€i0Zû‘@9Âo†€.0 &«]€€ã ±!é r,|uö`0CÿÛã<ëìÀ`‡þ·¦ x‹˜šu<ÄÿÛˆ¾Q}\ÄÿÛˆ¾Q0 @'‘0‘H/äpPà"pÈø@(!€‘6IH‡×GUð¨_¡œ&øpÀC ¯\† mƸsnR‹%˜ÖÎÉ€†|ÿï‘­¹€ì˜H Ž©#EãX˜¸ap*!0ðdrnÎJ½ƒ¬p»P‚i`P † –Y4¢€šJJó@‹jè0°€bƒ@’I¨G'ø ;rè H&§à0Pœ Í8,  àä2€nMÅbŠÅ­1G»’†Ï‹pz>a ˜CÃCJ/Brp^«¾öøè @âÉ©Bל#ŠúøÐhv¤åp?…Þ¹ \˜·}r4U&”º` À“¸ig™þèÛþÚÚÁ Æ|@Pгù't·_Oý*ߊ; ™d ¹"À ÐK„2a É… ¼—X‚€tœ’AŸ"‘ˆ/€\d°€3 ÀG&f@jÿ :ñ'c9¬uðý ïà,$ÀëádÀÌXŽj6'^¹ @0K¸ ;r ±¦Xb.H`‰*,†X&$†Xi°BNß+l¢ai4²Ñ’žÞõ €„$baa¬¿ÚðW¢rFŒÊkœ0¬Ï`dhN¨ @3ÍÒXÆð”BÖØ@6%3@`M¡¸40h@ ɉe)¨0±€y#ñÕ@`LG?I¹“p¡@GpX ’F€tCdC@& pL ",`ûô€†p€™t¤4„”’Và}s‘‰AhÉú&JÅ””stÀ4, >Qd$}âC(ÔÀü˜…w Fo(0 ð@— Nl{ð@°`€;²xAdyAõ€P#„G½ àBÿ¦0ûœ–¨ýaiäÐßúÿ÷Ê ÀÀGéÁ%¬:ú` ¸ ”†Vî›âdÀÌL AXäf±8hÌ2¢b½Š9kË/†è1Ü5-þ0 ?¡ˆf)ehà@` ` Ë<†è pP”‘\ †ó‚ ÃËçkwR,xB€ @è| Àø ìÄ0Ò`æ/"!` `ÌBÀ€”ÌÀ "€n¥ ;,ðÞ48̬–e[k00¨ÄGÀàPà€§ LA#¾3#Iøgàòh& ðÏ“¢i`;&<†Bo‹ëÀI pû%¥) •­áð@ÀªK90ƒË÷ö£ @`”Ä0ì‹ ÝÞM„>M­ 1& OZ1+‚@«@ Ô’Gÿß@*à:!•'pàjI0#ÿï´…>çY@†äÀ‘ëe“FG»\BpúGÐ ÀPÿê(4 £ö`ú RM #„x¿z° 2 ¼  ˜QéçŽfV_,2ï#Þ`Є„Ë ùx룟£„¦Ç4*|ø1$ Âhi© FJÅ;µ€P€€3+ °„â„ámì4½.C/÷sdm`hg ÄÒ¸iA9( q@<$¢L8À+±»£ÅâMÓÀLDÿÀGÿÄ‘âP!ÿGÀ`„‘ À ÿ©#Ä Cÿ€Á #]¿‰a¨ N)%“E’$ƒ×˜ ~M5%𧺀ͲÿJ@šR°4LÃ>à ~€ä‘;Îw»9iG+À&N° æÁ œ˜´q P3óó *!„À E¢à¾‹ì CpÀò=Y@†áä{0>ìA 8€ÿzC¶ütB #ÿÞ€L0A¼QÈÐÂ-ÁG¥XG™€™`]$@¨¢h ƒ††¤ 1çÅA¡§¨Q’ŒŸ¿Ûüwëø‹{I…Ÿ††§¥<@qEe`Ä/ÒLXJèJÔ(sDït|rq«ƒ ¡4$àâ~ ßJRüO‰€'8\RÁt¡“Î p"pȈ`(!€‘6tÔ@ Ã1ý,0(©'Qý‹Âo‡€&HÐ œšûp I5(No½â@ € À €GŸ¥0¶éØNÛû¨å$²•žÈ™öô1¾¦š[€Åv¼x Aõ€?(x5,¤!¿WÕ@€^ ;,›ßoÕ½Ðbax±¿}…Ù“S†)vÀ\@1ΠHÿˆôƒ´~‘dÐÀ;¬ƒ9DzÇ[Ùa¾B?û!€«A $!‚8–F€,&pBÿ¢vìâZID +Á ÖÀ:  À F“¢ƒpBN¾}GŒ× 0!€@`Ь’~Ð`ÙO`C€ÀHÿÒ<~`þPF±a”èèpôr4ø¡\09ŽG®tÜ €8à:À;BPS¸ïc[0ô‘(ý   J%“?Y÷Ïo¾>¼šø  šÎ?¾\€ ~˜ †`“@*,Ü^ì¾½ ’4j3î:ç /3z?){ @üà¡QÇ_ïs@G3Ól¢¸!€VYˆ+ví¯¨€;vMvCäÒÔ;Ó€HÑ¿}°ù—™µ‘€ÐG?è†È®€ÐG?è†È’e‚ ( "I¤Ð$¬ý :JFr%8AG Á¬ÒŒO¥eÑý–LK£ô}Ë,š‘©ý?›îP° €K)”ï„DP†3ç߈¬na¢©eµÏA @`GèÔà’ÎxÚÒ3ƒR3mšªöHa¼´ÿr! ¬$g-ô†` @÷哨ƒI„À(M&“´ɘ4¤°„ï €†%C œ„’^?éÂÀÈaDÜóÑòL‰¤"“ŽèÖkê`õÐ’08ÞŽ// N"ñ ƒû`  7 Éǽ‚h- áã>×" GÇë Æ€À@äÒ€¦/X¤þ PGÂ05$À)¶ G0Ñp @äÀ À–BÀi(¢!§3˜  ÒÆ ²Ç#ð¬ðN,%B¥©VhR€P*’ÀBLƒ`ÀÀ2À=ý¨ÈD0'Ä0ì‹ Ýç:M„>M­ 1&žŒJà"V€@©$À+‰ pƒ J“À¸p5$€˜v§Üè”`L¹ÖP!€90d{µ€P$€(ÿõ ²G€ GN€ÿZê` Iœ˜‰ ð÷ž2Š ©+ü«0 ~€o“€bRÔ–#ÞèÀ1 5ÐÎÉG{¡…ÿD ë>›Fa›$¥ås@G¹…GÛ³¡ Ù@<¢ñ$>(3 w$¤ò”z` DÿÀGÿÄÑ@‡ÿ!€##@0€"à#ÿádx`!ÿÀ`ÈÐË¥¥âLB Àa!¡LY;¯E±E°ÞÉÇ$õøÛ±òN]GdŠû€¾;¤9n+ü­‚îÎ`!€:zzBâ`A €&ˆÕh˜MI ¢± „x´Ê>;ße#?ð ¾2“½ö`0CÿÛÓÐ>æ!GÏ1?õâ/˜HEáè÷ÓÁ Aýx‹å?>˜@'Ò&=£É¥¯îgØ@+ÃJ!›°`n8#á¸9àrX`À“ð ñ-5®g|%Çß2°Ô'8PrH¸*˜Giü”€¾oç’¸nÁ±ÄCÃÚ@ Èp–ï–@"ÉsRƒ0 H8 À òÉ©0GGçéJ_ApQÊR‘.p"p±õ@‚€þ@LØ4ÒŽÉ.úP À„$ôP(´}ƒ¹ÞøV&ön»Ô&‡•›ç¹’L{Dò’MÈÆ%˜‚ŽdŒ-cEAìG"]”²Ë%šr–º$eVæŒc(šü„CÙ•ÛeGÿ`~ Vd!Ô­I;ØÀ2È (E#©#KWW<\ZÈA›/€[ŽÖ¡QòñhÅ”8Δ Ùíì:8À@Àà@Àà/¥€è˜X Àt|–äÌ4´` ð¨0(IDÂŽŽ_º>çîÄèbú“V×ÞZF§ÊÖ¥ €h¢À/K›”¸ qeŒ/–ã0\@ Ò ` ± ˜¾€q0G4 ”P#ÿêJGP¹ÿfv@í U,h¡Ö²N‚ö‘,ox@0ß!÷ÂsQùúR—Ð\~Ø?LÀd P‡IGh€8>!p*^ ,áZñ…”PnèJ2w?x! FAHÈØíŽ¹ðà`•hJ zNák@tDF€ëàÎp,Ž¢’X 8¯{ô|”vJ;î;èöíGõЀ:ÔôP(/£Œâu°¢’òŽŸÎGÛ?áWçMN¦ È^B0µß€3Ì´ì,`ÂP¨€`€ ÊÄ2 Pø1Ÿ†bÀ& *F&¶H”%0À1(0¡¤¡©&#„r’ká@c'¤[İšÛc &*®Z@LQ`€è œð˜Y@]¯ΫåôÏ{„ÐÐ2—f¸šÊ@3Ô2héÀ1¤ †­(F$ÌA\£¥ :û~É[gisfÌ9S¬GÛNOh`1¸h“Ç_DÀäüBmûV(`ƒÉwo—¼à9É HŽ`„…ß-`5 ×è(?a'‡ |ˆA¥†TbQ( 7å«—Äsƒ×‚Jšùè #â[OÂဇÿ%sH×Ë4 ÀP˜MO%âI)‹ä Öø¤¡Ô¡+×·'áùx/NÈÁ? }ªÚ‰K` ߀•&ÑH+!ÍüûK%s½”`V8’£½ò!ÇG:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ~‚?bkóZ±ÖÖH„L%Œ/(´¢PÔŸ€¸£ZÒ†kx@ üʶ i›Á üZs`¨¤ËHJy²ic'Î"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ!"pÎ""pÎG · F<~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPà´„€!Z3¤a_ÿû¸µ3A€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®Gºë®¹…Ð’Ô–1ƒ äÀĉ=>€JÀŒƒCÉeb7‹ *!X$'ý‚@pKÿÂd0‰H##ÉeË—.\¹råË—.\Âp(›ÆRj O@“"`0!‚8–F¦°ŠYHãÆ“ƒR‚6Š ˜0?ðÿè6²åË—.\¹råË—.]` "ºë®ºë®ºë®ºë®ºë®ºë®¹„ÐP@¨#ÿÞ° ˆeL@T öTGP@¨#ÿÞ° ˆeL@T öT4‰ˆÚ—.\¹råË—.\¹råËž(L †ä0GRÈÑ0 ‚ÁK#YôøÈgèÀ?ð›ÈgèÀ?ð›K—.\¹råË—.\¹rë "ºë®ºë®ºë®ºë®ºë®ºæ3x‹Û´›ƒ2VXjJ+|j¤4QZ2 €”Ž`ñ M‰í AÅYGñȚ `{X³ÂiâØÃñµ€'H#€.¿ý¿zî¶ –ô@VL°&E•ÀwÎÈÿVÀ…ÿDÃl°Cÿ*$0À ™(ŠØ©¬È‚ÔN>ÙNF# âºøŠ{‰ûãñ¢MPŽ%r IËÜXÆ'ŸLßo€ú2p¡@"ê¦Ô}¿V<Ž­Õñ€|¿€`¤¥kÙšt#‚ȹðºœz¹8C€üdz» Ü,‹G>P®y¸å… FFZÛ©ðXN@üž€Dÿ€TFÔôÀ=A/”º#R„2Òû#¤I’K@pÀ—ÿ@V¯þÍÂò¸ý[“éàØ£ÀZ@ ˜~8yœs>W3ÜÀÀê€f==Ë0)ÍÄH¦\n Õ¸ÔaïЖhíÀ#È¡´ø™þ](GùARKœšÿôM¿üM?°HÓ CÌ5öµ oÿŒ5OƒùGØ= Õ¶>#ö§½€¸¹÷|NDqøül‚Õ†š‡âPÊ8rY'êÞ3?˜?d‡zþÿ"·'šV;ǧ ¹ Ïñ-a%±Þ–OŠÀfF_ öp ¾Wzm¹¾ù÷PóõøîIà‰lIAûü†¿¾ÿs÷§P!ìÀšà§ˆ@;0&‚8$iéð&“NÐ#€0&á6&“NÐ#€0&Gá6—.\¹råË—.\¹råË"ºë®ºë®ºë®ºë®ºë®¹„¡Yž(P"Ñ@ŽdÒ4P"Ø`#€4|Àún‚`"Ðh#€!ŽMˆd#Ëp&‚X¦&'ý‚8ˆä؆B<°Gbh%€*m'@‘-ìsTà+HÖAD’#ÿé@–ºÀV¬‚‰$0GÿÒ,uâ@v"Sx“@8ü!‚_ý—@8ü!‚_ý—\ ☎èG ˆÄ;À€¬ÄbÂ6§À0†2Cˆú !€Lâ>ºÂJ0Ð#€*/÷&ÊÎü0nÉŸö Ø>%èÀ[Ý—¦ßnáö’QîV%ây+€¨`@”sPÀp`£‚(h+”&¾s[­x«ã•ó{SJ)BÔaéüY«gˆ˜ÃyàhU?Ά¥NZŒxˆE$~ç\VtŽÔŽFˆtGý¼¦Û4çþ'€E™Z›p&ìÀšà’4L †äÐG4€ +›†€A4ÿä6H`!€pA/þCj뮺뮺뮺ë”rÀ"ºë®ºë®ºë®ºë®ºë®ºæ‘Ç`ØFù©sèÀ«ñG°¥‡ÓÅŸºd¡`8) œ7ç(pB\,©µcpÔ'9è!ðåSNL¨ÌÀ=J\ÿõ.NG§ß”õ>€?ß‹§Êaç0?žÂÔ«üoÆ1H `99túhHìœ7’t†¹åŒ‰kp³0|YIêwAea¨% .” M¹:Ö/ð¾óf߸€ôûÿ”ð&ZKŸýOK gO €€ IB˜”K#q´ò‰ê: îF§ÓaˆB#gÆ€þŸ#Z¸½ÅðÇCéöRTúcHæñ >ÆmMè ÔGÀÒŽRPç³á©­6d!†“ËI`6¤òåË—.\¹råË—.]`"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë—ÈŒ véBùç ô¤AYÓØÕ67êb<"Ž4ʧñXß¿ˆc¸w—ò1¿#¾© È`#€4ŽB‹&ý“þÃG÷RŸ«|¹Š†_aõ¸Ý’?>´tB0&84Ög§ÀpÓ = N\X"2þÈdbe!äy…P+÷à p®¼ò0ùÅõ.B@ràCH²`!ÿÙ0ÿì08xXº\‡—.\¹råË—.\¹råË—#€"ºë®ºë®ºë®ºë®ºë®ºë®ºå˘V(OüàŽe0 »¿Ÿýƒ´; 8S˜/vYák§G°i΃ñ#ãòLaoM?ú Øñ$r5å7øà XáÇ实„$$ÀG2…L?ú&?ý”G’H` ˆdp)L?û&?þ çÙì‘åËá  ƒ4t‰h$èØ(ˆ±E˜MàX")@ÿd21 , Gÿ²…HysHI€*!€ @¤Yÿè˜ÿøQB@rLQ j"È@‡ÿDÀGÿGˆðÓ€[é,¹råË—.\¹råË—.\¹r €"ºë®ºë®¹røTœË(“@ #Sð°DD?ýÈÄÊ|䜀Gÿ´X“h° ‹RHÔ×HdÀ €và €Kÿ’7›ÚV+d†p+!øÿÙÅÿOÒ0ƒé³ÉHÎühÀ±èç8_70ä¨hÍM†ÒŸ«eÿÀ6†§`€,48°§/ F4údt,Qà3G§ã­  ”®kŽHü,“‡óµ<])$PGõÔœEÿÀ„‚?þ£8 Ã3@ ™dòu>kÉÙÆwŽ-#C >JP3¶8ôqåu OÔuô ?õ ˜häòÊôùç¶A'üÂ@gÌË’ŸHFxx”¥ËâÓéó…bIâ¶Å,ÔI˜?‹6§è±æŽâ@~;ê|ßwÇrŠÜWÎë7 Pˆ²‰<À4‰O&ŽÀÈàGRe“ÉÙéøX`!ÿÙÿì ­8B8CTC#H4˜ôBû(! 9 P#H²`!ÿÙÿì¢<ç‘ý(b0IÊ@óœX¤ÇóOOÝÌIÌy¸ƒ€yØOvÆäbt_˜0Hiú‚ÚšÀš Cÿ’`#ÿêñ4@‡ÿ$ÀGÿÔéº @(ÿì†F&O|F0²Ò5€™+mœÞ1|ÃÝfø˜Òpú~çG @â3‹4ïMžHãvW@ýÌã€Ð“¾ôÕHI€*!€ @¤Yÿè˜ÿøQB@rLQ j"È@‡ÿDÀGÿˆóœßM- .›YI s€WÀëc“éç6ƒ¤¸÷NøÑÉaúšXq€t^;‘þoJåË—.\¹råË—.\¹À"ºë®ºë®¹røTš $è@&0&8 IЀL`LpAY‰G‚-> @@#ÿÙ4ŒB’€ €Gÿ²i…OD“ÿô€KBm„€©4“ÿô€KBm„€©6`]4…I¡€8 Ž¨¿ú&DÐÀPGT_ý(õ6â–ŒžI-ÙÀñOÐ’Ó¹ùHñña ˆ˜q Xù?Ó⌤ô9ˆ/d¾n!(H™Ö¹‰ÿˆpäâùš¢ÖV•Êâ I ¿ý DL $@Gÿ¤G ´˜"›4|Â#ÿK ø3@”ü<•ä'ý•†¥Ùžv£Ë&€¬¤ƒ¯Ãä•–Z@$&%8WJC €–e—9ØC‡Ó¹'¶Cqé­Épçö$iÁÃÿéðŽcQû GÇî¶â†%ûtÃ@& Zp ÊÀe£S BÒq0ÀY¨%£”pàI;BC’Î?>6-'E¬EôØ~{±®ÜIß CŸàsÀ"/žG))_1 "à+0,  o63äŽwW$“‚p¥¦ƒ}ø¬´ŠF_áRÝÓÔ5l8 HdA¡¥rc“9éOAÜ@jY¹¨Bt‚ÿÂÓÔŒ=)R0]<É O,   GÿÔàðrP°2%y—ù!¥ *F~e«d~Bœ=%€?¤=¤$ ’bÈe8Z7­~š>,[ò#;m­ é^݆Hç?! ËîÈûJ'Š&G†sRŒ_.SM©ÐÁrœƒ¹â…à“Ezt€Â‹%¡Øgq…£ä¡IÀtï¢Ã )p&‘$ bj@%Ĺa€B‘IH#€)4‰^œ À|˜ *G’9$˜ *5—ˆ$j|I€‡ÿDÀGÿˆña€‡ÿd GÿˆôàmHCÀ© E“þÉ€ÿeä$!€Ž`TŽ"É€‡ÿdÀGÿ²€³‘9ÓGF„᭙Зq2ƒÿCA/TZv`ÁaÄ€Ü5aM¡ø.›&.-,PGÛ–Åp%€›‘äƒ0i0r€xCCÉ„ÂÃJ¯ýB)ñº–¶PÓÂ×ìîã$/g1 [ˆJ¹šƒ“ €‰ÿ`ÿA±Q0„q4ÿä6IœN¦ÒƒðB0&84ÒP~B0 p(i¬ÎE§löwü†Ä’ À=íÄmÒ¶åŠ`Gõø¾1@”†– 0IþžÓ¹ø?@FN¬nçãÅîrp®Nû ý!$ÎÿúW”v];tŒGÿµpGÿÔn’¸zÃ@ŒèàH4¤…'{J‹/JpW§‘p“È`P)öLü(\!€Žd0¨‹&ý“ÿ #ß8¾šoC,¡A8OtnÜ?îdña¹’ LŒ i=ý6LóÿjRGØpØþ)âÿÇ ,Ô‹+cé><óºÉù¹;·OkšäáûÖwèIŒ°&ŽrB÷ܨ즄Š`9M¢Ìøõ£‹Ç…¡|ÀAªÿeB‚2g?RåË—.\¹råË—.\¹À"ºë®ºë®¹ræ\† Cÿ’#ÿØ`×D/¡¾?/KYf2{gp‡rœxA?}M˜1`ˆÈC&“Êì~ç%ƒ“ŽH³þáÜ7G@ÁÿôÁŽ1¾ÓÏ-ŒÊÙ° þÑ©(®jrKÀŒ…q¥…àŒÔí}X9é à®|C&à`ލ¿ù!D2`và €Kÿ’r.#êp?êBxj -'ò `´4àè¢!€9À0i©°2*WŽœÿöGŽœÿöÐm> ?û KBä“þäÀºh¹Ga¼op@c R Oyåï€$-d¤¸Pc NŠJF æ8¤/î#'÷ýüäy•ßvo¾øyž›ð§äÒi šyI&¤—Ê !#óðG`fRE¦_s Výù`–üß'P±Ø þ‘„öhRÇóúCÒâ3c)–;„à&„ƒJ-!HÉŸ;㺎'Ó˜: ÌR$F+‰(#…³ˆú3ŒŽw'wAûÃzw_bNàM9ŸvÙy·“M¹…¸Ñæ¡#ÈÄji š•Q¡…mÄ¥%“xPô#ÿÚ"­cĉñ1 ‡ÿ@P?ð¦PQ›b¨IG$˜¢ HI$˜¢ Z8ôèP°ÀCÿ²#ÿÙDx°ÀCÿ²#ÿÙDyÓ´#€NLp¤p)L?ú!?ý”G¤’I€*!‘À¤L?û&?þG¾pw#úp4й'qä̓Ê,·'Ui9sl‡IBð"â¶NÇþScá„JtâÊœ¡cJYØ †$˜áÄ·ñ¢÷‹ýÏrXð D€ô`“û$ú|V3À$áFõi¨ÇG~?üHDzÖߜښµâa0?ìÿè²$B!'ý‚?ýMÑ “„Á„ CR`#€!@M%” ƒ@†¤ÀGB€šÀðyÓÜYäÄ Z’”p¹l¯{°Žœç9¨Ç£ô{Q‡`8Oy@%+c1eð²Å…A@-à?¡+O_àpͲ¶N˜<30Ò°pÜî#.úÿãÿátŽéüÀÇFœÜ@ ¯Ü©@ïNhGÉG@*&‘ÈPi0ÿì˜ÿøQ+€ä0DÒ9 &ýÿ #ØäMš,dXa`1IhW&«0cJ3§lKpÎÜBž ?ù¹ÈðÂ#SBqemÒÜÒ‹°>ŒKÄâ’Ž 9Ú’ÈŸDs°¬Aàš#mO†´}ÍÜj:ÇqÜŸ¢Ê5Ü”‚Hç1©‰ߘԖ\¹rGåË—.\¹råËL"ºë®ºë®ºåÌ+jvæå8 %Å5yCPš}1?n=©òeœÜŽDÎ"ƶlà=O(ä Fo àySî,‘ÿ¤Âq 3‘—O²Ë?80Q0¬î Þ° lQn‘©¼’ Ò¹ÙkàŽi<ÍO¸ã‰@ÇBº\úÒ¢‹à%Èã6bÀ›‘ÛšwEôëBˆ@:Aß3ãrùú›;s€{G€p'”èüÄ'µÑY ôS@X§_ùNX$€1Gš‚Ë+™nxK,5,(oZEÿé<ÖOŸ Ç%œó8Ýx׬,‹ðw ·O?n#0€ý¡&Óä/`ŠoÏýcE/¯Å”¯Ì@nS`#O#rH` ‰®ÈLÊ2€>j}¢i3˜Jã”çò§ÊäÁH&¸!3¨R ÐÀCÿ²g3•Å3ž}(§”°ƒAÀ8GÑÆ1ÀjàSïÌzNn¡f9í‡ó±ôÖÃ7Àe÷p Raø~.›·A%bƒ7Á˜ #ûŒÆK§ÈMñ$–^Næ%tq+K“”Ï[®xŽ&Ÿ{Q\…ìšuJÈÙí›`6oëÿ¯þýtîH(b€HMp²¢ÃM&~­ƒJq9Bý2žVùº÷WÜæçêf96c–€PIÀ€­~Xàú}äáêXv ý©ôŸÌGÙ‘‚ÅôóSÍâ6dmµ%—.\¹råË—.\¹rä"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºG뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºG7ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ뮺뮺뮺뮺뮺뮺뮺뮺ë¬GPà`„€!Z3ÀŸÿû¸µƒ33A€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®Gºë®»ÄA õ€€?hC24 (¬M(7¤i0¢Öކ$‰ñþ.p!‘Ê€v ’MFùòÏH¬?'€0#b¨Ðè†M&ra4›^ÀP1¸½Ÿ@€ à€‡üà?ü"ùð@5)è¶QŠˆDÏþïHòåË—.\¹råË—.@¿Á<ÍŸ!x=8áßëb>Äï裃Ëøp~#&“2åË—.\G¹råË—.\° "ºë®ºë®ºë®ºë®ºë®ºë®¹ƒ˜”\¤‘ÊŠ.RHåS²Òc%Ë—.\¹råË—.\¹¦¿SbµÐª9{ÓºJÇ!?a¯e€N$‰©± ØèÏý°=Ä g9ÐÐ)¡ˆÒ7#CBv?ÿiÏGð ?úˆ¢Ê° ‡pÓbd¹ÇuЧo~ésœÁb„žÂf2)$” &c©ÙÀéGÉBA0ÓÒ-p H&iÐÞ &ÿøÃEáéxzDò?§LI„ÅÐfK௓Þ)¤T䊒ÅpôòQáÉW#¢ùœô‚JD Ž\’±#3òtRr‘#—cÄ$iæ#b%:dÒ ¸–WGºc¨˜pnGB!éZHGôLOûýÄmM†÷Vƒ ˜ 4°.âNµs¨  F#S¢³gÿ€_ÜÊ|¤á¹a¤!Æa§€éâ™ø;‰ðîG¿NÎQD€–5ð#&(¢@Ëø “UU×]u×]u×]u×& "ºë®ºë®ºë®ºë®ºë®ºæ2,¥V‰Íl4{6Ãðá#‡N‡$’£w|EÄ`¦›šE·ÀÏÿô÷Œ K`õ+ËWGY¬ ‘­byœÈ†'þ`$ŽTŸù€T’9TáöI‰%%ë^"Ó„( >¾DŠ(€¯‘)ÔÄà gIÃQð© xhÓCXž{` e2ß`°44‘Ò0þ é8E62yâHôÂÔ;šŸÑ–[˜€¯ b8«øLÊÌv;Lx}:"„’P°L4ÈI%+ÀM;E@Ÿ’<ø”‘ç0úŸRà"§Š`{€¨G‹¬puóS£”‚JDb9pàO‚JDb9pàOKœ.è(ìG°<>4Ô‚F#ÀGÀšœ)Œ…(p@P]³¯/âNÀ˜qÜS©ÐíI‡ÄoøËäñJ'SúéÜq„ÜŠ<ٟñ¢VE‚¸qŸöSž,p‘Ðïf6ÀY…Å4;ÓùE2À¾DdÅpËø “I™råË—.\¹råË—.°G"ºë®ºë®ºë®ºë®ºë®ºë˜O’Ü’³îA}Á„i³"0sËv8ñä éö† +à¶ Sëv§Ü„3¬þá`Š}«‰Ëä} c8’DO¯‚†Ô=Ä!ˆüaO’ËÝÎ1” ÿÜŸs?GrAâ-.}ÛiÄàú}f|?1Ÿ+eþç¶ r > U‘`o²€ü•0B>‘¤æ³WB.­\‚‚”ÄaTGùrÀÙ´‘›2‘™BIÿû0<‰S5×]u×]u×]u×&@"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë—a°²a T3BžÉå¯Ɔ°½‰#ù̉¥’Lä=ÐÈ$¡Ø5Jë`çÕÎ,ÄŒÀÀ–`€€Ü0`ÒQ3%8nYG/3êò€œAÀÀt‚i$sÁ©•^ ˜Ðxà¤>LY-ø ÈÌ$—à@@@CþÂ#€J@¨€¨Ã0alƒš(®7.®ºŸxˆ3Ô„ø '£@lLa¤¬5+ù χ€ õÁ 3 öT’°Òѹ¿jêÞ˜1}»ç9Þ(˜HÀ.«®|˜œp¼äY)<8 K4SృGÖ)¢b@'(G#¢®ºë®ºë®ºë®ºë®ºè?"ºë®ºë®ºë®ºë®ºë®ºë®ºå˘1BRã{Áª%rsrqÄëýÈ&‡§C4þNØŠ¹ý;"”ž",Ñi<H°E8~Ä€NPŽ5DLHå¿Rc%Ëš*”¬ øT”X °%ÿéWÂu?¹Þ(0#Nwƒ €8e$2\ØÇIà"(À “ÀDPG%€)ÂÈ8åàTDÄ€NPŽGE&2\¹råË—.\¹råË—.\¹ð"ºë®ºë®¹v òe¤À$ ˆ ¿û*r+W¸,ŸpqjA ˆ@ŽÄÀ¦¦ u‰‰œ¡©óNÊé3 _@«páº_ùÎ0÷åÐ,{ uu×]u×]u×]u×]`"ºë®ºë®¹v ø§‚P_ý•'‚P_ý•LGñ§pø˜BƆš@8Ôì‰|PŽ5L_$#€ SNˆ@Hÿú €\M #ÿè&w¢c°ÒAHh&$Ó‰‚CHÁ’9èý(ÿ÷S±…`>“øPPöá@2Xì#S³¥8gøwh1˜‡Ç%‡¯4Yg€² OüútžM&˜V8 ¨äAE””¯éØÂ’“¶Á) é~>& ÿïŠV r?ôö¬Gr-“ÿð $î0ÅêhG(3ön¾ŽÀŸ'1ǯœxt„ä™Ôa9AQkl€±<‰ïNÃácÖ0 ‰ôÐ8>›æíð Wðƒ8!ÖÀŒ‰•R iB þšÂfpÕœQƒÒǬé…R ‡SÎÏG¤qÎ|”åñ>ŸÀDÿćG "`"âC€”áôYà"(À gà”#‘ô‘@–hƒ:_¯€ ˆšœ(Òxq@–h´žP%€ 8EÔà«b@rP ôLHJEÔØ .B;ÿÌÍ„óø±0„3€ô°KÿÔÉø‚7þ!ÌZy=¦†I5¤„hQ€»Óc =A@Õÿñ0›Øg£GÆ8W¦„  Ã¤ã’¬ øT‚‰N9 *À—ÿ…CðGšv½(å`”á£<{ü…fü~ÇÏÆ#ñÛòu âpU:$Ê8ñ FÏWŒbñ:›õ6#œ°ï´Ö^êƒÈ=üZ  ŽŽrH”И–Yà"(À ež",ÑOq0° ÊÈú&9B9I@P´éØ ”ŽJ7‡óG4RRr1'3 Æò–æ6ÄO’‚ȤHGõŒ"]Œ³‹Ü@yßD |"X;å0ŠÈG”üZSËü=/ä†!+Ú…¢ºë®ºë®ºë®ºë¬"ºë®ºë®¹s ä€«_þ•–{ ?’!jt÷ÑA€8À.›©âÊA]IN(rRü¡fJO;íñŠ>Iˆ3LØŸŠPá@õÓb R€È#€1 À:Z¾¡ŽFP}4Ò° Ë#A„2@zò@ö’0dM$ ®Á¿ÿ½~õ4ˆÒ|ÁGþð °×ÙgÁœÿï« |ç{±›R‚LQJC‚8“d—Ž/x#ÿé žNÇSB\po¼±BP玘^nÛz{Òrþ4ÜbN¶N>ù[S³ š7#é‰A 8HqLu6bŽ¥…ƒ¼ôЀu “ðãÂáÞ êcR à>@²0ñWb)„L$žŸø4Äù>¬&'ýàœ¸Ëņ$bQÇwG®<ܼF'œæ;ÓBc³mÐrÊ‚Ì#Lê{?i)ã{‹äÿ$çn¾[ÄPª|ÿ# ÀDÿĈÀJtt–~Q@–hˆE‚ý”#‘ô’ÏÀ*(À 0°Cÿ²ƒÈú¢©IøEX¢JOÀ*(À ÃDS¦…€N€DÂÀ'@ )±¼0„HaÅ–à“ÿ¿‘¾’N)(I;”G,#aŽ-|W8ŸˆÂå‰÷¢Ù¥\W9GŒ­Ó_£œ€¤¬ÉdJçNvx +顈AD‰8äˆÀ—ÿ…H $I0±™ÿ¥C §KoŸ|?4ÇpÏ‹A(YǾ=ü=çŸNÉ€ÍQx!`|ÁDc…*ìFÑ –‚€ëÙ@9H Î5؃‚GH§<.š*”˜¢,Ñ%&¨ K4Lh‚-=„ÂÀ'(AE†åñ&$t"êu”ÿýÎmðYùGÃäõ„ãOhÄ>’‡^=Ö(u>aùv£B±q>ŸÆº6ý[œàö¦Ce‰Ÿ¹ ËO¤cÇ~h6«+®ºë®ºë®ºë®ºÀ"ºë®ºë®ºåÌË<ð±àtŽk+€é³{V°OjXPïNŠB0Àóï`/Å¢É$À‚`Ù@9 ”[× ×ïÃò@/²†Ÿ$¥bkŽ(é£`4O¬õ呈ê|¡§›ÇcæqŸ¥·G™cz|ZÑÛ8…Ìu\þ“Ô®Gñ3¤–aØ@ðþ± :ŸæäèæS*ß>÷q LƒÈ¡cîÏFáà>áÞš2)Òb–"øM}>ƒ)ë[0PõSÅ‹K~€K4h3îP{7~°ãì÷'þ‰Â&F¿ÒJPp 0×SFL:’ (d{ý‡/ŽË»<´á…9ᯕ–ØÑ$a'ÒNSFH(㸷ÒPQ™ÿ¨§ÊæG…Ñ\j3„qÜ )Îä }¿Ø€@eÓäS$±H5ÏàpŽhéMO´ñCаE>‰‰Ü  óƒÁÔù Ј'é ÉÿáVÙì£$äˈÞ0€ªOOàÆ'c5]u×]u×]u×]u×X"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®Gºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG8Qÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G · F&L~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPà9õ„À 1Z51Z3Ü¡³<3Ü!Àµj¸i€ÿøµÿóA€#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".RG”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”G¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"åG)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”G¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"åG)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹GJR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".GR”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥G/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".GR”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹G”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Gå)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆG¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Gå)Hˆ #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"åjSõUyrÑ{ÀvhfWÁWx†¬2’Ø´H¢å„ïz°’n`Ä#Ÿµ¢¾ €„7„G¥’h¸$ †–{^Ä#ï(¦MFÇm÷Ìßù+WtÙÜ¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r?Â>"ô“Rƒ®À À€ì˜ã>‹\²mèÀ1:Ä­½^ôòb5‰hEÉ0ГI=k×ûÏ€`e‰e!ŽÖ›ñ÷æ ©IígÝídõ•W²µ¥)T®R”ˆ¹JGR"å)H‹”¥".R”ˆ¹JR"å)Hˆ #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"åyuåËEöBw½XÉ7” Þõ`;$Ü„ËTÞ` ¼  ½XGGÞPTM„_5uˆ«º¬®R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹ø‹ÖM½ '^l›z@ N± >¿~€Þx/Bï<—1gZkó„õ•¢aÚÊ‹·ØÚÒ”ªW)JD\¥)r”¤EÊR‘)JD\¥)r”¤D #óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"Gå)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥bRѽ;ZC@5 >Ø’µì€f_}¬J& ¯¥¯Í€ì¤@Pt€ˆ—X°@ü²b:€aø$àºö¤Ò€vzñ@À K80Ÿ®<ÌyØ ¤ËðÁ€ùÄÂÏ×@$Gë€ ®Y09 å#àð9} @†C úáhJgCTX&cˆòŦüÐÀvQyW©95Ü`Ô|€ëÓ€fÿ™1O¼¤ dÂùÀ<¹ÈÖ!gý^Û€À†ÕžD0Í'O×?&sí ~ü0?@˜ž`À‘ÿ ëФ *˜<_U„˜I(Ÿs4I43ç¶,AŒ¢=57ò‚€bQgUòjG5ê€4ßme!€œb.¾ÞÈmòˆ`I„#È÷h ‚ëBÁ #`•éÀ/ i}¯BXÙ©s†éûD†ûð ƒùdÇ0à“ÿ ë(` ~ ‹<˜œ=ï¢ b•àÂ~­Hà HG”Áö „ #PMü¸\@EBq(cg /14âˆaø MÿÛëˆ!£­ï<ƒªÑ 0 ÀnX57óÐAþ°(Î04)Ga4´ÄÃÃaEoþÝp^„ûÚ „Àí¿¯Èð@ý@ °"! ?1´–œB/€b ôDBi}Z e¯O¹À †‘íÊoÀ ?4˜žÀÜô]r€tZ¨ :F/¨€BL$”O±˜áŸ:¦DxÁ©¿“ Äçœ4é03?A|CoR¡ ,º¥ÑuÛnÖCoœNGaá„0¢7ÿm)ÓÓ CÆ }í€3Bíu€€¨o߇ÜÈ€gÀvÓ†¦þzX ~`pOÄHç“{Uð$èºú\!>“8J>€Â˜Mü˜@ È@Tä0}Ì(h,ëê€WÏxàﶺƒHYY ·¿5ɨÖ²aò=Ó 1èEë€/9i}ª(„7Ë–×æ¨ ~°!GLé=¼(1Á A+ÿ8ïpX€bCê+ú €bx ‰úäÀ0&Gµ)¿œ@@ýR òg@܉qÉ€I„<¥ß\@NBá(`û„€ CJmí ÑXG§óo硨N½&Ô€wÒ‹`RûÛ! èþû`~óà¯Bï<Ö!§T‹ó„ìºÔL:Ë®ße­)JU+”¥".R”ˆ¹JR"å)H‹”¥".R”ˆG¹JR"#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹>ÖMM•6Ð+N÷À1&Ÿzrñ,»€‰·l ÜA‡[{å€`dvUåÈ@:FÇ]` 6Uçɇ[§½Öü$Êô€dGVsuav£}-¯¼`ÍïTr—xð N÷¬‰&æ&Z&Ø-ýæÉ„,0붦]ç ü#_TRfZ®ÿC&ó@z2É4Õ4ëåÁ*€ CUX£¦‰Óðeõz i¸€›+µÖ Íæ2Ù© í£kç¤lu¼ &GÝWZÀbwº²{Ð×î@b „R›ë(rý` ¹ôZ2ï”Álè_¸`zíÄúÐ|G½Úfþó@P…²»  >óD"DÃ|‘{€NLÌuèƒPɼ¸ Î÷¤&’dæx@eŒ†H¶€Ë ‘>|¯ÐÐé±hBÏ­DÒMÌÈË?ÕUñÊ&l‹¨¨fÆ\Du€5·B{Ñõ÷ј»„¤¶×lÜ€(v±.´Y 7l}èC@©3$%$î@¹ îÝ^õ T˜ž¢‹âý$ÄM7ç@`ôà`H{@–DEÊÀ À3 G@š  }L©d€í" …ò2$À ó€0ׂ@@|„Žzx^ TKøËò1ràš‚àa¸ŽUÑ(`S¤ ·ä ²€€ Á3 !‚hÜð(ÐÙ\$ pq¨F$ð½2ü¸ ‰»ãà¯\`ĬhRqUí Ù{àë¤Ù™}l›Î€`uè°o:Ò :}ùÂGÚË­D#µ—]¾ÇZR”ªW)JD\¥)r”¤EÊR‘)JD\¥)r”¤D#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹ok&¡V*âÑ-;õ`†uÞñ…Þà:½ì€/Geö¸‰õ²oŽ€ò—y¢7}}k€f°uYÊ)Ô¥ +…ÒX’“š0n×ò^JEz@NW¾›€ @BC?„=ȤÐÓí@:¤ ï~pá¹:õ;á7´þUܤšC3M7”CõçC ô@yÐÂF˜ið‹Þ©×¢,“yÐ N½ I4 ¾h 2 •T>±À ÔOõÁ—êÜbo>€Ê»À‹+«]|GxÀuÔÖD¢^Un×ò¢‰¹­À!»n»è8¤(P‰ö‚hpÏÈÂÓÁ"¤uð@brSVd¿½Jv_]çÀ0þÅ% ÓÝïÎë²î>$]€ŸnQôû@y¢"ô  >óD"DÃO’/@ Î÷¥!’o4s½éHd™ ¼ 2ÄC$[@@eˆ†HŽ|ñ×Ý $ÜÀ Œºa¤›˜‘”$éß.¨·+.¨§[ Gú=÷@ýÇÖU×Ä›„d>±,ê‘z@NR®Ñ!+¼˜ƒQz  É…†ö€Ï4ëà€`CB¯8LÞÚúÆ~°u5H þè¹C 'É Q):x½¯åá  ñ mà¥~ݯ¤$˜ @v®09ì@&(4‡×0á‡ò|€Èëða+묨nK´@`Œtà')µ¦ÛuPeõðo<×¢À9¼èPuH>üéíeÖ¢ÚË®ßGc­)JU+”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".Γm!€:(†:çRY?Eúà‚V€Ò°— ]bÁ@GNž¢€#HÂùÝÃĽh5ûò` ° Já$2wHÂâ€è £ÃPO¼ËøÂ@vZc#__€.ß0 ØNEÖÔ€bû€°$+‚gþ^n•âju$­}â`v!'û€`LÿÏ`À†f¸û'ÃSàf¾±4†!‚'ý0$‚gþëw"߸È%0'Ýæé,MNšúä X„Ÿò43ÿ}Û`>áGÀvÇJ¹ÀÍ}p*À +×x`€å“@pM&a.@¼U)A (:|­ï耂@'pCÿ ¤af 7J T˜“ȃG³; ˜Eû,f€Eÿd`HOÁ3ÿuˆ„Eˆ@‰þÛ‚@‚wþ^n•p—ÍEõÁs0`”€ÿ¶°ÐŒŸìÀ® Ÿ÷yÚU‰©Ò¯Ð ±0?ÙÁ X?óÜô<Åf»‚G@€ î}'É©ð3_PšÓp!ÿÓ@¸Îè$‹Üå ;þï7HÄÔ诺L0ÄÀDÿq ¬ Ÿùê‹Y‹Ì[@wþÜz@ Ó5úT€d÷9`H`Nÿ»1!'û€`LÿÏpé S­{°æÌ@ ÚÈ` ± ?ä`$#‚gþëJ°oÒ¯Ò`,îr @ ß÷`!0Ä Dÿ¡ lG ŸûîU)äÔù’µë8ÌI'Û``PÌúäR¬_Ò¯Ú€ìÀ² ¤Ì%ÈD@è ‹ÿ@: ,a|æìp Ãu`aîÀ  ¡43¹d2Ò0¸@:H€ô{‚ñ© ;-2Á›^Ð-³ 'Zˆ` ± ?è`$#‚gþë‘KBZu-¯ÒçpJ`Nÿ»†€‰ÿ#A ?÷ܪK“SÍ™+]È!€ûG‡Ú­š¬ù\¥)9\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥G".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”‹Î’iH?Ä]qý­¥G€=€a$¶¯êÑ'“½#8ï7× T¢{ph $°äÚòh I¸!/z@ Ó¿öen{ÕÓ~e @4Ol@"¶À ÈDÒ@Ðý} o*¡”LByäûóø½ä´T] EŠR“•ÊR>"Û—‘i Ä„L$ 4븙ބ!çýäàÀ4Gn@"µÀ`0&’ aè·»&’nXXr66±¾üResGÕî÷@ ¬(º>¢Ò.ЬMR¶H(£ÞÜÄÄÂI,9v;;Þ¨3ý‰EdŸ_÷æÐ”DöÀd ;a Ì„M$ ÀvúÍå@4;PY19ç“ïÏb÷–ÐQÕèj,R”œ®R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JGR"å)H‹”¥".R”ˆ€#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹µ']@þÞã¶­H(³ÞÚwô z_Ý2bR6ù¹4€ ¤’Y8jKݼ@¹CCZô{ïN‘‹µÄÛÌ€hL Áz Q·ðR_Ç׸GD›Êheꀡ&ò Ù¢ø•¼2£]žÂÅ)IÅÈøGÄ]á·x3½Á »ÀìŠ>¯~ šI¹`u ¤›–—"NµÇß—‡k-àPí`EÚ›JÄÕÖ&¹^ðz  Ï÷•ÙתÌÿs-}(›Ê€hv½PÍå@4;Y“N©Ä*£W•Q®Ïcb”¤âå)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹G”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JGÄX¥¤4뺙ޔ lÿ¿4ú¯¦É74C,xlI'ÚÉb¯ÁÒôë°x˜æ“¤6üCê>¾¢‚MÄÑ"Ž“€ìÉb¯Ä¾ˆÔ×¾Õ*½PÀªQÕI@0ÉÀv8kàT˜GƒÃJÂS«¸à Ç€ì…#ÿPA¾ÞX¤Ñõà—Íö €='VqDûø:5‚N!“8‚ÐA©Á¥$äî}´À!,®I÷Ž|ý=ŸÚ†€À”kÒ€×2ü Ñõ× ; ûP À1%n»rW mðy41–Œ'êä€bdI˜?õé €9-/·÷§!€œ´óýÎPŸí8kÀ€™'RýA§Ãqháúûæ9hGçû)@ÃXÿGȤé€Z*þ5ð\_j!ï—ï<¤ Eª@L0“€í85Ì¿›=úhÉ^ %&`Ê$“€ì€È«ùU/X¡ õÏ,š«^ÜúF߇Þü0*ïv é³À:sIÀv¢X«ùKáú=(Æà»Ü@,Šà€?åo·˜]ÙäK¿ DI¡˜Juh”@Eÿ‚$ÿê7ØNyeþ¿uxËì0Žm G¢¯à¨8IÄÐÎ!( ÕbÑÀþ ×Þƒ3 A¾È€ K/­ã€hÒtZ*þø|/«dÓï2Q"Ù P`'Ú1neøúÄý{à›o!e€¢‰$à;±Wà€vuê€3?ÙI„‹ zÞÞ(IוÐËÕ€è“y€ÛH›R/‚Wj 2V=(ÁúïÀB1÷«¼¹}ööÈ&rýŸK_ÎÒ¨ x&a% ƒ6ÄàG¸$ê7Û¨K/ŸíXeã}ÎhÒu ¢¯àx “pi\Bt½(æà»î…? Êd!Ÿ—ælÒp€ E_Ç}ÝÌïz ‹:ÄRÈ´Á„®}#^úÄÒMÌÈ´f°}éNCè÷M —‡Ü `n´×òb`@tV !†a%ë"€ƒ‚'ü'ÿA¾ÞXCK7Р§sý|@ÈÑWðtRag•Ä'xtîn¾¶G€ÒÊø'Þ4@ä½—t®Q¶h {âìëÕf¼ùdѨ½}~DÈMï€9¼¨‡kÕ‰7›mµÓªEùò¾«¸b-O×£ˆ`c^¸ð%¥óûT¹tòÚþh @@ƒÀvBÂKA8øœà¸$â7ÛÉ 1-=ÎPÒŽ°4í`Š¿ƒ “H +ˆNõ{în¾¼€°Ò¾ ÷ŠÀÿ/göå€Gë”m {ò´µ £lÛ½»Qb”¤år”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘#óô¥/ ¸.R”ˆ¹ø‹ÐuÝÌïpƒN» ìŠ>¤ß¨!’nhF]"&æ€deÈ“­q÷ÃÄ‹²™·.ÈfÚ”}>û8“qGtH»x“qtu’N«]àå{Ñ2R½y°v6 ¤3ªiº@ð„YånrÒØL` PZ¨L«š^U¢CRçË#_±ØAHØ:PbW°€j·‰6czræÍ~|04"ê€jMýì{„]PŸZ2ä÷½:ºW®“‚JGµ¤B·úò`0Fi†ô4"ú…€,ƒ”½  ƒ v+`ëçÉFk¸™YG½¡D4¹ôòµû`À’uç@«¡Ñ±wD*È´¾«k ;!:.ù5¤Þ4°ÇEèÀ3! þ ÄÉ:À«5Ï ˆA÷¨A z´€…ñôðǘۨa¤´ÙÀ`öò` Syà›R=lÆ"î]ËK\ æ×cgMEseìÀÑDÞyâ`À2É…E YWŸ)­ &¤ÏNF¿Zp€Se#F½ ì•kç;FGûÞ¨R³ÐMO>iF¾€…7×› $]°`›„Q"a§Â/ªp$Ø@Cn„šPtýð‰„‹ {žL$]›Z§ÞÂ&à d^„„I¸¥).zô€jM>îò ÓrÀOϬ27M(Óë¼à `LJÒR8r¸À 0(-`6Úç|«d“RçÑŠ×ï5`L)Ø­„k¯€aŠIׂÕ¯PMFɱ éÕ¥^P ÍGc¸"¼Øë! ‘h’Lµú€“§À×µŒ5mÈÀ¬«._F©­@  2à ÑØà2ƒ ל&!Q!¡WH©sìÉZþˆ@0A *ÖPÊû\Ð JÏî¨b“s—[5ù²ƒ]P=ÞÈLáàûDeËÞ² ¸a…².ñ0“r·dR^z€5 u]B€a‰©^€a©Æû¼X À©\ š„'ë‘ÙV‰÷á€`ÀG |°Äpíg&€.Ó(˜PV¾†?ÚŠ8ð$Ùdõ€_Áý@v ?öYl.'Èj_™!€`Q3©X€2HϵìP¨ K$É©Zyá€`M/üéápY]—ã{ùè ‹}®R=ßÁ?ípÊ:ô‹W¹õç¤aiMÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)r”¤EÊR‘)JD\¥)rG”¤EÊR‘)JD\¥)r”¤EÊR‘)JD@#óô¥/ ¸.R”ˆ¹ D^Ó®èg{€^UÙÔ§ÞÈ£êMúâ&ç€eκ`!ä¤×€“\'‘î19Vλñ„] ùöÌ„ ÀdÈ@ €3!xB\,Z ÜïONºÐI¸`:ʽ R«ÌB‚(.h½`':ëâMÆmvq& :=ùð ¹É$] ¹É$[¤Gúuú Oöâ&À©þÚBÁ6:¯|´gEÔÞûÜ ÂLRc.¤uÇ»€@^Þò`0/}}ôÄ®å€Àƒ %°YA¡‰IÙá Úü2Sšîf›ÝÀ @4e“¹í€Äi0šHKÚB-ÎòåëËÒåÜ0 Œ½d´ÞH÷{ ÜÚ¤.ø#] @£ïp Ê´ì˜5R;{/¯é@!&%ÛŠB>ò€€™~êaÆGÜ-WG×”à)û^T˜LdZ€0ƒmpLUÔ[û$kô!+·»ÎɼHO½ë€C€Âh ï4ßžÀ¼Úóá‰Í} 5( pŸqC ÀA²ÃIÜQdÂùÚX½~heí¯T¨nZð™¸Yî€?ÄÞ¯Ha 8üÓIzø€0ë¸E/N¡oï4 7.} ÛÀ¡&Âp$Òƒ§ï„L$]Üòa"膬|½îG!n)X"ì‰7Ÿ!è‘s×Ù>ï\²np¤%^€²‰¥:=ø@¾×4nkßÀ8&RÁw;€€hÀ‡ÿx+Û¤˜[éÅëåj¶÷§&—ºk€Nœ˜M$%î‰@'Á©>Ä ÎŒººuù€{! ‘t@4Kía¼"¿—Kßd´²n@¹W¥‰ g˜ 7A ¯Ùrºuo4&'5iU뀠X‚CX.€T´ÉÁG®@º,-Îöd½t€b—uC›Xhø õ{ž gO{œgF]£½ò ˜"Þ{Œ€ÆEÖµG]>úÂMÈBP…‚naNŠKž¾ø ɈýxŸëÀ àx p—ˆÉ×(Rc-®Ðî‰Z¬ÑÿÊŸ¿4 àE’@`à‘ÿd2 mÌ@ C@@ _ô°Mÿ»Ñ€Àƒ %°]”°°| Ò9×€Z礟 ,*ø8GQG€›Oü€ÄîÌÐ1@M#þÀ¯#†Þø†Çx/ØÀ2!ËûâütYiI>NÚþzP @VÅl2ù5ÇnÐ ¸kgMÉ)Í»%ìµÓJRºnR”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"#óGô¥/ ¸.R”ˆ¹JR"Û絓@¡/X©-âý€ ¸nì‹Ù€jІWÇ ¾6ð"ç(|¡vœ1ïï|"k€ã…{šÄ2þÜ*ø©,V ¡,V±àЬ×îÀ0h’™ÐN¸(2vR8UÄz=Ô’oMž*ýh@@´’DÞ ¤ò%Ùf4À(`’¡  ç/àKô`*ÆA*ýh €L´HDÜ$¤â% PšÀ G\¿Åëá¯/Ü€œ §¨@Wˆ /‘-$ Àä¬;À¡  çƒ| ~€ Û2Uú@(nË / GÄI@¨7/>þ5ŸHËúHà ƒWò8Uê@¨Â\ ¾ò’Åk€OÐe|˜÷÷€RÎ ,+ØŸ‚ x‚“È—Ä@Ȭ3èàЍÁwõÐ(¸R¸!€HÁ$C@”À@•°Ò7G N#ëÆ”Äoµ,}&Sƒú‰Ù{àï"CY)t=›_¡ˆ f[ƒ2N¼ˆÍ̉( %¨ÄÖ¨eô€ ‰ZÅŠ¨mŒ¥}/K^Òh¯Bˆní¯#¥ôO翱jȆWà[…]”€\Cp$*øÙ@È­r V2ד/îÄÀÀ1 80°½„ À!ÀˆWˆ /‘/‹ž;D—ã€j*,NÐÀJùÀ`A$GK^t \€Cbh$€H“%¦#}²HcL£×îÀb Òp€¯L/‘-„ÀÀä¬À; _8àKñ€¨¨% ¿`ì°(MIÚ N“€tx‚a|‰x1¾ƒ|À-«ú)ð¹+€ð$(hÂó :7`ÀÔ Bqód¿3ÂHcL–)¯ºMË—˜g ½8à ‹îȾvôy ‡ÑGpØ¢_d…ZðÀ*ž¢’ïbÅh‘ZæÀŠ´²þà˜é@ â O"XI€ 5+‚€ï‚@–0¾<} ~|QRµûð\te€è á!…,„0 €wТ4@$ Æÿ ßmÈoΤeýX €5/ðB‚H–0ºe€$"€9 //Š’ý ~χã*µýä4° C ,/0`Ä?ÀGp¯|–+@ ŠÁTŠ˜‚ïë`0&¥œ®xð<á›*ò¼¿æ{pÐôЀƾÒ@t–RÄow@B ÒH„4ˆ /‘µâ}h&µ=ôB`à rVàHPÐ…À€&&ì(N"^h—âô¤†4ʱW耨Ü5‚uê@/\¶G ¾iG‚ˆ}å=ýÐ €>!•Àp¯^PD?Àp¯|–+@ ŠÁZç7Gá>ÐÁwö €Ó󕯀1³æ¼™.g¶ ßM kÖBgÚZ]½ÊR“‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ€#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JRG"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HGˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JRG"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”Gˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥G".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)GH‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥G".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)GH‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JGR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".RG”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ #óô¥/ ¸.R”ˆ¹JR"å)H‹”G¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".RG”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ!#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”G¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)Hˆ"#óô¥/ ¸.R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"åG9<ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)H‹”¥".R”ˆ¹JR"å)HˆGPà„€!Z3øÁÿû¸µƒ5SA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®Gºë®ºë¾%Æ#´M$zó@€€;oA4­…“ I@€ @€„7 ††' !‚6 Áþ¼¸\õ `` 8Ä@:~4úøžž& ®ŸèÿGú 0×]u×]u×0BP‡IHà–L+%´Ÿô&Äš=sÀDA¹”B¾Y ¤þ:€  J¾}%åË—.\¹råË—, G"ºë®ºë®ºë®ºë®ºë®ºë®ºë¾$Âi#ˆ‰„ÒG^` àx!ÿ× þ´¸^õà@ÀàCÿ­5@€`Zø „Œ"& E]?Ñþô a®ºë®ºë®`„˜Ÿô&Äš<Ÿô&Äš=$“€TA¼pyæPE`C’ ÀÀ$«çÒ^\¹råË—.\¹rÀ "ºë®ºë®ºë®Gºë®ºë®ºë®ýBR3=0F9 cà$†DRdÑ Àø%Ã!šC?’ 2&¬¾ƒŽÒ阯¶áÀt‰%·4<ø?Á‰&•”ä¾ŰðA>ADÒ“ÙÛŽ/|úˆþšŒš0˜ÜhGƒ—DˆÅ8ø@$±þž` É€†h £–R ÏÆ´`!€RìòO{潂¯¶Å#-øæŠ%¤p„tœÙÐ`k”y:›YÊGJRRÃJl?/VûPÃÆ'+Š,  ¼ <~½`îÕÆÅÀÕîD—¿ØàüPÔŽ'È„QÇù‰‰NVÁwD+Xô”ZH`{ <]”’·íÒÇŒb‹,˜’aí¸¯D§,$ûìPðÀ C9Øš¡EoþÃdâ ‚fGG€NJE4PÄ’¹xã\ú à6GO0 À@`X™? 3Ó­"o¤òþ+a£C˜ Ä$†–aX/!…t¨G‹i+ òu6³”å£:CoGroºôC)ÑÛ…Ô°À ¡‚î„*˜CHJbyGK€“I ƒ ÐÅÛ]ßv=`-‰a.& ¼,.ÐW/.û? Åð$ÑhÈH H/ <ÃÚ&^:ì-©”Ðÿï§Ét BB`ø Ùÿ@\B!†–H&ø#ÿîØÈÒI 1‘EnÎyœÓ­W¡B! Š˜÷‘†C>ä€÷ I@GbK$i aúôYö 2ÛÄÂ’‡@U]cY°åÀ0ÀÎmfƒã€Î†N:€!?ö À‚úà=.\¹råË—.\¹rÀ"ºë®ºë®ºë®ºë®ºë®ºë¯‚5PæŽÏ‹Á4TÌòiHQA˜v‹?åd`>Ið Ð$PCÿ€ë“è Â±Hdf¿‰\M|Pi7ó!&Å#3IéÿM®ö š 4G+@:&RDŒ'uS¨á€P¬Pfjüü?w‰Gj6ï…Šd`]'¾hM$ê+-$ó®… ‘±ÐE²C`Ô™aÔÄÚ»\…_ )°¾ˆnÑ(ø7Ý,4hˆnx@*B`.gäRBaŸÝ–è1D,Ƀp`‰€P˜ý€´7ÞMj¡ 9è„mP‰€LBòLºH­@aþe§••ý“0ФG&ì¤Ó€â³4Έ RÕ¨˜peᆠŒ~Y#Å£v€– ©f†_»ø„Àè1_À1BE@@ëMë¦Æ‚ɨÎ&¸ɦ@$ÿîh‹²‹Ã@¡'À'©dl?ʼn!Q4g¢›<š†BŒfÑ4%¸f&Žà9ø 9pjwõÂÅòW_ØBi¦ƒ2óH L ÉÙ\9GK:ÇÓm0Ä’?€gG˜4¢ñÉBø»G\M×î€ÁŸ%€—„±×º·`€ @vp|¬tõa0’ZIgço !ÿ®Vš !ÿ¶Vš—.\¹råË—.\¹`"ºë®ºë®ºë®ºë®ºë®ºë¯‚9ý†t |?zoW!¡$„áÒ@Bz®9™1E’ËãÉ_‘ Ð”ziG‘Õ_ì|2qúBŽø•‘»ü4ÿ÷„D§§Gg¿%boR8óâb{¢(ABt^P”É *H€LQØN€¡ ‘è3+ ÒqÀ-º(L$ E¤È¢a!/'Ý©PÑÉ4WZ@I4RPˆ¾uÐ`ô¡©;x@Ü0¸¼¼Ñ7â|Ê÷m4%öH\Mh ‡IÄÑ€{_¦– 05-ɘ ˜Ô¯ÀP01;’Ã~-8vd`¿oÿ®»±:Ñ!0(àZ€G‰®¬»ÐÈá!€”L°a€äLBÖ|™8뤤í8€8D’ý“0D’õÚÄè:A ˆh:(˜Kç_`00ù`8ñE£*~X¦É€€@ 9xhçÀaܘQ,Tˆ €2ãJI 7€ zˆÑ £! ƒ PÔÕ ÍYB³/$À O„À€’`€ þôC@mdá E E P GåËá¨YPZOÐä‚ý‡Å¤ý\Cÿ¹(:î¨òP¢ý ‹ô­åUì~»×˜Pˆà@P(`˜ À€€P‹Ÿ Ãnoƒ’g$Õ×]u×]u×]u×]u×]uÖ"ºåË—.\»ÁÏ00 ppBÉ« ãsœO¦|L´¸ÀMZ ]¡é™š4?û&ˆ€b@ј˜¸   Ð"H@G–¨hEψ˜ƒ¡%”œ²ÐVïØÀ 0¢“ŠAÐPi 4†J)96 E¡ÙÃØÖ7B‚b@¨A$š¸ ô1ƒ@qñb;‘ T dBòJK؃ÅÖ%~Hˆ@^ÄbøL”£¡#=dëî” ÿ°•@ø€t©B<Tˆ ×üdƒì­ËLžg8.þcíÿ>ñ¾½»%YBU Ò ,4‘G‚´¦6øY!âha@7 (X 8é–*Ÿ0ìK(°ÎnP Wè7uÝ18t˜jš€T`Ái¦ÜÀN€„$š<>,–”†¤ÿý4±è%•Jè¢İЀÃ0’ÈBŠÛÂîä>03ɉ$•ÀFD¶ã¼€2aÀ5 )?ýh4•CnDX3Ie ‡4¬6 0ƒ8Ђµ7æBÐ`Ä‚h›òíàÙ)°|ô×G@F˜‹á¸“bHj&òHšÑ ‘ëX9tL$aLƘà1(Et¤Ë‚'“p K , p¨jJAéÐ@vRCëá" Jë™~è丈²R@— ŠØaÐaa©Â ÔÛ˜ÊHÔêˆ!ÿǺm^ ´™>H!ÿÜ_2xÆÚ.øaZ€è04”PHWŸä{NCJP‚°B0sÅ3É5jº®={›­¸è0`u_À3t- g G¸ïEå] ðp  +ËäµsÇ@0™^r™å‰€lw›„]µA†k€?¼ tóæÎu4„]llÁ$…îh 8Ÿ & 0ð.Y©ë ·¦Ÿ‘‚T%X,é¾ç}ÄLð`hL@h‰Ä[µv8‚^çío¿~ýû÷ïß¿~ýû÷ïßV€"ºåË—.\»¿08„ÀY Ub  ‚$>Pq„5xÂG†ŸGLù€€ À†ºDZ\` ¤D2%2 ;\Á¢â@U)‰€:HÏOLöƒ®&#0`!2h Rcôˆ€Nl@ !“PI–w FcÚ(@é4††ƒx¥G€0 àÁ¨?Å÷¹¯F…1Ø` ¨`΢pa[“´ €¡L…g‰®¨@Wl'Þs®ÀQF+è…¥4CKbž G Gö!qH.×(š“ÅÀ 0—w™¤™µ;˜”€í'² @ ·ü.@ØÜWBQ×Då:0Ø›•™D€ ˜ Øhà ÷'%õÚztŸÉ_®€'h?Åü÷AjM’nÁ…ªÔ0†O *ì"D6”úõ§ Rhi€T°3Ú`U^È„«“³]@Ða +ø$2ÆbVŠ2Ka¼ÙÔ¿H‰×GïeÉ€‰¡* €få•‹üÄ  ‰‹ ˆd%¿ûVÔЖ€˜ )òúKéÓý“ ¡$¢%£«$Üh|RN»ZlèmÉœ˜ŸŒƒ\#D *pˆ¢fÚO^º\Cå €¯Ñh$D à-p?‰C0@P‘c€q@ p"\2êϺ ¸#‰‰ 7@|‚i >À`Mb©°ÄB»"Ô xD0ÍÍ€482xáG?€Z»ùð~¸ ãµü¤¾l…@:!\uÓf@1è(âR0v‰„Òa䬼O€w¤ü.ÕvX·@ƒ0Ó¬A>Ð?î8òRªl i$ è†D€0&’CW ìéÖ“°}8y¤ß€tVÿd†¤äN‚É«-àÑ NW0êÐ`ä„ÈÐhn ¬u—÷ïß¿~ýûG÷ïß¿~ýûðwÒ"ºåË—.\»ÌRz˜˜pa3p*±äX¤a€d1:`|y”B;è–}3¦€$4¸¨)0.0 ÿ< h úÀ 0c û¤ pK8àT˜XÞø']àøiD‚ÃI˜”˜¢b0\¸ 5@¤²SŒx˜Y{ù-ò“L°Á€00(F° ' À„QG(3h4‚CSa°Ë´8Ë gLŽ|fLŒx™):ç‚‚Š«ªÑ`ÿí•BÁþv- o & zÞr-àÔ¬«¨z±Š¡ {@ŒØLÐÇßDÂ’J¾½N§Šå îWÉ(qÉÄ„žZTQAü!ˆ4ÒÎXþ†-ì¾àdGƒJø0¡˜Óü’"îDŒá>ºÊËðõØ5x‚5<,øâÒGœúß@ÝèdÅ8ëC]">@‹ SÁ„Âö €LO€1!6~m§Ó˜ ´BÖøæ/x˜‚Ð[í¯P‘Š2 ã \C>^€0! `K@‰€â€r¡m%(¦›Ã ‘0¢ÒrC>äà΋& 3rY7»°¾uÚ“r„Bb<‚B €7å÷D‰<ë ÂD\šQ"&RÄÁ¡„ˆ„MÀ[‰¸‹— 0˜…xü‰G‰W€/À8†™u%…&à„‰€‰Ž€ª&ðŽ&!€hMÙúWã°â  Pˆ¢Â7^L$DГQðÛÑðCš¨^€tJI^ N—M§€îJO ¥!Œ¯€:ƒ ©ÿqd ±ˆÐð×ì]i€0}“™>÷ †8 Pp’ 5ÚÄ ˜&(°Ã)±(;Cìi…Öˆeò‰¥ƒUñ ½ŽŠå q GpâI:g:)=R4CY4^©ÈY< “P0܇Y:¯”QYƒ¤¯{a_€: BÂ"þA+ª!»àN%ðŠh#¤ C‚ÀWâÀb`\  @W$ †%ÓcŒ¹ I‹Ð`¥@0F§bXâPñxÒ §G ¨`(K)EßD"¹|þF€v‚Æ>Nù¼ŽQ(‘ñe:ŒH\ˆôÓë’„Z:QºP‚K,+G[rÏä¬jyì(¬ òj1X0˜¤bx±4ÛWÓÛ†:ŽJ>ni>¶Øí@b”bf%¬›Éâľ߸¢Ú›;š.É4pQ92 (²ÈJÈ`7ŠàT K(°†ê¦Ö1#Ìäø –Q3Gwä²À$)ÿ0ObuÒX`ÐЄ¹ÝM‡7‰ ;n6Ë÷O&7tPXf %„,ÕìÆ§‹T§T·Î9߇l¸YgW'ÖUÑ':‘-Û«ž:!€˜´£-{´ä%R&o²ó U5ØPÔèX`;( pŽ€Ò€y÷N‰€7(~"Ë×]ÆEdäçÑi1,j¹9TÛ@Ä|£N ¬ ô '<¼uÑcHi‚^È4˜”†G’ð­o'*ì‹ò%è° À*ä H>è·È˜4iÀrÃÌÄ¡è“I„CnÕ„‹A  H`;É%°ÞÈ`:¹¾ø;ç·¼Á 9Hq‹|&º7<ïN@±Hظa`ì’$wŽëÜn…âtŸObF|“0"ÿÙf! FZN •‡^ê: ÅlÙ¶2®ºë®ºë®ºë®ºë®ºÀ"ºë®ºë®ºë®ºë®ºë®ºë®ºëG®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºG뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëG3ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G@°Áàá$¬H„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGA°Áðð HDMVˆÿüüððÿ¸ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG@ðÿÿÁð cÁZ®ÿÿÿÿÿ€4çNÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG · F4\~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPàU„€!Z5á_ÿû¸µ„DCA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®Gºë®ºë®»Ä@œa¤Ä9\.¼‘ä úõæ€ÄÄÙ1,€ÐÆp(\´+ð,® ŒDÀ3Ÿ‰?åJ$`¨ ?zÏàA©-ø:$jƒýùùråË—@ˆë®ºë¾(Omuy€€€=8Ü '`o"‚î€7%° (€3;À€ xÿîĘR-*!G'úƦ ¸ø @«”£€‹b4„w ¢Š‰¡¹¼„Th?È?Ë—.\¹rå€ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®»Ä@^H€^H‹(úõæ-€f?#€4? À3Ÿ‰À„Àx Yø tHÐtHÖšƒýùùråË—.]#®ºï‰A§E^` ˆ3`@0Dÿ°øÄG™° "Ø|ô„H€¢O¬n` `C´QP `C´QQ š|„P{ ÿ ÿ.\¹råË– "ºë®ºë®ºë®ºë®ºë®ºë®ºïÐ €b¼LG¯0„°Âftø ààÁÂ9|K@€ @ @§ºüò”Ä)BSb Ö˜„ÑÕ‚Z€(jL+ö"E 5É9„ @‰¿>A>&'r’² •E»K+îC GAc¨ ¬¨°˜¤%—¢’ŠÚ 0ÎðƒË`Wÿ辸H-g³õlДQ˜!$â P®¤ žäH¼B N|R„ÄÀÔÍ+Wgƒyx0<]$g€`†É>8bÑuÎ¥ûDÀÒj3øå’´M ! ²ò8µ`t"€ €j‡ù¤>@ïýaŸŒAœå¥—ü€HyÊ(Ÿ©È~±ÖPJ&–µ’S€G \ŽV²h„’ƒRàŠät¢ !“Z ½Ã† °Dÿ½æÚ´@`غX¢€N4„ßMAYÆ…`Œ|QE¯D0@‹Sݵ‹3à &âöNAk€2 -g › b0™4§½ƒ(öù8n)9À%NÜ+o/â°$ÿïЊH5Òç7¾½&|Á¹|¬0~,EâºN`»ÃPèNƒ åôVaGPÐIèrPFaJè¨ {¼ Þé9u¡þÖ4x¤§ã¶I8‰B» ƒ@ƒ~q˜=[>€Ð'˜>! ˜4ä“¢`[®@!ç»( k£'{Aöxala‘, l²=ÀélÁ>MIE`DÿÅŽhi-#,2ðã0ÞIòF–¶PÿõècÎ(ž?¶æ,Vá10èýCXxÎÄi²pN8Um5Æ:L'Ði] Â`lGv%ë¤Ãâ\ Â€Rm‚@]HX!±•Ù*0‰sO¿Æ‚¢´K0D)(ܹråË—.\¹`"ºë®ºë®ºë®ºë®ºë®ºë®ºúD>„ª ­€Mé †5‚ Á€;§Ð*u‰2I„‰)íZµ”@Ã2©$À2|\^¥Öm¾J H²aâô‚#Ö«ˆ!Ë\xMKž>È ŸèGÉ`Šår`bG¤€ì2~t*u8MÕh‘®ŽIÜ}¤ÿïJa‘,ÿïºî¹ÈdÀÐ à·ý0 ÿ!ɬ‚æ€` {@ I›hP(tœ©§ÛVlက…·€†7€àSâWðÛŒªA´ (€ù‹ š @!€-½Ñd`—A1hùˆBl„` ¤\FYv90ÄŠ©TP€pS®Ê…£Iȉ|$¨oVGY$2luÑ`wÀ-Yh%8'H&ö-bù'V@²LÅÀäH„ìQg×|Ä€Ÿð"*¸¢M€Æ|Q&J†Ö1‡€5Ù GÄÐ(tzuûÖ`Òh+† KA…€Ä t¬°-ŽW @Q}*Bx„(,˜’AEñþ OÐñ P|h €© €$•å j¸Ás¬}Û’AY!Ÿï¼PБúG€&:>á$ ÜGDY 1,PGqn«Ã·/N˜´íñ7Znú`µGÐi 2,™D0(Z0cÁ¤Íé$Ô¹råË—.\¹`"ºë®ºë®ºë®ºë®ºë®ºë®ºì¸‰€;“½çÕ¢â™1@:îª!“4L&ƒö⯯VÃ<mÔ|œ´£3`÷ ÄÀÒR*¶èЕP>ÌhÛË ­PGq ÿadOñ0ÆEòEvÌwŽ‹Ù°Üt³dcïÜ¢†?þ ()? ˜:DÖQ4œ ’ †À!/ªÐicA´=lºa@:-GÀìð Š@Χˆh‰hÇ Ÿ C’&õ³0dÞ1ÄÞº-<6ÏyUîuÅÔðjÉò‰‚HÀ8ºq ÷ÁB"ƒ@I9!"ƒA+é/ë„POjÒ ÊíwGR$ü¤1Z!Àp‰(Hˆd0"é‡#`ïàW9hœ^€-KŽ.ÿõ’h@ fH„ìÊ.½¦ÀŠ$À¦ÀŠ$É(ëÖ"ÿ±%1¤1 LX`SK ù98˲šTW™$6ÄѣⳖSô@ ¨ ɨû}{=4Q@+âTP I  ˜„nçŠÑ Ìr;%¦‰¼LÃDŠÏH_´³)u¬¹€dÐ@ý2G¸BvÐAþÂ×¹>LB14†¿¢ m— &!æÿ݆ ôä€R‘y'®FQ5" ÌZý6Ú@vãât‚øø¤`y5&—.\¹råË—,"ºë®ºë®ºë®ºë®ºë®ºë®ºë°KdXÔ|ÉÐadÌ~UhE€t ¸ï˜[â$LA3ž_Ì+¹ߊ»-”´£bÐ…JkíÐÇëz,L !°$¿GH @5ÉÄY|â|€w€v('Ë ä°\‹ ä”$c$5 e#Y…@­D¤X,ÞNY,±Õ°Ð´’‘Ö‡ˆD Ñø/-ëå•°Äð9 AI9?@€ îf¶RBP2e eÓäçl:BP5–p 5|–C3N À䎻>rÝ[4è—ÆŒ0aØãÀz@Ü‹$oº-JHû—ܲPŒöêR«] Ò²Î!Œ€pLÿÍd$R~CÉ€øž_¬Fe‚P¸²[˜O•~ºë®ºë ÿAþƒø"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®Gºë®ºë¬"ºë®ºë®ºë®ºë®ºë®\¹wg±ðÄÐ`@ ÃX:¼ / ø’€Ñ ‘îc˜L¬¡ƒV ƒ@€è3:@Èrð Dx¸ 8‰¨FãÂä=ͱ¹lϾ{Ø V«®ºë®ºë®ºë®ºë®ºë®ƒð"ºë®ºë®ºë®ºë®ºë®\¹sÌÈÿŒð p>[ù +$ø°X  @sËÂRayÅ'=aiƒ’—Št’ @üÐAPG˜nI -šp° ÀLL!!8§€)BY¬g¬'6‚€OšÀ0ø0å¼q0ù8êÕ5ʇh¿Ñ~¢z3 &%ŠÓcÄ#¢o€*B´Z²«ad1 KÏò *Ú&“H|uD&sï ¸_ øäi{YV3ŠH ×nh&eA¤¥=W뮺뮺뮺뮺뮺À"ºåË—>7G¯X'è¡§@ƒI!ð :|I´W ˜Þ8:&ÂwŽ¢Ï¯1 1:x€‡É‰ÐÄCä”w¯^€€Àí„g@'Ñ#@1‰ÞC.´@ /ˆ`& ù•ƒö€$“`02ùÕ°‰€yEŽÀ@PhoØ;ä€è Òá·Aƒ,pÔø’ph` •²n¢ÜBˆ+§<€Ÿ€„\œuÚ²¿‰¤’GQJØþÒP‚QÍÅtk`.‘16¶[@ÀN—XÄaÖ ’N€8L”Vˆ‚ uh †> ì5ˆ ÖÄdM)½+h°È <“Ñ[ P߉AÐ ½ý$šù múaŠ­²¼:Cø<4”ˆ²M å‹­C¨!P×þ@ :ñÜ:|Y&@•¤õjÙI'(„Be”€© T ŠF€5€N“¢ž¶éÙ+~3@x GTÄ uÖˆ©€Ê$@fÀÊ$@fÒ¿^€ Š$è`  Š$è` 3[4ž1ø ŸàCäâEi‡( &`ˆ ¢9 yºëdŠ éHŸ”äðf Â`*L:ÒªÙ Úpc0ÌíJÎI8T„Z/ðÀÔ#©Pƒ4¢`\>,Þæ‹¾Ÿ(†´á0AÚ &öNââi'ëϦ§KL@GÔç¢Hi› ¤ía¨Ã¢j¾—ßðÁÜSi;dâYRK:@ J/&˼4X1""†»Å¤À&&Z€èÀPú9𠀡÷‰¦}¤Ì€®ÜtraA` Ê,̹a5°E†LÌ®–\BÈö™)1<9WέŸÄ†P`Åm„f€2!î„«Ù,³R¾AˆE¬òx­ OÜØnú1I >!”uúÁ,ÖZ®Gºë®ºë®ºë®ºë®ºë"ºåË—.Á>ša°àÒH|C-zj6öUvÐÞ8:€ã>0È<CG†žul „Æ|I¶Ißp ‰äå"é2AÀ &ƒI„’ÄQ EQ1!)œÿwž9ÀxM?û@ˆ‘DÐ Ð"é6ë\´’$€˜±i${0 nÝr\šB$ÃI%‰’I†,´‰¬Å€1€4!eÀGèÐ ƒ9[®ñÕ°âvHÐm`P¶Øl&“sÈáü:¶RB@®TøØ†1Àp“ù:´‰x˜¦€Bd‚¤­ƒhÙ>€@ž3‡À!æÀ0Š¡ƒ«¶€ à Š\‚ !ñ …%5¢W–0Í`;L»E^ªæ𼸘A¡æ)ÂK'[m ÿÅ'@ †Be§A T½Àp¹<*º¼„P³¢˰–GLO’2ëN€äàÐÀɇA '¬}l¦`$À“q`Q&̘€;˜el‡( Œñ@1?À ‡Þ$V˜cÀbBJ¤î,…Õǵl™@Å|6!“€.á‰Þ€ k6O´ÖÌÀ ~’C:½$Òc).äCý'o[ “wÅ”GQ¡°¢&BúPP d”VÒæ? Á´:`!¬0ÅCP„Ñ^ýs(€G:ð¹zЙ“¾€BL Ca¼œ!·¦Ë ílI,É `ÓËÛîF·V(¬ªÚ&€3&ŠЄܔÀThD6´ÇPvlðÙ°GÚ­1^²‰€1 2,„ˆ ì¶­“HÈ Þ4 "iYOø\¼(³ ÚO«b€ô`B’ $Â# À–M ¤¿À†‘¼‘3óÕ_Ѱa„p;%ËÊÄGB€@LAnl´nË]@—×]u×]u×]u×]u×]u€"ºë—.]‚}ÉtCÈZ,¶,3 È†Ê\‰Õµa d–<ŸÄ00býÝ#jdVAY¡©(››t¸íù¶á€Ác\”[9䯠œ Jˆ÷Záš“¢À¢[¨J®Ï‘5CA¸ýðõérË AzX€¡1¹-ð+úд™ÿ(ø bk› +w Ð »G(`nà€Eî ¶•ʈI{çøRïVÎ@; ›ëE”蔸²•$h­/ß°3I6ÛòÚJÉʉ…•ÐkجMÇi^v­˜!,˜Yˆ/€‹$“ h= @¿“´xûzÑ‹^‚Ð1¹hÂ|~ãDÊÕâÀ );î18Jj”dv–†„Ü;hÔHP*žvÚ‹rW™J¿w¤’‘,7roû¶B~u,Ó«´ÐGÐÒgá(Xˆ]Ê?È µ{H&º¯žv¯‘3“ uXrNJbX@œ0µxòÃQñûˆKÈ,—úŠOš×ëä0˜Yÿ' ² Ç‘ëg —V€Á ÿ[JJ!²Û‡Å†€íDÄV›€¡€T$íô‘0¢÷Áaè»×xµ`·F^a2© ºµ2!†N~ˆ\ U[VëîtJ!%#î´Q’ … ÏST }u×G]u×]u×]u×]u×X"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺뮺뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"Gºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG:¬ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ뮺뮺뮺ë¬GPà„À 1Z5…aZ51Wÿû€µ…_óA€"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ "pÎ "p4_äÿ'ùf(xª>'OÕœ5:T×&÷®6à;/ ­à'&ÁQM¡´èé7&ÁQG9&ÁZÓI6,ro7U —Ç[QPŠ›J&&§Õâý¡Z¯+àˆ­IþA²à "p4_äÿ'ùf%EQñÓ\š”×&÷®;Ó^š„צ‰ÑÙJR™ÑÔŠ„W¢¡Š:S«‘S«ò±þh­IþAªà "p:éhE3ùåþOò“üŸäÿ'ù?ÇçéJ_ApQȼfñjópÝ«í§É§GŸ€íÊä€b„O–ðßGí᤻!)qG†¦b¤7ÚĆø¢a#§€y˜4†gÇêrz‚Þ(P%/ò ðÎçì$h0 7' Ð(¡A¤ž^ E`bÐߢ_€vQõD¾­[œš i0r` ˆ`€XI&$/@ K¡„Ó‹Þ@`$›‚5ÛаÐ$¥»ÀÀBaäÀÐ0ÞC ,?óx욎ÐÀÙí0ÒGiˆcdCÅ"IšÆwÃI§½j  ðD0¶1 ! :%,'‡`Œ‘ P &€@A€ò4àÝìàÝÀÙýT4I)g‡b ¡4 LI:sɤ"Áÿ7’pÝd0¶t!!€ÃJR$`œ¸„xa}€TA€€VL&àŽñ@€iÃ_í íÌ T™€¡ÃR‘€GpÀÐeºÉ…€@A€–Xa.|ˆÉïölJnIÌ£pAýÀ( Y8ƒAýÀ( ½{° c¨a q>ô@ƒ,Êhü-!p$/I€¸ 8^½ö&Çêpa tø M…ä&pp½( ÿ(`œ/^àa tš:`"D¿"p:cù¿ž_äÿ'ù?ÉþOò“ü~~”ôMå›Ê(íMzGjS\šgG¥6¬é®ôWGw+y€mªiL5àhTŠˆHo†£ÕÀ¢+8ì>·Àß G¹$,:·“0ëk“Cùµ¾‡NJÖYKÔÔvŒˆÊºIá¨ì%J4²i¼5€6гTiaá¨ôY§³X懆£Öl: 6ìÞy<5à`UÀªšCÃQÚP•UHxj;IT%UÒŽÑ”VÔhyµ’„Pf’ŸCɨݴÁ¥ûÖ¥wG‰µ%”?æ´„ðW W$¤.íI&ð£iÀ"p:a7óËüŸäÿ'ù?ÉþOòÏÒ”¾‚à£y¼³yE©¯M6‚÷¦tzS]ü¥½´4´ë=«£§§D ë¨C íi97³%y½Ÿ:7×§àÅLfMH  m—º'áºô˜RoS€N_bchøü½YýÐÄ4ù ~4=<ÏHŠ93ǽgþS£G©åmIiÖ„Ãu#’KÐ:ïp“qš·€jC¤JóGçÎ ×£5&ŽÒà“GhÑð z$½v²øë:ióäô|ñºjÅÿU¼ÚŽ˜O¼'*1F"ŒR0‰ÑˆF*3gïF(6·ÿ\’ËÒœ"p8kçšYçžyçž¹¯’DÀ=âÀ&à0sté †›¬o³ci‘½ÉDù%rŠ@‡-þH +G€!È/0àË/Ê B ÄŽR §>´Œ€ -À+€¿ö@ @%ÀÎ`à›ÿ·ÿ£¬@p¿çHðŒÁþp$€¾âR÷n›ˆf£í‚7ý`I0|Ü0#Öˆ_p©7L ÖHÂY3L?'…d“x`nbW'YôX„~x„M!™‰úKû=‰è0&±‰ 0(4~ G Éé¬þ,B!OÀ ”™Òßý’7Ùò`1ù0ÍÀF.€Ï¹›ÀZߨÃ"Ã@l`ÐȲi4àyƒÜ‰gù†@l`ÐȲhh Àó¹Ïò ±ƒCÀäY44àyƒÜ‰gù†@l†€ŒA¡¤0€‘€F.³\€wÀNù€m'ÿA8àÀ £O QÖ 8ß÷€"ä΋ðDÿÄG{ÏÒ÷n›ˆf€"pÎ"rvzÌ¢Z )É¥ª6( ¢¡ƒà\dÀ'%¨ø •‡Îv‡…]€Ä˜ë¸ {ƒ.'£ä€“zr`B®È Ê2Žl‰Bfô|`’ga@v@ÐÁaWaYÑæJ'£æ€ZŽ>P2vÄUÔÒ£ÎKÂèP.ºxh£ Ô œô3 ´ûG“NÉ0XT@ É€=G º~jIZ”nLèTI€= ºÕz Z–z,*€¡‚®Œ³¤ôxC…Lr,*ß[àf›Ñó É€=  ¹0¡WV’%hz>HÈ`B¤?+ ºÈ¨DÉZˆhã¥ţÚÑRŠšW7„ñTÛÏ:#œŸär“üŸä |à"sn«J𼚞Ÿj/û•ÃYÀ¡^÷^â£îý¬¿ï=ÀLÇפG‚ìòtÚÑæpø×$  —ªj>¦þ·²€TP¹q1Œ•e*±Ötjý4t¢§V¢¦Òš9fóŠ;“^š„צ™ÑÝæ—ÍDèå^¬«Ñi,ÒÕ*6õ¾«ÖùN©JJ(ѯEB't"¡è¨E¥4ué4úM9RcyXìrÏ'ùŸäÿ'ù(8">, '‚ô ~¾¬‚o³ 6õ€zN·(GóGÃõ×ÑÐ]V.  …È Š°Õ™4ÁªÑ !ª²ŸÁt5Mp` ‰½´~{XL 3n,*Øyx ¥´È 1K$béì²e€N–>P¥ºâÉT6Ïæ+ó· ó”‘Ü+À€LRÇÀ€©7‹Og´@6 çX^‰&€H½è7Œ€  S&~^›ÕäÈ6õ€À²uÊ6Î× \€À¸GGç2P?T 4¬ð]êùêô€ïÀm¢`PIÍÃâP©d€Ï  €2ÑßÀ H]c¬¾0à 잀À€÷€§ ,rB ©Èƒ@vMån¹“g”$ Ð 8I04B¼ç£c ²hÍäâÅèÏ, '‚ôÀd &€½{Àÿ0ÿ½ …Üä»FZ`0”ä’‚ôÌ&> @^€L50 ƒ¢Ê>Þ-&GJ€½( Ã%@^¾†€¥ìÈ:GÞ˜Bîb]†á¥4êÎZž ׬(<}™;üÚ€lÆÈmžø.ƒP?ÝÐþ>€Á*ÑùôŒn ªA4¬Ðz„€ï¯H |p6Äâ0Tê¬I€”¾ƒÀOÇÌr‘ðP¸%Úd¤ÓÄ2”}€À)cà ÀN‘ô|0†J€½Y@OÞȘ¹Á€W½¾ÆÜGchüàÜ?Ñî¨a5ì¨.¾†¥ì¬{2fò)k“üŸäÿ'ù?ÉþOòÌñõÑùúR—Ð\ß‚#€"?RVÆ@Øu‡êÿznv£½¡/¬þS£™éFzÛs$Õ[˜¡@KG€dP×$fF‚_†£ë´@ µÊèÓ4‰~¦pÚ€Zæ €Èá¨ú`Å(°UËÈ”dÉ~ªlPÁR€#ísZ¦KðÔ{€,F2­Œ¨N­òx£-¨Ú³ÿ¯IiÂå:<£4@lŽeÐHi`M!u顸¥…úFCÑñÀ‘ÌÐ<( `«¿ÀGbC_ü,?8ÈÁþÃ@#äFqóz?3€LPÁU@K^¥!Ø"ÿÐh~ÊP @¨"ÿØh~®W¨ü±D$±”V×¥&R"ÿá`û˜L&†€J¿l”z53k2.¨aiæð» Iãíþ³Ôxu^´#ÔïiåG^–ytåKÿ'ù?ÉþOò“üŸó<{£óô¥/ ¸)/8#8">Ç­J&Ä4z½÷½+šG+ÖrG½€dÃÃΤJò’½€Ô{2*UöÓòѧ&£¯Uïlà;+Vð ÊÆÀÏGÍz=Öà†˜Jà•ÇCÑò¬þé•Í€Ú9²%qÓz9/PmÚ†0(% pJðô|~™†Ýp9CÈô3(|¼=!à6쀔G>e‚W‡£â’à7]°(`ø CÈ•áõnî°œ0 É€5+ù’¼>£Áë~¯À1G43¼4Q§F˜ tê ÒŠ2|Àñ?a€4œò€!I gi€+F6KàœðÀKÔ  Üò`%èhÆÞrð£ùqþGÈ(ÀE\ ?ø ¿ûe( E\ ?ø ¿ûwpô:„c€G?Ò¡Ô~}€c‰˜ð4cf@cƒ0$ÿé`¼P\ØÊßæÚ|XÿJ‡Qñ° €aŽF$¬B!c üƒtŠ&ñöR“ÇÚ÷M2QC‰þQš½ÕjåF¡4³•.B~Oò“üŸäÿ'ù?æx÷H!¯œ">Ñ@A ‹Ù Ð4D€Eï!KÙä72ã%Qúd™ K…z¬/yå‹aÕ™ £ïGqÄé¸ ¸ë϶ƒaÓ02Ó$N:ÔXIïØu)¼ÆZÀÀ ò™Þrbœ¿ƒá¡&5¡‹%HiTØ ;C?¼Œ‹5‚€= UÊXw€„dÒÜ`a4@ ²¼J²¶€P­–Z0~"ÄÀŒI#äˆYîÝogù$]/ì$ÀãHûˆ–Oã#-(ÂUÀªC:Xg6­€ @)G ‚H`ÃTåmü‘©ïýé­ú  í(l”$=zBÙI=-o ›µ’00øhÊ”¬%;Eí!…àCÿ²aÀ”A•+VU½ŸA/,h°žÒb’‹Ü ” ?úTªÙ¬a; Þ%TÊ/䣀™DU•ogó1 ÚìµEì²a{€RL8𢠩Z²­ìtX>°ÀEÿ²fZ4L?&'Gv!“'ÿ1›5¼`,rBtø $iÓ%®†EB ‚I¸"À`;!€™$‚k€ˆ°…Ø´lBŠ_ÁtÖ਀:V~Œ=€b¬Ä”êk{;‹$„Ë, IÿÔbˆ`QI(=oGÒ Ñ8{` Œ÷›z=íòmÆ2®PöTõ‰ãX×¥¨îÚF’“yRœ¾yçžyçžyçG"pÎG5aÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ"pÎ "pÎ!"pÎ""pÎG · FBl~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGPà„€!Z5M!ßÿû¸µ„ESA€"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºG뮺뮺뮺뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®Gºë®ºë®ºë®ºïˆgOÑ 5æ\CPw'@Á Àbƒ’€´È‡â6‘^` H ÿX M’h€^ž”E @¸°…Ÿ£Ðc×  ÂjOø*) ð‚LDšºë®¹#—.\¹ h_®øÞG¯@IiÐ"hHh;à¨ÅÀV/W˜HXã’€I= ¸x@$€ ƒ`@‚€N1G´^`àÀ @ªOø-è Ôóà d#WÁÅjºéþà "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºï‰ 1 5æ2!À€ä3`D8¼†lJЏæ€õŠû#A¥©äd®çYTqäÒE‰råË—.\¹råËŸyÁƒÐÎ7˜ã@ ¼ã@ “d\÷ƒMo¦éþà "ºë®ºë®ºë®ºë®ºG뮺뮺ë®Sõ×~†'×˜Ž rЀɭœ ¥qh)äpB‹æ#§h@Ð Ã *Ø”—âj ‘ý3^RBØ?ñàÀ×(ÁgÅ€V„ª(O×A1¡J€À°Ä¸X¬^æ@‘“q’[]–h‘‘P È ñ3¿pIp#ÔÑöƒø¤c/JIÑ5!Ÿã©¶Š2Æc· Ed=Ç@’ïGzé2 »Dœ¼:¼;Ÿ ï SËÃ8xÂ$ÿÙ`š±+%$–Áã@Z&âbA>OH ‰!ôÓa¤¡$â @v‚aá¼9›ÿ°nîwÔM&=-îúôhß̘€DP*`&ÿÜ!˜†@›ÿ¶–€. Ó½5ý‚@Ø ‘Äð9¤“ KÓ†«ë‚ã¤õÀñ> .dþ%kê|h’upÒ€zG€0kh¢Æ¹JO@(q4$oþÁ!€ÿ` ö Áˆ’^F6ï0@@âÃÚA,Q>&pÁqYP]Ù@F¿è„ø´w†³]ó-šrQ5À÷€bPÆ“ø ‰5Ò!!¥‡±7ÚpËïD´¼ æ^]lh‚©ià8@|aQ1!¦†a)à!€â1$£ô4UÂbÀµ²@À©i,GŸ6¤"j@I|¿¢¹pÅVÁEË/Å•?‹ ¦ ´¾MŠdÓüU&òåË–"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëåßp:A#˜¸à ƒ €W·÷‘xÀ  p °3  QoîñÓF~Hhhø¬YpN‹+êeKtïHÓ<€GŸu×uO!ù+¢&~\rËÓ—¹·8 cAÂ, Aº!Ü&›ú’æÉ)Ó×”šÌÙð(‚¢a*dé/«n6åIDŠÁÙô¤&²¦^{.&EV~ú\ÙLàÍX/AWE_¬÷U ¢àVm@"àf=$ïhàD2ƒx þ/"³´¦>3ÓH{ˆ°„ ÔÆ<8@š   €À)8DG> ˜_"@€œðüà CÄÀ‡Á0à„?7Ö€0ëmÁýð$€) @ÀN‚IWH†‚hÀ€hä@HðIÀ‚h@€€ ‚( ^ °MH`6( ð½7Ž®Ù:@ H\Y9$ · €2Å€d$D< €é +!pÄâ$Ÿ®k Qòê´Å¡ bGG ðÛ¨ èUªD—.\°"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºëä↓µÀëG@ †@‹¡ ˆa‰i/MòœÉkÒ ¹¼ˆ}8Ȳhg O¦ª2;Ŧ˜¥¿ð ÃFemn÷e1¨:RÕ€ѦY3nן¥êˆ\®:\3©²Uh† Ú R%Mqž{ Yv¹ :˹’ÁÚ€xtœŸGi!–*×zglÐôBñ ; Ÿ€°FDä·ºløfÑ3ÀQTˆŠ%¹•ƒ›È€`L.! eúÌθf‹DB´V¨ûA…Í&± ~LŠÑM6¬÷Éž ÑMHEÁ£ ¹¡ye{蛵e«¼Ó¦Êú³4]¯JƒuŸ«,oÈE@“´C P¸ËAÍpsyA Ø À0@ Ç +Û¦»ñ'^C®tXÏt.¶é:K/Gy%CPÒJ¹§ÛTµ"k®¹`"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¯‚Ï~Ø}3HȤÐnñ5ÓN]4²ÚI¡œçyJ³u齑A¨á |Š!¹û€wr00èd²Çàè <Ó1<èv% ¤â Ö¤a$ôþi8_)#ðP¾ø/Œ$Ç{'Ýºè² [€þ!r½óX±Ï€þ ³lG-ïòº0€_Y ÉÀûü’àÁÿñÜ Ûü‚zN·”i8ÝË|’à>·Û€—à LS—€D ßû“°æêy+'ÙX “€íÐd[É÷Å|‚ÉÀv Gùà}0"Èð")€~.•C aøž@’w ™+JÀ@_t˜R†XÔà$O²Y`<'nzº”ÖW×]rB"ºë®ºë®ºë®ºë®ºë®ºëG®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®¹råË—.\¹råËŸ2¸iXØP(ƒÓ]÷ž&r0ð¨3–B_ú@W€0 âj½cÆ!%ä@²`° ;`M!•Îð‡ÒvO[h13PÎ<(À‰–~²¼ë«½èåí^w –RJ>`“ #B€ìp„ù%,û„¾€(€†pЩoG4’'ëë;\qoíÐÑ Ñ ; AãB€ìBð"–¸õŒQ½Îp¨@RÚ’zE®ºë®ºë®ºë®ºë®ºë®ºë®º1Ñü"ºë®\¹råË—.\¹rçÄ„škôh1 à ôÄ>LBa Dž4©(Mv†Ón˜ih`H^ Q`t€&ˆ4 é+?J`0LY „Ѓ Ã6€«ÅVõ‚G¢Ã „ȰÉ)¬BoÚæº»ýà^wè˜ô)8ɺGDI¨/‰úEÝœ ac'D»40ÏÏAÍ—,²³ÀZ’Ÿ!î“FhzKFyµ%ÅÒ)<~€ËSO뮺뮺뮺뮺뮺뮺éþà#áAHDØ´[=ñ¼\@ÈÑH‹,p‰:̤hšq¸ó8™¬†uÃÈg£n:†ãS¢gð –™9[”,”G‘@é,/Gˆ0g€@‘rZê¢ ÛíÇx *£"@;¹¶3™7ðÀ€Gç% ŽïE‰‚ô’É®l:@vY7öYË ’3ÀQ 2Õ¢ðÒQ`I!@r&· @© g:°U\’Q`KÁ„-=›\) &aöã½·¢²è˜„¦ˆ‹Î$dÖ €b +pé†H?\š-JtRYHÈ Ä˜@ª’±˜â&GCJ –PÐ@ËH€ bKJ2&àÉXé€ Ä}àc:|Ž&AHxÉÐHªbŒL4šCS@&° Ópî›À5ûŽ€o¸¢"@0–€ aPi)W0ý¯ü¨>ˆ`ŸsgÉ¡·­ö6,4p@T ö6gæS˜pÀ t”€' @À(ÇÀ€`T%ƒ@l¹k3w÷ç¨4˜MçGàÅ€`¹’IMCn0ˆP_G††$t¡QCUmpXZ®@ÅN¸TB Ø’¨ ò É GÉ_¦šÉaä}§F95%ûüUÝe¹‡Cîn©7ÒP÷:«ÒŽXn]IJ;Ÿ”UØ8N¾œ\CQùÈ€`M&^v¼Ãît‘Ú#–ñ5 T…&†Oþâ ô!»8€„šï°ÛôϣɩGÆpª%G•€úû`–Ÿâa 0mÆïü6.!cozíæ -éê뮺뮹æ3.\¹råË—.\¹råË— þ#êxÀllÐ7Å•p9g¬xisI.·»qÒŽY ­ûŸi-âÆêÃi‹ÖB È ž±Á…ÁZr‘€ö ½ ¬ËĤc¶ƒuêÉšðßD¬˜¸7\ˆ•?öQ2LËŒ±cÀËáÁPÈš\Z5h}ðjéG r.ØPbÇŒ‹OU=lQ¢¶+“`@7€ ·’2»~L¬Ð)r«v…*%Ï+Ex•oë!1š¡\ý Þ `@T©2n“©ü­[6hÃC€HPQ;D0Ù »uÃå_:lºJlªß³uPj+?齃ö Ò@Æ©~áLó:" €LPâbzѢˈd#ìj•L|¹€:!€4€Šˆ Ð @ ¦@@ZbMDÌG˜R–‚5`›)DZnÍeÖ·õ¾AÒ‰¨ ’2î2~‡¾Ã¢²ÄE¤¦-æ´EÈHX+C6Æ`­jJˆ|2 ºd®x™IèhtZ}3AÊbI€2àÇ®&™'_$\È݇ &jÙ31ÒR?ÄÂi/âO¦¨`j ™(:Àà ±5Ø„4P`bI¬öX~XÀ‰þÄ< ö’ ºqÞ•L:˜Gš@¹@†¸( @wÀ:q€4!ìTå€fIÿ¢È0i1 UÖMIÜ5~›z`‹‰  d í} €0 ØJM à‘ÿ© ÄÀÂZR¾»o«’ á3Áš\<ëòÕu×]u× P».\¹råË—.\¹råË#æjß“K‹DCt­uŠ%äÔÓÉJP>œ40óB0»L  3A¨GˆX°À Hä ¸`âÛŽ¬+ ÿ?¤$lY÷½ïâ‘ZÔ}94™:ƒkkï{SÅêÄ7˜4¸ WXµz2€£ÄÄJ>À ɘÒ<ûúÌÐð Ãd'Å–bN/DÇG9:»”¼yZÐ’6n4K¸åÃóž˜0²†Å§£›ËÚ°ØœÀI+¼È„âb@`¹$ EôÓ\+„Ð¥1è\”'èü™”5Ýx.Êx÷€wGõ»_¨ÇÖ *fL€ù(‰H=1|ÁàHÇVd‡†“`)è²iI.ƒ2žŠÙ4åoQQd®:´ÉçªJ«OKʬÀ…ÖÐnú ý@#,h ÜtŸ‘€@ HEu¦Þç-  ôxš21` @MþÈäAþpDÿ²9ÉN¬ªa§Åo$ DõÁ™!œÛo[Vk{V6Ðhj1¶×4Ъ‚ËŠ †G80 ”ï_sï ÎW¬M `D.Hט‹€^¼ðZ@'ˆÀh­0 f€v3Н0’BCæà´¢eñÁP€dð¨›ôŠþBÅÿ!üA•?É~\¹t þ€ðiöºë®÷”õàÊôN_€0H Ð ¼Ø¸ºó$P+ÁZ0€Ä à´Tø ¶^`Gdb¾ðZtP I¼Ü@T¨2!ý‡EVÆ€bj@„LÉðˆZL "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºè*C}¥wùzüRi¯˜V˜± Z`@Ä@'ƒ)æ *xT€¨áQÈÔþ­@:Ðe.\¹rä~ÂGè$5dƒ.\þHðe=&ðbàx±pm<À Ø·ÀA° oG€w¢©æ* € €@;ñTÎèÉ @"!h¸ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®Wõ×]u×{犀uýz΀uÀvŒdð´ÀD2üXÊÀð0G÷Há½{Èj`uù‡ú× éàW`<İG €£'Á˜¢Àfþ6CÙY *ú¿“8ð MiNˆ]uè!`Ösðâ|WˆY 6×0 [GÑG°”ù΃OŠJ¦X!æfüt¼f Pj«“pû»°aËXä€  Ð2À@ÐÂX†Aä}vLCzˆ€“€G Þ€’IÄÃp\«vƒ€ï€œ„8š ¿ùÀvBC (ò ߀qX£ÖP#àHßý‘Ë@âÀ"À4 HèEÔÚ{ȃ]ñ„ø°Œn ƒ[ á÷r€$ýØÇ'b€Ëä”ÞJI•ŸúTР|´G B°Æ&„Ÿ"²/ ØÎN Á€dV “ìa ®ðÛÿÌt¼q<A¹gZC=ÜHXyÒ°\²‹îvŽ J@ß½f>’  ôEp ˆà‘ÿ è0ÒÇ{HßZÄ?À°uŒ+°9¸'è­ËÀxŸ«!`‚f h tüO‰\|™E¢~× ¡ËD'ôü<¨, xÊ T²hdɦô©Ð›G`lÀh:›ß+Äȯ@"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºïä\0ÿôC"¡—7L¢ô£ÈðÊÜ4A ñô‚ø€4€¡RB®ÒDÂ=gIøo*“ ¦Y;*ÓYÊ#R+!bølVoá5H×2ƒš.Y~ƒí0ÊÆì¿õÈõ’0ª·Œ:øùªµjErX^1}<ŠÏX>¨ªÙ¡b.µ`§z{H­1 ÖGªˆ ¢+PÀ&G€AÜtØ´"B½µa¾‚!“ I8DÀ ÈXðÒr`É(7œQ|\2°†a07‚@¤a3¬þa@ /ýP–   ô‹ÿ€@€ °€‚(œ@4@d p"PÁ$‰ šq|¤>N*³ú €à:çZ;4!h¨"€X Á$ÃA4àÒa†ƒÈA¸GIIZvF¬-Ðö&  ‘â;À:@a7L IIO€òp½ÀîĽâiR¢Ê¦byÊðdàÈ"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºï´z·´êûÀQ:KÈþµl¡‘1-*ȃ9 ˆ·zì‘¢Þðnœd0,Q>W­³†ùézÕ!eä"ž³"⊺Ӓt}!¥Þõ¹eÊh«‘ûG«%cÆ@;Gœ"&rjp­ýU>B`(jxˆ[€Ö­JŠŠÞ9« ’µ`n : ’d‚¤ÖÁcQäkÚ³›Q"KV‰‡´¯D:Û$a~DëùR)pbFÖt#x†Qh€@Yià€¥ã5Œ{’@~Å膂Ñà84RÀ{[]£#ú Åï'¥¤KçHˆ"°Ÿ >¼°3¼LÛÃ55Ö¦øØ†Tˆ4ªff¯Až €G"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë @ˆí *]i˜I#p¢’SÝËùZFœ´†â‚ÀÕ³‹ÀlGûÛúúüºù%ä½f:P®öÁ`hÁZæ2¦"Ð ƒ"’B+ÛÖõ€¦&Eb˜ÚÒéUwÉ/%Á„nÐrò¯¤ml6¡`VƒizÜëzÛäÀ5òFЏ#FØIŠ*)$Ä$æêàæ€ý”(ž%»yþGNžfÒ>vQäX„azÃ9(]½ÈáÏiÝ©™å3Š0\"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®¹råË—.\ùÃtÃJODòèÜdÌà‰–Ú³k¸0ä KÃRgõ¦ò€Ê0æ(èÀpÒ‡À!:¿·pÌ‘ž *ÙTþ‚^¡°´OóÐGØ2&_EûHåí¦Ñ6°ã÷KA€7@Þ&a[«KGÀP«Eh—&G¬;ùd¯‡ErÐð C`ëþP Ð7ŠºðÑ{¨s/CdT«]u×]uÈ*råË—.\¹råË—.\¹råË—.\¹r9€"ºë®\¹råË—°Cûoo^UkLB‹>H@Ú½0€uP€$ti5½d‚*8nâf&ɬGTQ!ÑO@ 4ëA’iü2&A‘2±rË€@CˆeÀ !Ú+ tè&a €2“«rÑ"­«EúÑúb“&)5‚ûäß!17ÈMhèÑ0h˜‹­”ˆ¸¤EÔ¯]u×]uȧ.\¹råË—.\¹råË—.\¹råË—#˜"ô,DP Ã%@z17øRCK’×ÄèÀ€v‘ðît‹è§­mûEGǃ@øû½Šùô½H²  UU©AçÃåáðaÀ zÍÿn,*ÆqpD1 V ‹L:(½s8!lÓáu›æ»õµâ+I|5…OÅÄ$û‹X"¹zaÛ™uˆܱdi/DºÑúblCh¿«Cá¾Bm­« ‚JHîÑÞ/[ÖÝ—Šñ4j輄$kNðV»Ä ôIÈO9‚ämå®Õ‹‹—x:,fIšéЪaÿ’:!¸Gèš2 &Ýêlt@!>!ÕVé (¤Ph Ñ —À—pàùÅ¢à @W±ñ@ñö×VÓÖ:d#Üä’€Z|X>¼o[VDM|>/_­rs–äý|ñ7µoèHÔ'ë€2D€Ï ­naˆ.êK«Z뮺뮺ä CyråË—.\¹råË—.\¹rä"ìyÉÀö ƒ]Yú€P‘ G”Ø*ëìÚKaÕXRNO“­UâžO @âtCDOëjÁ…`©ÉMmºÒ§ÕøFülñ3¦·¨‘±lZ6§Ïm_ʘªƒuËPra-6W€¥Z–CAX*ÞÕ]uts»uóÖWè< Þ+E"&¢ìïrfO‹+áЉU‘1ëh°3^Eg~X—"«!AÑ",Èô”@1ÕÿHfFÀ>€¯Ó×µr^ën€íÁ‰zÔGÐ|€"ÇøÝ)|/Úë3»² )’&¿Hÿ­o“™(ñHh7l;V¶{R*·®ºë®ºë®BgÒåË—.\¹råË—.\¹rä‘ü"Ó§áš- “ÉRêÆæ?¿r+~íåÈÞK긟Iñ0”.FîO@Ç¥>,¯;ö°¤ÿ k(—«ô«“tMóí§VÑâ /@:J"r>›Ö÷ÀM‘‘dA¨ÕµSý?G‚Q\42µº"Ñ#áu‹@ºj…¢TBÅ&,¥V ž@ÔÓ0©›:èßtsëýY;„D4QÓêþi° Ðù½ëOèŠx¬¹8¯Yê‰ ´õ’°ú éXØ¿å»òb¼Nôy•‘úíü2KVý\*ÚUnôAŒ‹iV«É› 'Ö ( ù }¤’«c1 €$'–A’J&`šëG-a"²Z/w»t¬Í€ºÝ3IÉ׈¨×_#ÅÚÇzÌräÝeÄX Ìœg'Á¡‰~ïäù!#àÜ»­Øt¥FJ–/Ûû¼¦A Ñ¢ôYî@1üÞ“ZHÐJ Κ´Qb‹+aø.püÀ¥¾„ÐÌïvè òÊJÄ>Suf,$˜ntrü¤&.å,2fã‚ç ŠÈ2)4YÕ©ÒªK®ºë®ºë®ºë®ºë®ºë®ºG뮺ë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®Gºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬"ºë®ºë®ºëG®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬ "ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬!"ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë¬""ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®ºë®G3´ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿºë¬pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/eit_categories.txt000066400000000000000000000255201360567320200246060ustar00rootroot00000000000000# You could make own map by dropping the customized file 'eit_categories.txt' # into path '$KODI_ROOT$/userdata/addon_data/pvr.mythtv/' # # # en_GB categories # 0x00;"Agriculture" 0x00;"Collectibles" 0x00;"Community" 0x00;"Fishing" 0x00;"Fundraiser" 0x00;"Gaming" 0x00;"History" 0x00;"Holiday" 0x00;"Paranormal" 0x00;"Parenting" 0x00;"Reality" 0x00;"Special" 0x00;"Standup" 0x10;"Movie" 0x11;"Crime" 0x11;"Crime drama" 0x11;"Movie - Detective/Thriller" 0x11;"Mystery" 0x11;"Suspense" 0x12;"Action" 0x12;"Adventure" 0x12;"Movie - Adventure/Western/War" 0x12;"War" 0x12;"Western" 0x13;"Fantasy" 0x13;"Horror" 0x13;"Movie - Science Fiction/Fantasy/Horror" 0x13;"Science fiction" 0x14;"Comedy" 0x14;"Comedy-drama" 0x14;"Movie - Comedy" 0x14;"Sitcom" 0x15;"Movie - Soap/melodrama/folkloric" 0x15;"Soap" 0x16;"Movie - Romance" 0x16;"Romance" 0x16;"Romance-comedy" 0x17;"Docudrama" 0x17;"Historical drama" 0x17;"Movie - Serious/Classical/Religious/Historical Movie/Drama" 0x18;"Adults only" 0x18;"Movie - Adult" 0x1F;"Drama" 0x20;"News" 0x20;"Public affairs" 0x21;"News/weather report" 0x21;"Weather" 0x22;"News magazine" 0x22;"Newsmagazine" 0x23;"Documentary" 0x24;"Intelligent Programmes" 0x24;"Interview" 0x30;"Entertainment" 0x31;"Game show" 0x31;"Game Show" 0x32;"Variety" 0x32;"Variety Show" 0x33;"Talk" 0x33;"Talk Show" 0x40;"Boxing" 0x40;"Pro wrestling" 0x40;"Sports" 0x40;"Sports event" 0x40;"Sports non-event" 0x40;"Sports talk" 0x40;"Wrestling" 0x41;"Special Events (World Cup, World Series, etc)" 0x42;"Sports Magazines" 0x43;"Football (Soccer)" 0x44;"Tennis/Squash" 0x45;"Misc. Team Sports" 0x46;"Athletics" 0x47;"Auto" 0x47;"Auto racing" 0x47;"Motor Sport" 0x48;"Water Sport" 0x49;"Winter Sports" 0x4A;"Equestrian" 0x4B;"Martial Sports" 0x50;"Children" 0x50;"Kids" 0x51;"Pre-School Children's Programmes" 0x52;"Entertainment Programmes for 6 to 14" 0x53;"Entertainment Programmes for 10 to 16" 0x54;"Informational/Educational" 0x55;"Animated" 0x55;"Cartoons/Puppets" 0x60;"Dance" 0x60;"Music" 0x60;"Music/Ballet/Dance" 0x61;"Rock/Pop" 0x62;"Classical Music" 0x63;"Folk Music" 0x64;"Jazz" 0x64;"Musical" 0x64;"Musical comedy" 0x65;"Musical/Opera" 0x66;"Ballet" 0x70;"Art" 0x70;"Arts/crafts" 0x70;"Arts/Culture" 0x71;"Performing Arts" 0x72;"Fine Arts" 0x73;"Religion" 0x73;"Religious" 0x74;"Popular Culture/Traditional Arts" 0x75;"Literature" 0x76;"Film/Cinema" 0x77;"Experimental Film/Video" 0x78;"Broadcasting/Press" 0x79;"New Media" 0x7A;"Arts/Culture Magazines" 0x7B;"Fashion" 0x80;"Bus./financial" 0x80;"Politics" 0x80;"Social/Policical/Economics" 0x81;"Magazines/Reports/Documentary" 0x82;"Economics/Social Advisory" 0x83;"Remarkable People" 0x90;"Biography" 0x90;"Educational" 0x90;"Education/Science/Factual" 0x90;"Science" 0x91;"Animals" 0x91;"Environment" 0x91;"Nature" 0x91;"Nature/animals/Environment" 0x92;"Computers" 0x92;"Technology" 0x92;"Technology/Natural Sciences" 0x93;"Medical" 0x93;"Medicine/Physiology/Psychology" 0x94;"Foreign Countries/Expeditions" 0x95;"Social/Spiritual Sciences" 0x96;"Further Education" 0x97;"French" 0x97;"Languages" 0x97;"Spanish" 0xA0;"Home improvement" 0xA0;"Hunting" 0xA0;"Leisure/Hobbies" 0xA0;"Outdoors" 0xA0;"Self improvement" 0xA1;"Tourism/Travel" 0xA1;"Travel" 0xA2;"Handicraft" 0xA2;"How-to" 0xA3;"Motoring" 0xA4;"Exercise" 0xA4;"Fitness & Health" 0xA4;"Health" 0xA5;"Cooking" 0xA6;"Advertizement/Shopping" 0xA6;"Consumer" 0xA6;"Shopping" 0xA7;"Gardening" 0xA7;"House/garden" 0xB0;"Original Language" 0xB1;"Black & White" 0xB2;"""Unpublished"" Programmes" 0xB3;"Live Broadcast" # # fr_FR categories # 0x00;"Feuilleton" 0x00;"Série" 0x00;"Série/Feuilleton" 0x00;"Téléfilm" 0x00;"Théâtre" 0x00;"Téléréalité" 0x10;"Court métrage" 0x10;"Film" 0x11;"Film - Détective/Thriller" 0x12;"Film - Aventure/Western/Guerre" 0x13;"Film - Science-fiction/Fantastique/Horreur" 0x14;"Film - Comédie" 0x15;"Film - Sitcom/Mélodrame/Folklorique" 0x16;"Film - Romance" 0x17;"Film - Sérieux/Classique/Religieux/Film Historique/Drame" 0x18;"Film - Adulte" 0x1F;"Drame" 0x20;"Nouvelles" 0x20;"Journal" 0x20;"Information" 0x21;"Nouvelles/Météo" 0x21;"Météo" 0x22;"Magazine d'informations" 0x23;"Documentaire" 0x23;"Série documentaire" 0x24;"Programmes intelligents" 0x30;"Divertissement" 0x31;"Jeu" 0x31;"Émission de jeu" 0x32;"Émission de variétés" 0x33;"Débat" 0x40;"Sport" 0x41;"Special Events (World Cup, World Series, etc)" 0x42;"Magazines sportifs" 0x43;"Football (Soccer)" 0x44;"Tennis/Squash" 0x45;"Sports en équipes divers" 0x46;"Athlétisme" 0x47;"Sports motorisés" 0x48;"Sports nautiques" 0x49;"Sports d'hiver" 0x4A;"Équestre" 0x4B;"Sports de combats" 0x50;"Enfants" 0x51;"Pre-School Children's Programmes" 0x54;"Informatif/Éducatif" 0x55;"Dessins animés/Marionnettes" 0x55;"Dessin animé" 0x60;"Musique/Ballet/Danse" 0x60;"Musique" 0x61;"Rock/Pop" 0x62;"Musique classique" 0x63;"Musique populaire" 0x64;"Jazz" 0x64;"Comédie musicale" 0x64;"Concert" 0x64;"Clips" 0x65;"Musical/Opéra" 0x65;"Opéra" 0x66;"Ballet" 0x70;"Arts/Culture" 0x71;"Arts du spectacle" 0x72;"Beaux-arts" 0x73;"Religion" 0x73;"Emission religieuse" 0x74;"Culture populaire/Arts traditionnels" 0x75;"Literature" 0x76;"Film/Cinéma" 0x77;"Film expérimental/Vidéo" 0x78;"Diffusion/Presse" 0x79;"Nouveaux médias" 0x7A;"Magazines de Culture/Arts" 0x7B;"Mode" 0x80;"Social/Policical/Economics" 0x81;"Magazines/Rapports/Documentaires" 0x81;"Magazine" 0x81;"Reportage" 0x82;"Économie/Conseil social" 0x90;"Éducation/Science/Faits" 0x91;"Nature/Animaux/Environnement" 0x92;"Technologie/Sciences naturelles" 0x93;"Médecine/Physiologie/Psychologie" 0x94;"Pays étrangers/Expéditions" 0x95;"Social/Spiritual Sciences" 0x96;"Informatif/Educatif" 0xA0;"Loisirs" 0xA1;"Tourisme/Voyages" 0xA2;"Bricolage" 0xA3;"Automobile" 0xA4;"Fitness et santé" 0xA5;"Cuisine" 0xA6;"Promotion/Shopping" 0xA6;"Shopping" 0xA7;"Jardinage" 0xB0;"Bande originale" 0xB1;"Noir et blanc" 0xB3;"Diffusion en direct" 0xC1;"Suspense" 0xC3;"Science fiction" 0xC4;"Horreur" 0xC6;"Comédie" # # fr_FR categories : xmltv_telerama # 0x00;"feuilleton dramatique" 0x00;"feuilleton policier" 0x00;"feuilleton réaliste" 0x00;"feuilleton sentimental" 0x00;"humour" 0x00;"série burlesque" 0x00;"série d'action" 0x00;"série d'animation" 0x00;"série d'aventures" 0x00;"série d'horreur" 0x00;"série de science-fiction" 0x00;"série de suspense" 0x00;"série de téléréalité" 0x00;"série dramatique" 0x00;"série fantastique" 0x00;"série hospitalière" 0x00;"série humoristique" 0x00;"série jeunesse" 0x00;"série judiciaire" 0x00;"série policière" 0x00;"série réaliste" 0x00;"série sentimentale" 0x00;"téléréalité" 0x10;"film : autre" 0x10;"film : court métrage d'animation" 0x10;"film : essai" 0x10;"film d'animation" 0x10;"téléfilm d'animation" 0x10;"téléfilm pour la jeunesse" 0x11;"film : thriller" 0x11;"film policier" 0x11;"téléfilm de suspense" 0x11;"téléfilm policier" 0x12;"film : aventure" 0x12;"film catastrophe" 0x12;"film d'action" 0x12;"film d'aventures" 0x12;"film d'espionnage" 0x12;"téléfilm d'action" 0x12;"téléfilm d'aventures" 0x13;"film : fantastique" 0x13;"film d'horreur" 0x13;"film de science-fiction" 0x13;"film fantastique" 0x13;"téléfilm d'horreur" 0x13;"téléfilm de science-fiction" 0x13;"téléfilm fantastique" 0x13;"téléfilm féerique" 0x14;"film : comédie" 0x14;"film : comédie dramatique" 0x14;"film : comédie romantique" 0x14;"film : comédie sentimentale" 0x14;"téléfilm humoristique" 0x15;"film : drame" 0x15;"téléfilm dramatique" 0x15;"téléfilm sentimental" 0x17;"film : documentaire" 0x17;"film documentaire" 0x18;"magazine pornographique" 0x18;"téléfilm érotique" 0x20;"journal" 0x21;"météo" 0x22;"magazine d'actualité" 0x22;"magazine de l'économie" 0x23;"documentaire : animalier" 0x23;"documentaire : aventures" 0x23;"documentaire : beaux-arts" 0x23;"documentaire : cinéma" 0x23;"documentaire : civilisations" 0x23;"documentaire : culture" 0x23;"documentaire : découvertes" 0x23;"documentaire : economie" 0x23;"documentaire : environnement" 0x23;"documentaire : fiction" 0x23;"documentaire : gastronomie" 0x23;"documentaire : géopolitique" 0x23;"documentaire : histoire" 0x23;"documentaire : justice" 0x23;"documentaire : musique" 0x23;"documentaire : musique classique" 0x23;"documentaire : nature" 0x23;"documentaire : politique" 0x23;"documentaire : santé" 0x23;"documentaire : sciences et technique" 0x23;"documentaire : société" 0x23;"documentaire : sport" 0x23;"documentaire : téléréalité" 0x23;"documentaire : voyage" 0x30:divertissement" 0x30:divertissement-humour" 0x31;"jeu" 0x31;"loterie" 0x32;"magazine du show-biz" 0x32;"variétés" 0x33;"débat" 0x33;"débat parlementaire" 0x33;"talk-show" 0x40;"cyclisme" 0x40;"sport : cyclisme" 0x40;"sport : cyclo-cross" 0x40;"sport : fitness" 0x40;"sport : plongeon" 0x40;"sport : pétanque" 0x40;"sport : rallycross" 0x40;"sport : rallye" 0x40;"sport : trail" 0x40;"triathlon" 0x42;"jt sport" 0x42;"magazine sportif" 0x43;"sport : football" 0x44;"sport : tennis" 0x45;"rugby" 0x45;"sport : basket-ball" 0x45;"sport : boule lyonnaise" 0x45;"sport : handball" 0x45;"sport : hockey sur glace" 0x45;"sport : multisports" 0x45;"sport : rugby" 0x46;"sport : biathlon" 0x47;"motocyclisme" 0x47;"sport : automobilisme" 0x47;"sport : formule 1" 0x47;"sports mécaniques" 0x48;"sport : voile" 0x48;"voile" 0x49;"sport : ski" 0x49;"sport : snowboard" 0x4A;"hippisme" 0x4B;"catch" 0x4B;"kick-boxing" 0x4B;"sport : boxe" 0x4B;"sport : judo" 0x50;"emission jeunesse" 0x50;"magazine jeunesse" 0x55;"jeunesse : dessin animé" 0x55;"jeunesse : dessin animé jeunesse" 0x55;"jeunesse : dessin animé manga" 0x60:contemporain" 0x60;"magazine musical" 0x60;"world music" 0x61;"pop & rock" 0x62;"classique" 0x64;"clips" 0x65;"opéra" 0x65;"opéra bouffe" 0x71;"cirque" 0x71;"one man show" 0x73;"emission religieuse" 0x73;"magazine religieux" 0x75;"magazine littéraire" 0x77;"film : court métrage" 0x78;"magazine des médias" 0x79;"magazine du multimédia" 0x7A;"magazine culturel" 0x7A;"magazine des beaux-arts" 0x7A;"magazine du cinéma" 0x7A;"magazine du court métrage" 0x7B;"magazine de la mode" 0x80;"emission politique" 0x80;"magazine de géopolitique" 0x80;"magazine de société" 0x80;"magazine politique" 0x81;"magazine d'information" 0x81;"magazine de charme" 0x81;"magazine de découvertes" 0x81;"magazine de l'emploi" 0x81;"magazine de la femme" 0x81;"magazine de la mer" 0x81;"magazine de reportages" 0x81;"magazine de services" 0x81;"magazine historique" 0x81;"magazine judiciaire" 0x81;"magazine régional" 0x82;"magazine du consommateur" 0x91;"magazine animalier" 0x91;"magazine de l'environnement" 0x91;"magazine hippique" 0x92;"magazine scientifique" 0x93;"magazine de la santé" 0x93;"magazine médical" 0x96;"magazine éducatif" 0xA0;"magazine de la décoration" 0xA1;"magazine du tourisme" 0xA3;"magazine de l'automobile" 0xA4;"fitness" 0xA5;"magazine culinaire" 0xA5;"magazine de l'art de vivre" 0xA5;"magazine de la gastronomie" 0xA6;"magazine de télé-achat" 0xA7;"magazine du jardinage" 0xB2;"programme indéterminé"pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/000077500000000000000000000000001360567320200226365ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.af_za/000077500000000000000000000000001360567320200273265ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.af_za/strings.po000066400000000000000000000232221360567320200313600ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Afrikaans (South Africa) (http://www.transifex.com/projects/p/kodi-main/language/af_ZA/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: af_ZA\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "MythTV Agterkant Gasheernaam of IP" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "MythTV Agterkant Poort" msgctxt "#30002" msgid "MythTV Database Username" msgstr "MythTV Databasis Gebruikernaam" msgctxt "#30003" msgid "MythTV Database Password" msgstr "MythTV Databasis Wagwoord" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "MythTV Databasis Databasisnaam" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Sluit meer ontfoutings inligting in log lêer in" msgctxt "#30006" msgid "Enable Live TV" msgstr "Stel Lewendige TV in staat" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Laat Lewendige TV toe om geskeduleerde vertonings te skuif" msgctxt "#30008" msgid "Conflict handling" msgstr "Konflik hantering" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Verkies Live TV wanneer opname later gleuf het" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Verkies opname en stop Live TV" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Verkies Live TV en kanselleer botsende opname" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "MythTV Agterkant Ethernet adres (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "MythTV Agterkant Poort vir API dienste" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "MythTV Sekuriteits Pin vir API dienste" msgctxt "#30019" msgid "General" msgstr "Algemeen" msgctxt "#30020" msgid "Template provider" msgstr "Templaat verskaffer" msgctxt "#30021" msgid "Internal" msgstr "Intern" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "Interne templaat" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Soek outomaties Metadata op" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Advertensie Vlag nuwe opnames" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Transkodeer nuwe opnames" msgctxt "#30029" msgid "Run User Job #1" msgstr "Loop Gebruiker Taak #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Loop Gebruiker Taak #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Loop Gebruiker Taak #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Loop Gebruiker Taak #4" msgctxt "#30033" msgid "Transcoder" msgstr "Transkodeerder" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Laat opnames toe om te verval" msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "Vra om die gekykte opname uit te wis" msgctxt "#30048" msgid "Show 'Original Airdate' instead of 'Recording Time'" msgstr "Wys 'Oorspronklike Lugdatum' in plaas van 'Opname Tyd'" msgctxt "#30049" msgid "Recording template" msgstr "Opneem templaat" msgctxt "#30050" msgid "Advanced" msgstr "Gevorderde" msgctxt "#30051" msgid "Preferences" msgstr "Voorkeure" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Stel demux van MPEG-TS in staat" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Instem vertraging (sek)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Groepeer opnames volgens titel" msgctxt "#30055" msgid "Always" msgstr "Altyd" msgctxt "#30056" msgid "Only for series" msgstr "Slegs vir reekse" msgctxt "#30057" msgid "Never" msgstr "Nooit" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Stel advertensie oorslaan (EDL) in staat" msgctxt "#30059" msgid "Always" msgstr "Altyd" msgctxt "#30060" msgid "Dialog" msgstr "Dialoog" msgctxt "#30061" msgid "Never" msgstr "Nooit" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Laat agterkant afskakel" msgctxt "#30063" msgid "Enable channel icons" msgstr "Stel kanaal ikone in staat" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Stel opneem van ondersteunerkuns / duimnaelsketse in staat" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "Beperk kanaal instem pogings" msgctxt "#30066" msgid "Show inactive upcomings (alternative/recorded/expired)" msgstr "Wys onaktiewe opkomendes (alternatief/opgeneem/verstreke)" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Protokol weergawe: %i - Databasis weergawe: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "Stel EDL in staat" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "'n Sny lys of advertensie oorslane is gevind.\nWil jy EDL funksionaliteit aktiveer vir hierdie vertoning ?" msgctxt "#30112" msgid "Connection failed" msgstr "Konneksie het gefaal" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "Wil jy weer probeer ?" msgctxt "#30300" msgid "Failed to connect the MythTV backend with the known protocol versions. Please check the compatibility map of the addon and upgrade your backend to a supported version." msgstr "Konnekteer van die MythTV agterkant met die bekende protokol weergawes het gefaal. Gaan asseblief die versoenbaarheids kaart van die byvoegsel na en opgradeer jou agterkant na 'n ondersteunde weergawe." msgctxt "#30301" msgid "Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. The PIN code has to be configured in your backend to allow connection." msgstr "Konnekteer van die API dienste van MythTV agterkant het gefaal. Gaan asseblief jou PIN kode of agterkant opstelling na. Die PIN kode moet in jou agterkant opgestel wees om konneksie toe te laat." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Konneksie met MythTV agterkant verloor" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Konneksie met MythTV herstel" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "Geen reaksie vanaf MythTV agterkant" msgctxt "#30305" msgid "Channel unavailable" msgstr "Kanaal beskikbaar" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Opnemer nie beskikbaar" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Kanselleer botsende opname: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Stop Live TV weens botsende opname: %s" msgctxt "#30309" msgid "Not recording" msgstr "Neem nie op" msgctxt "#30310" msgid "Enabled" msgstr "In staat gestel" msgctxt "#30311" msgid "Disabled" msgstr "Nie in staat gestel" msgctxt "#30312" msgid "No broadcast found" msgstr "Geen uitsending gevind" msgctxt "#30411" msgid "Delete and re-record" msgstr "Wis uit en neem weer op" msgctxt "#30412" msgid "Keep recording" msgstr "Hou aan met opneem" msgctxt "#30421" msgid "Toggle display of alternative/recorded/expired" msgstr "Wissel vertoon van alternatief/opgeneem/verstreke" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "Verfris kas vir kanaal ikone" msgctxt "#30423" msgid "Trigger channels update" msgstr "Sneller kanale opdatering" msgctxt "#30424" msgid "Show status of scheduling" msgstr "Wys status van skedulering" msgctxt "#30451" msgid "Unhandled" msgstr "Ongehanteer" msgctxt "#30452" msgid "Upcoming" msgstr "Opkomend" msgctxt "#30453" msgid "Overriden" msgstr "Oorskryf" msgctxt "#30454" msgid "Don't record" msgstr "Moenie opneem" msgctxt "#30455" msgid "Upcoming manual" msgstr "Opkomend handrolies" msgctxt "#30456" msgid "Zombie" msgstr "Zombie" msgctxt "#30457" msgid "Alternative" msgstr "Alternatief" msgctxt "#30458" msgid "Currently recorded" msgstr "Huidiglik opgeneem" msgctxt "#30459" msgid "Expired recording" msgstr "Verstreke opname" msgctxt "#30460" msgid "Manual" msgstr "Handrolies" msgctxt "#30461" msgid "Record one" msgstr "Neem een op" msgctxt "#30462" msgid "Record weekly" msgstr "Neem weekliks op" msgctxt "#30463" msgid "Record daily" msgstr "Neem daagliks op" msgctxt "#30464" msgid "Record all" msgstr "Neem almal op" msgctxt "#30465" msgid "Record this" msgstr "Neem hierdie op" msgctxt "#30466" msgid "Record series" msgstr "Neem reeks op" msgctxt "#30467" msgid "Search keyword" msgstr "Soek sleutelwoord" msgctxt "#30468" msgid "Search people" msgstr "Soek mense" msgctxt "#30469" msgid "Rule disabled" msgstr "Reël nie in staat gestel" msgctxt "#30501" msgid "Don't match duplicates" msgstr "Moenie duplikate pas nie" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "Pas duplikate deur onderskrifte te gebruik" msgctxt "#30503" msgid "Match duplicates using description" msgstr "Pas duplikate deur beskrywing te gebruik" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "Pas duplikate deur onderskrifte en beskrywing te gebruik" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "Pas duplikate deur onderskrifte en dan beskrywing te gebruik" msgctxt "#30506" msgid "Recordings never expire" msgstr "Opnames verval nooit" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Laat opnames toe om te verval" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "Hou tot %d opnames" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "Hou %d nuutste en verval oues" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.am_et/000077500000000000000000000000001360567320200273335ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.am_et/strings.po000066400000000000000000000044551360567320200313740ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Amharic (Ethiopia) (http://www.transifex.com/projects/p/kodi-main/language/am_ET/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: am_ET\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" msgctxt "#30019" msgid "General" msgstr "ባጠቃላይ" msgctxt "#30020" msgid "Template provider" msgstr "ቴáˆá•ሌት አቅራቢ" msgctxt "#30021" msgid "Internal" msgstr "የ á‹áˆµáŒ¥" msgctxt "#30025" msgid "Internal template" msgstr "የ á‹áˆµáŒ¥ ቴáˆá•ሌት" msgctxt "#30029" msgid "Run User Job #1" msgstr "የ ተጠቃሚ ስራ ማስኬጃ #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "የ ተጠቃሚ ስራ ማስኬጃ #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "የ ተጠቃሚ ስራ ማስኬጃ #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "የ ተጠቃሚ ስራ ማስኬጃ #4" msgctxt "#30050" msgid "Advanced" msgstr "የረቀቀ" msgctxt "#30055" msgid "Always" msgstr "áˆáˆáŒŠá‹œ" msgctxt "#30056" msgid "Only for series" msgstr "ለ ተከታታይ ብቻ" msgctxt "#30057" msgid "Never" msgstr "በáጹሠ" msgctxt "#30059" msgid "Always" msgstr "áˆáˆáŒŠá‹œ" msgctxt "#30060" msgid "Dialog" msgstr "ንáŒáŒáˆ­" msgctxt "#30061" msgid "Never" msgstr "በáጹሠ" msgctxt "#30305" msgid "Channel unavailable" msgstr "ጣቢያዠአáˆá‰°áŒˆáŠ˜áˆ" msgctxt "#30306" msgid "Recorder unavailable" msgstr "መቅረጫዠá‹áŒáŒ አይደለáˆ" msgctxt "#30309" msgid "Not recording" msgstr "እየቀረጸ አይደለáˆ" msgctxt "#30310" msgid "Enabled" msgstr "ተችáˆáˆ" msgctxt "#30311" msgid "Disabled" msgstr "ተሰናክáˆáˆ " msgctxt "#30312" msgid "No broadcast found" msgstr "áˆáŠ•áˆ á‹¨áˆšá‰°áˆ‹áˆˆá አáˆá‰°áŒˆáŠ˜áˆ " msgctxt "#30411" msgid "Delete and re-record" msgstr "ማጥáŠá‹« እና እንደገና-መቅረጫ" msgctxt "#30460" msgid "Manual" msgstr "በእጅ " pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.ar_sa/000077500000000000000000000000001360567320200273335ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.ar_sa/strings.po000066400000000000000000000024141360567320200313650ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Arabic (Saudi Arabia) (http://www.transifex.com/projects/p/kodi-main/language/ar_SA/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ar_SA\n" "Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" msgctxt "#30019" msgid "General" msgstr "عام" msgctxt "#30050" msgid "Advanced" msgstr "Ù…ÙØªÙ‚دم" msgctxt "#30055" msgid "Always" msgstr "دائما" msgctxt "#30057" msgid "Never" msgstr "أبداً" msgctxt "#30059" msgid "Always" msgstr "دائما" msgctxt "#30061" msgid "Never" msgstr "أبداً" msgctxt "#30305" msgid "Channel unavailable" msgstr "محطة غير Ù…ØªÙˆÙØ±Ø©" msgctxt "#30310" msgid "Enabled" msgstr "ممكن" msgctxt "#30311" msgid "Disabled" msgstr "معطلة" msgctxt "#30460" msgid "Manual" msgstr "يدوي" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.az_az/000077500000000000000000000000001360567320200273525ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.az_az/strings.po000066400000000000000000000014401360567320200314020ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Azerbaijani (Azerbaijan) (http://www.transifex.com/projects/p/kodi-main/language/az_AZ/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: az_AZ\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30019" msgid "General" msgstr "Ümumi" msgctxt "#30055" msgid "Always" msgstr "HÉ™miÅŸÉ™" msgctxt "#30059" msgid "Always" msgstr "HÉ™miÅŸÉ™" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.be_by/000077500000000000000000000000001360567320200273265ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.be_by/strings.po000066400000000000000000000040161360567320200313600ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Belarusian (Belarus) (http://www.transifex.com/projects/p/kodi-main/language/be_BY/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: be_BY\n" "Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "MythTV Backend Hostname or IP" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "MythTV Backend Port" msgctxt "#30002" msgid "MythTV Database Username" msgstr "MythTV Database Username" msgctxt "#30003" msgid "MythTV Database Password" msgstr "Пароль да базы зьвеÑтак MythTV" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "MythTV Database Databasename" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Include more debug information in the log file" msgctxt "#30006" msgid "Enable Live TV" msgstr "Enable Live TV" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Allow Live TV to move scheduled shows" msgctxt "#30019" msgid "General" msgstr "General" msgctxt "#30050" msgid "Advanced" msgstr "Advanced" msgctxt "#30055" msgid "Always" msgstr "Заўжды" msgctxt "#30057" msgid "Never" msgstr "Ðіколі" msgctxt "#30059" msgid "Always" msgstr "Заўжды" msgctxt "#30061" msgid "Never" msgstr "Ðіколі" msgctxt "#30305" msgid "Channel unavailable" msgstr "Channel unavailable" msgctxt "#30310" msgid "Enabled" msgstr "Уключана" msgctxt "#30311" msgid "Disabled" msgstr "Забаронена" msgctxt "#30460" msgid "Manual" msgstr "Ручны" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.bg_bg/000077500000000000000000000000001360567320200273065ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.bg_bg/strings.po000066400000000000000000000312661360567320200313470ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Bulgarian (Bulgaria) (http://www.transifex.com/projects/p/kodi-main/language/bg_BG/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: bg_BG\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "Име или IP Ð°Ð´Ñ€ÐµÑ Ð½Ð° Ñървъра на MythTV" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "Порт на Ñървъра на MythTV" msgctxt "#30002" msgid "MythTV Database Username" msgstr "ПотребителÑко име за базата данни на MythTV" msgctxt "#30003" msgid "MythTV Database Password" msgstr "Парола за базата данни на MythTV" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "Име на базата данни на MythTV" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Повече Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° дебъгване в журнала" msgctxt "#30006" msgid "Enable Live TV" msgstr "Ð¢ÐµÐ»ÐµÐ²Ð¸Ð·Ð¸Ñ Ð½Ð° живо" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "ТелевизиÑта на живо да премеÑтва планираните предаваниÑ" msgctxt "#30008" msgid "Conflict handling" msgstr "Обработка на конфликти" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Предпочитане на Ñ‚ÐµÐ»ÐµÐ²Ð¸Ð·Ð¸Ñ Ð½Ð° живо, когато запиÑÑŠÑ‚ е за по-къÑно" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Предпочитане на запиÑа, Ñпиране на телевизиÑта на живо" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Предпочитане на Ñ‚ÐµÐ»ÐµÐ²Ð¸Ð·Ð¸Ñ Ð½Ð° живо, отмÑна на ÐºÐ¾Ð½Ñ„Ð»Ð¸ÐºÑ‚Ð½Ð¸Ñ Ð·Ð°Ð¿Ð¸Ñ" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "Интернет Ð°Ð´Ñ€ÐµÑ Ð½Ð° Ñървъра на MythTV (Ñъбуждане по мрежата)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "Порт на Ñървъра на MythTV за уÑлугите за ППИ (API)" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "Код за ÑигурноÑÑ‚ на MythTV за уÑлугите за ППИ (API)" msgctxt "#30019" msgid "General" msgstr "ОÑновни" msgctxt "#30020" msgid "Template provider" msgstr "Шаблон на доÑтавчика" msgctxt "#30021" msgid "Internal" msgstr "Вътрешен" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "Вътрешен шаблон" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Ðвтоматично търÑене на метаданни" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "ОтбелÑзване на новите запиÑи като реклами" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Преобразуване на новите запиÑи" msgctxt "#30029" msgid "Run User Job #1" msgstr "Стартиране на задача â„–1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Стартиране на задача â„–2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Стартиране на задача â„–3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Стартиране на задача â„–4" msgctxt "#30033" msgid "Transcoder" msgstr "Преобразувател" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "ОÑтарÑване на запиÑите" msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "Питане за изтриване на изгледаните запиÑи" msgctxt "#30048" msgid "Show 'Original Airdate' instead of 'Recording Time'" msgstr "Показване на „дата на излъчване“ вмеÑто „дата на запиÑ“" msgctxt "#30049" msgid "Recording template" msgstr "Шаблон за запиÑване" msgctxt "#30050" msgid "Advanced" msgstr "Допълнителни" msgctxt "#30051" msgid "Preferences" msgstr "ПредпочитаниÑ" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "ДемултиплекÑиране на MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "ЗабавÑне при наÑтройка (Ñек)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Групиране на запиÑите по заглавие" msgctxt "#30055" msgid "Always" msgstr "Винаги" msgctxt "#30056" msgid "Only for series" msgstr "Само за Ñериалите" msgctxt "#30057" msgid "Never" msgstr "Ðикога" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "ПропуÑкане на рекламите (ПР)" msgctxt "#30059" msgid "Always" msgstr "Винаги" msgctxt "#30060" msgid "Dialog" msgstr "Диалогов прозорец" msgctxt "#30061" msgid "Never" msgstr "Ðикога" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Разрешаване на Ñпирането на Ñървъра" msgctxt "#30063" msgid "Enable channel icons" msgstr "Иконки на каналите" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Ð—Ð°Ð¿Ð¸Ñ Ð½Ð° фен-арт/миниатюри" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "Ограничаване на опитите на наÑтройване на канала" msgctxt "#30066" msgid "Show inactive upcomings (alternative/recorded/expired)" msgstr "Показване на неактивните предÑтоÑщи (алтернативни/запиÑани/Ñтари)" msgctxt "#30067" msgid "Show LiveTV recordings" msgstr "Показване на запиÑите на Ñ‚ÐµÐ»ÐµÐ²Ð¸Ð·Ð¸Ñ Ð½Ð° живо" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "ВерÑÐ¸Ñ Ð½Ð° протокола: %i – верÑÐ¸Ñ Ð½Ð° базата данни: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "ПропуÑкане на рекламите" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "Открит е ÑпиÑък Ñ Ð¾Ñ‚Ñ€ÑÐ·Ð²Ð°Ð½Ð¸Ñ Ð¸Ð»Ð¸ пропуÑкане на реклами.\nИÑкате ли да включите пропуÑкането на реклами за това предаване?" msgctxt "#30112" msgid "Connection failed" msgstr "Ðе може да Ñе уÑтанови връзка" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "ИÑкате ли да опитате отново?" msgctxt "#30300" msgid "Failed to connect the MythTV backend with the known protocol versions. Please check the compatibility map of the addon and upgrade your backend to a supported version." msgstr "Свързването ÑÑŠÑ Ñървъра на MythTV, използвайки познатите верÑии на протокола, е невъзможно. МолÑ, проверете таблицата за ÑъвмеÑтимоÑÑ‚ на добавката или обновете Ñървъра Ñи до поддържана верÑиÑ." msgctxt "#30301" msgid "Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. The PIN code has to be configured in your backend to allow connection." msgstr "ÐеуÑпешно Ñвързване към уÑлугите за ППИ (API) на Ñървъра MythTV. МолÑ, проверете ПИРкода Ñи и наÑтройките на Ñървъра. ПИРкодът трÑбва да бъде зададен в Ñървъра, за да може да Ñе оÑъщеÑтви връзка." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Връзката ÑÑŠÑ Ñървъра на MythTV Ñе разпадна" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Връзката Ñ MythTV е възÑтановена" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "Сървърът на MythTV не отговарÑ" msgctxt "#30305" msgid "Channel unavailable" msgstr "Каналът не е наличен" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Ðе е налично запиÑващо уÑтройÑтво" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "ПрекъÑване на ÐºÐ¾Ð½Ñ„Ð»Ð¸ÐºÑ‚Ð½Ð¸Ñ Ð·Ð°Ð¿Ð¸Ñ: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Спиране на телевизиÑта на живо заради конфликтен запиÑ: %s" msgctxt "#30309" msgid "Not recording" msgstr "Ðе Ñе запиÑва" msgctxt "#30310" msgid "Enabled" msgstr "Включено" msgctxt "#30311" msgid "Disabled" msgstr "Изключено" msgctxt "#30312" msgid "No broadcast found" msgstr "ÐÑма открито излъчване" msgctxt "#30411" msgid "Delete and re-record" msgstr "Изтриване и запиÑване отново" msgctxt "#30412" msgid "Keep recording" msgstr "Продължаване на запиÑа" msgctxt "#30421" msgid "Toggle display of alternative/recorded/expired" msgstr "Превключване на показването на алтернативни/запиÑани/Ñтари" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "ОпреÑнÑване на кеша за иконки на каналите" msgctxt "#30423" msgid "Trigger channels update" msgstr "Предизвикване на обновÑване на каналите" msgctxt "#30424" msgid "Show status of scheduling" msgstr "Показване на ÑÑŠÑтоÑнието на планиране" msgctxt "#30451" msgid "Unhandled" msgstr "Ðеобработвано" msgctxt "#30452" msgid "Upcoming" msgstr "ПредÑтоÑщо" msgctxt "#30453" msgid "Overriden" msgstr "Заменено" msgctxt "#30454" msgid "Don't record" msgstr "Да не Ñе запиÑва" msgctxt "#30455" msgid "Upcoming manual" msgstr "ПредÑтоÑщо, ръчно" msgctxt "#30457" msgid "Alternative" msgstr "Ðлтернативно" msgctxt "#30458" msgid "Currently recorded" msgstr "Текущо запиÑвано" msgctxt "#30459" msgid "Expired recording" msgstr "ОÑтарÑл запиÑ" msgctxt "#30460" msgid "Manual" msgstr "Ръчно" msgctxt "#30461" msgid "Record one" msgstr "Еднократен запиÑ" msgctxt "#30462" msgid "Record weekly" msgstr "ЕжеÑедмичен запиÑ" msgctxt "#30463" msgid "Record daily" msgstr "Ежедневен запиÑ" msgctxt "#30464" msgid "Record all" msgstr "ЗапиÑване на вÑичко" msgctxt "#30465" msgid "Record this" msgstr "ЗапиÑване на това" msgctxt "#30466" msgid "Record series" msgstr "ЗапиÑване на Ñериал" msgctxt "#30467" msgid "Search keyword" msgstr "ТърÑене по ключова дума" msgctxt "#30468" msgid "Search people" msgstr "ТърÑене на хора" msgctxt "#30469" msgid "Rule disabled" msgstr "Правилото е изключено" msgctxt "#30501" msgid "Don't match duplicates" msgstr "Да не Ñе откриват еднаквите" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "Откриване на еднаквите по Ñубтитрите" msgctxt "#30503" msgid "Match duplicates using description" msgstr "Откриване на еднаквите по опиÑанието" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "Откриване на еднаквите по Ñубтитрите и опиÑанието" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "Откриване на еднаквите по Ñубтитрите, Ñлед това то опиÑанието" msgctxt "#30506" msgid "Recordings never expire" msgstr "ЗапиÑите да не оÑтарÑват никога" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "ОÑтарÑване на запиÑите" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "СъхранÑване на до %d запиÑа" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "СъхранÑване на най-новите %d, другите да Ñе отбелÑзват като „Ñтари“" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.bs_ba/000077500000000000000000000000001360567320200273145ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.bs_ba/strings.po000066400000000000000000000022731360567320200313510ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Bosnian (Bosnia and Herzegovina) (http://www.transifex.com/projects/p/kodi-main/language/bs_BA/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: bs_BA\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" msgctxt "#30019" msgid "General" msgstr "OpÅ¡te" msgctxt "#30055" msgid "Always" msgstr "Uvijek" msgctxt "#30057" msgid "Never" msgstr "Nikada" msgctxt "#30059" msgid "Always" msgstr "Uvijek" msgctxt "#30061" msgid "Never" msgstr "Nikada" msgctxt "#30305" msgid "Channel unavailable" msgstr "Kanal nedostupan" msgctxt "#30310" msgid "Enabled" msgstr "Omogućeno" msgctxt "#30311" msgid "Disabled" msgstr "Onemogućeno" msgctxt "#30460" msgid "Manual" msgstr "RuÄno" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.ca_es/000077500000000000000000000000001360567320200273205ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.ca_es/strings.po000066400000000000000000000171101360567320200313510ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Catalan (Spain) (http://www.transifex.com/projects/p/kodi-main/language/ca_ES/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ca_ES\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "Nom d'amfitrió o IP del dorsal de MythTV" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "Port del dorsal de MythTV" msgctxt "#30002" msgid "MythTV Database Username" msgstr "Nom d'usuari de la base de dades del MythTV" msgctxt "#30003" msgid "MythTV Database Password" msgstr "Contrasenya de la base de dades del MythTV" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "Nom de la base de dades de MythTV" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Inclou més informació de depuració en el fitxer de registre" msgctxt "#30006" msgid "Enable Live TV" msgstr "Habilita la televisió en directe" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Permet que la TV en directe canviï els programes de TV programats" msgctxt "#30008" msgid "Conflict handling" msgstr "Tractament de conflictes" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Prefereix la TV en directe i deixar l'enregistrament per més tard" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Preferència per enregistrar i parar la TV en directe" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Prefereix la TV en directe i la cancel·lació del conflicte en l'enregistrament " msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "Adreça IP del dorsal de MythTV (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "Port del dorsal de MythTV per als serveis de l'API" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "Pin de Seguretat de MythTV per als serveis API" msgctxt "#30019" msgid "General" msgstr "General" msgctxt "#30020" msgid "Template provider" msgstr "Proveïdor de plantilla" msgctxt "#30021" msgid "Internal" msgstr "Intern" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "Plantilla interna" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Busca automàticament les metadades" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Indicador Comercial en nous enregistraments" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Transcodifica els enregistraments nous" msgctxt "#30029" msgid "Run User Job #1" msgstr "Executa la tasca de l'usuari #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Executa la tasca de l'usuari #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Executa la tasca de l'usuari #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Executa la tasca de l'usuari #4" msgctxt "#30033" msgid "Transcoder" msgstr "Transcodificador" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Permet el venciment dels enregistraments" msgctxt "#30049" msgid "Recording template" msgstr "Plantilla d'enregistrament" msgctxt "#30050" msgid "Advanced" msgstr "Avançat" msgctxt "#30051" msgid "Preferences" msgstr "Preferències" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Habilita el desmultiplexatge MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Retard de la sintonització (s)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Agrupa els enregistraments pel títol" msgctxt "#30055" msgid "Always" msgstr "Sempre" msgctxt "#30056" msgid "Only for series" msgstr "Solament per a sèries" msgctxt "#30057" msgid "Never" msgstr "Mai" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Habilita l'omissió dels anuncis (EDL)" msgctxt "#30059" msgid "Always" msgstr "Sempre" msgctxt "#30060" msgid "Dialog" msgstr "Diàleg" msgctxt "#30061" msgid "Never" msgstr "Mai" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Concedir l'apagada del dorsal" msgctxt "#30063" msgid "Enable channel icons" msgstr "Habilita les icones dels canals" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Habilita l'enregistrament de fanart/miniatures" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "Limita els intents de sintonització de canals" msgctxt "#30067" msgid "Show LiveTV recordings" msgstr "Mostra els enregistraments de LiveTV" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Versió del protocol: %i - versió de la base de dades: %i " msgctxt "#30110" msgid "Enabling EDL" msgstr "S'està habilitant EDL" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "S'ha trobat una llista de tall o de passar anuncis.\nVoleu activar la funcionalitat EDL per a aquest programa de TV?" msgctxt "#30112" msgid "Connection failed" msgstr "Ha fallat la connexió" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "Voleu tornar-ho a provar?" msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Connexió perduda amb el dorsal de MythTV" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Connexió amb backend de MythTV restaurada" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "No hi ha resposta del dorsal de MythTV" msgctxt "#30305" msgid "Channel unavailable" msgstr "Canal no disponible" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Enregistrament no disponible" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Cancel·lació de l'enregistrament conflictiu: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Aturada de la TV en directe a causa de l'enregistrament conflictiu: %s" msgctxt "#30309" msgid "Not recording" msgstr "No enregistra" msgctxt "#30310" msgid "Enabled" msgstr "Habilitat" msgctxt "#30311" msgid "Disabled" msgstr "Inhabilitat" msgctxt "#30312" msgid "No broadcast found" msgstr "No s'ha trobat cap difusió" msgctxt "#30411" msgid "Delete and re-record" msgstr "Esborra i torna a enregistrar" msgctxt "#30412" msgid "Keep recording" msgstr "Mantén l'enregistrament" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "Refresca la memòria cau per a les icones dels canals" msgctxt "#30454" msgid "Don't record" msgstr "No enregistris" msgctxt "#30458" msgid "Currently recorded" msgstr "Enregistrant actualment" msgctxt "#30460" msgid "Manual" msgstr "Manual" msgctxt "#30461" msgid "Record one" msgstr "Enregistra un" msgctxt "#30462" msgid "Record weekly" msgstr "Enregistra setmanalment" msgctxt "#30463" msgid "Record daily" msgstr "Enregistra diàriament" msgctxt "#30464" msgid "Record all" msgstr "Enregistra-ho tot" msgctxt "#30465" msgid "Record this" msgstr "Enregistra aquest" msgctxt "#30466" msgid "Record series" msgstr "Enregistra les sèries" msgctxt "#30469" msgid "Rule disabled" msgstr "Regla inhabilitada" msgctxt "#30506" msgid "Recordings never expire" msgstr "Els enregistraments no vencen mai" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Permet el venciment dels enregistraments" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "Mantén fins a %d enregistraments" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.cs_cz/000077500000000000000000000000001360567320200273475ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.cs_cz/strings.po000066400000000000000000000240141360567320200314010ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Czech (Czech Republic) (http://www.transifex.com/projects/p/kodi-main/language/cs_CZ/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: cs_CZ\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "Název hostitele nebo adresa IP backendu MythTV" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "Port backendu MythTV" msgctxt "#30002" msgid "MythTV Database Username" msgstr "Uživatelské jméno databáze MythTV" msgctxt "#30003" msgid "MythTV Database Password" msgstr "Heslo databáze MythTV" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "Název databáze MythTV" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Zahrnout více ladících informací do souboru protokolu" msgctxt "#30006" msgid "Enable Live TV" msgstr "Zapnout živé vysílání" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Povolit živému vysílání pÅ™esouvat naplánované poÅ™ady" msgctxt "#30008" msgid "Conflict handling" msgstr "ŘeÅ¡ení konfliktů" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "UpÅ™ednostnit živé vysílání, když má nahrávka pozdÄ›jší slot" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "UpÅ™ednostnit nahrávku a zastavit živé vysílání" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "UpÅ™ednostnit živé vysílání a zruÅ¡it konfliktní nahrávku" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "Ethernetová adresa backendu MythTV (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "Port backendu MythTV pro služby API" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "BezpeÄnostní PIN MythTV pro služby API" msgctxt "#30019" msgid "General" msgstr "Obecné" msgctxt "#30020" msgid "Template provider" msgstr "Poskytovatel Å¡ablon" msgctxt "#30021" msgid "Internal" msgstr "Interní" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "Interní Å¡ablona" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Automaticky vyhledat metadata" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "OznaÄit reklamy v nových nahrávkách" msgctxt "#30028" msgid "Transcode new recordings" msgstr "PÅ™ekódovat nové nahrávky" msgctxt "#30029" msgid "Run User Job #1" msgstr "Spustit úlohu uživatele Ä. 1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Spustit úlohu uživatele Ä. 2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Spustit úlohu uživatele Ä. 3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Spustit úlohu uživatele Ä. 4" msgctxt "#30033" msgid "Transcoder" msgstr "PÅ™evadÄ›Ä" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Umožnit aby nahrávky vyprÅ¡ely" msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "Vyzvat k odstranÄ›ní zhlédnutých nahrávek" msgctxt "#30048" msgid "Show 'Original Airdate' instead of 'Recording Time'" msgstr "Zobrazit „Původní datum vysílání“ namísto „Okamžik nahrání“" msgctxt "#30049" msgid "Recording template" msgstr "Å ablona nahrávání" msgctxt "#30050" msgid "Advanced" msgstr "Rozšířené" msgctxt "#30051" msgid "Preferences" msgstr "PÅ™edvolby" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Povolit demuxování MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Prodleva pÅ™i ladÄ›ní (s)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Seskupit nahrávky podle názvu" msgctxt "#30055" msgid "Always" msgstr "Vždy" msgctxt "#30056" msgid "Only for series" msgstr "Jenom pro seriály" msgctxt "#30057" msgid "Never" msgstr "Nikdy" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Povolit pÅ™eskakování reklam (EDL)" msgctxt "#30059" msgid "Always" msgstr "Vždy" msgctxt "#30060" msgid "Dialog" msgstr "Dialog" msgctxt "#30061" msgid "Never" msgstr "Nikdy" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Povolit vypnutí backendu" msgctxt "#30063" msgid "Enable channel icons" msgstr "Povolit ikony kanálů" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Povolit fanart nebo náhledy pro nahrávky" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "Omezit pokusy o naladÄ›ní kanálů" msgctxt "#30066" msgid "Show inactive upcomings (alternative/recorded/expired)" msgstr "Zobrazit neaktivní nadcházející (alternativní, nahrané, s vyprÅ¡enou platností)" msgctxt "#30067" msgid "Show LiveTV recordings" msgstr "Zobrazit nahrávání živého vysílání" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Verze protokolu: %i - Verze databáze: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "Povolení EDL" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "Byl nalezen seznam stÅ™ihů nebo pÅ™eskoÄení reklam.\nChcete aktivovat funkce EDL pro tento poÅ™ad?" msgctxt "#30112" msgid "Connection failed" msgstr "PÅ™ipojení selhalo" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "Chcete to zkusit znovu?" msgctxt "#30300" msgid "Failed to connect the MythTV backend with the known protocol versions. Please check the compatibility map of the addon and upgrade your backend to a supported version." msgstr "NepodaÅ™ilo se spojit s backendem MythTV se známou verzí protokolu. Zkontrolujte kompatibilitu doplňku a aktualizujte váš backend na podporovanou verzi." msgctxt "#30301" msgid "Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. The PIN code has to be configured in your backend to allow connection." msgstr "NepodaÅ™ilo se spojit se službami API backendu MythTV. Zkontrolujte svůj kód PIN nebo nastavení backendu. Ve vaÅ¡em backendu musí být nakonfigurován kód PIN pro povolení pÅ™ipojení." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Spojení s backendem MythTV ztraceno" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Spojení s MythTV obnoveno" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "Žádná odpovÄ›Ä od backendu MythTV" msgctxt "#30305" msgid "Channel unavailable" msgstr "Kanál není dostupný" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Rekordér není dostupný" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "RuÅ¡ení konfliktní nahrávky: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Zastavování živého vysílání kvůli konfliktní nahrávce: %s" msgctxt "#30309" msgid "Not recording" msgstr "Nenahrávat" msgctxt "#30310" msgid "Enabled" msgstr "Povoleno" msgctxt "#30311" msgid "Disabled" msgstr "Zakázáno" msgctxt "#30312" msgid "No broadcast found" msgstr "Nenalezeno žádné vysílání" msgctxt "#30411" msgid "Delete and re-record" msgstr "Odstranit a znovu nahrát" msgctxt "#30412" msgid "Keep recording" msgstr "Ponechat nahrávku" msgctxt "#30421" msgid "Toggle display of alternative/recorded/expired" msgstr "PÅ™epnout zobrazení alternativní, nahrané, se skonÄenou platností" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "Obnovit mezipaměť pro ikony kanálů" msgctxt "#30423" msgid "Trigger channels update" msgstr "Aktivovat aktualizaci kanálů" msgctxt "#30424" msgid "Show status of scheduling" msgstr "Zobrazit stav plánování" msgctxt "#30451" msgid "Unhandled" msgstr "NeoÅ¡etÅ™ené" msgctxt "#30452" msgid "Upcoming" msgstr "Nadcházející" msgctxt "#30453" msgid "Overriden" msgstr "PÅ™epsaný" msgctxt "#30454" msgid "Don't record" msgstr "Nenahrávat" msgctxt "#30455" msgid "Upcoming manual" msgstr "Nadcházející ruÄnÄ›" msgctxt "#30456" msgid "Zombie" msgstr "Zombie" msgctxt "#30457" msgid "Alternative" msgstr "Alternativní" msgctxt "#30458" msgid "Currently recorded" msgstr "AktuálnÄ› nahrané" msgctxt "#30459" msgid "Expired recording" msgstr "VyprÅ¡ená platnost nahrávky" msgctxt "#30460" msgid "Manual" msgstr "RuÄnÄ›" msgctxt "#30461" msgid "Record one" msgstr "Nahrát jednou" msgctxt "#30462" msgid "Record weekly" msgstr "Nahrávat týdnÄ›" msgctxt "#30463" msgid "Record daily" msgstr "Nahrávat dennÄ›" msgctxt "#30464" msgid "Record all" msgstr "Nahrát vÅ¡e" msgctxt "#30465" msgid "Record this" msgstr "Nahrát toto" msgctxt "#30466" msgid "Record series" msgstr "Nahrát seriál" msgctxt "#30467" msgid "Search keyword" msgstr "Vyhledat klíÄové slovo" msgctxt "#30468" msgid "Search people" msgstr "Vyhledat osobnosti" msgctxt "#30469" msgid "Rule disabled" msgstr "Pravidlo zakázáno" msgctxt "#30501" msgid "Don't match duplicates" msgstr "Neporovnávat duplicity" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "Porovnat duplicity pomocí podtitulu" msgctxt "#30503" msgid "Match duplicates using description" msgstr "Porovnat duplicity pomocí popisu" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "Porovnat duplicity pomocí podtitulu a popisu" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "Porovnat duplicity pomocí podtitulu, pak popisu" msgctxt "#30506" msgid "Recordings never expire" msgstr "Nahrávky nikdy nevyprší" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Povolit vyprÅ¡ení nahrávek" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "Ponechat až %d nahrávek" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "Ponechat %d nejnovÄ›jších a nechat vyprÅ¡et staré" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.cy_gb/000077500000000000000000000000001360567320200273315ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.cy_gb/strings.po000066400000000000000000000137441360567320200313730ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Welsh (United Kingdom) (http://www.transifex.com/projects/p/kodi-main/language/cy_GB/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: cy_GB\n" "Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3;\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "Enw gwesteiwr cefn MythTV neu IP" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "Porth Cefn MythTV" msgctxt "#30002" msgid "MythTV Database Username" msgstr "Enw Defnyddiwr Cronfa Ddata MythTV" msgctxt "#30003" msgid "MythTV Database Password" msgstr "Cyfrinair Cronfa Ddata MythTV" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "Enw Cronfa Ddata Cronfa Ddata MythTV" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Cynnwys rhagor o wybodaeth dadfygio yn y ffeil cofnod" msgctxt "#30006" msgid "Enable Live TV" msgstr "Galluogi Teledu Byw" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Caniatáu i Deledu Byw symud sioeau wedi eu hamserlenni" msgctxt "#30008" msgid "Conflict handling" msgstr "Trin gwrthdaro" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Ffafrio Teledu Byw pan fod slot hwyrach gan recordiad" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Ffafrio recordio ac atal Teledu Byw" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Ffafrio Teledu Byw a diddymu recordio sy'n gwrthdaro" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "Cyfeiriad ethernet Cefn MythTV (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "Cefn MythTV ar gyfer gwasanaethau API" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "Pin Diogelwch MythTV ar gyfer gwasanaethau API" msgctxt "#30019" msgid "General" msgstr "Cyffredinol" msgctxt "#30020" msgid "Template provider" msgstr "Darparwr templed" msgctxt "#30021" msgid "Internal" msgstr "Mewnol" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "Templed mewnol" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Chwilio'r Metadata'n Awtomatig" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Baner Masnachol i recordiadau newydd" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Trawscodio recordiadau newydd" msgctxt "#30029" msgid "Run User Job #1" msgstr "Rhedeg Gwaith Defnyddiwr #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Rhedeg Gwaith Defnyddiwr #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Rhedeg Gwaith Defnyddiwr #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Rhedeg Gwaith Defnyddiwr #4" msgctxt "#30033" msgid "Transcoder" msgstr "Trawscodydd" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Caniatáu i recordiadau ddod i ben" msgctxt "#30049" msgid "Recording template" msgstr "Templed recordio" msgctxt "#30050" msgid "Advanced" msgstr "Uwch" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Galluogi demux MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Oedi tiwnio (eil)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Crynhoi recordiadau yn ôl teitl" msgctxt "#30055" msgid "Always" msgstr "Bob tro" msgctxt "#30056" msgid "Only for series" msgstr "Dim ond am gyfres" msgctxt "#30057" msgid "Never" msgstr "Byth" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Galluogi hepgor hysbysebion (EDL)" msgctxt "#30059" msgid "Always" msgstr "Bob tro" msgctxt "#30060" msgid "Dialog" msgstr "Deialog" msgctxt "#30061" msgid "Never" msgstr "Byth" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Caniatáu cau'r cefn" msgctxt "#30063" msgid "Enable channel icons" msgstr "Galluogi eiconau sianeli" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Galluogi celf selogion/lluniau bach recordiadau" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Fersiwn protocol: %i - Fersiwn cronfa ddata: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "Galluogi EDL" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "Mae rhestr dorri neu hepgoriadau hysbysebion wedi eu canfod.\nHoffech chi weithredu swyddogaethau EDL ar gyfer y sioe yma" msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Cysylltiad wedi ei golli i gefn MythTV" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Wedi adfer cysylltiad i MythTV" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "Dim ymateb gan gefn MythTV" msgctxt "#30305" msgid "Channel unavailable" msgstr "Sianel ddim ar gael" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Recordydd ddim ar gael" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Diddymu recordio sy'n gwrthdaro: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Atal Teledu Byw oherwydd recordio sy'n gwrthdaro: %s" msgctxt "#30309" msgid "Not recording" msgstr "Ddim yn recordio" msgctxt "#30310" msgid "Enabled" msgstr "Galluogwyd" msgctxt "#30311" msgid "Disabled" msgstr "Analluogwyd" msgctxt "#30312" msgid "No broadcast found" msgstr "Heb ganfod darlledu" msgctxt "#30411" msgid "Delete and re-record" msgstr "Dileu ac ail recordio" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "Ail-lwytho'r gelc ar gyfer eiconau sianeli" msgctxt "#30460" msgid "Manual" msgstr "Gyda llaw" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Caniatáu i recordiadau ddod i ben" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.da_dk/000077500000000000000000000000001360567320200273105ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.da_dk/strings.po000066400000000000000000000251601360567320200313450ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière # Translators: # Jean-Luc Barrière , 2019 msgid "" msgstr "" "Project-Id-Version: pvr.mythtv\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: 2019-01-06 13:14+0000\n" "Last-Translator: Jean-Luc Barrière \n" "Language-Team: Danish (Denmark) (http://www.transifex.com/janbar/pvrmythtv/language/da_DK/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: da_DK\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" # Settings labels msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "MythTV Backend værtsnavn eller IP" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "MythTV Backend port" msgctxt "#30002" msgid "MythTV Database Username" msgstr "MythTV Database brugernavn" msgctxt "#30003" msgid "MythTV Database Password" msgstr "MythTV Database adgangskode" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "MythTV database databasenavn" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Tilføj mere debug-information i logfilen" msgctxt "#30006" msgid "Enable Live TV" msgstr "Aktivér TV" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Tillad direkte TV at flytte planlagte programmer" msgctxt "#30008" msgid "Conflict handling" msgstr "KonflikthÃ¥ndtering" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Foretræk live TV nÃ¥r optagelse er senere" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Foretræk optagelse og stop Live TV" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Foretræk Live TV og aflys modstridende optagelser" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "MythTV Backend Ethernet-adressen (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "MythTV Backend API service port" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "MythTV PIN kode til API service" # empty strings from id 30015 to 30018 msgctxt "#30019" msgid "General" msgstr "Generelt" msgctxt "#30020" msgid "Template provider" msgstr "SkabelonhÃ¥ndtering" msgctxt "#30021" msgid "Internal" msgstr "Intern" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" # empty strings from id 30023 to 30024 msgctxt "#30025" msgid "Internal template" msgstr "Intern skabelon" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Automatisk hentning af Metadata" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Markér reklamer i nye optagelser" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Transkod nye optagelser" msgctxt "#30029" msgid "Run User Job #1" msgstr "Kør brugerjob #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Kør brugerjob #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Kør brugerjob #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Kør brugerjob #4" msgctxt "#30033" msgid "Transcoder" msgstr "Transkoder" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Tillad at optagelser udløber" # empty strings from id 30035 to 30046 msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "Spørg om sletning efter visning af optagelse" msgctxt "#30048" msgid "Show 'Original Airdate' instead of 'Recording Time'" msgstr "Vis oprindelig udsendelsestid i stedet for optagelsestid" msgctxt "#30049" msgid "Recording template" msgstr "Optagelsesskabelon" msgctxt "#30050" msgid "Advanced" msgstr "Avanceret" msgctxt "#30051" msgid "Preferences" msgstr "Indstillinger" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Aktivér demuxing MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Tuning forsinkelse (sekunder)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Gruppér optagelser efter titel" msgctxt "#30055" msgid "Always" msgstr "Altid" msgctxt "#30056" msgid "Only for series" msgstr "Kun for serier" msgctxt "#30057" msgid "Never" msgstr "Aldrig" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Aktivér reklame-skip (EDL)" msgctxt "#30059" msgid "Always" msgstr "Altid" msgctxt "#30060" msgid "Dialog" msgstr "Dialog" msgctxt "#30061" msgid "Never" msgstr "Aldrig" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Tillad backend nedlukning" msgctxt "#30063" msgid "Enable channel icons" msgstr "Aktivér kanal ikoner" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Aktivér optagelser af Fanart/Thumbnails" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "Begræns kanal tuningsforsøg" msgctxt "#30066" msgid "Show inactive upcomings (alternative/recorded/expired)" msgstr "Vis inaktive optagelsesregler (alternativ/optaget/udløbet)" msgctxt "#30067" msgid "Show LiveTV recordings" msgstr "Vis 'LiveTV' optagelser" msgctxt "#30068" msgid "Use bookmarks of the backend MythTV" msgstr "Brug bogmærker fra MythTV backenden" msgctxt "#30069" msgid "Show default recording group as root" msgstr "Vis standard optagegruppe som root" # empty strings from id 30070 to 30099 # Systeminformation labels msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Protokolversion: %i - Databaseversion: %i" # empty strings from id 30101 to 30109 # Dialog labels msgctxt "#30110" msgid "Enabling EDL" msgstr "Aktiverer EDL (reklame-skip)" msgctxt "#30111" msgid "" "A cut list or commercial skips have been found.\n" "Do you want to activate EDL functionality for this show ?" msgstr "En reklameudeladelsesliste (EDL) er blevet fundet.\nVil du aktivere automatisk reklame-skip for dette show?" msgctxt "#30112" msgid "Connection failed" msgstr "Forbindelse fejlede" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "Vil du prøve igen?" msgctxt "#30114" msgid "Connected" msgstr "Forbundet" # empty strings from id 30114 to 30299 # Notifications msgctxt "#30300" msgid "" "Failed to connect the MythTV backend with the known protocol versions. " "Please check the compatibility map of the addon and upgrade your backend to " "a supported version." msgstr "Kunne ikke forbinde til MythTV backend med den aktuelle protokolversion. Tjek venligst kompatibiliteten af tilføjelsen og opgrader din backend til en understøttet version." msgctxt "#30301" msgid "" "Failed to connect the API services of MythTV backend. Please check your PIN " "code or backend setup. The PIN code has to be configured in your backend to " "allow connection." msgstr "Kunne ikke forbinde til MythTV backend API service. Tjek venligst din PIN kode eller backend opsætning. PIN koden skal være opsat i backenden for at tillade forbindelse." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Forbindelse til MythTV backend mistet" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Forbindelse til MythTV genoprettet" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "Ingen svar fra MythTV backend" msgctxt "#30305" msgid "Channel unavailable" msgstr "Kanal utilgængelig" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Optager ikke tilgængelig" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Aflyser modstridende optagelse: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Stopper direkte TV pÃ¥ grund af modstridende optagelse: %s" msgctxt "#30309" msgid "Not recording" msgstr "Optager ikke" msgctxt "#30310" msgid "Enabled" msgstr "Aktiveret" msgctxt "#30311" msgid "Disabled" msgstr "Deaktiveret" msgctxt "#30312" msgid "No broadcast found" msgstr "Ingen udsendelse fundet" # empty strings from id 30313 to 30410 # Menu Hooks msgctxt "#30411" msgid "Delete and re-record" msgstr "Slet og optag pÃ¥ ny" msgctxt "#30412" msgid "Keep recording" msgstr "Behold optagelse" # empty strings from id 30413 to 30420 msgctxt "#30421" msgid "Toggle display of alternative/recorded/expired" msgstr "Skift visning af alternativ/optaget/udløbet" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "Opdatér kanal ikoner" msgctxt "#30423" msgid "Trigger channels update" msgstr "Opdatér kanaler" msgctxt "#30424" msgid "Show status of scheduling" msgstr "Vis planlægningsstatus" msgctxt "#30425" msgid "Show status of recording" msgstr "Vis optagelsestatus" msgctxt "#30426" msgid "Show status of broadcast" msgstr "Vis udsendelsestatus" # empty strings from id 30427 to 30450 msgctxt "#30451" msgid "Unhandled" msgstr "UhÃ¥ndteret" msgctxt "#30452" msgid "Upcoming" msgstr "Fremtidig" msgctxt "#30453" msgid "Overriden" msgstr "Tilsidesat" msgctxt "#30454" msgid "Don't record" msgstr "Optag ikke" msgctxt "#30455" msgid "Upcoming manual" msgstr "Fremtidig manuel" msgctxt "#30456" msgid "Zombie" msgstr "Zombie" msgctxt "#30457" msgid "Alternative" msgstr "Alternativ" msgctxt "#30458" msgid "Currently recorded" msgstr "Aktuelt optaget" msgctxt "#30459" msgid "Expired recording" msgstr "Udløbet optagelse" msgctxt "#30460" msgid "Manual" msgstr "Manuelt" msgctxt "#30461" msgid "Record one" msgstr "Optag én gang" msgctxt "#30462" msgid "Record weekly" msgstr "Optag ugentligt" msgctxt "#30463" msgid "Record daily" msgstr "Optag dagligt" msgctxt "#30464" msgid "Record all" msgstr "Optag alle" msgctxt "#30465" msgid "Record this" msgstr "Optag denne" msgctxt "#30466" msgid "Record series" msgstr "Optag serie" msgctxt "#30467" msgid "Search keyword" msgstr "Søg nøgleord" msgctxt "#30468" msgid "Search people" msgstr "Søg medvirkende" msgctxt "#30469" msgid "Rule disabled" msgstr "Regel deaktiveret" # empty strings from id 30470 to 30500 msgctxt "#30501" msgid "Don't match duplicates" msgstr "Identificér ikke dubletter" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "Identificér dubletter ved hjælp af undertitel" msgctxt "#30503" msgid "Match duplicates using description" msgstr "Identificér dubletter ved hjælp af beskrivelse" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "Identificér dubletter ved hjælp af undertitel & beskrivelse" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "Identificér dubletter ved hjælp af undertitel, derefter beskrivelse" msgctxt "#30506" msgid "Recordings never expire" msgstr "Optagelser udløber aldrig" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Tillad at optagelser udløber" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "Behold op til %d optagelser" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "Behold %d nyeste og lad ældre udløbe" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.de_de/000077500000000000000000000000001360567320200273065ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.de_de/strings.po000066400000000000000000000262521360567320200313460ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière # Translators: # Jean-Luc Barrière , 2019 msgid "" msgstr "" "Project-Id-Version: pvr.mythtv\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: 2019-01-06 13:14+0000\n" "Last-Translator: Jean-Luc Barrière \n" "Language-Team: German (Germany) (http://www.transifex.com/janbar/pvrmythtv/language/de_DE/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: de_DE\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" # Settings labels msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "MythTV Backend Hostname oder IP" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "MythTV Backend Port" msgctxt "#30002" msgid "MythTV Database Username" msgstr "MythTV Datenbank Benutzername" msgctxt "#30003" msgid "MythTV Database Password" msgstr "MythTV Datenbank Passwort" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "MythTV Datenbank Datenbankname" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Schreibe ausführliche Debug-Informationen in die Logdatei" msgctxt "#30006" msgid "Enable Live TV" msgstr "Aktiviere Live TV" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Erlaube Live TV geplante Aufnahmen zu verschieben" msgctxt "#30008" msgid "Conflict handling" msgstr "Konfliktbehandlung" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Bevorzuge Live TV, wenn Aufnahme später beginnt" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Bevorzuge Aufnahmen und unterbreche Live TV" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Bevorzuge Live TV und breche überschneidende Aufnahme ab" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "MythTV-Backend-Ethernet-Adresse (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "MythTV Backend-Port für API-Dienste" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "MythTV-Sicherheits-PIN für API-Dienste" # empty strings from id 30015 to 30018 msgctxt "#30019" msgid "General" msgstr "Allgemein" msgctxt "#30020" msgid "Template provider" msgstr "Vorlagenanbieter" msgctxt "#30021" msgid "Internal" msgstr "Intern" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" # empty strings from id 30023 to 30024 msgctxt "#30025" msgid "Internal template" msgstr "Interne Vorlage" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Automatisch Metadaten suchen" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Kennzeichne Werbung in neuen Aufnahmen" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Transkodiere neue Aufnahmen" msgctxt "#30029" msgid "Run User Job #1" msgstr "Starte benutzerdefinierten Job #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Starte benutzerdefinierten Job #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Starte benutzerdefinierten Job #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Starte benutzerdefinierten Job #4" msgctxt "#30033" msgid "Transcoder" msgstr "Transcoder" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Erlaube Aufnahmen abzulaufen" # empty strings from id 30035 to 30045 msgctxt "#30046" msgid "Show damaged recordings as color" msgstr "Farbe der beschädigten Aufnahmen" msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "Frage ob gesehene Aufnahme gelöscht werden soll" msgctxt "#30048" msgid "Show 'Original Airdate' instead of 'Recording Time'" msgstr "Zeige Austrahlungszeitraum anstelle des Aufnahmezeitraums" msgctxt "#30049" msgid "Recording template" msgstr "Aufnahmevorlage" msgctxt "#30050" msgid "Advanced" msgstr "Erweitert" msgctxt "#30051" msgid "Preferences" msgstr "Präferenzen" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Demuxen des MPEG-TS aktivieren" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Abstimmungsverzögerung (s)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Aufnahmen nach Titel gruppieren" msgctxt "#30055" msgid "Always" msgstr "Immer" msgctxt "#30056" msgid "Only for series" msgstr "Nur für Serien" msgctxt "#30057" msgid "Never" msgstr "Nie" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Werbespotüberspringungen aktivieren (EDL)" msgctxt "#30059" msgid "Always" msgstr "Immer" msgctxt "#30060" msgid "Dialog" msgstr "Dialog" msgctxt "#30061" msgid "Never" msgstr "Nie" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Erlaube des Backends verhindern" msgctxt "#30063" msgid "Enable channel icons" msgstr "Senderzeichen aktivieren" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Aufnahme von Fankunst/Vorschaubilder aktivieren" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "Reduzieren versuche tuning" msgctxt "#30066" msgid "Show inactive upcomings (alternative/recorded/expired)" msgstr "Zeige inaktive bevorstehende Aufnahmen (alternativ/aufgenommen/abgelaufen)" msgctxt "#30067" msgid "Show LiveTV recordings" msgstr "LiveTV-Aufnahmen anzeigen" msgctxt "#30068" msgid "Use bookmarks of the backend MythTV" msgstr "Verwenden Sie Lesezeichen des Backends MythTV" msgctxt "#30069" msgid "Show default recording group as root" msgstr "Standard-Aufnahmegruppe als root anzeigen" msgctxt "#30070" msgid "Scene Only" msgstr "Lesezeichen" # empty strings from id 30071 to 30099 # Systeminformation labels msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Protokollversion: %i - Datenbankversion: %i" # empty strings from id 30101 to 30109 # Dialog labels msgctxt "#30110" msgid "Enabling EDL" msgstr "EDL wird aktiviert" msgctxt "#30111" msgid "" "A cut list or commercial skips have been found.\n" "Do you want to activate EDL functionality for this show ?" msgstr "Eine Schnittliste oder Werbungsmarkierungen wurden gefunden.\nSoll für diese Sendung die Schnittlisten-Funktionalität aktiviert werden?" msgctxt "#30112" msgid "Connection failed" msgstr "Verbindung fehlgeschlagen" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "Erneut versuchen?" msgctxt "#30114" msgid "Connected" msgstr "Verbunden" # empty strings from id 30114 to 30299 # Notifications msgctxt "#30300" msgid "" "Failed to connect the MythTV backend with the known protocol versions. " "Please check the compatibility map of the addon and upgrade your backend to " "a supported version." msgstr "Mit den bekannten Protokoll-Versionen konnte keine Verbindung zum MythTV Backend hergestellt werden. Bitte die Kompatibilitäts-Matrix des Addons überprüfen und auf eine unterstützte Version upgraden." msgctxt "#30301" msgid "" "Failed to connect the API services of MythTV backend. Please check your PIN " "code or backend setup. The PIN code has to be configured in your backend to " "allow connection." msgstr "Verbindung zu den API-Diensten des MythTV Backends fehlgeschlagen. Bitte PIN oder Backend Einstellungen überprüfen. Der PIN muss im Backend konfiguriert sein um eine Verbindung zu ermöglichen." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Die Verbindung zum MythTV Backend wurde unterbrochen" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Verbindung zu MythTV wiederhergestellt" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "Keine Antwort vom MythTV Backend" msgctxt "#30305" msgid "Channel unavailable" msgstr "Kanal nicht verfügbar" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Aufnahmegerät nicht verfügbar" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Breche überschneidende Aufnahme ab: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Unterbreche Live TV wegen überschneidender Aufnahme: %s" msgctxt "#30309" msgid "Not recording" msgstr "Keine Aufnahme" msgctxt "#30310" msgid "Enabled" msgstr "Aktiviert" msgctxt "#30311" msgid "Disabled" msgstr "Ausschalten" msgctxt "#30312" msgid "No broadcast found" msgstr "Keine Ausstrahlung gefunden" # empty strings from id 30313 to 30410 # Menu Hooks msgctxt "#30411" msgid "Delete and re-record" msgstr "Löschen und neu aufnehmen" msgctxt "#30412" msgid "Keep recording" msgstr "Aufnahme fortsetzen" # empty strings from id 30413 to 30420 msgctxt "#30421" msgid "Toggle display of alternative/recorded/expired" msgstr "Wechsle zwischen alternative/aufgenomme/abgelaufene Aufnahmen" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "Cache für Senderlogos aktualisieren" msgctxt "#30423" msgid "Trigger channels update" msgstr "Kanal-Update auslösen" msgctxt "#30424" msgid "Show status of scheduling" msgstr "Zeige Status der Programmierung" msgctxt "#30425" msgid "Show status of recording" msgstr "Zeige Status der Aufnahme" msgctxt "#30426" msgid "Show status of broadcast" msgstr "Zeige Status der Ausstrahlung" # empty strings from id 30427 to 30450 msgctxt "#30451" msgid "Unhandled" msgstr "Nicht gehandhabt" msgctxt "#30452" msgid "Upcoming" msgstr "Bevorstehend" msgctxt "#30453" msgid "Overriden" msgstr "Überschrieben" msgctxt "#30454" msgid "Don't record" msgstr "Nicht aufnehmen" msgctxt "#30455" msgid "Upcoming manual" msgstr "Bevorstehend Manuell" msgctxt "#30456" msgid "Zombie" msgstr "Zombie" msgctxt "#30457" msgid "Alternative" msgstr "Alternative" msgctxt "#30458" msgid "Currently recorded" msgstr "Momentane Aufnahme" msgctxt "#30459" msgid "Expired recording" msgstr "Abgelaufene Aufnahme" msgctxt "#30460" msgid "Manual" msgstr "Manuell" msgctxt "#30461" msgid "Record one" msgstr "Einmal aufnehmen" msgctxt "#30462" msgid "Record weekly" msgstr "Wöchentlich aufnehmen" msgctxt "#30463" msgid "Record daily" msgstr "Täglich aufnehmen" msgctxt "#30464" msgid "Record all" msgstr "Alle aufnehmen" msgctxt "#30465" msgid "Record this" msgstr "Aufnehmen" msgctxt "#30466" msgid "Record series" msgstr "Serie aufnehmen" msgctxt "#30467" msgid "Search keyword" msgstr "Schlüsselwort suchen" msgctxt "#30468" msgid "Search people" msgstr "Personen suchen" msgctxt "#30469" msgid "Rule disabled" msgstr "Regel deaktiviert" # empty strings from id 30470 to 30500 msgctxt "#30501" msgid "Don't match duplicates" msgstr "Duplikate nicht abgleichen" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "Duplikate über Untertitel abgleichen" msgctxt "#30503" msgid "Match duplicates using description" msgstr "Duplikate über Beschreibung abgleichen" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "Duplikate über Untertitel & Beschreibung abgleichen" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "Duplikate zuerst über Untertitel dann über Beschreibung abgleichen" msgctxt "#30506" msgid "Recordings never expire" msgstr "Aufnahmen haben kein Ablaufdatum" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Erlaube Aufnahmen abzulaufen" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "Behalte bis zu %d Aufnahmen" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "Behalte die %d Neuesten und lasse Alte auslaufen" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.el_gr/000077500000000000000000000000001360567320200273365ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.el_gr/strings.po000066400000000000000000000200151360567320200313650ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Greek (Greece) (http://www.transifex.com/projects/p/kodi-main/language/el_GR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: el_GR\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "Όνομα Υπολογιστή ή IP του Backend MythTV" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "ΘÏÏα του Backend MythTV" msgctxt "#30002" msgid "MythTV Database Username" msgstr "Όνομα ΧÏήστη της Βάσης Δεδομένων του MythTV" msgctxt "#30003" msgid "MythTV Database Password" msgstr "Κωδικός της Βάσης Δεδομένων του MythTV" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "Όνομα της Βάσης Δεδομένων του MythTV" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "ΠεÏισσότεÏες πληÏοφοÏίες από τον εντοπισμό σφαλμάτων στο αÏχείο καταγÏαφής" msgctxt "#30006" msgid "Enable Live TV" msgstr "ΕνεÏγοποίηση Live TV" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Îα επιτÏέπεται στο Live TV να μετακινεί Ï€ÏογÏαμματισμένες εκπομπές" msgctxt "#30008" msgid "Conflict handling" msgstr "ΔιαχείÏιση διένεξης" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Îα Ï€Ïοτιμάται η Live TV όταν υπάÏχει εγγÏαφή αÏγότεÏα" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Îα Ï€Ïοτιμάται η εγγÏαφή και να διακοπεί η Live TV" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Îα Ï€Ïοτιμάται η Live TV και να ακυÏωθεί η εγγÏαφή που Ï€Ïοκαλεί διένεξη" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "ΔιεÏθυνση Ethernet του Backend MythTV (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "ΘÏÏα του Backend MythTV για υπηÏεσίες API" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "Κωδικός Pin του MythTV για υπηÏεσίες API" msgctxt "#30019" msgid "General" msgstr "Γενικά" msgctxt "#30020" msgid "Template provider" msgstr "ΠάÏοχος Ï€ÏοτÏπων" msgctxt "#30021" msgid "Internal" msgstr "ΕσωτεÏικό" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "ΕσωτεÏικό Ï€Ïότυπο" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Αυτόματη Αναζήτηση Μεταδεδομένων" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "ΕμποÏική Σήμανση νέων εγγÏαφών" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Διακωδικοποίηση νέων εγγÏαφών" msgctxt "#30029" msgid "Run User Job #1" msgstr "Εκτέλεση ΕÏγασίας #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Εκτέλεση ΕÏγασίας #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Εκτέλεση ΕÏγασίας #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Εκτέλεση ΕÏγασίας #4" msgctxt "#30033" msgid "Transcoder" msgstr "Διακωδικοποιητής" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Îα επιτÏέπεται η χÏονική λήξη των εγγÏαφών;" msgctxt "#30049" msgid "Recording template" msgstr "ΠÏότυπο εγγÏαφής" msgctxt "#30050" msgid "Advanced" msgstr "Για Ï€ÏοχωÏημένους" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "ΕνεÏγοποίηση διαχωÏÎ¹ÏƒÎ¼Î¿Ï (demux) MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "ΚαθυστέÏηση ÏƒÏ…Î½Ï„Î¿Î½Î¹ÏƒÎ¼Î¿Ï (δευτ)" msgctxt "#30054" msgid "Group recordings by title" msgstr "ΕγγÏαφές σε γκÏουπ ανά τίτλο" msgctxt "#30055" msgid "Always" msgstr "Πάντα" msgctxt "#30056" msgid "Only for series" msgstr "Μόνο για σειÏές" msgctxt "#30057" msgid "Never" msgstr "Ποτέ" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "ΕνεÏγοποίηση αποφυγής διαφημίσεων (EDL)" msgctxt "#30059" msgid "Always" msgstr "Πάντα" msgctxt "#30060" msgid "Dialog" msgstr "ΠαÏάθυÏο" msgctxt "#30061" msgid "Never" msgstr "Ποτέ" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Αφήστε τον τεÏματισμό του backend" msgctxt "#30063" msgid "Enable channel icons" msgstr "ΕνεÏγοποίηση εικονιδίων καναλιών" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "ΕνεÏγοποίηση μικÏογÏαφιών/fanart εγγÏαφών" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "ÎŒÏιο Ï€Ïοσπαθειών ÏƒÏ…Î½Ï„Î¿Î½Î¹ÏƒÎ¼Î¿Ï ÎºÎ±Î½Î±Î»Î¹Î¿Ï" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Έκδοση Ï€Ïωτοκόλλου: %i - Έκδοση βάσης δεδομένων: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "ΕνεÏγοποίηση EDL" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "Î’Ïέθηκαν διαφημίσεις ή κάποια λίστα αποφυγής.\nÎα ενεÏγοποιηθεί η λειτουÏγία EDL για αυτήν τη σειÏά ;" msgctxt "#30112" msgid "Connection failed" msgstr "ΣÏνδεση απέτυχε" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "Θέλετε να ξαναδοκιμάσετε ?" msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Απώλεια σÏνδεσης με το backend του MythTV" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Αποκαταστάθηκε η σÏνδεση με το MythTV" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "Καμία απόκÏιση από το backend του MythTV" msgctxt "#30305" msgid "Channel unavailable" msgstr "Μη διαθέσιμο κανάλι" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Μη διαθέσιμος εγγÏαφέας" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "ΑκÏÏωση της εγγÏαφής που Ï€Ïοκαλεί διένεξη: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Διακοπή της Live TV λόγω διένεξης με την εγγÏαφή: %s" msgctxt "#30309" msgid "Not recording" msgstr "Δεν γίνεται εγγÏαφή" msgctxt "#30310" msgid "Enabled" msgstr "ΕνεÏγό/ή" msgctxt "#30311" msgid "Disabled" msgstr "ΑνενεÏγή" msgctxt "#30312" msgid "No broadcast found" msgstr "Δε βÏέθηκε εκπομπή" msgctxt "#30411" msgid "Delete and re-record" msgstr "ΔιαγÏαφή και επανεγγÏαφή" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "Ανανεώστε τη μνήμη cache για εικ. καναλιών" msgctxt "#30452" msgid "Upcoming" msgstr "ΕπεÏχόμενο" msgctxt "#30460" msgid "Manual" msgstr "ΧειÏοκίνητα" msgctxt "#30467" msgid "Search keyword" msgstr "Αναζήτηση λέξης-κλειδί" msgctxt "#30468" msgid "Search people" msgstr "Αναζήτηση ανθÏώπων" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Îα επιτÏέπεται η χÏονική λήξη των εγγÏαφών;" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.en_au/000077500000000000000000000000001360567320200273355ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.en_au/strings.po000066400000000000000000000137271360567320200314000ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: English (Australia) (http://www.transifex.com/projects/p/kodi-main/language/en_AU/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: en_AU\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "MythTV Backend Hostname or IP" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "MythTV Backend Port" msgctxt "#30002" msgid "MythTV Database Username" msgstr "MythTV Database Username" msgctxt "#30003" msgid "MythTV Database Password" msgstr "MythTV Database Password" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "MythTV Database Databasename" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Include more debug information in the log file" msgctxt "#30006" msgid "Enable Live TV" msgstr "Enable Live TV" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Allow Live TV to move scheduled shows" msgctxt "#30008" msgid "Conflict handling" msgstr "Conflict handling" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Prefer Live TV when recording has later slot" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Prefer recording and stop Live TV" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Prefer Live TV and cancel conflicting recording" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "MythTV Backend Ethernet address (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "MythTV Backend Port for API services" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "MythTV Security Pin for API services" msgctxt "#30019" msgid "General" msgstr "General" msgctxt "#30020" msgid "Template provider" msgstr "Template provider" msgctxt "#30021" msgid "Internal" msgstr "Internal" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "Internal template" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Automatically Look Up Metadata" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Commercial Flag new recordings" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Transcode new recordings" msgctxt "#30029" msgid "Run User Job #1" msgstr "Run User Job #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Run User Job #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Run User Job #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Run User Job #4" msgctxt "#30033" msgid "Transcoder" msgstr "Transcoder" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Allow recordings to expire" msgctxt "#30049" msgid "Recording template" msgstr "Recording template" msgctxt "#30050" msgid "Advanced" msgstr "Advanced" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Enable demuxing MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Tuning delay (sec)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Group recordings by title" msgctxt "#30055" msgid "Always" msgstr "Always" msgctxt "#30056" msgid "Only for series" msgstr "Only for series" msgctxt "#30057" msgid "Never" msgstr "Never" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Enable commercial skips (EDL)" msgctxt "#30059" msgid "Always" msgstr "Always" msgctxt "#30060" msgid "Dialog" msgstr "Dialogue" msgctxt "#30061" msgid "Never" msgstr "Never" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Allow backend shutdown" msgctxt "#30063" msgid "Enable channel icons" msgstr "Enable channel icons" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Enable recording fanart/thumbnails" msgctxt "#30067" msgid "Show LiveTV recordings" msgstr "Show LiveTV recordings" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Protocol version: %i - Database version: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "Enabling EDL" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgctxt "#30112" msgid "Connection failed" msgstr "Connection failed" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "Do you want to retry ?" msgctxt "#30114" msgid "Connected" msgstr "Connected" msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Connection to MythTV backend lost" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Connection to MythTV restored" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "No response from MythTV backend" msgctxt "#30305" msgid "Channel unavailable" msgstr "Channel unavailable" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Recorder unavailable" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Cancelling conflicting recording: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Stopping Live TV due to conflicting recording: %s" msgctxt "#30309" msgid "Not recording" msgstr "Not recording" msgctxt "#30310" msgid "Enabled" msgstr "Enabled" msgctxt "#30311" msgid "Disabled" msgstr "Disabled" msgctxt "#30312" msgid "No broadcast found" msgstr "No broadcast found" msgctxt "#30411" msgid "Delete and re-record" msgstr "Delete and re-record" msgctxt "#30412" msgid "Keep recording" msgstr "Keep recording" msgctxt "#30460" msgid "Manual" msgstr "Manual" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Allow recordings to expire" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.en_gb/000077500000000000000000000000001360567320200273205ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.en_gb/strings.po000066400000000000000000000174241360567320200313610ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: English (United Kingdom) (http://www.transifex.com/projects/p/kodi-main/language/en_GB/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: en_GB\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" # Settings labels msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "" msgctxt "#30002" msgid "MythTV Database Username" msgstr "" msgctxt "#30003" msgid "MythTV Database Password" msgstr "" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "" msgctxt "#30006" msgid "Enable Live TV" msgstr "" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "" msgctxt "#30008" msgid "Conflict handling" msgstr "" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "" # empty strings from id 30015 to 30018 msgctxt "#30019" msgid "General" msgstr "" msgctxt "#30020" msgid "Template provider" msgstr "" msgctxt "#30021" msgid "Internal" msgstr "" msgctxt "#30022" msgid "MythTV" msgstr "" # empty strings from id 30023 to 30024 msgctxt "#30025" msgid "Internal template" msgstr "" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "" msgctxt "#30028" msgid "Transcode new recordings" msgstr "" msgctxt "#30029" msgid "Run User Job #1" msgstr "" msgctxt "#30030" msgid "Run User Job #2" msgstr "" msgctxt "#30031" msgid "Run User Job #3" msgstr "" msgctxt "#30032" msgid "Run User Job #4" msgstr "" msgctxt "#30033" msgid "Transcoder" msgstr "" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "" # empty strings from id 30035 to 30045 msgctxt "#30046" msgid "Show damaged recordings as color" msgstr "" msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "" msgctxt "#30048" msgid "Show 'Original Airdate' instead of 'Recording Time'" msgstr "" msgctxt "#30049" msgid "Recording template" msgstr "" msgctxt "#30050" msgid "Advanced" msgstr "" msgctxt "#30051" msgid "Preferences" msgstr "" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "" msgctxt "#30054" msgid "Group recordings by title" msgstr "" msgctxt "#30055" msgid "Always" msgstr "" msgctxt "#30056" msgid "Only for series" msgstr "" msgctxt "#30057" msgid "Never" msgstr "" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "" msgctxt "#30059" msgid "Always" msgstr "" msgctxt "#30060" msgid "Dialog" msgstr "" msgctxt "#30061" msgid "Never" msgstr "" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "" msgctxt "#30063" msgid "Enable channel icons" msgstr "" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "" msgctxt "#30066" msgid "Show inactive upcomings (alternative/recorded/expired)" msgstr "" msgctxt "#30067" msgid "Show LiveTV recordings" msgstr "" msgctxt "#30068" msgid "Use bookmarks of the backend MythTV" msgstr "" msgctxt "#30069" msgid "Show default recording group as root" msgstr "" msgctxt "#30070" msgid "Scene Only" msgstr "" # empty strings from id 30071 to 30099 # Systeminformation labels msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "" # empty strings from id 30101 to 30109 # Dialog labels msgctxt "#30110" msgid "Enabling EDL" msgstr "" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "" msgctxt "#30112" msgid "Connection failed" msgstr "" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "" msgctxt "#30114" msgid "Connected" msgstr "" # empty strings from id 30114 to 30299 # Notifications msgctxt "#30300" msgid "Failed to connect the MythTV backend with the known protocol versions. Please check the compatibility map of the addon and upgrade your backend to a supported version." msgstr "" msgctxt "#30301" msgid "Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. The PIN code has to be configured in your backend to allow connection." msgstr "" msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "" msgctxt "#30305" msgid "Channel unavailable" msgstr "" msgctxt "#30306" msgid "Recorder unavailable" msgstr "" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "" msgctxt "#30309" msgid "Not recording" msgstr "" msgctxt "#30310" msgid "Enabled" msgstr "" msgctxt "#30311" msgid "Disabled" msgstr "" msgctxt "#30312" msgid "No broadcast found" msgstr "" # empty strings from id 30313 to 30410 # Menu Hooks msgctxt "#30411" msgid "Delete and re-record" msgstr "" msgctxt "#30412" msgid "Keep recording" msgstr "" # empty strings from id 30413 to 30420 msgctxt "#30421" msgid "Toggle display of alternative/recorded/expired" msgstr "" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "" msgctxt "#30423" msgid "Trigger channels update" msgstr "" msgctxt "#30424" msgid "Show status of scheduling" msgstr "" msgctxt "#30425" msgid "Show status of recording" msgstr "" msgctxt "#30426" msgid "Show status of broadcast" msgstr "" # empty strings from id 30427 to 30450 msgctxt "#30451" msgid "Unhandled" msgstr "" msgctxt "#30452" msgid "Upcoming" msgstr "" msgctxt "#30453" msgid "Overriden" msgstr "" msgctxt "#30454" msgid "Don't record" msgstr "" msgctxt "#30455" msgid "Upcoming manual" msgstr "" msgctxt "#30456" msgid "Zombie" msgstr "" msgctxt "#30457" msgid "Alternative" msgstr "" msgctxt "#30458" msgid "Currently recorded" msgstr "" msgctxt "#30459" msgid "Expired recording" msgstr "" msgctxt "#30460" msgid "Manual" msgstr "" msgctxt "#30461" msgid "Record one" msgstr "" msgctxt "#30462" msgid "Record weekly" msgstr "" msgctxt "#30463" msgid "Record daily" msgstr "" msgctxt "#30464" msgid "Record all" msgstr "" msgctxt "#30465" msgid "Record this" msgstr "" msgctxt "#30466" msgid "Record series" msgstr "" msgctxt "#30467" msgid "Search keyword" msgstr "" msgctxt "#30468" msgid "Search people" msgstr "" msgctxt "#30469" msgid "Rule disabled" msgstr "" # empty strings from id 30470 to 30500 msgctxt "#30501" msgid "Don't match duplicates" msgstr "" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "" msgctxt "#30503" msgid "Match duplicates using description" msgstr "" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "" msgctxt "#30506" msgid "Recordings never expire" msgstr "" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.en_nz/000077500000000000000000000000001360567320200273575ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.en_nz/strings.po000066400000000000000000000227431360567320200314200ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: English (New Zealand) (http://www.transifex.com/projects/p/kodi-main/language/en_NZ/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: en_NZ\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "MythTV Backend Hostname or IP" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "MythTV Backend Port" msgctxt "#30002" msgid "MythTV Database Username" msgstr "MythTV Database Username" msgctxt "#30003" msgid "MythTV Database Password" msgstr "MythTV Database Password" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "MythTV Database Databasename" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Include more debug information in the log file" msgctxt "#30006" msgid "Enable Live TV" msgstr "Enable Live TV" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Allow Live TV to move scheduled shows" msgctxt "#30008" msgid "Conflict handling" msgstr "Conflict handling" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Prefer Live TV when recording has later slot" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Prefer recording and stop Live TV" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Prefer Live TV and cancel conflicting recording" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "MythTV Backend Ethernet address (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "MythTV Backend Port for API services" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "MythTV Security Pin for API services" msgctxt "#30019" msgid "General" msgstr "General" msgctxt "#30020" msgid "Template provider" msgstr "Template provider" msgctxt "#30021" msgid "Internal" msgstr "Internal" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "Internal template" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Automatically Look Up Metadata" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Commercial Flag new recordings" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Transcode new recordings" msgctxt "#30029" msgid "Run User Job #1" msgstr "Run User Job #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Run User Job #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Run User Job #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Run User Job #4" msgctxt "#30033" msgid "Transcoder" msgstr "Transcoder" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Allow recordings to expire" msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "Prompt to delete the watched recording" msgctxt "#30048" msgid "Show 'Original Airdate' instead of 'Recording Time'" msgstr "Show 'Original Airdate' instead of 'Recording Time'" msgctxt "#30049" msgid "Recording template" msgstr "Recording template" msgctxt "#30050" msgid "Advanced" msgstr "Advanced" msgctxt "#30051" msgid "Preferences" msgstr "Preferences" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Enable demuxing MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Tuning delay (sec)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Group recordings by title" msgctxt "#30055" msgid "Always" msgstr "Always" msgctxt "#30056" msgid "Only for series" msgstr "Only for series" msgctxt "#30057" msgid "Never" msgstr "Never" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Enable commercial skips (EDL)" msgctxt "#30059" msgid "Always" msgstr "Always" msgctxt "#30060" msgid "Dialog" msgstr "Dialog" msgctxt "#30061" msgid "Never" msgstr "Never" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Allow backend shutdown" msgctxt "#30063" msgid "Enable channel icons" msgstr "Enable channel icons" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Enable recording fanart/thumbnails" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "Limit channel tuning attempts" msgctxt "#30066" msgid "Show inactive upcomings (alternative/recorded/expired)" msgstr "Show inactive upcomings (alternative/recorded/expired)" msgctxt "#30067" msgid "Show LiveTV recordings" msgstr "Show LiveTV recordings" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Protocol version: %i - Database version: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "Enabling EDL" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgctxt "#30112" msgid "Connection failed" msgstr "Connection failed" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "Do you want to retry ?" msgctxt "#30114" msgid "Connected" msgstr "Connected" msgctxt "#30300" msgid "Failed to connect the MythTV backend with the known protocol versions. Please check the compatibility map of the addon and upgrade your backend to a supported version." msgstr "Failed to connect the MythTV backend with the known protocol versions. Please check the compatibility map of the addon and upgrade your backend to a supported version." msgctxt "#30301" msgid "Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. The PIN code has to be configured in your backend to allow connection." msgstr "Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. The PIN code has to be configured in your backend to allow connection." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Connection to MythTV backend lost" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Connection to MythTV restored" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "No response from MythTV backend" msgctxt "#30305" msgid "Channel unavailable" msgstr "Channel unavailable" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Recorder unavailable" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Canceling conflicting recording: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Stopping Live TV due to conflicting recording: %s" msgctxt "#30309" msgid "Not recording" msgstr "Not recording" msgctxt "#30310" msgid "Enabled" msgstr "Enabled" msgctxt "#30311" msgid "Disabled" msgstr "Disabled" msgctxt "#30312" msgid "No broadcast found" msgstr "No broadcast found" msgctxt "#30411" msgid "Delete and re-record" msgstr "Delete and re-record" msgctxt "#30412" msgid "Keep recording" msgstr "Keep recording" msgctxt "#30421" msgid "Toggle display of alternative/recorded/expired" msgstr "Toggle display of alternative/recorded/expired" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "Refresh cache for channel icons" msgctxt "#30423" msgid "Trigger channels update" msgstr "Trigger channels update" msgctxt "#30424" msgid "Show status of scheduling" msgstr "Show status of scheduling" msgctxt "#30451" msgid "Unhandled" msgstr "Unhandled" msgctxt "#30452" msgid "Upcoming" msgstr "Upcoming" msgctxt "#30453" msgid "Overriden" msgstr "Overriden" msgctxt "#30454" msgid "Don't record" msgstr "Don't record" msgctxt "#30455" msgid "Upcoming manual" msgstr "Upcoming manual" msgctxt "#30456" msgid "Zombie" msgstr "Zombie" msgctxt "#30457" msgid "Alternative" msgstr "Alternative" msgctxt "#30458" msgid "Currently recorded" msgstr "Currently recorded" msgctxt "#30459" msgid "Expired recording" msgstr "Expired recording" msgctxt "#30460" msgid "Manual" msgstr "Manual" msgctxt "#30461" msgid "Record one" msgstr "Record one" msgctxt "#30462" msgid "Record weekly" msgstr "Record weekly" msgctxt "#30463" msgid "Record daily" msgstr "Record daily" msgctxt "#30464" msgid "Record all" msgstr "Record all" msgctxt "#30465" msgid "Record this" msgstr "Record this" msgctxt "#30466" msgid "Record series" msgstr "Record series" msgctxt "#30467" msgid "Search keyword" msgstr "Search keyword" msgctxt "#30468" msgid "Search people" msgstr "Search people" msgctxt "#30469" msgid "Rule disabled" msgstr "Rule disabled" msgctxt "#30501" msgid "Don't match duplicates" msgstr "Don't match duplicates" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "Match duplicates using subtitle" msgctxt "#30503" msgid "Match duplicates using description" msgstr "Match duplicates using description" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "Match duplicates using subtitle & description" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "Match duplicates using subtitle then description" msgctxt "#30506" msgid "Recordings never expire" msgstr "Recordings never expire" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Allow recordings to expire" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "Keep up to %d recordings" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "Keep %d newest and expire old" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.en_us/000077500000000000000000000000001360567320200273575ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.en_us/strings.po000066400000000000000000000232171360567320200314150ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: English (United States) (http://www.transifex.com/projects/p/kodi-main/language/en_US/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: en_US\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "MythTV Backend Hostname or IP" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "MythTV Backend Port" msgctxt "#30002" msgid "MythTV Database Username" msgstr "MythTV Database Username" msgctxt "#30003" msgid "MythTV Database Password" msgstr "MythTV Database Password" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "MythTV Database Databasename" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Include more debug information in the log file" msgctxt "#30006" msgid "Enable Live TV" msgstr "Enable Live TV" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Allow Live TV to move scheduled shows" msgctxt "#30008" msgid "Conflict handling" msgstr "Conflict handling" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Prefer Live TV when recording has later slot" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Prefer recording and stop Live TV" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Prefer Live TV and cancel conflicting recording" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "MythTV Backend Ethernet address (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "MythTV Backend Port for API services" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "MythTV Security Pin for API services" msgctxt "#30019" msgid "General" msgstr "General" msgctxt "#30020" msgid "Template provider" msgstr "Template provider" msgctxt "#30021" msgid "Internal" msgstr "Internal" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "Internal template" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Automatically Look Up Metadata" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Commercial Flag new recordings" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Transcode new recordings" msgctxt "#30029" msgid "Run User Job #1" msgstr "Run User Job #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Run User Job #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Run User Job #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Run User Job #4" msgctxt "#30033" msgid "Transcoder" msgstr "Transcoder" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Allow recordings to expire" msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "Prompt to delete the watched recording" msgctxt "#30048" msgid "Show 'Original Airdate' instead of 'Recording Time'" msgstr "Show 'Original Airdate' instead of 'Recording Time'" msgctxt "#30049" msgid "Recording template" msgstr "Recording template" msgctxt "#30050" msgid "Advanced" msgstr "Advanced" msgctxt "#30051" msgid "Preferences" msgstr "Preferences" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Enable demuxing MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Tuning delay (sec)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Group recordings by title" msgctxt "#30055" msgid "Always" msgstr "Always" msgctxt "#30056" msgid "Only for series" msgstr "Only for series" msgctxt "#30057" msgid "Never" msgstr "Never" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Enable commercial skips (EDL)" msgctxt "#30059" msgid "Always" msgstr "Always" msgctxt "#30060" msgid "Dialog" msgstr "Dialog" msgctxt "#30061" msgid "Never" msgstr "Never" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Allow backend shutdown" msgctxt "#30063" msgid "Enable channel icons" msgstr "Enable channel icons" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Enable recording fanart/thumbnails" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "Limit channel tuning attempts" msgctxt "#30066" msgid "Show inactive upcomings (alternative/recorded/expired)" msgstr "Show inactive upcomings (alternative/recorded/expired)" msgctxt "#30067" msgid "Show LiveTV recordings" msgstr "Show LiveTV recordings" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Protocol version: %i - Database version: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "Enabling EDL" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgctxt "#30112" msgid "Connection failed" msgstr "Connection failed" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "Do you want to retry ?" msgctxt "#30114" msgid "Connected" msgstr "Connected" msgctxt "#30300" msgid "Failed to connect the MythTV backend with the known protocol versions. Please check the compatibility map of the addon and upgrade your backend to a supported version." msgstr "Failed to connect the MythTV backend with the known protocol versions. Please check the compatibility map of the addon and upgrade your backend to a supported version." msgctxt "#30301" msgid "Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. The PIN code has to be configured in your backend to allow connection." msgstr "Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. The PIN code has to be configured in your backend to allow connection." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Connection to MythTV backend lost" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Connection to MythTV restored" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "No response from MythTV backend" msgctxt "#30305" msgid "Channel unavailable" msgstr "Channel unavailable" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Recorder unavailable" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Canceling conflicting recording: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Stopping Live TV due to conflicting recording: %s" msgctxt "#30309" msgid "Not recording" msgstr "Not recording" msgctxt "#30310" msgid "Enabled" msgstr "Enabled" msgctxt "#30311" msgid "Disabled" msgstr "Disabled" msgctxt "#30312" msgid "No broadcast found" msgstr "No broadcast found" msgctxt "#30411" msgid "Delete and re-record" msgstr "Delete and re-record" msgctxt "#30412" msgid "Keep recording" msgstr "Keep recording" msgctxt "#30421" msgid "Toggle display of alternative/recorded/expired" msgstr "Toggle display of alternative/recorded/expired" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "Refresh cache for channel icons" msgctxt "#30423" msgid "Trigger channels update" msgstr "Trigger channels update" msgctxt "#30424" msgid "Show status of scheduling" msgstr "Show status of scheduling" msgctxt "#30425" msgid "Show status of recording" msgstr "Show status of recording" msgctxt "#30426" msgid "Show status of broadcast" msgstr "Show status of broadcast" msgctxt "#30451" msgid "Unhandled" msgstr "Unhandled" msgctxt "#30452" msgid "Upcoming" msgstr "Upcoming" msgctxt "#30453" msgid "Overriden" msgstr "Overriden" msgctxt "#30454" msgid "Don't record" msgstr "Don't record" msgctxt "#30455" msgid "Upcoming manual" msgstr "Upcoming manual" msgctxt "#30456" msgid "Zombie" msgstr "Zombie" msgctxt "#30457" msgid "Alternative" msgstr "Alternative" msgctxt "#30458" msgid "Currently recorded" msgstr "Currently recorded" msgctxt "#30459" msgid "Expired recording" msgstr "Expired recording" msgctxt "#30460" msgid "Manual" msgstr "Manual" msgctxt "#30461" msgid "Record one" msgstr "Record one" msgctxt "#30462" msgid "Record weekly" msgstr "Record weekly" msgctxt "#30463" msgid "Record daily" msgstr "Record daily" msgctxt "#30464" msgid "Record all" msgstr "Record all" msgctxt "#30465" msgid "Record this" msgstr "Record this" msgctxt "#30466" msgid "Record series" msgstr "Record series" msgctxt "#30467" msgid "Search keyword" msgstr "Search keyword" msgctxt "#30468" msgid "Search people" msgstr "Search people" msgctxt "#30469" msgid "Rule disabled" msgstr "Rule disabled" msgctxt "#30501" msgid "Don't match duplicates" msgstr "Don't match duplicates" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "Match duplicates using subtitle" msgctxt "#30503" msgid "Match duplicates using description" msgstr "Match duplicates using description" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "Match duplicates using subtitle & description" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "Match duplicates using subtitle then description" msgctxt "#30506" msgid "Recordings never expire" msgstr "Recordings never expire" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Allow recordings to expire" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "Keep up to %d recordings" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "Keep %d newest and expire old" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.eo/000077500000000000000000000000001360567320200266515ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.eo/strings.po000066400000000000000000000016431360567320200307060ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Esperanto (http://www.transifex.com/projects/p/kodi-main/language/eo/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: eo\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30019" msgid "General" msgstr "Generalo" msgctxt "#30057" msgid "Never" msgstr "Never" msgctxt "#30061" msgid "Never" msgstr "Never" msgctxt "#30310" msgid "Enabled" msgstr "Enabled" msgctxt "#30311" msgid "Disabled" msgstr "Disabled" msgctxt "#30460" msgid "Manual" msgstr "Manual" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.es_ar/000077500000000000000000000000001360567320200273375ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.es_ar/strings.po000066400000000000000000000141671360567320200314010ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Spanish (Argentina) (http://www.transifex.com/projects/p/kodi-main/language/es_AR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: es_AR\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "Hostname o IP del Back-end the MythTV" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "Puerto del Back-end de MythTV" msgctxt "#30002" msgid "MythTV Database Username" msgstr "Usuario de la Base de Datos de MythTV" msgctxt "#30003" msgid "MythTV Database Password" msgstr "Contraseña de la Base de Datos de MythTV" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "Nombre de la Base de Datos de MythTV" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Incluir mas información de depuración en el archivo de log" msgctxt "#30006" msgid "Enable Live TV" msgstr "Activar TV en Vivo" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Permitir a la TV en Vivo cambiar los eventos programados" msgctxt "#30008" msgid "Conflict handling" msgstr "Conflicto de manejo" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Preferir TV en vivo cuando es posible dejar la grabación para mas tarde" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Preferir grabación y parar TV en vivo" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Preferir TV en vivo y cancelar la grabación en conflicto" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "Dirección Ethernet del MythTV de fondo (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "Puerto para servicios API de Backend MythTV" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "Pin de seguridad de servicios API MythTV" msgctxt "#30019" msgid "General" msgstr "General" msgctxt "#30020" msgid "Template provider" msgstr "Proveedor de plantilla" msgctxt "#30021" msgid "Internal" msgstr "Interna" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "Plantilla interna" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Buscar Metadatos automáticamente" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Indicador Comercial en nuevas grabaciones" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Transcodificar nuevas grabaciones" msgctxt "#30029" msgid "Run User Job #1" msgstr "Ejecutar Trabajo de Usuario #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Ejecutar Trabajo de Usuario #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Ejecutar Trabajo de Usuario #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Ejecutar Trabajo de Usuario #4" msgctxt "#30033" msgid "Transcoder" msgstr "Transcodificador" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Permitir expirar a las grabaciones" msgctxt "#30049" msgid "Recording template" msgstr "Plantilla de grabación" msgctxt "#30050" msgid "Advanced" msgstr "Avanzado" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Habilitar desmultiplexación MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Demora de sintonización (seg)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Agrupar grabaciones por título" msgctxt "#30055" msgid "Always" msgstr "Siempre" msgctxt "#30056" msgid "Only for series" msgstr "Solamente para series" msgctxt "#30057" msgid "Never" msgstr "Nunca" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Activar salteo de comerciales (EDL)" msgctxt "#30059" msgid "Always" msgstr "Siempre" msgctxt "#30060" msgid "Dialog" msgstr "Diálogo" msgctxt "#30061" msgid "Never" msgstr "Nunca" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Permitir apagado del backend" msgctxt "#30063" msgid "Enable channel icons" msgstr "Activar iconos de canales" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Activar fanart/miniaturas de grabaciones" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Versión de protocolo: %i - Versión de base de datos: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "Activando EDL" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "Se halló una cut list o salteo de comerciales.\n¿Desea activar la funcionalidad EDL para este show?" msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Conexión con backend de MythTV perdida" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Conexión con backend de MythTV restaurada" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "No hay respuesta del backend de MythTV" msgctxt "#30305" msgid "Channel unavailable" msgstr "Canal no disponible" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Grabador no disponible" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Cancelando grabación en conflicto: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Deteniendo TV en vivo debido a la grabación en conflicto: %s" msgctxt "#30309" msgid "Not recording" msgstr "No está grabando" msgctxt "#30310" msgid "Enabled" msgstr "Activado" msgctxt "#30311" msgid "Disabled" msgstr "Deshabilitado" msgctxt "#30312" msgid "No broadcast found" msgstr "No se encontró difusión" msgctxt "#30411" msgid "Delete and re-record" msgstr "Eliminar y volver a grabar" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "Refrescar cache de ícones de canales" msgctxt "#30460" msgid "Manual" msgstr "Manual" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Permitir expirar a las grabaciones" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.es_es/000077500000000000000000000000001360567320200273445ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.es_es/strings.po000066400000000000000000000261311360567320200314000ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière # Translators: # Jean-Luc Barrière , 2019 msgid "" msgstr "" "Project-Id-Version: pvr.mythtv\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: 2019-01-06 13:20+0000\n" "Last-Translator: Jean-Luc Barrière \n" "Language-Team: Spanish (Spain) (http://www.transifex.com/janbar/pvrmythtv/language/es_ES/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: es_ES\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" # Settings labels msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "Hostname o IP del Back-end de MythTV" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "Puerto del Back-end de MythTV" msgctxt "#30002" msgid "MythTV Database Username" msgstr "Usuario de la Base de Datos de MythTV" msgctxt "#30003" msgid "MythTV Database Password" msgstr "Contraseña de la Base de Datos de MythTV" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "Nombre de la Base de Datos de MythTV" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Incluir más información de depuración en el archivo de log" msgctxt "#30006" msgid "Enable Live TV" msgstr "Activar TV en Vivo" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Permitir a la TV en Vivo cambiar los eventos programados" msgctxt "#30008" msgid "Conflict handling" msgstr "Conflicto de manejo" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Prefiero TV en vivo y dejar la grabación para mas tarde" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Prefiero grabación y parar TV en vivo" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Prefiero TV en vivo y cancelar la grabación en conflictivo" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "Dirección IP MythTV Backend (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "Puerto del Backend de MythTV para los servicios API" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "Pin de Seguridad de MythTV para los servicios API" # empty strings from id 30015 to 30018 msgctxt "#30019" msgid "General" msgstr "General" msgctxt "#30020" msgid "Template provider" msgstr "Proveedor de plantilla" msgctxt "#30021" msgid "Internal" msgstr "Interna" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" # empty strings from id 30023 to 30024 msgctxt "#30025" msgid "Internal template" msgstr "Plantilla interna" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Buscar Metadatos automáticamente" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Indicador Comercial en nuevas grabaciones" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Transcodificar nuevas grabaciones" msgctxt "#30029" msgid "Run User Job #1" msgstr "Ejecutar Trabajo de Usuario #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Ejecutar Trabajo de Usuario #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Ejecutar Trabajo de Usuario #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Ejecutar Trabajo de Usuario #4" msgctxt "#30033" msgid "Transcoder" msgstr "Transcodificador" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Permitir expirar a las grabaciones" # empty strings from id 30035 to 30046 msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "Preguntar si borrar la grabación ya vista" msgctxt "#30048" msgid "Show 'Original Airdate' instead of 'Recording Time'" msgstr "Mostrar 'Día Emitido' en lugar de 'Día Grabado'" msgctxt "#30049" msgid "Recording template" msgstr "Plantilla de grabación" msgctxt "#30050" msgid "Advanced" msgstr "Avanzado" msgctxt "#30051" msgid "Preferences" msgstr "Preferencias" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Habilitar demux MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Retardo de Sintonizado (seg)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Agrupar grabaciones por título" msgctxt "#30055" msgid "Always" msgstr "Siempre" msgctxt "#30056" msgid "Only for series" msgstr "Solo para series" msgctxt "#30057" msgid "Never" msgstr "Nunca" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Habilitar pasar anuncios (EDL)" msgctxt "#30059" msgid "Always" msgstr "Siempre" msgctxt "#30060" msgid "Dialog" msgstr "Diálogos" msgctxt "#30061" msgid "Never" msgstr "Nunca" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Permitir apagado de backend" msgctxt "#30063" msgid "Enable channel icons" msgstr "Habilitar iconos de canal" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Habilitar guardado de fanart/miniaturas" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "Limitar los intentos sintonizado" msgctxt "#30066" msgid "Show inactive upcomings (alternative/recorded/expired)" msgstr "Mostrar Proximamente inactivos (alternativos/grabados/expirados)" msgctxt "#30067" msgid "Show LiveTV recordings" msgstr "Mostrar grabaciones de TV en Directo" msgctxt "#30068" msgid "Use bookmarks of the backend MythTV" msgstr "Usa los marcadores del backend MythTV" msgctxt "#30069" msgid "Show default recording group as root" msgstr "Mostrar el grupo de grabación predeterminado como root" # empty strings from id 30070 to 30099 # Systeminformation labels msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Versión de protocolo: %i - Versión de base de datos: %i" # empty strings from id 30101 to 30109 # Dialog labels msgctxt "#30110" msgid "Enabling EDL" msgstr "Habilitando EDL" msgctxt "#30111" msgid "" "A cut list or commercial skips have been found.\n" "Do you want to activate EDL functionality for this show ?" msgstr "Se ha encontrado una lista de corte o de pasar anuncios.\n¿Quiere activar la funcionalidad EDL para este programa?" msgctxt "#30112" msgid "Connection failed" msgstr "Fallo en la conexión" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "¿Volver a intentar?" msgctxt "#30114" msgid "Connected" msgstr "Conectado" # empty strings from id 30114 to 30299 # Notifications msgctxt "#30300" msgid "" "Failed to connect the MythTV backend with the known protocol versions. " "Please check the compatibility map of the addon and upgrade your backend to " "a supported version." msgstr "Ha fallado la conexión al backend MythTV con las versionesde protocolos conocidas. Por favor, compruebe la tabla de compatibilidades del addon y actualice su backend a una versión soportada." msgctxt "#30301" msgid "" "Failed to connect the API services of MythTV backend. Please check your PIN " "code or backend setup. The PIN code has to be configured in your backend to " "allow connection." msgstr "Fallo en la conexión del API del backend de MythTV. Por favor revisa tu código PIN o configuración del backend. El código PIN debe ser configurado en el backend para permitir la conexión" msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Conexión con backend de MythTV perdida" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Conexión con backend de MythTV restaurada" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "No hay respuesta del backend de MythTV" msgctxt "#30305" msgid "Channel unavailable" msgstr "Canal no disponible" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Grabador no disponible" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Cancelando grabación en conflicto: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Detención de TV en vivo debido a la grabación en conflicto: %s" msgctxt "#30309" msgid "Not recording" msgstr "No se esta grabando" msgctxt "#30310" msgid "Enabled" msgstr "Activado" msgctxt "#30311" msgid "Disabled" msgstr "Deshabilitado" msgctxt "#30312" msgid "No broadcast found" msgstr "No se ha encontrado broadcast" # empty strings from id 30313 to 30410 # Menu Hooks msgctxt "#30411" msgid "Delete and re-record" msgstr "Borrar y volver a grabar" msgctxt "#30412" msgid "Keep recording" msgstr "Mantener grabación" # empty strings from id 30413 to 30420 msgctxt "#30421" msgid "Toggle display of alternative/recorded/expired" msgstr "Cambiar entre alternativos/grabados/expirados" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "Refrescar cache de los iconos para los canales" msgctxt "#30423" msgid "Trigger channels update" msgstr "Provocar la actualización de los canales" msgctxt "#30424" msgid "Show status of scheduling" msgstr "Muestra el estado de la programación" msgctxt "#30425" msgid "Show status of recording" msgstr "Muestra el estado de la grabación" msgctxt "#30426" msgid "Show status of broadcast" msgstr "Muestra el estado de la emisión" # empty strings from id 30427 to 30450 msgctxt "#30451" msgid "Unhandled" msgstr "No soportado" msgctxt "#30452" msgid "Upcoming" msgstr "Por venir" msgctxt "#30453" msgid "Overriden" msgstr "Anulado" msgctxt "#30454" msgid "Don't record" msgstr "No grabar" msgctxt "#30455" msgid "Upcoming manual" msgstr "Siguiente programa manual" msgctxt "#30456" msgid "Zombie" msgstr "Zombi" msgctxt "#30457" msgid "Alternative" msgstr "Alternativo" msgctxt "#30458" msgid "Currently recorded" msgstr "Grabado actualmente" msgctxt "#30459" msgid "Expired recording" msgstr "Grabación expirada" msgctxt "#30460" msgid "Manual" msgstr "Manual" msgctxt "#30461" msgid "Record one" msgstr "Grabar una vez" msgctxt "#30462" msgid "Record weekly" msgstr "Grabación semanal" msgctxt "#30463" msgid "Record daily" msgstr "Grabación diaria" msgctxt "#30464" msgid "Record all" msgstr "Grabarlo todo" msgctxt "#30465" msgid "Record this" msgstr "Grabar esto" msgctxt "#30466" msgid "Record series" msgstr "Grabar series" msgctxt "#30467" msgid "Search keyword" msgstr "Buscar palabra clave" msgctxt "#30468" msgid "Search people" msgstr "Buscar gente" msgctxt "#30469" msgid "Rule disabled" msgstr "Regla deshabilitada" # empty strings from id 30470 to 30500 msgctxt "#30501" msgid "Don't match duplicates" msgstr "No detectar duplicados" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "Detectar duplicados usando subtítulos" msgctxt "#30503" msgid "Match duplicates using description" msgstr "Detectar duplicados usando la descripción" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "Detectar duplicados usando subtítulos y las descripciones" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "Detectar duplicados usando subtítulos y, después, las descripciones" msgctxt "#30506" msgid "Recordings never expire" msgstr "LAs grabaciones nunca caducan" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Permitir expirar a las grabaciones" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "Mantener hasta %d grabaciones" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "Mantener las %d más nuevas y borrar las viejas" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.es_mx/000077500000000000000000000000001360567320200273615ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.es_mx/strings.po000066400000000000000000000260351360567320200314200ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière # Translators: # Jean-Luc Barrière , 2019 msgid "" msgstr "" "Project-Id-Version: pvr.mythtv\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: 2019-01-06 13:20+0000\n" "Last-Translator: Jean-Luc Barrière \n" "Language-Team: Spanish (Mexico) (http://www.transifex.com/janbar/pvrmythtv/language/es_MX/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: es_MX\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" # Settings labels msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "Nombre del host o IP del backend de MythTV" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "Puerto del Backend de MythTV" msgctxt "#30002" msgid "MythTV Database Username" msgstr "Usuario BD MythTV" msgctxt "#30003" msgid "MythTV Database Password" msgstr "Contraseña BD MythTV" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "Nombre BD MythTV" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Incluir mayor información en el archivo de log" msgctxt "#30006" msgid "Enable Live TV" msgstr "Activar TV en vivo" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Permitir TV en vivo mover shows programados" msgctxt "#30008" msgid "Conflict handling" msgstr "Manejo de conflictos" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Preferir TV en directo cuando la grabación tiene una ranura posterior" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Prefiere grabar y detener TV en directo" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Preferir TV en directo y cancelar la grabación en conflicto" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "MythTV backend dirección Ethernet (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "MythTV Backend Port para servicios API" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "Pin de seguridad MythTV para servicios de API" # empty strings from id 30015 to 30018 msgctxt "#30019" msgid "General" msgstr "General" msgctxt "#30020" msgid "Template provider" msgstr "Proveedor de plantillas" msgctxt "#30021" msgid "Internal" msgstr "interno" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" # empty strings from id 30023 to 30024 msgctxt "#30025" msgid "Internal template" msgstr "Plantilla interna" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Mire automáticamente los metadatos" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Bandera comercial nuevas grabaciones" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Transcodificar nuevas grabaciones" msgctxt "#30029" msgid "Run User Job #1" msgstr "Ejecutar trabajo de usuario #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Ejecutar trabajo de usuario #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Ejecutar trabajo de usuario #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Ejecutar trabajo de usuario #4" msgctxt "#30033" msgid "Transcoder" msgstr "Transcodificador" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Permitir la caducidad de las grabaciones" # empty strings from id 30035 to 30046 msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "Solicitar borrar la grabación vista" msgctxt "#30048" msgid "Show 'Original Airdate' instead of 'Recording Time'" msgstr "Mostrar 'Fecha original' en lugar de 'Tiempo de grabación'" msgctxt "#30049" msgid "Recording template" msgstr "Recording template" msgctxt "#30050" msgid "Advanced" msgstr "Avanzado" msgctxt "#30051" msgid "Preferences" msgstr "Preferencias" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Habilitar demuxing MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Retardo de sintonización (seg)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Grabaciones de grupo por título" msgctxt "#30055" msgid "Always" msgstr "Siempre" msgctxt "#30056" msgid "Only for series" msgstr "Sólo para series" msgctxt "#30057" msgid "Never" msgstr "Nunca" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Habilitar saltos comerciales (EDL)" msgctxt "#30059" msgid "Always" msgstr "Siempre" msgctxt "#30060" msgid "Dialog" msgstr "Diálogo" msgctxt "#30061" msgid "Never" msgstr "Nunca" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Permitir el cierre del backend" msgctxt "#30063" msgid "Enable channel icons" msgstr "Activar iconos de canal" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Habilitar grabación fanart/miniaturas" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "Limitar los intentos de ajuste del canal" msgctxt "#30066" msgid "Show inactive upcomings (alternative/recorded/expired)" msgstr "Mostrar actualizaciones inactivas (alternativas / grabadas / caducadas)" msgctxt "#30067" msgid "Show LiveTV recordings" msgstr "Mostrar grabaciones de TV en Directo" msgctxt "#30068" msgid "Use bookmarks of the backend MythTV" msgstr "Usa los marcadores del backend MythTV" msgctxt "#30069" msgid "Show default recording group as root" msgstr "Mostrar el grupo de grabación predeterminado como root" # empty strings from id 30070 to 30099 # Systeminformation labels msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Versión del protocolo:%i - Versión de la base de datos: %i" # empty strings from id 30101 to 30109 # Dialog labels msgctxt "#30110" msgid "Enabling EDL" msgstr "Habilitación de EDL" msgctxt "#30111" msgid "" "A cut list or commercial skips have been found.\n" "Do you want to activate EDL functionality for this show ?" msgstr "Se ha encontrado una lista de cortes o saltos comerciales.\n¿Desea activar la funcionalidad EDL para este programa?" msgctxt "#30112" msgid "Connection failed" msgstr "La conexión falló" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "Quieres volver a intentarlo ?" msgctxt "#30114" msgid "Connected" msgstr "Conectado" # empty strings from id 30114 to 30299 # Notifications msgctxt "#30300" msgid "" "Failed to connect the MythTV backend with the known protocol versions. " "Please check the compatibility map of the addon and upgrade your backend to " "a supported version." msgstr "Error al conectar el backend de MythTV con las versiones de protocolo conocidas. Compruebe el mapa de compatibilidad del complemento y actualice el backend a una versión compatible." msgctxt "#30301" msgid "" "Failed to connect the API services of MythTV backend. Please check your PIN " "code or backend setup. The PIN code has to be configured in your backend to " "allow connection." msgstr "Error al conectar los servicios de API del backend de MythTV. Compruebe su código PIN o la configuración del backend. El código PIN debe configurarse en el backend para permitir la conexión." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Conexión al backend de MythTV perdido" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Conexión a MythTV restaurada" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "No hay respuesta de MythTV backend" msgctxt "#30305" msgid "Channel unavailable" msgstr "Canal no disponible" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Grabador no disponible" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Cancelando conflictos de grabación: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Detención de TV en directo debido a una grabación en conflicto: %s" msgctxt "#30309" msgid "Not recording" msgstr "Not recording" msgctxt "#30310" msgid "Enabled" msgstr "Activado" msgctxt "#30311" msgid "Disabled" msgstr "Deshabilitado" msgctxt "#30312" msgid "No broadcast found" msgstr "No se ha encontrado ninguna emisora" # empty strings from id 30313 to 30410 # Menu Hooks msgctxt "#30411" msgid "Delete and re-record" msgstr "Eliminar y volver a grabar" msgctxt "#30412" msgid "Keep recording" msgstr "Seguir grabando" # empty strings from id 30413 to 30420 msgctxt "#30421" msgid "Toggle display of alternative/recorded/expired" msgstr "Alternar visualización de alternativas/grabadas /caducadas" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "Actualizar caché para los iconos de canal" msgctxt "#30423" msgid "Trigger channels update" msgstr "Actualización de los canales de activación" msgctxt "#30424" msgid "Show status of scheduling" msgstr "Mostrar el estado de la programación" msgctxt "#30425" msgid "Show status of recording" msgstr "Mostrar el estado de la grabación" msgctxt "#30426" msgid "Show status of broadcast" msgstr "Mostrar el estado de la emisión" # empty strings from id 30427 to 30450 msgctxt "#30451" msgid "Unhandled" msgstr "sin tratamiento" msgctxt "#30452" msgid "Upcoming" msgstr "próximo" msgctxt "#30453" msgid "Overriden" msgstr "Sustituido" msgctxt "#30454" msgid "Don't record" msgstr "No grabe" msgctxt "#30455" msgid "Upcoming manual" msgstr "Próximos manuales" msgctxt "#30456" msgid "Zombie" msgstr "Zombie" msgctxt "#30457" msgid "Alternative" msgstr "Alternativo" msgctxt "#30458" msgid "Currently recorded" msgstr "Actualmente grabado" msgctxt "#30459" msgid "Expired recording" msgstr "Grabación caducado" msgctxt "#30460" msgid "Manual" msgstr "Manual" msgctxt "#30461" msgid "Record one" msgstr "Grabar uno" msgctxt "#30462" msgid "Record weekly" msgstr "Grabar semanal" msgctxt "#30463" msgid "Record daily" msgstr "Grabar diario" msgctxt "#30464" msgid "Record all" msgstr "Grabar todo" msgctxt "#30465" msgid "Record this" msgstr "Grabar esto" msgctxt "#30466" msgid "Record series" msgstr "Grabar series" msgctxt "#30467" msgid "Search keyword" msgstr "Buscar la palabra clave" msgctxt "#30468" msgid "Search people" msgstr "Buscar personas" msgctxt "#30469" msgid "Rule disabled" msgstr "Regla desactivada" # empty strings from id 30470 to 30500 msgctxt "#30501" msgid "Don't match duplicates" msgstr "No coincidir con duplicados" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "Coincidir duplicados usando subtítulos" msgctxt "#30503" msgid "Match duplicates using description" msgstr "Coincidir duplicados usando descripción" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "Coincidir duplicados usando subtítutlos y descripción" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "Coincidir duplicados usando subtítulos y entonces descripción" msgctxt "#30506" msgid "Recordings never expire" msgstr "Las grabaciones nunca caducan" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Permitir la caducidad de las grabaciones" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "Mantener hasta %d grabaciones" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "Mantener %d más reciente y caducados" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.et_ee/000077500000000000000000000000001360567320200273275ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.et_ee/strings.po000066400000000000000000000105611360567320200313630ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Estonian (Estonia) (http://www.transifex.com/projects/p/kodi-main/language/et_EE/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: et_EE\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "MythTV taustaprogrammi hosti nimi või IP" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "MythTV taustaprogrammi port" msgctxt "#30002" msgid "MythTV Database Username" msgstr "MythTV andmebaasi kasutajanimi" msgctxt "#30003" msgid "MythTV Database Password" msgstr "MythTV andmebaasi salasõna" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "MythTV andmebaasi baasi nimi" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Kaasa logifaili rohkem silumisinfot" msgctxt "#30006" msgid "Enable Live TV" msgstr "Võimalda TV" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Võimalda TVl liigutada plaanitud saateid" msgctxt "#30008" msgid "Conflict handling" msgstr "Vastuolulisuse käsitlemine" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Kui salvestisel on viibiv sisselõige siis eelista Otse TV-d" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Eelista salvestamist ja peata Otse TV" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Eelists Otse TV-d ja loobu probleemsest salvestamisest" msgctxt "#30019" msgid "General" msgstr "Üldine" msgctxt "#30020" msgid "Template provider" msgstr "Malli pakkuja" msgctxt "#30021" msgid "Internal" msgstr "Sisemine" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "Sisemine mall" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Otsi metainfo automaatselt" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Märgista uues salvestises reklaamid" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Transkodeeri uued salvestised" msgctxt "#30029" msgid "Run User Job #1" msgstr "Käivita kasutaja töö #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Käivita kasutaja töö #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Käivita kasutaja töö #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Käivita kasutaja töö #4" msgctxt "#30033" msgid "Transcoder" msgstr "Transkodeerija" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Luba salvestistel aeguda" msgctxt "#30049" msgid "Recording template" msgstr "Salvestus mall" msgctxt "#30050" msgid "Advanced" msgstr "Põhjalikumad seaded" msgctxt "#30055" msgid "Always" msgstr "Alati" msgctxt "#30057" msgid "Never" msgstr "Mitte kunagi" msgctxt "#30059" msgid "Always" msgstr "Alati" msgctxt "#30061" msgid "Never" msgstr "Mitte kunagi" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Protokolli versioon: %i - Andmebaasi versioon: %i" msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Ühendus MythTV taustaprogrammiga katkes" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "MythTVga ühendus taastatud" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "MythTV taustprogramm ei vasta" msgctxt "#30305" msgid "Channel unavailable" msgstr "Kanal pole saadaval" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Salvestaja pole saadaval" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Probleemse salvestamise tühistamine: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Otse TV peatamine probleemse salvestuse tõttu: %s" msgctxt "#30309" msgid "Not recording" msgstr "Ei salvesta" msgctxt "#30310" msgid "Enabled" msgstr "Lubatud" msgctxt "#30311" msgid "Disabled" msgstr "Ei kasutata" msgctxt "#30411" msgid "Delete and re-record" msgstr "Kustuta ja salvesta uuesti" msgctxt "#30460" msgid "Manual" msgstr "Käsitsi" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Luba salvestistel aeguda" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.eu_es/000077500000000000000000000000001360567320200273465ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.eu_es/strings.po000066400000000000000000000022221360567320200313750ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Basque (Spain) (http://www.transifex.com/projects/p/kodi-main/language/eu_ES/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: eu_ES\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30019" msgid "General" msgstr "Orokorra" msgctxt "#30050" msgid "Advanced" msgstr "Aurreratua" msgctxt "#30055" msgid "Always" msgstr "Beti" msgctxt "#30057" msgid "Never" msgstr "Inoiz ez" msgctxt "#30059" msgid "Always" msgstr "Beti" msgctxt "#30061" msgid "Never" msgstr "Inoiz ez" msgctxt "#30305" msgid "Channel unavailable" msgstr "Katea eskuraezina" msgctxt "#30310" msgid "Enabled" msgstr "Gaituta" msgctxt "#30311" msgid "Disabled" msgstr "Ezgaituta" msgctxt "#30460" msgid "Manual" msgstr "Eskuz" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.fa_af/000077500000000000000000000000001360567320200273025ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.fa_af/strings.po000066400000000000000000000017751360567320200313450ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Persian (Afghanistan) (http://www.transifex.com/projects/p/kodi-main/language/fa_AF/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: fa_AF\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30019" msgid "General" msgstr "عمومی" msgctxt "#30050" msgid "Advanced" msgstr "Ù¾ÛŒØ´Ø±ÙØªÙ‡" msgctxt "#30055" msgid "Always" msgstr "همیشه" msgctxt "#30057" msgid "Never" msgstr "هرگز" msgctxt "#30059" msgid "Always" msgstr "همیشه" msgctxt "#30061" msgid "Never" msgstr "هرگز" msgctxt "#30311" msgid "Disabled" msgstr "ØºÛŒØ±ÙØ¹Ø§Ù„" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.fa_ir/000077500000000000000000000000001360567320200273265ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.fa_ir/strings.po000066400000000000000000000023001360567320200313520ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Persian (Iran) (http://www.transifex.com/projects/p/kodi-main/language/fa_IR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: fa_IR\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30019" msgid "General" msgstr "عمومی" msgctxt "#30050" msgid "Advanced" msgstr "Ù¾ÛŒØ´Ø±ÙØªÙ‡" msgctxt "#30055" msgid "Always" msgstr "همیشه" msgctxt "#30057" msgid "Never" msgstr "هرگز" msgctxt "#30059" msgid "Always" msgstr "همیشه" msgctxt "#30061" msgid "Never" msgstr "هرگز" msgctxt "#30305" msgid "Channel unavailable" msgstr "کانال در دسترس نیست" msgctxt "#30310" msgid "Enabled" msgstr "ÙØ¹Ø§Ù„ شده" msgctxt "#30311" msgid "Disabled" msgstr "غیر ÙØ¹Ø§Ù„" msgctxt "#30460" msgid "Manual" msgstr "دستی" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.fi_fi/000077500000000000000000000000001360567320200273225ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.fi_fi/strings.po000066400000000000000000000235001360567320200313530ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Finnish (Finland) (http://www.transifex.com/projects/p/kodi-main/language/fi_FI/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: fi_FI\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "MythTV-taustaosan isäntänimi tai IP-osoite" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "MythTV-taustaosan portti" msgctxt "#30002" msgid "MythTV Database Username" msgstr "MythTV-tietokannan käyttäjänimi" msgctxt "#30003" msgid "MythTV Database Password" msgstr "MythTV-tietokannan salasana" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "MythTV-tietokannan tietokantanimi" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Tarkempi virheenkorjaustietojen kirjaaminen" msgctxt "#30006" msgid "Enable Live TV" msgstr "Salli tv-lähetysten katsominen" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Salli tv-lähetysten siirtää ajastuksia" msgctxt "#30008" msgid "Conflict handling" msgstr "Ristiriitojen käsittely" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Suosi tv-lähetystä, jos tallennus alkaa myöhemmin" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Suosi tallennuksia ja pysäytä tv-lähetys" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Suosi tv-lähetystä ja peru ristiriitainen tallennus" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "MythTV-taustaosan verkko-osoite (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "MythTV-taustaosan API-portti" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "MythTV-taustaosan API:n Pin-koodi " msgctxt "#30019" msgid "General" msgstr "Yleiset" msgctxt "#30020" msgid "Template provider" msgstr "Mallin tarjoaja" msgctxt "#30021" msgid "Internal" msgstr "Sisäinen" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "Sisäinen malli" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Etsi automaattisesti metatietoja" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Tunnista mainokset uusista tallenteista" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Transkoodaa uudet tallenteet" msgctxt "#30029" msgid "Run User Job #1" msgstr "Suorita tehtävä #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Suorita tehtävä #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Suorita tehtävä #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Suorita tehtävä #4" msgctxt "#30033" msgid "Transcoder" msgstr "Transkooderi" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Salli tallenteiden vanheneminen" msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "Kysy poistetaanko katsottu tallenne" msgctxt "#30048" msgid "Show 'Original Airdate' instead of 'Recording Time'" msgstr "Näytä ensiesityksen päivämäärä tallennuspäivän sijaan" msgctxt "#30049" msgid "Recording template" msgstr "Tallennusmalli" msgctxt "#30050" msgid "Advanced" msgstr "Lisäasetukset" msgctxt "#30051" msgid "Preferences" msgstr "Asetukset" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Demuxaa MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Viritysviive (sek)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Järjestä tallennukset kansioihin" msgctxt "#30055" msgid "Always" msgstr "Aina" msgctxt "#30056" msgid "Only for series" msgstr "Vain sarjat" msgctxt "#30057" msgid "Never" msgstr "Ei koskaan" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Hyppää mainoskatkojen yli (EDL)" msgctxt "#30059" msgid "Always" msgstr "Aina" msgctxt "#30060" msgid "Dialog" msgstr "Kysy" msgctxt "#30061" msgid "Never" msgstr "Ei koskaan" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Salli taustaosan sammutus" msgctxt "#30063" msgid "Enable channel icons" msgstr "Näytä kanavalogot" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Näytä tallenteiden fanitaide/kuvat" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "Rajoita kanavan viritysyritysten määrää" msgctxt "#30066" msgid "Show inactive upcomings (alternative/recorded/expired)" msgstr "Näytä epäaktiiviset ajastukset (tuplat/tallennetut/vanhentuneet)" msgctxt "#30067" msgid "Show LiveTV recordings" msgstr "Näytä tallenteet" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Protokollan versio: %i - Tietokannan versio: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "Ota EDL käyttöön" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "Mainoskatkojen leikkauslista löytyi.\nHaluatko ottaa EDL-toiminnon käyttöön tälle ohjelmalle?" msgctxt "#30112" msgid "Connection failed" msgstr "Yhteys epäonnistui" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "Haluatko yrittää uudelleen?" msgctxt "#30300" msgid "Failed to connect the MythTV backend with the known protocol versions. Please check the compatibility map of the addon and upgrade your backend to a supported version." msgstr "Yhdistäminen MythTV:n taustaosaan epäonnistui. Tarkista PVR-lisäosan vaatima minimiversio ja päivitä taustaosa uudempaan versioon." msgctxt "#30301" msgid "Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. The PIN code has to be configured in your backend to allow connection." msgstr "Yhdistäminen MythTV:n taustaosan API-palveluun epäonnistui. Tarkista PIN-koodisi ja taustaosan asetukset. Taustaosassa pitää olla määriteltynä PIN-koodi, jotta yhteys voidaan muodostaa." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Yhteys MythTv:hen katkennut" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Yhteys MythTV:hen palautettu" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "MythTv ei vastaa" msgctxt "#30305" msgid "Channel unavailable" msgstr "Kanava ei ole saatavilla" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Tallennin ei saatavilla" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Perutaan päällekkäinen tallennus: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Pysäytetään tv-lähetys päällekkäisen tallennuksen vuoksi: %s" msgctxt "#30309" msgid "Not recording" msgstr "Ei tallenna" msgctxt "#30310" msgid "Enabled" msgstr "Käytössä" msgctxt "#30311" msgid "Disabled" msgstr "Ei käytössä" msgctxt "#30312" msgid "No broadcast found" msgstr "Lähetystä ei löytynyt" msgctxt "#30411" msgid "Delete and re-record" msgstr "Poista ja uudelleentallenna" msgctxt "#30412" msgid "Keep recording" msgstr "Jatka tallentamista" msgctxt "#30421" msgid "Toggle display of alternative/recorded/expired" msgstr "Näytä vaihtoehtoiset/tallennetut/vanhentuneet" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "Päivitä kanavalogojen välimuisti" msgctxt "#30423" msgid "Trigger channels update" msgstr "Käynnistä kanavatietojen päivitys" msgctxt "#30424" msgid "Show status of scheduling" msgstr "Näytä ajastusten tila" msgctxt "#30451" msgid "Unhandled" msgstr "Käsittelemätön" msgctxt "#30452" msgid "Upcoming" msgstr "Tuleva" msgctxt "#30453" msgid "Overriden" msgstr "Ohitettu" msgctxt "#30454" msgid "Don't record" msgstr "Älä tallenna" msgctxt "#30455" msgid "Upcoming manual" msgstr "Tuleva manuaalinen" msgctxt "#30456" msgid "Zombie" msgstr "Zombi" msgctxt "#30457" msgid "Alternative" msgstr "Vaihtoehtoinen" msgctxt "#30458" msgid "Currently recorded" msgstr "Tällä hetkellä tallennettava" msgctxt "#30459" msgid "Expired recording" msgstr "Vanhentunut tallennus" msgctxt "#30460" msgid "Manual" msgstr "Manuaalisesti" msgctxt "#30461" msgid "Record one" msgstr "Tallenna yksi" msgctxt "#30462" msgid "Record weekly" msgstr "Tallenna viikoittain" msgctxt "#30463" msgid "Record daily" msgstr "Tallenna päivittäin" msgctxt "#30464" msgid "Record all" msgstr "Tallenna kaikki" msgctxt "#30465" msgid "Record this" msgstr "Tallenna tämä" msgctxt "#30466" msgid "Record series" msgstr "Tallenna sarjoja" msgctxt "#30467" msgid "Search keyword" msgstr "Etsi avainsanalla" msgctxt "#30468" msgid "Search people" msgstr "Etsi ihmisiä" msgctxt "#30469" msgid "Rule disabled" msgstr "Sääntö poistettu käytöstä" msgctxt "#30501" msgid "Don't match duplicates" msgstr "Älä etsi kaksoiskappaleita" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "Selvitä kaksoiskappaleet juonitiivistelmän avulla" msgctxt "#30503" msgid "Match duplicates using description" msgstr "Selvitä kaksoiskappaleet juonen avulla" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "Selvitä kaksoiskappaleet juonitiivistelmän ja juonen avulla" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "Selvitä kaksoiskappaleet ensijaisesti juonitiivistelmän, sitten vasta juonen perusteella" msgctxt "#30506" msgid "Recordings never expire" msgstr "Tallennukset eivät koskaan vanhene" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Salli tallennusten vanheta" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "Pidä enintään %d tallennusta" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "Pidä %d uusinta ja poista vanha" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.fo_fo/000077500000000000000000000000001360567320200273365ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.fo_fo/strings.po000066400000000000000000000020711360567320200313670ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Faroese (Faroe Islands) (http://www.transifex.com/projects/p/kodi-main/language/fo_FO/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: fo_FO\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30019" msgid "General" msgstr "Vanligt" msgctxt "#30055" msgid "Always" msgstr "Altíð" msgctxt "#30057" msgid "Never" msgstr "Ongantíð" msgctxt "#30059" msgid "Always" msgstr "Altíð" msgctxt "#30061" msgid "Never" msgstr "Ongantíð" msgctxt "#30305" msgid "Channel unavailable" msgstr "Rás er ikki tøk" msgctxt "#30310" msgid "Enabled" msgstr "Virkin" msgctxt "#30311" msgid "Disabled" msgstr "Sløkt" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.fr_ca/000077500000000000000000000000001360567320200273205ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.fr_ca/strings.po000066400000000000000000000275261360567320200313650ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière # Translators: # Jean-Luc Barrière , 2018-2019 msgid "" msgstr "" "Project-Id-Version: pvr.mythtv\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: 2019-01-06 13:13+0000\n" "Last-Translator: Jean-Luc Barrière \n" "Language-Team: French (Canada) (http://www.transifex.com/janbar/pvrmythtv/language/fr_CA/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: fr_CA\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" # Settings labels msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "Nom d'hôte ou adresse IP du dorsal MythTV" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "Port du dorsal MythTV" msgctxt "#30002" msgid "MythTV Database Username" msgstr "Nom d'utilisateur de la base de données MythTV" msgctxt "#30003" msgid "MythTV Database Password" msgstr "Mot de passe de la base de données MythTV" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "Nom de la base de données MythTV" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Inclure plus d'informations de débogage dans le fichier journal" msgctxt "#30006" msgid "Enable Live TV" msgstr "Activer la télé en direct" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Permettre à la télé en direct de déplacer les émissions planifiées" msgctxt "#30008" msgid "Conflict handling" msgstr "Gestion des conflits" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Préférer la télé en direct quand l'enregistrement a une tranche horaire ultérieure" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Préférer l'enregistrement et arrêter la télé en direct" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Préférer la télé en direct et arrêter les enregistrements en conflit" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "Adresse Ethernet (WOL) du dorsal MythTV" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "Port du dorsal MythTV pour les services d'API" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "NIP de sécurité de MthTV pour les services d'API" # empty strings from id 30015 to 30018 msgctxt "#30019" msgid "General" msgstr "Général" msgctxt "#30020" msgid "Template provider" msgstr "Fournisseur de modèles" msgctxt "#30021" msgid "Internal" msgstr "Interne" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" # empty strings from id 30023 to 30024 msgctxt "#30025" msgid "Internal template" msgstr "Modèle interne" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Rechercher automatiquement les métadonnées" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Marquer les publicités des nouveaux enregistrements" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Transcoder les nouveaux enregistrements" msgctxt "#30029" msgid "Run User Job #1" msgstr "Exécuter le travail d'utilisateur no 1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Exécuter le travail d'utilisateur no 2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Exécuter le travail d'utilisateur no 3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Exécuter le travail d'utilisateur no 4" msgctxt "#30033" msgid "Transcoder" msgstr "Transcodeur" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Permettre l'expiration des enregistrements" # empty strings from id 30035 to 30045 msgctxt "#30046" msgid "Show damaged recordings as color" msgstr "Couleur des enregistrements endommagés" msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "Demander de supprimer l'enregistrement visionné" msgctxt "#30048" msgid "Show 'Original Airdate' instead of 'Recording Time'" msgstr "Afficher la date de diffusion originale au lieu de la date d'enregistrement" msgctxt "#30049" msgid "Recording template" msgstr "Modèle d'enregistrement" msgctxt "#30050" msgid "Advanced" msgstr "Avancé" msgctxt "#30051" msgid "Preferences" msgstr "Préférences" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Activer le démultiplexage MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Délai de syntonisation (secondes)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Regrouper les enregistrements par titre" msgctxt "#30055" msgid "Always" msgstr "Toujours" msgctxt "#30056" msgid "Only for series" msgstr "Seulement pour les séries" msgctxt "#30057" msgid "Never" msgstr "Jamais" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Activer le saut des publicités (liste de montage)" msgctxt "#30059" msgid "Always" msgstr "Toujours" msgctxt "#30060" msgid "Dialog" msgstr "Boîte de dialogue" msgctxt "#30061" msgid "Never" msgstr "Jamais" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Permettre l'extinction du dorsal" msgctxt "#30063" msgid "Enable channel icons" msgstr "Activer les icônes de chaînes" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Activer l'enregistrement du fanart/des imagettes" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "Limiter les tentatives de syntonisation des chaînes" msgctxt "#30066" msgid "Show inactive upcomings (alternative/recorded/expired)" msgstr "Afficher les « À venir » inactifs (autre/enregistré/expiré)" msgctxt "#30067" msgid "Show LiveTV recordings" msgstr "Afficher les enregistrements de la télé en direct" msgctxt "#30068" msgid "Use bookmarks of the backend MythTV" msgstr "Utiliser les signets du serveur MythTV" msgctxt "#30069" msgid "Show default recording group as root" msgstr "Groupe d'enregistrement par défaut à la racine" msgctxt "#30070" msgid "Scene Only" msgstr "Signets" # empty strings from id 30071 to 30099 # Systeminformation labels msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Version du protocole : %i - Version de la base de données : %i" # empty strings from id 30101 to 30109 # Dialog labels msgctxt "#30110" msgid "Enabling EDL" msgstr "Activation des listes de montage" msgctxt "#30111" msgid "" "A cut list or commercial skips have been found.\n" "Do you want to activate EDL functionality for this show ?" msgstr "Une liste de montage ou de saut de publicités a été trouvée.\nVoulez-vous activer la fonction de listes de montage pour cette émission ?" msgctxt "#30112" msgid "Connection failed" msgstr "Échec de connexion" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "Voulez-vous ressayer ?" msgctxt "#30114" msgid "Connected" msgstr "Connecté" # empty strings from id 30114 to 30299 # Notifications msgctxt "#30300" msgid "" "Failed to connect the MythTV backend with the known protocol versions. " "Please check the compatibility map of the addon and upgrade your backend to " "a supported version." msgstr "Échec de connexion du dorsal MythTV avec les versions de protocoles connus. Veuillez consulter la carte de compatibilité de l'addiciel et mettre votre dorsal à niveau vers une version prise en charge." msgctxt "#30301" msgid "" "Failed to connect the API services of MythTV backend. Please check your PIN " "code or backend setup. The PIN code has to be configured in your backend to " "allow connection." msgstr "Échec de connexion des services d'API du dorsal MythTV. Veuillez vérifier votre NIP ou la configuration du dorsal. Le NIP doit être configuré dans le dorsal afin de permettre la connexion." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "La connexion du dorsal MythTV a été perdue" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "La connexion à MythTV est rétablie" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "Aucune réponse du dorsal MythTV" msgctxt "#30305" msgid "Channel unavailable" msgstr "Chaîne non disponible" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Enregistreur non disponible" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Annulation de l'enregistrement en conflit : %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Arrêt de la télé en direct dû à un enregistrement en conflit : %s" msgctxt "#30309" msgid "Not recording" msgstr "N'enregistre pas" msgctxt "#30310" msgid "Enabled" msgstr "Activé" msgctxt "#30311" msgid "Disabled" msgstr "Désactivé" msgctxt "#30312" msgid "No broadcast found" msgstr "Aucune diffusion n’a été trouvée" # empty strings from id 30313 to 30410 # Menu Hooks msgctxt "#30411" msgid "Delete and re-record" msgstr "Supprimer et ré-enregistrer" msgctxt "#30412" msgid "Keep recording" msgstr "Garder l'enregistrement" # empty strings from id 30413 to 30420 msgctxt "#30421" msgid "Toggle display of alternative/recorded/expired" msgstr "Activer ou désactiver l'affichage autre/enregistré/expiré" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "Rafraîchir le cache des icônes de chaînes" msgctxt "#30423" msgid "Trigger channels update" msgstr "Déclencher la mise à jour des chaînes" msgctxt "#30424" msgid "Show status of scheduling" msgstr "Afficher l'état de la programmation" msgctxt "#30425" msgid "Show status of recording" msgstr "Afficher l'état de l'enregistrement" msgctxt "#30426" msgid "Show status of broadcast" msgstr "Afficher l'état de l'émission" # empty strings from id 30427 to 30450 msgctxt "#30451" msgid "Unhandled" msgstr "Non géré" msgctxt "#30452" msgid "Upcoming" msgstr "À venir" msgctxt "#30453" msgid "Overriden" msgstr "Remplacé" msgctxt "#30454" msgid "Don't record" msgstr "Ne pas enregistrer" msgctxt "#30455" msgid "Upcoming manual" msgstr "Manuel à venir " msgctxt "#30456" msgid "Zombie" msgstr "Zombie" msgctxt "#30457" msgid "Alternative" msgstr "Autre" msgctxt "#30458" msgid "Currently recorded" msgstr "Enregistré actuellement" msgctxt "#30459" msgid "Expired recording" msgstr "Enregistrement expiré" msgctxt "#30460" msgid "Manual" msgstr "Manuel" msgctxt "#30461" msgid "Record one" msgstr "En enregistrer un" msgctxt "#30462" msgid "Record weekly" msgstr "Enregistrer hebdomadairement" msgctxt "#30463" msgid "Record daily" msgstr "Enregistrer quotidiennement" msgctxt "#30464" msgid "Record all" msgstr "Tout enregistrer" msgctxt "#30465" msgid "Record this" msgstr "Enregistrer ceci" msgctxt "#30466" msgid "Record series" msgstr "Enregistrer la série" msgctxt "#30467" msgid "Search keyword" msgstr "Rechercher par mot-clef" msgctxt "#30468" msgid "Search people" msgstr "Rechercher par personne" msgctxt "#30469" msgid "Rule disabled" msgstr "La règle est désactivée" # empty strings from id 30470 to 30500 msgctxt "#30501" msgid "Don't match duplicates" msgstr "Ne pas faire correspondre les doublons" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "Faire correspondre les doublons en utilisant les sous-titres" msgctxt "#30503" msgid "Match duplicates using description" msgstr "Faire correspondre les doublons en utilisant la description" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "Faire correspondre les doublons en utilisant les sous-titres et la description" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "Faire correspondre les doublons en utilisant les sous-titres puis la description" msgctxt "#30506" msgid "Recordings never expire" msgstr "Les enregistrements n'expirent jamais" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Permettre l'expiration des enregistrements" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "Garder jusqu'à %d enregistrements" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "Garder les %d plus récents et faire expirer les anciens" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.fr_fr/000077500000000000000000000000001360567320200273445ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.fr_fr/strings.po000066400000000000000000000271241360567320200314030ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière # Translators: # Jean-Luc Barrière , 2019 msgid "" msgstr "" "Project-Id-Version: pvr.mythtv\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: 2019-01-06 13:12+0000\n" "Last-Translator: Jean-Luc Barrière \n" "Language-Team: French (France) (http://www.transifex.com/janbar/pvrmythtv/language/fr_FR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: fr_FR\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" # Settings labels msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "Nom d'hôte ou IP du serveur MythTV" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "Port du serveur MythTV" msgctxt "#30002" msgid "MythTV Database Username" msgstr "Nom d'utilisateur de base de données MythTV" msgctxt "#30003" msgid "MythTV Database Password" msgstr "Mot de passe de base de données MythTV" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "Nom de la base de données MythTV" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Inclure plus d'informations de débogage dans le fichier de journal" msgctxt "#30006" msgid "Enable Live TV" msgstr "Activer la TV en direct" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Autoriser la TV en direct à modifier la planification des programmes" msgctxt "#30008" msgid "Conflict handling" msgstr "Gestion des conflits" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Préférer la TV en direct si possible" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Préférer l'enregistrement et stopper la TV en direct" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Préférer la TV en direct et annuler l'enregistrement en conflit" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "Adresse Ethernet du serveur MythTV (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "Port du serveur MythTV pour les services API" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "Code PIN de sécurité MythTV pour les services API" # empty strings from id 30015 to 30018 msgctxt "#30019" msgid "General" msgstr "Général" msgctxt "#30020" msgid "Template provider" msgstr "Fournisseur de modèles" msgctxt "#30021" msgid "Internal" msgstr "Interne" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" # empty strings from id 30023 to 30024 msgctxt "#30025" msgid "Internal template" msgstr "Modèle interne" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Rechercher automatiquement les métadonnées" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Marquer les annonces publicitaires des enregistrements" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Transcoder les nouveaux enregistrements" msgctxt "#30029" msgid "Run User Job #1" msgstr "Lancer la tâche utilisateur #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Lancer la tâche utilisateur #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Lancer la tâche utilisateur #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Lancer la tâche utilisateur #4" msgctxt "#30033" msgid "Transcoder" msgstr "Transcodeur" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Autoriser les enregistrements à expirer" # empty strings from id 30035 to 30045 msgctxt "#30046" msgid "Show damaged recordings as color" msgstr "Couleur des enregistrements endommagés" msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "Proposer de supprimer l'enregistrement visionné" msgctxt "#30048" msgid "Show 'Original Airdate' instead of 'Recording Time'" msgstr "Afficher la « Date de diffusion » au lieu de la « Date d'enregistrement »" msgctxt "#30049" msgid "Recording template" msgstr "Modèle d'enregistrement" msgctxt "#30050" msgid "Advanced" msgstr "Avancé" msgctxt "#30051" msgid "Preferences" msgstr "Préférences" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Activer le démultiplexage MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Délai de syntonisation (s)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Regrouper les enregistrements par titre" msgctxt "#30055" msgid "Always" msgstr "Toujours" msgctxt "#30056" msgid "Only for series" msgstr "Seulement pour les séries" msgctxt "#30057" msgid "Never" msgstr "Jamais" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Activer la prise en charge des sauts publicitaires (EDL)" msgctxt "#30059" msgid "Always" msgstr "Toujours" msgctxt "#30060" msgid "Dialog" msgstr "Boîte de dialogue" msgctxt "#30061" msgid "Never" msgstr "Jamais" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Permettre l'arrêt du serveur" msgctxt "#30063" msgid "Enable channel icons" msgstr "Afficher les icônes des chaînes" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Afficher les FanArts/miniatures des enregistrements" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "Limiter les tentatives de syntonisation" msgctxt "#30066" msgid "Show inactive upcomings (alternative/recorded/expired)" msgstr "Afficher les programmes à venir inactifs (alternatifs/enregistrés/expirés)" msgctxt "#30067" msgid "Show LiveTV recordings" msgstr "Afficher les enregistrements de la TV en direct" msgctxt "#30068" msgid "Use bookmarks of the backend MythTV" msgstr "Utiliser les signets du serveur MythTV" msgctxt "#30069" msgid "Show default recording group as root" msgstr "Groupe d'enregistrement par défaut à la racine" msgctxt "#30070" msgid "Scene Only" msgstr "Signets" # empty strings from id 30071 to 30099 # Systeminformation labels msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Version du protocole : %i - Version de la base de données : %i" # empty strings from id 30101 to 30109 # Dialog labels msgctxt "#30110" msgid "Enabling EDL" msgstr "Activation de l'EDL" msgctxt "#30111" msgid "" "A cut list or commercial skips have been found.\n" "Do you want to activate EDL functionality for this show ?" msgstr "Une liste de coupures ou de sauts publicitaires a été trouvée.\nFaut-il activer la fonctionnalité EDL pour cette émission ?" msgctxt "#30112" msgid "Connection failed" msgstr "Connexion échouée" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "Faut-il réessayer ?" msgctxt "#30114" msgid "Connected" msgstr "Connecté" # empty strings from id 30114 to 30299 # Notifications msgctxt "#30300" msgid "" "Failed to connect the MythTV backend with the known protocol versions. " "Please check the compatibility map of the addon and upgrade your backend to " "a supported version." msgstr "Impossible de se connecter au serveur MythTV avec les versions connues du protocole. Merci de vérifier la compatibilité de l'extension et de mettre à jour le serveur vers une version prise en charge." msgctxt "#30301" msgid "" "Failed to connect the API services of MythTV backend. Please check your PIN " "code or backend setup. The PIN code has to be configured in your backend to " "allow connection." msgstr "Impossible de se connecter au services API du serveur MythTV. Merci de vérifier le code PIN ou la configuration du serveur. Le code PIN doit être configuré sur le serveur pour permettre la connexion." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Connexion au serveur MythTV perdue" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Connexion au serveur MythTV rétablie" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "Pas de réponse du serveur MythTV" msgctxt "#30305" msgid "Channel unavailable" msgstr "Chaîne indisponible" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Enregistreur indisponible" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Annuler l'enregistrement en conflit : %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "TV en direct stoppée à cause d'enregistrement en conflit : %s" msgctxt "#30309" msgid "Not recording" msgstr "N'enregistre pas" msgctxt "#30310" msgid "Enabled" msgstr "Activé" msgctxt "#30311" msgid "Disabled" msgstr "Désactivé" msgctxt "#30312" msgid "No broadcast found" msgstr "Aucune diffusion trouvée" # empty strings from id 30313 to 30410 # Menu Hooks msgctxt "#30411" msgid "Delete and re-record" msgstr "Supprimer et réenregistrer" msgctxt "#30412" msgid "Keep recording" msgstr "Conserver l'enregistrement" # empty strings from id 30413 to 30420 msgctxt "#30421" msgid "Toggle display of alternative/recorded/expired" msgstr "Afficher/Masquer les programmes à venir inactifs" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "Actualiser le cache d'icônes de chaines" msgctxt "#30423" msgid "Trigger channels update" msgstr "Mettre à jour les chaînes" msgctxt "#30424" msgid "Show status of scheduling" msgstr "Voir le statut de la programmation" msgctxt "#30425" msgid "Show status of recording" msgstr "Voir le statut de l'enregistrement" msgctxt "#30426" msgid "Show status of broadcast" msgstr "Voir le statut de l'émission" # empty strings from id 30427 to 30450 msgctxt "#30451" msgid "Unhandled" msgstr "Non géré" msgctxt "#30452" msgid "Upcoming" msgstr "Programme à venir" msgctxt "#30453" msgid "Overriden" msgstr "Surchargé" msgctxt "#30454" msgid "Don't record" msgstr "Ne pas enregistrer" msgctxt "#30455" msgid "Upcoming manual" msgstr "Programme à venir manuel" msgctxt "#30456" msgid "Zombie" msgstr "Zombie" msgctxt "#30457" msgid "Alternative" msgstr "Alternatif" msgctxt "#30458" msgid "Currently recorded" msgstr "Actuellement enregistré" msgctxt "#30459" msgid "Expired recording" msgstr "Enregistrement expiré" msgctxt "#30460" msgid "Manual" msgstr "Manuel" msgctxt "#30461" msgid "Record one" msgstr "Enregistrer une diffusion" msgctxt "#30462" msgid "Record weekly" msgstr "Programmation hebdomadaire" msgctxt "#30463" msgid "Record daily" msgstr "Programmation journalière" msgctxt "#30464" msgid "Record all" msgstr "Enregistrer toutes les diffusions" msgctxt "#30465" msgid "Record this" msgstr "Enregistrer cette diffusion" msgctxt "#30466" msgid "Record series" msgstr "Enregistrer une série" msgctxt "#30467" msgid "Search keyword" msgstr "Rechercher un mot clé" msgctxt "#30468" msgid "Search people" msgstr "Rechercher une personne" msgctxt "#30469" msgid "Rule disabled" msgstr "Règles désactivées" # empty strings from id 30470 to 30500 msgctxt "#30501" msgid "Don't match duplicates" msgstr "Ne pas chercher les doublons" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "Chercher les doublons par sous-titre" msgctxt "#30503" msgid "Match duplicates using description" msgstr "Chercher les doublons par description" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "Chercher les doublons par sous-titre et description" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "Chercher les doublons par sous-titre puis description" msgctxt "#30506" msgid "Recordings never expire" msgstr "Les enregistrements n'expirent jamais" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Permettre l'expiration des enregistrements" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "Conserver un maximum de %d enregistrements" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "Conserver les %d plus récents et expirer les vieux" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.gl_es/000077500000000000000000000000001360567320200273375ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.gl_es/strings.po000066400000000000000000000224511360567320200313740ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Galician (Spain) (http://www.transifex.com/projects/p/kodi-main/language/gl_ES/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: gl_ES\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "Nome do host ou IP do motor de MythTV" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "Porto do motor de MythTV" msgctxt "#30002" msgid "MythTV Database Username" msgstr "Nome de usuario da Base de datos de MythTV" msgctxt "#30003" msgid "MythTV Database Password" msgstr "Contrasinal da Base de datos de MythTV" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "Nome da Base de datos de MythTV" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Incluír máis información de depuración no ficheiro de rexistro" msgctxt "#30006" msgid "Enable Live TV" msgstr "Habilitar TV ao vivo" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Permitir á TV ao vivo mover as series programadas." msgctxt "#30008" msgid "Conflict handling" msgstr "Manipulación de conflitos" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Prefiro a TV ao vivo e deixar a gravación para máis tarde" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Prefiro a gravación e deter a TV ao vivo" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Prefiro a TV ao vivo e cancelar as gravacións en conflito" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "Enderezo IP do Motor MythTV (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "Porto do motor de MythTV para os servizos API" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "Pin de seguridade do MythTV para os servizos API" msgctxt "#30019" msgid "General" msgstr "Xeral" msgctxt "#30020" msgid "Template provider" msgstr "Provedor do modelo" msgctxt "#30021" msgid "Internal" msgstr "Interno" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "Modelo interno" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Busar metadatos automaticamente" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Etiqueta de publicidade nas novas gravacións" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Transcodificar novas gravacións" msgctxt "#30029" msgid "Run User Job #1" msgstr "Executar o traballo #1 do Usuario" msgctxt "#30030" msgid "Run User Job #2" msgstr "Executar o traballo #2 do Usuario" msgctxt "#30031" msgid "Run User Job #3" msgstr "Executar o traballo #3 do Usuario" msgctxt "#30032" msgid "Run User Job #4" msgstr "Executar o traballo #4 do Usuario" msgctxt "#30033" msgid "Transcoder" msgstr "Transcodificador" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Permitir que expiren as gravacións" msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "Preguntar ao eliminar as gravacións vistas" msgctxt "#30048" msgid "Show 'Original Airdate' instead of 'Recording Time'" msgstr "Amosar 'Data do Ar Orixinal' no canto de 'Data de Gravación'" msgctxt "#30049" msgid "Recording template" msgstr "Modelo de gravación" msgctxt "#30050" msgid "Advanced" msgstr "Avanzado" msgctxt "#30051" msgid "Preferences" msgstr "Preferencias" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Activar demux MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Retardo na sintonización (seg)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Agrupar gravacións por título" msgctxt "#30055" msgid "Always" msgstr "Sempre" msgctxt "#30056" msgid "Only for series" msgstr "Só para series" msgctxt "#30057" msgid "Never" msgstr "Nunca" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Activar a omisión de anuncios (EDL)" msgctxt "#30059" msgid "Always" msgstr "Sempre" msgctxt "#30060" msgid "Dialog" msgstr "diálogo" msgctxt "#30061" msgid "Never" msgstr "Nunca" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Permitir o apagado do motor" msgctxt "#30063" msgid "Enable channel icons" msgstr "Permitir iconas das canles" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Activar gravación do fanart/miniaturas" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "Nº de intentos para sintonizar a canle" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Versión do protocolo: %i - Versión da Base de Datos: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "Activando o EDL" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "Atopouse unha listaxe de corte.\nTen a certeza de querer activar a funcionalidade EDL para esta serie?" msgctxt "#30112" msgid "Connection failed" msgstr "Fallou conexión" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "Queres tentalo de novo?" msgctxt "#30300" msgid "Failed to connect the MythTV backend with the known protocol versions. Please check the compatibility map of the addon and upgrade your backend to a supported version." msgstr "Non se puido conectar o motor de MythTV " msgctxt "#30301" msgid "Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. The PIN code has to be configured in your backend to allow connection." msgstr "Non se puido conectar cos servizos da API do servidor de MythTV. Por favor comproba o teu código PIN ou os axustes do servidor. O código PIN ten de ser definido no teu servidor para permitir a conexión." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Perdeuse a conexión co motor MythTV" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Restabeleceuse a conexión a MythTV" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "Sen resposta do motor MythTV" msgctxt "#30305" msgid "Channel unavailable" msgstr "Canle non dispoñíbel" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Gravador non dispoñíbel" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Cancelando a gravación en conflito: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Detendo a TV ao vivo debido á gravación en conflito: %s" msgctxt "#30309" msgid "Not recording" msgstr "Non se está gravando" msgctxt "#30310" msgid "Enabled" msgstr "Activado" msgctxt "#30311" msgid "Disabled" msgstr "Desactivado" msgctxt "#30312" msgid "No broadcast found" msgstr "Non se atopou emisión" msgctxt "#30411" msgid "Delete and re-record" msgstr "Eliminar e volver gravar" msgctxt "#30412" msgid "Keep recording" msgstr "Continuar gravando" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "Actualizar a caché de iconas das canles" msgctxt "#30423" msgid "Trigger channels update" msgstr "Ativar a actualizanción de canles" msgctxt "#30424" msgid "Show status of scheduling" msgstr "Amosar o estado da programación" msgctxt "#30452" msgid "Upcoming" msgstr "Vindeiro" msgctxt "#30454" msgid "Don't record" msgstr "Non gravar" msgctxt "#30456" msgid "Zombie" msgstr "Zombi" msgctxt "#30457" msgid "Alternative" msgstr "Alternativa" msgctxt "#30458" msgid "Currently recorded" msgstr "Gravado actualmente" msgctxt "#30459" msgid "Expired recording" msgstr "Gravación caducada" msgctxt "#30460" msgid "Manual" msgstr "Manual" msgctxt "#30461" msgid "Record one" msgstr "Gravar un" msgctxt "#30462" msgid "Record weekly" msgstr "Gravar semanalmente" msgctxt "#30463" msgid "Record daily" msgstr "Gravar diariamente" msgctxt "#30464" msgid "Record all" msgstr "Gravar todo" msgctxt "#30465" msgid "Record this" msgstr "Gravar isto" msgctxt "#30466" msgid "Record series" msgstr "Gravar series" msgctxt "#30467" msgid "Search keyword" msgstr "Percurar palabra chave" msgctxt "#30468" msgid "Search people" msgstr "Buscar xente" msgctxt "#30469" msgid "Rule disabled" msgstr "Regra desactivada" msgctxt "#30501" msgid "Don't match duplicates" msgstr "Non se atoparon duplicados" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "Buscar duplicados polo subtítulo" msgctxt "#30503" msgid "Match duplicates using description" msgstr "Buscar duplicados pola descrición" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "Buscar duplicados polo subtítulo e a descrición" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "Buscar duplicados primeiro polo subtítulo e logo pola descrición" msgctxt "#30506" msgid "Recordings never expire" msgstr "As gravacións nunca caducan" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Permitir que expiren as gravacións" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "Manter até %d gravacións" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "Manter os %d máis novos e eliminar os vellos" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.he_il/000077500000000000000000000000001360567320200273265ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.he_il/strings.po000066400000000000000000000250741360567320200313670ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Hebrew (Israel) (http://www.transifex.com/projects/p/kodi-main/language/he_IL/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: he_IL\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "×©× ×ž×רח ×ו כתובת IP" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "פורט" msgctxt "#30002" msgid "MythTV Database Username" msgstr "×©× ×ž×©×ª×ž×© למסד נתוני MythTV" msgctxt "#30003" msgid "MythTV Database Password" msgstr "סיסמת מסד נתוני MythTV" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "×©× ×ž×¡×“ נתוני MythTV" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "כלול פירוט ××™×¨×•×¢×™× × ×•×¡×£ ביומן הרישו×" msgctxt "#30006" msgid "Enable Live TV" msgstr "×פשר שידור ×—×™" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "×פשר לצפייה בשידור ×—×™ לדחות תזמון הקלטה" msgctxt "#30008" msgid "Conflict handling" msgstr "טיפול בהתנגשויות" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "העדף שידור ×—×™ ×›×שר ×§×™×™× ×©×™×“×•×¨ חוזר להקלטה מתוזמנת" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "העדף הקלטה והפסק צפייה בשידור ×—×™" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "העדף שידור ×—×™ ובטל תזמון הקלטה חופפת" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "כתובת IP של שרת ×חורי (עבור WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "פורט לשירותי API" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "קוד ×בטחה של MythTV עבור שירותי API" msgctxt "#30019" msgid "General" msgstr "כללי" msgctxt "#30020" msgid "Template provider" msgstr "ספק תבניות" msgctxt "#30021" msgid "Internal" msgstr "פנימי" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "תבנית פנימית" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "חיפוש מידע נוסף ×וטומטי" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "סמן פרסומות בהקלטות חדשות" msgctxt "#30028" msgid "Transcode new recordings" msgstr "קודד מחדש הקלטות חדשות" msgctxt "#30029" msgid "Run User Job #1" msgstr "הרץ משימת משתמש #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "הרץ משימת משתמש #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "הרץ משימת משתמש #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "הרץ משימת משתמש #4" msgctxt "#30033" msgid "Transcoder" msgstr "מקודד מחדש" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "×פשר פקיעת תוקף הקלטות" msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "בקש ×ישור ×›×שר ×ž×•×—×§×™× ×”×§×œ×˜×” שנצפתה" msgctxt "#30048" msgid "Show 'Original Airdate' instead of 'Recording Time'" msgstr "הר××” 'ת×ריך שידור מקורי' ×‘×ž×§×•× 'שעת הקלטה'" msgctxt "#30049" msgid "Recording template" msgstr "תבנית הקלטה" msgctxt "#30050" msgid "Advanced" msgstr "מתקד×" msgctxt "#30051" msgid "Preferences" msgstr "העדפות" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "×פשר פילוג (demuxing) של MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "השהיית העברת ערוץ (שנ')" msgctxt "#30054" msgid "Group recordings by title" msgstr "קבץ הקלטות לפי כותרת" msgctxt "#30055" msgid "Always" msgstr "תמיד" msgctxt "#30056" msgid "Only for series" msgstr "לסדרות בלבד" msgctxt "#30057" msgid "Never" msgstr "××£ פע×" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "×פשר דילוג פרסומות (EDL)" msgctxt "#30059" msgid "Always" msgstr "תמיד" msgctxt "#30060" msgid "Dialog" msgstr "די×לוג" msgctxt "#30061" msgid "Never" msgstr "××£ פע×" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "×פשר לכבות משרת" msgctxt "#30063" msgid "Enable channel icons" msgstr "×פשר סמלי ערוצי×" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "×פשר פ×× ×רט/תמונות ממוזערות של הקלטות" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "הגבל מס' ניסיונות צפייה בערוץ" msgctxt "#30066" msgid "Show inactive upcomings (alternative/recorded/expired)" msgstr "הר××” ממשמש ×•×‘× ×œ× ×¤×¢×™×œ (חלופה/הקלטה/×œ× ×‘×ª×•×§×£)" msgctxt "#30067" msgid "Show LiveTV recordings" msgstr "הצג הקלטות לטלוויזיה ×—×™×”" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "גרסת פרוטוקול: %i - גרסת מסד נתוני×: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "מפעיל EDL" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "רשימת × ×§' חיתוך הקלטה ×ו דילוגי פרסומות נמצ×ו.\n×”×× ×œ×פשר ×ת תכונת EDL עבור תכנית זו?" msgctxt "#30112" msgid "Connection failed" msgstr "החיבור נכשל" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "×”×× ×‘×¨×¦×•× ×š לנסות שנית?" msgctxt "#30300" msgid "Failed to connect the MythTV backend with the known protocol versions. Please check the compatibility map of the addon and upgrade your backend to a supported version." msgstr "נכשל בהתחברות ×ל MythTV backend ×¢× ×’×¨×¡×ª פרוטוקול ×œ× ×™×“×•×¢. בדוק בבקשה ×ת מפת הת×ימות של התוסף ועדכן ×ת ×”backend שלך כדי לתמוך בגרסה זו." msgctxt "#30301" msgid "Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. The PIN code has to be configured in your backend to allow connection." msgstr "נכשל בחיבור לשירות API של MythTV backend. בדוק בבקשה ×ת הקוד PIN ×ו ×ת התקנת backend שלך. הקוד PIN צריך להיות מוגדר בbackend על מנת שיוכל להתחבר." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "נותק משרת MythTV" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "חובר חזרה לשרת MythTV" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "×ין תגובה משרת MythTV" msgctxt "#30305" msgid "Channel unavailable" msgstr "הערוץ ×œ× ×–×ž×™×Ÿ" msgctxt "#30306" msgid "Recorder unavailable" msgstr "המקליט ×œ× ×–×ž×™×Ÿ" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "מבטל תזמון הקלטה חופף: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "עוצר שידור ×—×™ עקב תזמון הקלטה חופף: %s" msgctxt "#30309" msgid "Not recording" msgstr "×œ× ×ž×§×œ×™×˜" msgctxt "#30310" msgid "Enabled" msgstr "פעיל" msgctxt "#30311" msgid "Disabled" msgstr "מנוטרל" msgctxt "#30312" msgid "No broadcast found" msgstr "×œ× × ×ž×¦× ×©×™×“×•×¨" msgctxt "#30411" msgid "Delete and re-record" msgstr "מחיקה והקלטה מחדש" msgctxt "#30412" msgid "Keep recording" msgstr "המשך להקליט" msgctxt "#30421" msgid "Toggle display of alternative/recorded/expired" msgstr "הר××” חלופה/הקלטה/×œ× ×‘×ª×•×§×£" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "רענן מטמון סמלי ערוץ" msgctxt "#30423" msgid "Trigger channels update" msgstr "×’×•×¨× ×ž×¤×¢×™×œ עדכון ערוצי×" msgctxt "#30424" msgid "Show status of scheduling" msgstr "הצג סטטוס של תזמון" msgctxt "#30451" msgid "Unhandled" msgstr "×œ× ×ž×˜×•×¤×œ" msgctxt "#30452" msgid "Upcoming" msgstr "בקרוב" msgctxt "#30453" msgid "Overriden" msgstr "עקיפה" msgctxt "#30454" msgid "Don't record" msgstr "×œ× ×œ×”×§×œ×™×˜" msgctxt "#30455" msgid "Upcoming manual" msgstr "בקרוב ידני" msgctxt "#30456" msgid "Zombie" msgstr "זומבי" msgctxt "#30457" msgid "Alternative" msgstr "חלופה" msgctxt "#30458" msgid "Currently recorded" msgstr "הקלטות נוכחיות" msgctxt "#30459" msgid "Expired recording" msgstr "הקלטות שפגו" msgctxt "#30460" msgid "Manual" msgstr "ידני" msgctxt "#30461" msgid "Record one" msgstr "הקלטה חד פעמית" msgctxt "#30462" msgid "Record weekly" msgstr "הקלטה שבועית" msgctxt "#30463" msgid "Record daily" msgstr "הקלטה יומית" msgctxt "#30464" msgid "Record all" msgstr "הקלט הכל" msgctxt "#30465" msgid "Record this" msgstr "הקלט ×–×”" msgctxt "#30466" msgid "Record series" msgstr "הקלטת סדרה" msgctxt "#30467" msgid "Search keyword" msgstr "חיפוש מילת מפתח" msgctxt "#30468" msgid "Search people" msgstr "חיפוש ×נשי×" msgctxt "#30469" msgid "Rule disabled" msgstr "חוק מנוטרל" msgctxt "#30501" msgid "Don't match duplicates" msgstr "×ל תת××™× ×›×¤×™×œ×•×™×•×ª" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "הת×× ×›×¤×™×œ×•×™×•×ª בעזרת כתוביות" msgctxt "#30503" msgid "Match duplicates using description" msgstr "הת×× ×›×¤×™×œ×•×™×•×ª בעזרת תי×ור" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "הת×× ×›×¤×™×œ×•×™×•×ª בעזרת כתוביות ותי×ור" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "הת×× ×›×¤×™×œ×•×™×•×ª בעזרת כתוביות ו××– תי×ור" msgctxt "#30506" msgid "Recordings never expire" msgstr "הקלטות ×œ× ×¤×’×•×ª" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "×פשר פקיעת תוקף הקלטות" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "שמור עד ל %d הקלטות" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "שמור %d ×—×“×©×™× ×•×™×©× ×™× ×¤×’×™ תוקף" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.hi_in/000077500000000000000000000000001360567320200273345ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.hi_in/strings.po000066400000000000000000000016741360567320200313750ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Hindi (India) (http://www.transifex.com/projects/p/kodi-main/language/hi_IN/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: hi_IN\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30019" msgid "General" msgstr "सामानà¥à¤¯" msgctxt "#30050" msgid "Advanced" msgstr "उनà¥à¤¨à¤¤" msgctxt "#30310" msgid "Enabled" msgstr "सकà¥à¤°à¤¿à¤¯" msgctxt "#30311" msgid "Disabled" msgstr "विकलांग" msgctxt "#30460" msgid "Manual" msgstr "मैनà¥à¤…ल" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.hr_hr/000077500000000000000000000000001360567320200273505ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.hr_hr/strings.po000066400000000000000000000236351360567320200314120ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Croatian (Croatia) (http://www.transifex.com/projects/p/kodi-main/language/hr_HR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: hr_HR\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "MythTV naziv raÄunala ili IP" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "Ulaz MythTV pozadinskog softvera" msgctxt "#30002" msgid "MythTV Database Username" msgstr "KorisniÄko ime MythTV baze podataka" msgctxt "#30003" msgid "MythTV Database Password" msgstr "Lozinka MythTV baze podataka" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "Naziv MythTV baze podataka" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "UkljuÄi viÅ¡e informacija otklanjanja greÅ¡ke u datoteku zapisa" msgctxt "#30006" msgid "Enable Live TV" msgstr "Omogući televiziju" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Omogući TV programu da pomiÄe rasporede emisija" msgctxt "#30008" msgid "Conflict handling" msgstr "Rukovanje sukobom" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Preferiraj gledanje televizije kada snimanje poÄine kasnije" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Preferiraj snimanje i zaustavi gledanje televizije" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Preferiraj gledanje televizije i poniÅ¡ti sukobljeno snimanje" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "Ethernet adresa (WOL) MythTV pozadinskog softvera" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "Ulaz MythTV pozadinskog softvera za API usluge" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "MythTV sigurnosni pin za API usluge" msgctxt "#30019" msgid "General" msgstr "Općenito" msgctxt "#30020" msgid "Template provider" msgstr "Predložak usluga" msgctxt "#30021" msgid "Internal" msgstr "Unutarnji" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "Unutarnji predložak" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Automatski potraži meta podatke" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Oznaka reklamiranja novog snimanja" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Enkôdiraj novo snimanje" msgctxt "#30029" msgid "Run User Job #1" msgstr "Pokreni korisnikov posao #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Pokreni korisnikov posao #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Pokreni korisnikov posao #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Pokreni korisnikov posao #4" msgctxt "#30033" msgid "Transcoder" msgstr "Enkôder" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Dopusti istek snimanja" msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "Upitaj za brisnje pogledanih snimaka" msgctxt "#30048" msgid "Show 'Original Airdate' instead of 'Recording Time'" msgstr "Prikaži 'Izvorni datum emitiranja' umjesto 'Datuma snimanja'" msgctxt "#30049" msgid "Recording template" msgstr "PredloÅ¡ci snimanja" msgctxt "#30050" msgid "Advanced" msgstr "Napredno" msgctxt "#30051" msgid "Preferences" msgstr "Osobitosti" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Omogući razdvajanje MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Odgoda prilagodbe (sek)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Grupno snimanje prema naslovu" msgctxt "#30055" msgid "Always" msgstr "Uvijek" msgctxt "#30056" msgid "Only for series" msgstr "Samo za emisije" msgctxt "#30057" msgid "Never" msgstr "Nikada" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Omogući preskakanje reklama (EDL)" msgctxt "#30059" msgid "Always" msgstr "Uvijek" msgctxt "#30060" msgid "Dialog" msgstr "Dijalog" msgctxt "#30061" msgid "Never" msgstr "Nikada" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Dopusti pozadinsko iskljuÄivanje" msgctxt "#30063" msgid "Enable channel icons" msgstr "Omogući ikone programa" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Omogući snimanje postere/minijature" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "OgraniÄi pokuÅ¡aje podeÅ¡avanja programa" msgctxt "#30066" msgid "Show inactive upcomings (alternative/recorded/expired)" msgstr "Prikaži neaktivne nadolezeće (alternativno/snimljeno/isteklo snimanje)" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "InaÄica protokola: %i - InaÄica baze podataka: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "Omogućavanje EDL" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "Popis izbacivanja ili preskakanja reklama je pronaÄ‘en.\nŽelite li aktivirati EDL funkciju za ovu emisiju?" msgctxt "#30112" msgid "Connection failed" msgstr "Neuspjelo povezivanje" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "Želite li ponovno pokuÅ¡ati?" msgctxt "#30300" msgid "Failed to connect the MythTV backend with the known protocol versions. Please check the compatibility map of the addon and upgrade your backend to a supported version." msgstr "Neuspjelo povezivanje s MythTV pozadinskim softverom s nepoznatom inaÄicom protokola. Provjerite mapu kompatibilnosti dodatka i nadogradite svoj pozadinski softver na podržanu inaÄicu." msgctxt "#30301" msgid "Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. The PIN code has to be configured in your backend to allow connection." msgstr "Neuspjelo povezivanje s API uslugama MythTV pozadinskog softvera. Provjerite svoj PIN kôd ili postavke pozadinskog softvera. PIN kôd mora biti postavljen u vaÅ¡em pozadinskom softverom kako bi dopustio povezivanje." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Povezivanje na MythTV pozadinski softver izgubljeno" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Povezivanje na MythTV pozadinski softver uspostavljeno" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "Nema odgovora od MythTV pozadinskog softvera" msgctxt "#30305" msgid "Channel unavailable" msgstr "Program nedostupan" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Snimanje nedostupno" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "PoniÅ¡tavanje sukobljenog snimanja: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Zaustavljanje gledanja televizije zbog sukoba snimanja: %s" msgctxt "#30309" msgid "Not recording" msgstr "Ne snima se" msgctxt "#30310" msgid "Enabled" msgstr "Omogućeno" msgctxt "#30311" msgid "Disabled" msgstr "Onemogućeno" msgctxt "#30312" msgid "No broadcast found" msgstr "Nema pronaÄ‘enog emitiranja" msgctxt "#30411" msgid "Delete and re-record" msgstr "ObriÅ¡i i ponovno snimi" msgctxt "#30412" msgid "Keep recording" msgstr "Nastavi snimanje" msgctxt "#30421" msgid "Toggle display of alternative/recorded/expired" msgstr "Prebaci prikaz izmeÄ‘u alternativnog/snimljenog/isteklog snimanja" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "Osvježi predmemoriju za prikaz ikona programa" msgctxt "#30423" msgid "Trigger channels update" msgstr "Pokreni ažuriranje programa" msgctxt "#30424" msgid "Show status of scheduling" msgstr "Prikaži stanje rasporeda" msgctxt "#30451" msgid "Unhandled" msgstr "Slobodne" msgctxt "#30452" msgid "Upcoming" msgstr "Nadolazeće" msgctxt "#30453" msgid "Overriden" msgstr "ProÅ¡le" msgctxt "#30454" msgid "Don't record" msgstr "Ne snimaj" msgctxt "#30455" msgid "Upcoming manual" msgstr "Nadolazeće ruÄno" msgctxt "#30456" msgid "Zombie" msgstr "Zombi" msgctxt "#30457" msgid "Alternative" msgstr "Alternativno" msgctxt "#30458" msgid "Currently recorded" msgstr "Trenutno snimljeno" msgctxt "#30459" msgid "Expired recording" msgstr "Isteklo snimanje" msgctxt "#30460" msgid "Manual" msgstr "RuÄno" msgctxt "#30461" msgid "Record one" msgstr "Snimi jednom" msgctxt "#30462" msgid "Record weekly" msgstr "Snimi tjedno" msgctxt "#30463" msgid "Record daily" msgstr "Snimi dnevno" msgctxt "#30464" msgid "Record all" msgstr "Snimi sve" msgctxt "#30465" msgid "Record this" msgstr "Snimi ovo" msgctxt "#30466" msgid "Record series" msgstr "Snimi seriju" msgctxt "#30467" msgid "Search keyword" msgstr "Pretraži kljuÄnu rijeÄ" msgctxt "#30468" msgid "Search people" msgstr "Pretraži ljude" msgctxt "#30469" msgid "Rule disabled" msgstr "Pravilo onemogućeno" msgctxt "#30501" msgid "Don't match duplicates" msgstr "Ne usporeÄ‘uj duplikate" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "UsporeÄ‘uj duplikate pomoću podnaslova" msgctxt "#30503" msgid "Match duplicates using description" msgstr "UsporeÄ‘uj duplikate pomoću opisa" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "UsporeÄ‘uj duplikate pomoću podnaslova i opisa" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "UsporeÄ‘uj duplikate pomoću podnaslova zatim opisa" msgctxt "#30506" msgid "Recordings never expire" msgstr "Snimanje nikada ne istjeÄe" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Dopusti istek snimanja" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "Zadrži do %d snimka" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "Zadrži %d najnovijih i ukloni stare" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.hu_hu/000077500000000000000000000000001360567320200273565ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.hu_hu/strings.po000066400000000000000000000237711360567320200314210ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Hungarian (Hungary) (http://www.transifex.com/projects/p/kodi-main/language/hu_HU/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: hu_HU\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "MythTV háttér-kiszolgáló Kiszolgálónév vagy IP cím " msgctxt "#30001" msgid "MythTV Backend Port" msgstr "MythTV háttér-kiszolgáló port" msgctxt "#30002" msgid "MythTV Database Username" msgstr "MythTV adatbázis felhasználónév" msgctxt "#30003" msgid "MythTV Database Password" msgstr "MythTV adatbázis jelszó" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "MythTV adatbázis név" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Többletinformáció írása a naplóba" msgctxt "#30006" msgid "Enable Live TV" msgstr "ÉlÅ‘ TV engedélyezése" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Az élÅ‘ TV elmozdíthatja az ütemezett műsorokat" msgctxt "#30008" msgid "Conflict handling" msgstr "Konfliktuskezelés" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "ÉlÅ‘ tévé elÅ‘nyben részesítése felvételkor" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Felvétel elÅ‘nyben részesítése, ÉlÅ‘ tv megállítása" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "ÉlÅ‘ tévé elÅ‘nyben részesítése és a felvételi konfliktus törlése" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "MythTV háttérkiszolgáló ethernet cím (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "MythTV háttér-kiszolgáló port az API szolgáltatáshoz" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "MythTV Biztonsági PIN az API szolgáltatáshoz" msgctxt "#30019" msgid "General" msgstr "Menük" msgctxt "#30020" msgid "Template provider" msgstr "Minta szolgáltató" msgctxt "#30021" msgid "Internal" msgstr "BelsÅ‘" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "BelsÅ‘ minta" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Metaadatok automatikus átnézése" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Új felvételek megjelölése" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Új felvételek átkódolása" msgctxt "#30029" msgid "Run User Job #1" msgstr "User Job #1 futtatása" msgctxt "#30030" msgid "Run User Job #2" msgstr "User Job #2 futtatása" msgctxt "#30031" msgid "Run User Job #3" msgstr "User Job #3 futtatása" msgctxt "#30032" msgid "Run User Job #4" msgstr "User Job #4 futtatása" msgctxt "#30033" msgid "Transcoder" msgstr "Ãtkódoló" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Engedélyezed a felvételek lejártát" msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "Kérdezzen a megtekintett felvétel törlése elÅ‘tt" msgctxt "#30049" msgid "Recording template" msgstr "Felvétel minta" msgctxt "#30050" msgid "Advanced" msgstr "Haladó" msgctxt "#30051" msgid "Preferences" msgstr "Beállítások" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Az MPEG-TS adatfolyamok szétválasztásának engedélyezése" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Késleltetés állítása (mp)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Csoport felvételek cím szerint" msgctxt "#30055" msgid "Always" msgstr "Mindig" msgctxt "#30056" msgid "Only for series" msgstr "Csak sorozatoknál" msgctxt "#30057" msgid "Never" msgstr "Soha" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Reklámok átugrásának engedélyezése (EDL)" msgctxt "#30059" msgid "Always" msgstr "Mindig" msgctxt "#30060" msgid "Dialog" msgstr "Párbeszéd" msgctxt "#30061" msgid "Never" msgstr "Soha" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Háttérszolgáltatás leállításának lehetÅ‘vé" msgctxt "#30063" msgid "Enable channel icons" msgstr "Csatorna ikonok engedélyezése" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Felvételhez Fanart/bélyegkép engedéyezése" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "Csatornahangolási kísérletek korlátozása" msgctxt "#30066" msgid "Show inactive upcomings (alternative/recorded/expired)" msgstr "Inaktív hamarosan érkezÅ‘k megjelenítése (alternatív/rögzített/lejárt)" msgctxt "#30067" msgid "Show LiveTV recordings" msgstr "LiveTV felvételek megjelenítése" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Protokoll verzió: %i – Adatbázis verzió: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "EDL engedélyezése" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "ElérhetÅ‘ reklám kivágás lista.\nBekapcsolja az EDL funkciót ehhez az adáshoz?" msgctxt "#30112" msgid "Connection failed" msgstr "Kapcsolódás sikertelen" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "Megpróbálod újra?" msgctxt "#30300" msgid "Failed to connect the MythTV backend with the known protocol versions. Please check the compatibility map of the addon and upgrade your backend to a supported version." msgstr "Sikertelen kapcsolódás a MythTV háttérrendszeréhez az ismert protokoll verziókon keresztül. EllenÅ‘rizze a bÅ‘vítmény kompatibilitási térképét, és frissítse a háttérrendszert a támogatott verzióra. " msgctxt "#30301" msgid "Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. The PIN code has to be configured in your backend to allow connection." msgstr "Sikertelen kapcsolódás a MythTV API szolgáltatásához. EllenÅ‘rizze a PIN kódját, vagy a háttérrendszer beállításokat. A háttérrendszerben a PIN-t be kell állítani a kapcsolódáshoz." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "A kapcsolat a MythTV-vel megszakadt" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "A kapcsolat a MythTV-vel visszaállt" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "A MythTV nem válaszol" msgctxt "#30305" msgid "Channel unavailable" msgstr "A csatorna nem elérhetÅ‘" msgctxt "#30306" msgid "Recorder unavailable" msgstr "FelvevÅ‘ nem elérhetÅ‘" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Felvételi konfliktus törlése: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "ÉlÅ‘ tv megállítása és a felvételi konfliktus törlése : %s" msgctxt "#30309" msgid "Not recording" msgstr "Nem vesz fel" msgctxt "#30310" msgid "Enabled" msgstr "Engedélyezve" msgctxt "#30311" msgid "Disabled" msgstr "Letiltva" msgctxt "#30312" msgid "No broadcast found" msgstr "Nem található adás" msgctxt "#30411" msgid "Delete and re-record" msgstr "Törlés és újra-felvétel" msgctxt "#30412" msgid "Keep recording" msgstr "Felvétel megtartása" msgctxt "#30421" msgid "Toggle display of alternative/recorded/expired" msgstr "Alternatív/rögzített/lejárt adások megjelenítése be/ki" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "Csatornaikon gyorsítótár frissítése" msgctxt "#30423" msgid "Trigger channels update" msgstr "Csatornák frissítése" msgctxt "#30424" msgid "Show status of scheduling" msgstr "Ütemezés állapotának megtekintése" msgctxt "#30451" msgid "Unhandled" msgstr "Nem kezelt" msgctxt "#30452" msgid "Upcoming" msgstr "Hamarosan" msgctxt "#30453" msgid "Overriden" msgstr "Felülbírált" msgctxt "#30454" msgid "Don't record" msgstr "Ne rögzítse" msgctxt "#30455" msgid "Upcoming manual" msgstr "Hamarosan kézi" msgctxt "#30456" msgid "Zombie" msgstr "Zombi" msgctxt "#30457" msgid "Alternative" msgstr "Alternatívák" msgctxt "#30458" msgid "Currently recorded" msgstr "Mostanában rögzített" msgctxt "#30459" msgid "Expired recording" msgstr "Lejárt felvétel" msgctxt "#30460" msgid "Manual" msgstr "Kézi" msgctxt "#30461" msgid "Record one" msgstr "Rögzítés egyszer" msgctxt "#30462" msgid "Record weekly" msgstr "Rögzítés hetente" msgctxt "#30463" msgid "Record daily" msgstr "Rögzítés naponta" msgctxt "#30464" msgid "Record all" msgstr "Mind rögzítése" msgctxt "#30465" msgid "Record this" msgstr "Rögzítse ezt" msgctxt "#30466" msgid "Record series" msgstr "Sorozatok rögzítése" msgctxt "#30467" msgid "Search keyword" msgstr "Keresés kulcsszóra" msgctxt "#30468" msgid "Search people" msgstr "Emberek keresése" msgctxt "#30469" msgid "Rule disabled" msgstr "Szabály kikapcsolva" msgctxt "#30501" msgid "Don't match duplicates" msgstr "Ne egyeztesse a duplikációkat" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "Egyeztesse a duplikációkat felirat alapján" msgctxt "#30503" msgid "Match duplicates using description" msgstr "Egyeztesse a duplikációkat leírás alapját" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "Egyeztesse a duplikációkat felirat és leírás alapján" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "Egyeztesse a duplikációkat elÅ‘ször felirat, majd leírás alapján" msgctxt "#30506" msgid "Recordings never expire" msgstr "Felvételek nem évülnek el" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Engedélyezed a felvételek lejártát" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "Maximum %d megtartása" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "%d legújabb megtartása csak" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.hy_am/000077500000000000000000000000001360567320200273435ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.hy_am/strings.po000066400000000000000000000014621360567320200313770ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Armenian (Armenia) (http://www.transifex.com/projects/p/kodi-main/language/hy_AM/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: hy_AM\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30019" msgid "General" msgstr "Ô³Õ¬Õ­Õ¡Õ¾Õ¸Ö€" msgctxt "#30310" msgid "Enabled" msgstr "Õ„Õ«Õ¡ÖÕ¾Õ¡Õ®" msgctxt "#30460" msgid "Manual" msgstr "ÕÕ¥Õ¼Ö„Õ¸Õ¾" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.id_id/000077500000000000000000000000001360567320200273165ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.id_id/strings.po000066400000000000000000000143541360567320200313560ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Indonesian (Indonesia) (http://www.transifex.com/projects/p/kodi-main/language/id_ID/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: id_ID\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "Hostname atau IP Backend MythTV" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "Port Backend MythTV" msgctxt "#30002" msgid "MythTV Database Username" msgstr "Nama pengguna Database MythTV" msgctxt "#30003" msgid "MythTV Database Password" msgstr "Kata Kunci Database MythTV" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "Nama Database MythTV" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Sertakan informasi debug yang lebih banyak ke dalam berkas log" msgctxt "#30006" msgid "Enable Live TV" msgstr "Aktifkan Siaran TV Langsung" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Perbolehkan Siaran TV Langsung mengeser acara terjadwal" msgctxt "#30008" msgid "Conflict handling" msgstr "Penanganan Konflik" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Utamakan Siaran Langsung TV ketika perekaman mempunyai slot nanti." msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Utamakan perekaman dan hentikan Siaran Langsung TV." msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Utamakan Siaran Langsung TV dan batalkan perekaman yang bertabrakan" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "Alamat Ethernet Backend MythTV (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "Port Backend MythTV untuk layanan API" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "Pin Keamanan MythTV untuk layanan API" msgctxt "#30019" msgid "General" msgstr "Umum" msgctxt "#30020" msgid "Template provider" msgstr "Penyedia Templat" msgctxt "#30021" msgid "Internal" msgstr "Internal" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "Templat Internal" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Otomatis mencari metadata" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Deteksi iklan untuk rekaman baru" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Transkode rekaman baru" msgctxt "#30029" msgid "Run User Job #1" msgstr "Jalankan pekerjaan pengguna #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Jalankan pekerjaan pengguna #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Jalankan pekerjaan pengguna #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Jalankan pekerjaan pengguna #4" msgctxt "#30033" msgid "Transcoder" msgstr "Transkoder" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Perbolehkan rekaman untuk kedaluwarsa" msgctxt "#30049" msgid "Recording template" msgstr "Templat Rekaman" msgctxt "#30050" msgid "Advanced" msgstr "Tingkat Lanjut" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Aktifkan demuksing MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Penalaan tunda (detik)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Kelompokan rekaman dengan judul" msgctxt "#30055" msgid "Always" msgstr "Selalu" msgctxt "#30056" msgid "Only for series" msgstr "Hanya untuk seri" msgctxt "#30057" msgid "Never" msgstr "Tidak Pernah" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Aktifkan lompatan komersial (EDL)" msgctxt "#30059" msgid "Always" msgstr "Selalu" msgctxt "#30060" msgid "Dialog" msgstr "dialog" msgctxt "#30061" msgid "Never" msgstr "Tidak Pernah" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Izinkan penutupan backend" msgctxt "#30063" msgid "Enable channel icons" msgstr "Aktifkan ikon channel" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Aktifkan fanart / gambar mini rekaman" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "Batas upaya pencarian kanal" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Versi Protokol: %i - Versi Database: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "Mengaktifkan EDL" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "Sebuah daftar potong atau lompatan komersial telah ditemukan.\nApakah anda ingin mengaktifkan fungsi EDL untuk acara ini ?" msgctxt "#30112" msgid "Connection failed" msgstr "Koneksi Gagal" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "Anda ingin mencoba kembali?" msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Koneksi ke backend MythTV terputus" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Koneksi ke MythTV tersambung kembali" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "Tidak ada respon dari backend MythTV" msgctxt "#30305" msgid "Channel unavailable" msgstr "Saluran tak tersedia" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Perekam tidak tersedia" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Batalkan rekaman yang bertabrakan: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Hentikan Siaran Langsung TV karena bertabrakan dengan perekaman: %s" msgctxt "#30309" msgid "Not recording" msgstr "Tidak merekam" msgctxt "#30310" msgid "Enabled" msgstr "Aktifkan" msgctxt "#30311" msgid "Disabled" msgstr "Non Aktif" msgctxt "#30312" msgid "No broadcast found" msgstr "Tidak ada siaran yang ditemukan" msgctxt "#30411" msgid "Delete and re-record" msgstr "Hapus dan rekam ulang" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "Perbarui cache untuk ikon kanal" msgctxt "#30460" msgid "Manual" msgstr "Manual" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Perbolehkan rekaman untuk kedaluwarsa" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.is_is/000077500000000000000000000000001360567320200273545ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.is_is/strings.po000066400000000000000000000237111360567320200314110ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Icelandic (Iceland) (http://www.transifex.com/projects/p/kodi-main/language/is_IS/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: is_IS\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "Hýsilnafn MythTV bakenda eða IP" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "Gátt MythTV bakenda" msgctxt "#30002" msgid "MythTV Database Username" msgstr "Notandanafn MythTV gagnagrunns" msgctxt "#30003" msgid "MythTV Database Password" msgstr "Lykilorð MythTV gagnagrunns" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "Nafn MythTV gangagrunns" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Ãtarlegri villukembiupplýsingar í atvikaskránni" msgctxt "#30006" msgid "Enable Live TV" msgstr "Virkja beina útsendingu" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Leyfa beinum útsendingum að færa til dagskrárliði sem eru komnir á dagskrá" msgctxt "#30008" msgid "Conflict handling" msgstr "Meðhöndlun árekstra" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Kjósa frekar beina útsendingu þegar upptaka er áætluð síðar" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Kjósa upptöku og stöðva beina útsendingu" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Kjósa beina útsendingu og hætta við upptöku sem rekst á" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "Ethernet vistfang MythTV bakenda (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "Gátt MythTV bakenda fyrir API þjónustur" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "MythTV Öryggiskóði fyrir API þjónustur" msgctxt "#30019" msgid "General" msgstr "Almennt" msgctxt "#30020" msgid "Template provider" msgstr "Veita sniðmáts" msgctxt "#30021" msgid "Internal" msgstr "Innbyggt" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "Innbyggt sniðmát" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Leita sjálfvirkt að lýsigögnum" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Auglýsinga-merkja nýjar upptökur" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Umkóða nýjar upptökur" msgctxt "#30029" msgid "Run User Job #1" msgstr "Keyra Notandaverk #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Keyra Notandaverk #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Keyra Notandaverk #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Keyra Notandaverk #4" msgctxt "#30033" msgid "Transcoder" msgstr "Umkóðari" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Leyfa upptökum að renna út?" msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "Bjóðast til að eyða skoðaðri upptöku" msgctxt "#30048" msgid "Show 'Original Airdate' instead of 'Recording Time'" msgstr "Birta upprunalegan útsendingartíma í stað upptökutíma" msgctxt "#30049" msgid "Recording template" msgstr "Sniðmát upptakna" msgctxt "#30050" msgid "Advanced" msgstr "Ãtarlegt" msgctxt "#30051" msgid "Preferences" msgstr "Kjörstillingar" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Virkja MPEG-TS demuxing" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Seinkun á rásaskiptingu (sek)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Hópa saman upptökum eftir titlum" msgctxt "#30055" msgid "Always" msgstr "Alltaf" msgctxt "#30056" msgid "Only for series" msgstr "Aðeins fyrir þáttaraðir" msgctxt "#30057" msgid "Never" msgstr "Aldrei" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Virkja að hoppa yfir auglýsingar (EDL)" msgctxt "#30059" msgid "Always" msgstr "Alltaf" msgctxt "#30060" msgid "Dialog" msgstr "Gluggi" msgctxt "#30061" msgid "Never" msgstr "Aldrei" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Leyfa að slökkt sé á bakenda" msgctxt "#30063" msgid "Enable channel icons" msgstr "Gera táknmyndir rása virkar" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Virkja upptöku aðdáendamynda/smámynda" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "Takmarka fjölda tilrauna til rásaleitar" msgctxt "#30066" msgid "Show inactive upcomings (alternative/recorded/expired)" msgstr "Birta óvirkt á næstunni ('til vara'/'tekið upp'/'útrunnið')" msgctxt "#30067" msgid "Show LiveTV recordings" msgstr "Sýna upptökur á beinum útsendingum" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Útgáfa samskiptareglna: %i - Útgáfa gagnagrunns: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "Virkja að sleppa auglýsingum (EDL)" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "Skynjaði lista yfir klippingar á upptökum eða hopp yfir auglýsingar.\nViltu virkja að sleppa auglýsingum (EDL) fyrir þetta efni ?" msgctxt "#30112" msgid "Connection failed" msgstr "Tenging mistókst" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "Viltu reyna aftur?" msgctxt "#30300" msgid "Failed to connect the MythTV backend with the known protocol versions. Please check the compatibility map of the addon and upgrade your backend to a supported version." msgstr "Mistókst að tengja MythTV-bakendann við útgáfur þekktra samskiptamáta. Athugaðu samhæfingarvörpun viðbótarinnar og uppfærðu bakendann í studda útgáfu." msgctxt "#30301" msgid "Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. The PIN code has to be configured in your backend to allow connection." msgstr "Mistókst að tengja API-þjónustur MythTV-bakenda. Athugaðu PIN-númerið þitt og uppsetningu bakendans. PIN-númerið þarf að vera stillt í bakendanum til að tenging geti komist á." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Tenging við MythTV bakenda rofnaði" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Tenging við MythTV bakenda endurheimt" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "Engin svörun frá M;ythTV bakenda" msgctxt "#30305" msgid "Channel unavailable" msgstr "Rás ekki tiltæk" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Upptökutæki ekki tiltækt" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Hætta við upptöku sem rekst á: " msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Stöðva beina útsendingu vegna upptöku sem rekst á: %s" msgctxt "#30309" msgid "Not recording" msgstr "Ekki að taka upp" msgctxt "#30310" msgid "Enabled" msgstr "Virkt" msgctxt "#30311" msgid "Disabled" msgstr "Óvirkt" msgctxt "#30312" msgid "No broadcast found" msgstr "Engin útsending fannst" msgctxt "#30411" msgid "Delete and re-record" msgstr "Eyða og taka upp aftur" msgctxt "#30412" msgid "Keep recording" msgstr "Halda upptöku" msgctxt "#30421" msgid "Toggle display of alternative/recorded/expired" msgstr "Víxla birtingu á 'til vara'/'tekið upp'/'útrunnið'" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "Uppfæra flýtiminni fyrir táknmyndir rása" msgctxt "#30423" msgid "Trigger channels update" msgstr "Gangsetja uppfærslu rása" msgctxt "#30424" msgid "Show status of scheduling" msgstr "Birta stöðu áætlunar" msgctxt "#30451" msgid "Unhandled" msgstr "Ómeðhöndlað" msgctxt "#30452" msgid "Upcoming" msgstr "à næstunni" msgctxt "#30453" msgid "Overriden" msgstr "Yfirtekið" msgctxt "#30454" msgid "Don't record" msgstr "Ekki taka upp" msgctxt "#30455" msgid "Upcoming manual" msgstr "à næstunni handvirkt" msgctxt "#30456" msgid "Zombie" msgstr "Draugur" msgctxt "#30457" msgid "Alternative" msgstr "Til vara" msgctxt "#30458" msgid "Currently recorded" msgstr "Þegar tekið upp" msgctxt "#30459" msgid "Expired recording" msgstr "Útrunnin upptaka" msgctxt "#30460" msgid "Manual" msgstr "Handvirkt" msgctxt "#30461" msgid "Record one" msgstr "Taka upp einn" msgctxt "#30462" msgid "Record weekly" msgstr "Taka upp vikulega" msgctxt "#30463" msgid "Record daily" msgstr "Taka upp daglega" msgctxt "#30464" msgid "Record all" msgstr "Taka allt upp" msgctxt "#30465" msgid "Record this" msgstr "Taka þetta upp" msgctxt "#30466" msgid "Record series" msgstr "Taka upp þáttaröð" msgctxt "#30467" msgid "Search keyword" msgstr "Leita að stikkorði" msgctxt "#30468" msgid "Search people" msgstr "Leita að fólki" msgctxt "#30469" msgid "Rule disabled" msgstr "Regla óvirk" msgctxt "#30501" msgid "Don't match duplicates" msgstr "Ekki samsvara tvítökum" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "Samsvara tvítökum með skjátexta" msgctxt "#30503" msgid "Match duplicates using description" msgstr "Samsvara tvítökum með lýsingu" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "Samsvara tvítökum með skjátexta og lýsingu" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "Samsvara tvítökum með skjátexta og síðan lýsingu" msgctxt "#30506" msgid "Recordings never expire" msgstr "Upptökur verða aldrei útrunnar" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Leyfa upptökum að renna út?" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "Halda allt að %d upptökum" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "Halda %d nýjustu og úrelda þær eldri" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.it_it/000077500000000000000000000000001360567320200273565ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.it_it/strings.po000066400000000000000000000242741360567320200314200ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Italian (Italy) (http://www.transifex.com/projects/p/kodi-main/language/it_IT/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it_IT\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "Hostname o indirizzo IP per il pannello di amministrazione di MythTV" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "Porta del pannello di amministrazione di MythTV" msgctxt "#30002" msgid "MythTV Database Username" msgstr "Username del database di MythTV" msgctxt "#30003" msgid "MythTV Database Password" msgstr "Password del database di MythTV" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "Nome del database di MythTV" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Includi maggiori informazioni di debug nel file di log" msgctxt "#30006" msgid "Enable Live TV" msgstr "Attiva la TV Live" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Consenti a TV Live di spostare gli spettacoli programmati" msgctxt "#30008" msgid "Conflict handling" msgstr "Gestione conflitto" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Preferisci la TV dal Vivo quando la registrazione è spostata" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Preferisci la registrazione e ferma la TV dal Vivo" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Preferisci Live TV e cancella le registrazioni incompatibili" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "Indirizzo ethernet backend MythTV (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "Porta Backend MythTV per servizi API" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "Pin di sicurezza MythTV per servizi API" msgctxt "#30019" msgid "General" msgstr "Menu" msgctxt "#30020" msgid "Template provider" msgstr "Fornitore modello" msgctxt "#30021" msgid "Internal" msgstr "Interno" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "Modello interno" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Guarda automaticamente i Metadata" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Nuove registrazioni bandiere commerciali" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Transcodifica nuove registrazioni" msgctxt "#30029" msgid "Run User Job #1" msgstr "Esegui Processo User #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Esegui Processo User #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Esegui Processo User #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Esegui Processo User #4" msgctxt "#30033" msgid "Transcoder" msgstr "Transcodificatore" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Permetti alle registrazioni di scadere" msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "Scegliere per cancellare le registrazioni visualizzate" msgctxt "#30048" msgid "Show 'Original Airdate' instead of 'Recording Time'" msgstr "Mostra 'Data di messa in onda originale' invece di 'Ora di registrazione'" msgctxt "#30049" msgid "Recording template" msgstr "Modello registrazione" msgctxt "#30050" msgid "Advanced" msgstr "Avanzate" msgctxt "#30051" msgid "Preferences" msgstr "Preferenze" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Abilita demuxing MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Ritardo regolazione (sec)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Raggruppa registrazioni per titolo" msgctxt "#30055" msgid "Always" msgstr "Sempre" msgctxt "#30056" msgid "Only for series" msgstr "Solo per le serie" msgctxt "#30057" msgid "Never" msgstr "Mai" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Abilita il salto della pubblicità (EDL)" msgctxt "#30059" msgid "Always" msgstr "Sempre" msgctxt "#30060" msgid "Dialog" msgstr "Dialogo" msgctxt "#30061" msgid "Never" msgstr "Mai" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Consenti chiusura backend" msgctxt "#30063" msgid "Enable channel icons" msgstr "Abilita icone canale" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Abilita fanart/thumbnails per le registrazioni" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "Limite i tentativi di regolazione" msgctxt "#30066" msgid "Show inactive upcomings (alternative/recorded/expired)" msgstr "Mostra tutte le ultime inattività (alternativi/registrati/scaduti)" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Versione Protocollo: %i - Versione Database: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "Abilitazione EDL" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "E' stata trovata una lista di tagli o di salti di pubblicità.\nDesideri attivare la funzionalità EDL per questa serie?" msgctxt "#30112" msgid "Connection failed" msgstr "Connessione fallita" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "Vuoi riprovare?" msgctxt "#30300" msgid "Failed to connect the MythTV backend with the known protocol versions. Please check the compatibility map of the addon and upgrade your backend to a supported version." msgstr "Connessione al backend MythTV fallita con le versioni conosciute del protocollo. Controlla la mappa compatibilità dell'Add-on e aggiorna il backend a una versione supportata." msgctxt "#30301" msgid "Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. The PIN code has to be configured in your backend to allow connection." msgstr "Connessione ai servizi API di MythTV fallita. Controlla il tuo codice PIN o la configurazione del backend. Il codice PIN deve essere configurato nel tuo backend per permettere la connessione." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Connessione al backend MythTV persa" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Connessione a MythTV ripristinata" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "Nessuna risposta dal backend di MythTV" msgctxt "#30305" msgid "Channel unavailable" msgstr "Canale non disponibile" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Registratore non disponibile" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Eliminazione delle registrazioni incompatibili: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Blocco di Live TV a causa di registrazioni incompatibili: %s" msgctxt "#30309" msgid "Not recording" msgstr "Nessuna registrazione in corso" msgctxt "#30310" msgid "Enabled" msgstr "Abilitato" msgctxt "#30311" msgid "Disabled" msgstr "Disabilitato" msgctxt "#30312" msgid "No broadcast found" msgstr "Nessuna trasmissione trovata" msgctxt "#30411" msgid "Delete and re-record" msgstr "Elimina e registra di nuovo" msgctxt "#30412" msgid "Keep recording" msgstr "Mantieni registrazione" msgctxt "#30421" msgid "Toggle display of alternative/recorded/expired" msgstr "Alterna la visualizzazione di alternativi/registrati/scaduti" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "Ricarica la cache per le icone dei canali" msgctxt "#30423" msgid "Trigger channels update" msgstr "Impostazioni aggiornamento canali" msgctxt "#30424" msgid "Show status of scheduling" msgstr "Mostra stato operazioni pianificate" msgctxt "#30425" msgid "Show status of recording" msgstr "Mostra stato della registrazione" msgctxt "#30426" msgid "Show status of broadcast" msgstr "Mostra stato della trasmissione" msgctxt "#30451" msgid "Unhandled" msgstr "Non gestito" msgctxt "#30452" msgid "Upcoming" msgstr "Prossimamente" msgctxt "#30453" msgid "Overriden" msgstr "Sovrascritto" msgctxt "#30454" msgid "Don't record" msgstr "Non registrare" msgctxt "#30455" msgid "Upcoming manual" msgstr "Manuale imminente" msgctxt "#30456" msgid "Zombie" msgstr "Zombie" msgctxt "#30457" msgid "Alternative" msgstr "Alternativi" msgctxt "#30458" msgid "Currently recorded" msgstr "In Registrazione" msgctxt "#30459" msgid "Expired recording" msgstr "Registrazione scaduta" msgctxt "#30460" msgid "Manual" msgstr "Manuale" msgctxt "#30461" msgid "Record one" msgstr "Registra una" msgctxt "#30462" msgid "Record weekly" msgstr "Registra settimanalmente" msgctxt "#30463" msgid "Record daily" msgstr "Registra giornalmente" msgctxt "#30464" msgid "Record all" msgstr "Registra tutto" msgctxt "#30465" msgid "Record this" msgstr "Registra questo" msgctxt "#30466" msgid "Record series" msgstr "Registra serie" msgctxt "#30467" msgid "Search keyword" msgstr "Cerca parola chiave" msgctxt "#30468" msgid "Search people" msgstr "Cerca persone" msgctxt "#30469" msgid "Rule disabled" msgstr "Regola disabilitata" msgctxt "#30501" msgid "Don't match duplicates" msgstr "Non confrontare i duplicati" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "Confronta i duplicati usando il sottotitolo" msgctxt "#30503" msgid "Match duplicates using description" msgstr "Confronta i duplicati usando la descrizione" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "Confronta i duplicati usando il sottotitolo e la descrizione" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "Confronta i duplicati usando il sottotitolo e poi la descrizione" msgctxt "#30506" msgid "Recordings never expire" msgstr "Le registrazioni non scadono mai" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Permetti alle registrazioni di scadere" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "Mantieni fino a %d registrazioni" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "Mantieni %d recenti e lascia scadere quelle vecchie" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.ja_jp/000077500000000000000000000000001360567320200273315ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.ja_jp/strings.po000066400000000000000000000144561360567320200313740ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Japanese (Japan) (http://www.transifex.com/projects/p/kodi-main/language/ja_JP/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ja_JP\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "MythTV ãƒãƒƒã‚¯ã‚¨ãƒ³ãƒ‰ã®ãƒ›ã‚¹ãƒˆåã¾ãŸã¯IPアドレス" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "MythTV ãƒãƒƒã‚¯ã‚¨ãƒ³ãƒ‰ã®ãƒãƒ¼ãƒˆç•ªå·" msgctxt "#30002" msgid "MythTV Database Username" msgstr "MythTV データベースã®ãƒ¦ãƒ¼ã‚¶å" msgctxt "#30003" msgid "MythTV Database Password" msgstr "MythTV データベースã®ãƒ‘スワード" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "MythTV データベースå" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "ãƒ­ã‚°ãƒ•ã‚¡ã‚¤ãƒ«ã«æ›´ã«è©³ã—ã„デãƒãƒƒã‚°æƒ…報をå«ã‚ã‚‹" msgctxt "#30006" msgid "Enable Live TV" msgstr "Live TV を有効ã«" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Live TvãŒã‚¹ã‚±ã‚¸ãƒ¥ãƒ¼ãƒ«ã•れãŸã‚·ãƒ§ãƒ¼ã®ç§»å‹•を許å¯ã™ã‚‹" msgctxt "#30008" msgid "Conflict handling" msgstr "コンフリクトã®å‡¦ç†" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "録画用ã®ã‚¹ãƒ­ãƒƒãƒˆãŒã‚ã‚‹é™ã‚Šã€ãƒ†ãƒ¬ãƒ“放é€ã‚’優先ã™ã‚‹" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "録画を優先ã—ã¦ã€ãƒ†ãƒ¬ãƒ“放é€è¦–è´ã‚’æ­¢ã‚ã‚‹" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "テレビ放é€è¦–è´ã‚’優先ã—ã¦ã€ç«¶åˆã™ã‚‹éŒ²ç”»ã‚’中止ã™ã‚‹" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "MythTV ãƒãƒƒã‚¯ã‚¨ãƒ³ãƒ‰ã®ã‚¤ãƒ¼ã‚µãƒãƒƒãƒˆã‚¢ãƒ‰ãƒ¬ã‚¹ (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "APIサービスã®MythTVãƒãƒƒã‚¯ã‚¨ãƒ³ãƒ‰ãƒãƒ¼ãƒˆ" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "APIサービスã®MythTVセキュリティピン" msgctxt "#30019" msgid "General" msgstr "一般" msgctxt "#30020" msgid "Template provider" msgstr "テンプレートæä¾›" msgctxt "#30021" msgid "Internal" msgstr "内部" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "内部テンプレート" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "メタデータを自動ã§ãƒ­ãƒƒã‚¯" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "æ–°ã—ã„録画ã§CM検知ã™ã‚‹" msgctxt "#30028" msgid "Transcode new recordings" msgstr "æ–°ã—ã„録音をトランスコード" msgctxt "#30029" msgid "Run User Job #1" msgstr "ユーザージョブ #1 を実行" msgctxt "#30030" msgid "Run User Job #2" msgstr "ユーザージョブ #2 を実行" msgctxt "#30031" msgid "Run User Job #3" msgstr "ユーザージョブ #3 を実行" msgctxt "#30032" msgid "Run User Job #4" msgstr "ユーザージョブ #4 を実行" msgctxt "#30033" msgid "Transcoder" msgstr "トランスコーダー" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "éŒ²éŸ³ã®æœŸé™åˆ‡ã‚Œã‚’許å¯ã—ã¾ã™ã‹" msgctxt "#30049" msgid "Recording template" msgstr "録画ã®ãƒ†ãƒ³ãƒ—レート" msgctxt "#30050" msgid "Advanced" msgstr "高度ãªè¨­å®š" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "MPEG-TS 分離を有効" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "åŒèª¿é…å»¶ (ç§’)" msgctxt "#30054" msgid "Group recordings by title" msgstr "タイトルã§ã‚°ãƒ«ãƒ¼ãƒ—化" msgctxt "#30055" msgid "Always" msgstr "常ã«" msgctxt "#30056" msgid "Only for series" msgstr "シリーズã®ã¿" msgctxt "#30057" msgid "Never" msgstr "使用ã—ãªã„" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "CMスキップ(EDL)有効" msgctxt "#30059" msgid "Always" msgstr "常ã«" msgctxt "#30060" msgid "Dialog" msgstr "メッセージ" msgctxt "#30061" msgid "Never" msgstr "使用ã—ãªã„" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "ãƒãƒƒã‚¯ã‚¨ãƒ³ãƒ‰ã®é›»æºåˆ‡æ–­ã‚’許å¯ã™ã‚‹" msgctxt "#30063" msgid "Enable channel icons" msgstr "ãƒãƒ£ãƒ³ãƒãƒ« アイコン を有効" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "録画ã«é–¢ã™ã‚‹ç”»åƒãƒ»ã‚µãƒ ãƒãƒ¼ãƒ«æœ‰åй" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "プロトコルã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³: %i - データベースã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "EDL有効" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "カットリストもã—ãã¯CMスキップデータãŒã‚りã¾ã™ã€‚\nEDL機能を利用ã—ã¾ã™ã‹?" msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "MythTVãƒãƒƒã‚¯ã‚¨ãƒ³ãƒ‰ã®æŽ¥ç¶šã‚’失ã£ãŸ" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "MythTVã®æŽ¥ç¶šãŒå¾©å…ƒã•れãŸ" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "MythTVãƒãƒƒã‚¯ã‚¨ãƒ³ãƒ‰ã‹ã‚‰å¿œç­”ãŒã‚りã¾ã›ã‚“" msgctxt "#30305" msgid "Channel unavailable" msgstr "ãƒãƒ£ãƒ³ãƒãƒ«åˆ©ç”¨ä¸å¯" msgctxt "#30306" msgid "Recorder unavailable" msgstr "レコーダーãŒä½¿ç”¨ã§ããªã„" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "ç«¶åˆã™ã‚‹éŒ²ç”»ã‚’中止ã—ã¦ã„ã¾ã™ : %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "録画ã¨ç«¶åˆã™ã‚‹ãŸã‚テレビ放é€è¦–è´ã‚’åœæ­¢ã—ã¾ã—㟠: %s" msgctxt "#30309" msgid "Not recording" msgstr "録画ã—ãªã„" msgctxt "#30310" msgid "Enabled" msgstr "有効" msgctxt "#30311" msgid "Disabled" msgstr "無効" msgctxt "#30312" msgid "No broadcast found" msgstr "放é€ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" msgctxt "#30411" msgid "Delete and re-record" msgstr "削除ã—ã¦å†éŒ²ç”»" msgctxt "#30460" msgid "Manual" msgstr "マニュアル" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "éŒ²éŸ³ã®æœŸé™åˆ‡ã‚Œã‚’許å¯ã—ã¾ã™ã‹" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.ko_kr/000077500000000000000000000000001360567320200273535ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.ko_kr/strings.po000066400000000000000000000214151360567320200314070ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Korean (Korea) (http://www.transifex.com/projects/p/kodi-main/language/ko_KR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ko_KR\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "MythTV 백엔드 호스트네임 ë˜ëŠ” IP 주소" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "MythTV 백엔드 í¬íЏ" msgctxt "#30002" msgid "MythTV Database Username" msgstr "MythTV ë°ì´í„°ë² ì´ìФ 사용ìžëª…" msgctxt "#30003" msgid "MythTV Database Password" msgstr "MythTV ë°ì´í„°ë² ì´ìФ 비밀번호" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "MythTV ë°ì´í„°ë² ì´ìФ ë°ì´í„°ë² ì´ìŠ¤ëª…" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "로그파ì¼ì— 추가 디버그 ì •ë³´ í¬í•¨" msgctxt "#30006" msgid "Enable Live TV" msgstr "ë¼ì´ë¸Œ TV 사용" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "ë¼ì´ë¸Œ TVê°€ ì˜ˆì•½ëœ í”„ë¡œê·¸ëž¨ì„ ì´ë™í•˜ë„ë¡ í—ˆìš©" msgctxt "#30008" msgid "Conflict handling" msgstr "ì¶©ëŒ ì²˜ë¦¬" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "ë…¹í™”ì‹œê°„ì´ ë” ëŠ¦ëŠ” 경우 ë¼ì´ë¸Œ TV ìš°ì„ " msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "ë¼ì´ë¸Œ TV를 멈추고 녹화 ìš°ì„ " msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "ì¶©ëŒí•˜ëŠ” 녹화를 취소하고 ë¼ì´ë¸Œ TV ìš°ì„ " msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "MythTV 백엔드 ì´ë”ë„· 주소 (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "MythTV 백엔드 í¬íЏ (API 서비스용)" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "API 서비스용 MythTV 보안 PIN" msgctxt "#30019" msgid "General" msgstr "ì¼ë°˜" msgctxt "#30020" msgid "Template provider" msgstr "템플릿 제공ìž" msgctxt "#30021" msgid "Internal" msgstr "ë‚´ë¶€ì˜" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "ë‚´ë¶€ 탬플릿" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "메타ë°ì´íƒ€ ìžë™ 조회" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "새 녹화 ê´‘ê³  플래그" msgctxt "#30028" msgid "Transcode new recordings" msgstr "새 녹화 트랜스코드" msgctxt "#30029" msgid "Run User Job #1" msgstr "ì‚¬ìš©ìž ìž‘ì—… #1 실행" msgctxt "#30030" msgid "Run User Job #2" msgstr "ì‚¬ìš©ìž ìž‘ì—… #2 실행" msgctxt "#30031" msgid "Run User Job #3" msgstr "ì‚¬ìš©ìž ìž‘ì—… #3 실행" msgctxt "#30032" msgid "Run User Job #4" msgstr "ì‚¬ìš©ìž ìž‘ì—… #4 실행" msgctxt "#30033" msgid "Transcoder" msgstr "트랜스코ë”" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "녹화 만료 허용" msgctxt "#30049" msgid "Recording template" msgstr "녹화 템플릿" msgctxt "#30050" msgid "Advanced" msgstr "고급" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "MPEG-TS 디먹싱 사용" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "íŠœë‹ ì§€ì—° (ì´ˆ)" msgctxt "#30054" msgid "Group recordings by title" msgstr "ì œëª©ì„ ê¸°ì¤€ìœ¼ë¡œ 그룹 녹화" msgctxt "#30055" msgid "Always" msgstr "í•­ìƒ" msgctxt "#30056" msgid "Only for series" msgstr "시리즈만" msgctxt "#30057" msgid "Never" msgstr "사용 안 함" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "ê´‘ê³  건너뛰기 사용 (EDL)" msgctxt "#30059" msgid "Always" msgstr "í•­ìƒ" msgctxt "#30060" msgid "Dialog" msgstr "대화창" msgctxt "#30061" msgid "Never" msgstr "사용 안 함" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "백엔드 종료 허용" msgctxt "#30063" msgid "Enable channel icons" msgstr "ì±„ë„ ì•„ì´ì½˜ 사용" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "녹화 팬아트/ì¸ë„¤ì¼ 사용" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "ì±„ë„ íŠœë‹ ì‹œë„수 제한" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "프로토콜 버전: %i - ë°ì´í„°ë² ì´ìФ 버전: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "EDL 사용" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "ì»· ëª©ë¡ ë˜ëŠ” ê´‘ê³  건너뛰기가 발견ë습니다.\nì´ ì‡¼ì— ëŒ€í•´ EDL ê¸°ëŠ¥ì„ ì‚¬ìš©í•˜ê² ìŠµë‹ˆê¹Œ?" msgctxt "#30112" msgid "Connection failed" msgstr "ì—°ê²° 실패" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "다시 시ë„하시겠습니까?" msgctxt "#30300" msgid "Failed to connect the MythTV backend with the known protocol versions. Please check the compatibility map of the addon and upgrade your backend to a supported version." msgstr "알려진 프로토콜 버젼과 MythTV 백엔드 ì—°ê²° 실패. ì• ë“œì˜¨ì˜ í˜¸í™˜ì„± ë§µì„ í™•ì¸í•˜ì‹œê³  ì§€ì›ë˜ëŠ” 버전으로 백엔드를 업그레ì´ë“œí•˜ì„¸ìš”." msgctxt "#30301" msgid "Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. The PIN code has to be configured in your backend to allow connection." msgstr "MythTV 백엔드 API 서비스 ì—°ê²° 실패. PIN 코드나 백엔드 ì…‹ì—…ì„ í™•ì¸í•˜ì„¸ìš”. 연결하려면 백엔드ì—서 PIN 코드가 설정ë˜ì–´ì•¼ 합니다." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "MythTV 백엔드 ì—°ê²° ëŠê¹€ " msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "MythTV 재 ì—°ê²° " msgctxt "#30304" msgid "No response from MythTV backend" msgstr "MythTV 백엔드로부터 ì‘답 ì—†ìŒ " msgctxt "#30305" msgid "Channel unavailable" msgstr "ì±„ë„ ì‚¬ìš©í•  수 ì—†ìŒ" msgctxt "#30306" msgid "Recorder unavailable" msgstr "녹화 í•  수 ì—†ìŒ " msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "ì¶©ëŒí•˜ëŠ” 녹화를 취소: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "녹화와 ì¶©ëŒí•˜ë¯€ë¡œ ë¼ì´ë¸Œ TV 중지: %s " msgctxt "#30309" msgid "Not recording" msgstr "녹화 중 아님" msgctxt "#30310" msgid "Enabled" msgstr "사용함" msgctxt "#30311" msgid "Disabled" msgstr "사용 안 함" msgctxt "#30312" msgid "No broadcast found" msgstr "방송 ì—†ìŒ" msgctxt "#30411" msgid "Delete and re-record" msgstr "지우고 다시 녹화" msgctxt "#30412" msgid "Keep recording" msgstr "ê³„ì† ë…¹í™”" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "ì±„ë„ ì•„ì´ì½˜ ìºì‹œ 새로 고침" msgctxt "#30423" msgid "Trigger channels update" msgstr "ì±„ë„ ì—…ë°ì´íЏ 트리거" msgctxt "#30424" msgid "Show status of scheduling" msgstr "예약 ìƒíƒœ 표시" msgctxt "#30451" msgid "Unhandled" msgstr "처리하지 않ìŒ" msgctxt "#30452" msgid "Upcoming" msgstr "예정ë¨" msgctxt "#30453" msgid "Overriden" msgstr "무시함" msgctxt "#30454" msgid "Don't record" msgstr "녹화하지 않ìŒ" msgctxt "#30455" msgid "Upcoming manual" msgstr "ì˜ˆì •ëœ ë§¤ë‰´ì–¼" msgctxt "#30456" msgid "Zombie" msgstr "좀비" msgctxt "#30460" msgid "Manual" msgstr "수ë™" msgctxt "#30461" msgid "Record one" msgstr "한 번 녹화" msgctxt "#30462" msgid "Record weekly" msgstr "매주 녹화" msgctxt "#30463" msgid "Record daily" msgstr "ë§¤ì¼ ë…¹í™”" msgctxt "#30464" msgid "Record all" msgstr "ëª¨ë‘ ë…¹í™”" msgctxt "#30465" msgid "Record this" msgstr "ì´ê²ƒ 녹화" msgctxt "#30466" msgid "Record series" msgstr "시리즈 녹화" msgctxt "#30467" msgid "Search keyword" msgstr "키워드 검색" msgctxt "#30468" msgid "Search people" msgstr "ì¸ë¬¼ 검색" msgctxt "#30501" msgid "Don't match duplicates" msgstr "중복 제외" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "ìžë§‰ 기준 중복 맞춤" msgctxt "#30503" msgid "Match duplicates using description" msgstr "설명 기준 중복 맞춤" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "ìžë§‰ê³¼ 설명 기준 중복 맞춤" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "ìžë§‰ 후 설명 기준 중복 맞춤" msgctxt "#30506" msgid "Recordings never expire" msgstr "녹화를 만료하지 않ìŒ" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "녹화 만료 허용" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "녹화 %d편만 ë³´ì¡´" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "최신 %d편만 보존하고 나머지는 만료" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.lt_lt/000077500000000000000000000000001360567320200273645ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.lt_lt/strings.po000066400000000000000000000243221360567320200314200ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Lithuanian (Lithuania) (http://www.transifex.com/projects/p/kodi-main/language/lt_LT/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: lt_LT\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "MythTV galinÄ—s sÄ…sajos serverio pavadinimas arba IP" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "MythTV galinÄ—s sÄ…sajos portas" msgctxt "#30002" msgid "MythTV Database Username" msgstr "MythTV galinÄ—s sÄ…sajos naudotojo vardas" msgctxt "#30003" msgid "MythTV Database Password" msgstr "MythTV galinÄ—s sÄ…sajos slaptažodis" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "MythTV galinÄ—s sÄ…sajos duomenų bazÄ—s pavadinimas" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Ä®traukti derinimo informacijÄ… žurnalo faile" msgctxt "#30006" msgid "Enable Live TV" msgstr "Ä®galinti Live TV" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Leisti Live TV perkelti į oficialų sÄ…rašą rodymui/naudojimui" msgctxt "#30008" msgid "Conflict handling" msgstr "Konfliktų valdymas" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Teikti pirmenybÄ™ TV transliacijai, kai yra vÄ—liau suplanuotas įraÅ¡ymas" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Teikti pirmenybÄ™ įraÅ¡ymui ir stabdyti TV transliacijÄ…" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Teikti pirmenybÄ™ TV transliacijai ir atÅ¡aukti konfliktuojantį įrašą" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "MythTV posistemÄ—s laidinio tinklo adresas (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "MythTV posistemÄ—s prievadas API paslaugoms" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "MythTV saugumo PIN kodas, skirtas API paslaugoms" msgctxt "#30019" msgid "General" msgstr "Pagrindinis" msgctxt "#30020" msgid "Template provider" msgstr "Å ablono tiekÄ—jas" msgctxt "#30021" msgid "Internal" msgstr "Vidinis" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "Vidinis Å¡ablonas" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "AutomatiÅ¡kai ieÅ¡koti metaduomenų" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Reklamos žymÄ— naujiems įraÅ¡ams" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Perkoduoti naujus įraÅ¡us" msgctxt "#30029" msgid "Run User Job #1" msgstr "Paleisti vartotojo darbÄ… #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Paleisti vartotojo darbÄ… #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Paleisti vartotojo darbÄ… #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Paleisti vartotojo darbÄ… #4" msgctxt "#30033" msgid "Transcoder" msgstr "Perkodavimas" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Leisti įraÅ¡ymu galiojimo laikÄ…" msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "PraÅ¡yti patvirtinti peržiÅ«rÄ—to įraÅ¡o trynimÄ…" msgctxt "#30048" msgid "Show 'Original Airdate' instead of 'Recording Time'" msgstr "Rodyti 'Premjeros datÄ…' vietoje 'Ä®raÅ¡ymo laiko'" msgctxt "#30049" msgid "Recording template" msgstr "Ä®raÅ¡o Å¡ablonas" msgctxt "#30050" msgid "Advanced" msgstr "Pažangus" msgctxt "#30051" msgid "Preferences" msgstr "Nustatymai" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Ä®jungti MPEG-TS iÅ¡skaidymÄ…" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Perjungimo uždelsimas (sek.)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Grupuoti įraÅ¡ymus pagal pavadinimÄ…" msgctxt "#30055" msgid "Always" msgstr "Visada" msgctxt "#30056" msgid "Only for series" msgstr "Tik serialams" msgctxt "#30057" msgid "Never" msgstr "Niekada" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Ä®jungti reklamų praleidimÄ… (EDL)" msgctxt "#30059" msgid "Always" msgstr "Visada" msgctxt "#30060" msgid "Dialog" msgstr "Dialogas" msgctxt "#30061" msgid "Never" msgstr "Niekada" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Leisti posistemÄ—s iÅ¡jungimÄ…" msgctxt "#30063" msgid "Enable channel icons" msgstr "Ä®jungti kanalų piktogramas" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Ä®jungti fanart/miniatiÅ«rų įraÅ¡ymÄ…" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "Apriboti kanalo nustatymo bandymus" msgctxt "#30066" msgid "Show inactive upcomings (alternative/recorded/expired)" msgstr "Rodyti neaktyvius bÅ«simus įvykius (alternatyvius/įraÅ¡ytus/nebegaliojanÄius)" msgctxt "#30067" msgid "Show LiveTV recordings" msgstr "Rodyti televizijos įraÅ¡us" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Protokolo versija: %i - Duomenų bazÄ—s versija: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "Ä®jungiamas EDL" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "Rastas iÅ¡karpymų sÄ…raÅ¡as ar reklamų praleidimai.\nAr norite aktyvuoti EDL funkcionalumÄ… Å¡iai laidai?" msgctxt "#30112" msgid "Connection failed" msgstr "Prisijungimas nepavyko" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "Ar norite pamÄ—ginti dar kartÄ…?" msgctxt "#30300" msgid "Failed to connect the MythTV backend with the known protocol versions. Please check the compatibility map of the addon and upgrade your backend to a supported version." msgstr "Nepavyko prisijungti prie MythTV posistemÄ—s, naudojant žinomas protokolo versijas. Patikrinkite priedo suderinamumo žemÄ—lapį ir atnaujinkite posistemÄ™ į palaikomÄ… versijÄ…." msgctxt "#30301" msgid "Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. The PIN code has to be configured in your backend to allow connection." msgstr "Nepavyko prisijungti prie MythTV posistemÄ—s API paslaugų. Patikrinkite savo PIN kodÄ… arba posistemÄ—s nustatymus. PIN kodas turi bÅ«ti nustatytas posistemÄ—je tam, kad bÅ«tų galima prisijungti." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Atsijungta nuo MythTV posistemÄ—s" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Prisijungimas prie MythTV atkurtas" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "NÄ—ra atsako iÅ¡ MythTV posistemÄ—s" msgctxt "#30305" msgid "Channel unavailable" msgstr "Kanalas nepasiekiamas" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Ä®raÅ¡o įrenginys nepasiekiamas" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "AtÅ¡aukiamas konfliktuojantis įraÅ¡ymas: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Stabdoma TV transliacija dÄ—l konfliktuojanÄio įraÅ¡ymo: %s" msgctxt "#30309" msgid "Not recording" msgstr "NeįraÅ¡oma" msgctxt "#30310" msgid "Enabled" msgstr "Ä®jungta" msgctxt "#30311" msgid "Disabled" msgstr "Atjungta" msgctxt "#30312" msgid "No broadcast found" msgstr "Nerasta transliacijų" msgctxt "#30411" msgid "Delete and re-record" msgstr "IÅ¡trinti ir įraÅ¡yti iÅ¡ naujo" msgctxt "#30412" msgid "Keep recording" msgstr "Ä®raÅ¡inÄ—ti toliau" msgctxt "#30421" msgid "Toggle display of alternative/recorded/expired" msgstr "Perjungti alternatyvių/įraÅ¡ytų/nebegaliojanÄių rodymÄ…" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "Atnaujinti kanalų piktogramų podÄ—lį" msgctxt "#30423" msgid "Trigger channels update" msgstr "Orientaciniai kanalų atnaujinimai" msgctxt "#30424" msgid "Show status of scheduling" msgstr "Rodyti bÅ«klÄ—s planavimÄ…" msgctxt "#30451" msgid "Unhandled" msgstr "Nepalaikomas" msgctxt "#30452" msgid "Upcoming" msgstr "Artimiausia (-as)" msgctxt "#30453" msgid "Overriden" msgstr "Svarbesnis" msgctxt "#30454" msgid "Don't record" msgstr "NeįraÅ¡inÄ—ti" msgctxt "#30455" msgid "Upcoming manual" msgstr "Artimiausia instrukcija" msgctxt "#30456" msgid "Zombie" msgstr "Zombie" msgctxt "#30457" msgid "Alternative" msgstr "Alternatyvus" msgctxt "#30458" msgid "Currently recorded" msgstr "Å iuo metu įraÅ¡omas" msgctxt "#30459" msgid "Expired recording" msgstr "Nebegaliojantis įraÅ¡ymas" msgctxt "#30460" msgid "Manual" msgstr "Rankiniu bÅ«du" msgctxt "#30461" msgid "Record one" msgstr "Dienos įraÅ¡as" msgctxt "#30462" msgid "Record weekly" msgstr "SavaitÄ—s įraÅ¡as" msgctxt "#30463" msgid "Record daily" msgstr "Kasdieninis įraÅ¡as" msgctxt "#30464" msgid "Record all" msgstr "Visi įraÅ¡ai" msgctxt "#30465" msgid "Record this" msgstr "Å is įraÅ¡as" msgctxt "#30466" msgid "Record series" msgstr "Serijos įraÅ¡as" msgctxt "#30467" msgid "Search keyword" msgstr "PaieÅ¡ka pagal raktinį žodį" msgctxt "#30468" msgid "Search people" msgstr "IeÅ¡koti draugų" msgctxt "#30469" msgid "Rule disabled" msgstr "TaisyklÄ— iÅ¡jungta" msgctxt "#30501" msgid "Don't match duplicates" msgstr "Neatitinka dublikatai" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "Atitikimo dublikatai naudojant subtitrus" msgctxt "#30503" msgid "Match duplicates using description" msgstr "Atitikimo dublikatai naudojant aprašą" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "Atitikimo dublikatai naudojant subtitrus & aprašą" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "Atitikimo dublikatai naudojant subtitrus po to aprašą" msgctxt "#30506" msgid "Recordings never expire" msgstr "Ä®raÅ¡as laikas niekada nesibaigs" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Leisti įraÅ¡ymu galiojimo laikÄ…" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "Nuolat atnaujinama %d įraÅ¡ai" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "IÅ¡laikyti %d naujausia ir/arba baigia galioti" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.lv_lv/000077500000000000000000000000001360567320200273705ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.lv_lv/strings.po000066400000000000000000000157141360567320200314310ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Latvian (Latvia) (http://www.transifex.com/projects/p/kodi-main/language/lv_LV/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: lv_LV\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "MythTV galasistÄ“mas saimniekvÄrds vai IP" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "MythTV galasistÄ“mas ports" msgctxt "#30002" msgid "MythTV Database Username" msgstr "MythTV datubÄzes lietotÄjs" msgctxt "#30003" msgid "MythTV Database Password" msgstr "MythTV datubÄzes parole" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "MythTV datubÄzes nosaukums" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Iekļaut vairÄk atkļūdoÅ¡anas informÄcijas žurnÄla failÄ" msgctxt "#30006" msgid "Enable Live TV" msgstr "IeslÄ“gt tieÅ¡raides TV" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Atļaut tieÅ¡raides TV pÄrcelt ieplÄnotus raidÄ«jumus" msgctxt "#30008" msgid "Conflict handling" msgstr "Konfliktu apstrÄde" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Dot priekÅ¡roku tieÅ¡raides TV, ja ierakstam ir vÄ“lÄks laiks" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Dot priekÅ¡roku ierakstam un apturÄ“t tieÅ¡raides TV" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Dot priekÅ¡roku tieÅ¡raides TV un atcelt konfliktÄ“joÅ¡o ierakstu" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "MythTV galasistÄ“mas datortÄ«kla adrese (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "MythTV galasistÄ“mas ports API pakalpojumiem" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "MythTV drošības PIN uz API pakalpojumiem" msgctxt "#30019" msgid "General" msgstr "VispÄrÄ«gi" msgctxt "#30020" msgid "Template provider" msgstr "Veidnes piegÄdÄtÄjs" msgctxt "#30021" msgid "Internal" msgstr "Iekšējs" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "IekšējÄ veidne" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "AutomÄtiski uzmeklÄ“t metadatus" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "KomerciÄlais karogs jauniem ierakstiem" msgctxt "#30028" msgid "Transcode new recordings" msgstr "TranskodÄ“t jaunos ierakstus" msgctxt "#30029" msgid "Run User Job #1" msgstr "DarbinÄt lietotÄja uzdevumu #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "DarbinÄt lietotÄja uzdevumu #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "DarbinÄt lietotÄja uzdevumu #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "DarbinÄt lietotÄja uzdevumu #4" msgctxt "#30033" msgid "Transcoder" msgstr "PÄrkodÄ“tÄjs" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Atļaut beigties ierakstu termiņam" msgctxt "#30049" msgid "Recording template" msgstr "Ierakstīšanas veidne" msgctxt "#30050" msgid "Advanced" msgstr "Papildus" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "IeslÄ“gt MPEG-TS demultipleksu" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "UtverÅ¡anas aizkave (sek)" msgctxt "#30054" msgid "Group recordings by title" msgstr "GrupÄ“t ierakstus pÄ“c nosaukuma" msgctxt "#30055" msgid "Always" msgstr "VienmÄ“r" msgctxt "#30056" msgid "Only for series" msgstr "Tikai sÄ“rijÄm" msgctxt "#30057" msgid "Never" msgstr "Nekad" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "IeslÄ“gt reklÄmu izlaiÅ¡anu (EDL)" msgctxt "#30059" msgid "Always" msgstr "VienmÄ“r" msgctxt "#30060" msgid "Dialog" msgstr "Dialogs" msgctxt "#30061" msgid "Never" msgstr "Nekad" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Piekrist galasistÄ“mas izslÄ“gÅ¡anu" msgctxt "#30063" msgid "Enable channel icons" msgstr "IeslÄ“gt kanÄlu ikonas" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "IeslÄ“gt ierakstīšanas fanumÄkslu/sÄ«ktÄ“lus" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Protokola versija: %i - DatubÄzes versija: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "EDL ieslÄ“gÅ¡ana" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "Atrasts griezumu saraksts vai reklÄmu izlaiÅ¡ana.\nVai vÄ“laties aktivizÄ“t EDL funkciju Å¡ajÄ pÄrraidÄ“?" msgctxt "#30112" msgid "Connection failed" msgstr "NeizdevÄs pieslÄ“gties" msgctxt "#30300" msgid "Failed to connect the MythTV backend with the known protocol versions. Please check the compatibility map of the addon and upgrade your backend to a supported version." msgstr "NeizdevÄs pieslÄ“gties MythTV galasistÄ“mai ar zinÄmajÄm protokola versijÄm. LÅ«dzu, pÄrbaudiet pielikuma savietojamÄ«bas karti un atjauniniet galasistÄ“mu uz atbalstÄ«tu versiju." msgctxt "#30301" msgid "Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. The PIN code has to be configured in your backend to allow connection." msgstr "NeizdevÄs pieslÄ“gties API pakalpojumiem MythTV galasistÄ“mÄ. LÅ«dzu, pÄrbaudiet PIN kodu vai galasistÄ“mas uzstÄdÄ«jumus. Lai atļautu pieslÄ“gumu, galasistÄ“mÄ jÄkonfigurÄ“ PIN kods." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Zudis pieslÄ“gums MythTV galasistÄ“mai" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "MythTV pieslÄ“gums atjaunots" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "MythTV galasistÄ“ma neatbild." msgctxt "#30305" msgid "Channel unavailable" msgstr "KanÄls nav pieejams" msgctxt "#30306" msgid "Recorder unavailable" msgstr "IerakstÄ«tÄjs nepieejams" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Atceļ konfliktÄ“joÅ¡o ierakstīšanu: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Aptur tieÅ¡raides TV, jo konfliktÄ“ ar ierakstu: %s" msgctxt "#30309" msgid "Not recording" msgstr "Neieraksta" msgctxt "#30310" msgid "Enabled" msgstr "IeslÄ“gts" msgctxt "#30311" msgid "Disabled" msgstr "IzslÄ“gts" msgctxt "#30312" msgid "No broadcast found" msgstr "PÄrraide nav atrasta" msgctxt "#30411" msgid "Delete and re-record" msgstr "DzÄ“st un ierakstÄ«t no jauna" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "AtsvaidzinÄt keÅ¡atmiņu kanÄlu ikonÄm" msgctxt "#30460" msgid "Manual" msgstr "PaÅ¡rocÄ«gi" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Atļaut beigties ierakstu termiņam" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.mi/000077500000000000000000000000001360567320200266535ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.mi/strings.po000066400000000000000000000022351360567320200307060ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Maori (http://www.transifex.com/projects/p/kodi-main/language/mi/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: mi\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" msgctxt "#30019" msgid "General" msgstr "Ä€huawhÄnui" msgctxt "#30050" msgid "Advanced" msgstr "ArÄ Atu AnÅ" msgctxt "#30055" msgid "Always" msgstr "Tonu" msgctxt "#30057" msgid "Never" msgstr "Kore rawa" msgctxt "#30059" msgid "Always" msgstr "Tonu" msgctxt "#30061" msgid "Never" msgstr "Kore rawa" msgctxt "#30305" msgid "Channel unavailable" msgstr "Kaore wÄtea te hongere" msgctxt "#30310" msgid "Enabled" msgstr "Kua whakahohe" msgctxt "#30311" msgid "Disabled" msgstr "Kua mono" msgctxt "#30460" msgid "Manual" msgstr "pukawhakaatu" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.mk_mk/000077500000000000000000000000001360567320200273445ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.mk_mk/strings.po000066400000000000000000000161161360567320200314020ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Macedonian (Macedonia) (http://www.transifex.com/projects/p/kodi-main/language/mk_MK/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: mk_MK\n" "Plural-Forms: nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "MythTV Backend Hostname или IP" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "MythTV Backend Port" msgctxt "#30002" msgid "MythTV Database Username" msgstr "MythTV Database КориÑничко име" msgctxt "#30003" msgid "MythTV Database Password" msgstr "MythTV Database Лозинка" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "MythTV Database име на база на податоци" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Вклучувај повеќе информации за дебагирање во log фајлот" msgctxt "#30006" msgid "Enable Live TV" msgstr "Вклучи Live TV" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Дозволи Live TV да премеÑтува планирани емиÑии" msgctxt "#30008" msgid "Conflict handling" msgstr "Справување Ñо конфликти" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Live TV-то добива поÑледно меÑто при Ñнимање" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Снимањето е на прво меÑто, Ñтопирај го Live TV-то" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Live TV-то е на прво меÑто, Ñтопирај го Ñнимањето ако му пречи" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "MythTV Backend Ethernet адреÑа (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "MythTV Backend Port за API ÑервиÑи" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "ПИРза ÑигурноÑÑ‚ на MythTV за API ÑервиÑите" msgctxt "#30019" msgid "General" msgstr "Општо" msgctxt "#30020" msgid "Template provider" msgstr "Провајдер на темплејти" msgctxt "#30021" msgid "Internal" msgstr "Внатрешно" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "Внатрешен темплејт" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "ÐвтоматÑки провери ја Metadata-та" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Обележи ги новите Ñнимки" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Смени го форматот на новите Ñнимки" msgctxt "#30029" msgid "Run User Job #1" msgstr "Пушти ја задачата #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Пушти ја задачата #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Пушти ја задачата #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Пушти ја задачата #4" msgctxt "#30033" msgid "Transcoder" msgstr "ТранÑкодер" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Снимките имаат рок на траење" msgctxt "#30049" msgid "Recording template" msgstr "Темплејт за Ñнимање" msgctxt "#30050" msgid "Advanced" msgstr "Ðапредно" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Вклучи demuxing на MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Одложување на менувањето фреквенција (Ñекунди)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Групирај ги Ñнимките Ñпоред наÑловот" msgctxt "#30055" msgid "Always" msgstr "Секогаш" msgctxt "#30056" msgid "Only for series" msgstr "Само за Ñерии" msgctxt "#30057" msgid "Never" msgstr "Ðикогаш" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Вклучи преÑкокнување на реклами (EDL)" msgctxt "#30059" msgid "Always" msgstr "Секогаш" msgctxt "#30060" msgid "Dialog" msgstr "Диалог" msgctxt "#30061" msgid "Never" msgstr "Ðикогаш" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Дозволи го гаÑењето на backend-от" msgctxt "#30063" msgid "Enable channel icons" msgstr "Овозможи икони за каналот" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Овозможи Ñнимање на фан арт / мали Ñликички" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Верзија на протоколот: %i - Верзија на датабазата: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "Вклучи EDL" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "Ðајдена е лиÑта за преÑкокнување реклами. Сакаш ли да ја активираш за оваа емиÑија?" msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Изгубена е конекцијата Ñо MythTV" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Повратена е конекцијата Ñо MythTV" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "Ðема одговор од backend-от на MythTV" msgctxt "#30305" msgid "Channel unavailable" msgstr "Каналот е недоÑтапен" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Снимачот е недоÑтапен" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Откажи го Ñнимањето кое пречи: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Се прекинува Live TV-то поради Ñнимање кое пречи: %s" msgctxt "#30309" msgid "Not recording" msgstr "Ðе Ñе Ñнима" msgctxt "#30310" msgid "Enabled" msgstr "Вклучено" msgctxt "#30311" msgid "Disabled" msgstr "ИÑклучено" msgctxt "#30312" msgid "No broadcast found" msgstr "Ðе е пронајден преноÑ" msgctxt "#30411" msgid "Delete and re-record" msgstr "Избриши и Ñними од почеток" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "ОÑвежи го кешот за иконите на каналот" msgctxt "#30460" msgid "Manual" msgstr "Рачно" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Снимките имаат рок на траење" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.ml_in/000077500000000000000000000000001360567320200273445ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.ml_in/strings.po000066400000000000000000000013151360567320200313750ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Malayalam (India) (http://www.transifex.com/projects/p/kodi-main/language/ml_IN/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ml_IN\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30019" msgid "General" msgstr "പോതàµà´µà´¾à´¯à´¤àµ" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.mn_mn/000077500000000000000000000000001360567320200273525ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.mn_mn/strings.po000066400000000000000000000015211360567320200314020ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Mongolian (Mongolia) (http://www.transifex.com/projects/p/kodi-main/language/mn_MN/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: mn_MN\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30019" msgid "General" msgstr "Ерөнхий" msgctxt "#30310" msgid "Enabled" msgstr "ИдÑвхижүүлÑÑ…" msgctxt "#30311" msgid "Disabled" msgstr "ИдвÑхгүй болÑон" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.ms_my/000077500000000000000000000000001360567320200273725ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.ms_my/strings.po000066400000000000000000000234401360567320200314260ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Malay (Malaysia) (http://www.transifex.com/projects/p/kodi-main/language/ms_MY/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ms_MY\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "Nama hos atau alamat IP MythTV" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "Port Bahagian Belakang MythTV" msgctxt "#30002" msgid "MythTV Database Username" msgstr "Nama Pengguna Pangkalan Data MythTV" msgctxt "#30003" msgid "MythTV Database Password" msgstr "Kata Laluan Pangkalan Data MythTV" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "Nama Pangkalan Data Pangkalan Data MythTV" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Sertakan lebih maklumat nyahpepijat dalam fail log" msgctxt "#30006" msgid "Enable Live TV" msgstr "Benarkan TV Langsung" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Benarkan TV Langsung untuk alih rancangan terjadual" msgctxt "#30008" msgid "Conflict handling" msgstr "Pengendalian konflik" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Utamakan TV Langsung bila rakaman mempunyai slot terkemudian" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Utamakan rakaman dan hentikan TV Langsung" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Utamakan TV Langsung dan batalkan rakaman berkonflik" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "Alamat Ethernet Bahagian-Belakang MythTV (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "Port Bahagian Belakang MythTV untuk perkhidmatan API" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "Pin Keselamatan MythTV untuk perkhidmatan API" msgctxt "#30019" msgid "General" msgstr "Am" msgctxt "#30020" msgid "Template provider" msgstr "Penyedia templat" msgctxt "#30021" msgid "Internal" msgstr "Dalaman" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "Templat dalaman" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Cari Data Meta Secara Automatik" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Rakaman Baru Bendera Komersial" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Rakaman baru transkod" msgctxt "#30029" msgid "Run User Job #1" msgstr "Jalan Kerja Pengguna #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Jalan Kerja Pengguna #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Jalan Kerja Pengguna #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Jalan Kerja Pengguna #4" msgctxt "#30033" msgid "Transcoder" msgstr "Transkoder" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Benarkan rakaman menjadi luput" msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "Maklum sebelum memadam rakaman ditonton" msgctxt "#30048" msgid "Show 'Original Airdate' instead of 'Recording Time'" msgstr "Tunjuk 'Tarikh Keudara Asal' selain dari 'Masa Rakaman'" msgctxt "#30049" msgid "Recording template" msgstr "Templat rakaman" msgctxt "#30050" msgid "Advanced" msgstr "Lanjutan" msgctxt "#30051" msgid "Preferences" msgstr "Keutamaan" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Benarkan demux MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Lengah penalaan (saat)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Rakaman kumpulan mengikut tajuk" msgctxt "#30055" msgid "Always" msgstr "Sentiasa" msgctxt "#30056" msgid "Only for series" msgstr "Hanya untuk siri" msgctxt "#30057" msgid "Never" msgstr "Tidak sesekali" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Benarkan langkau komersial (EDL)" msgctxt "#30059" msgid "Always" msgstr "Sentiasa" msgctxt "#30060" msgid "Dialog" msgstr "Dialog" msgctxt "#30061" msgid "Never" msgstr "Tidak sesekali" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Benarkan bahagian belakang matikan" msgctxt "#30063" msgid "Enable channel icons" msgstr "Benarkan ikon saluran" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Benarkan seni peminat/lakaran kenit rakaman" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "Hadkan cubaan penalaan saluran" msgctxt "#30066" msgid "Show inactive upcomings (alternative/recorded/expired)" msgstr "Tunjuk mendatang tak aktif (alternatif/dirakam/luput)" msgctxt "#30067" msgid "Show LiveTV recordings" msgstr "Tunjuk rakaman TV Langsung" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Protokol versi: %i = Pangkalan data versi: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "Membenarkan EDL" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "Senarai potong atau langkau komersial telah ditemui.\nAnda mahu aktifkan kefungsian EDL untuk rancangan ini ?" msgctxt "#30112" msgid "Connection failed" msgstr "Sambungan gagal" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "Anda mahu cuba lagi?" msgctxt "#30300" msgid "Failed to connect the MythTV backend with the known protocol versions. Please check the compatibility map of the addon and upgrade your backend to a supported version." msgstr "Gagal sambung ke bahagian belakang MythTV dengan versi protokol diketahui. Sila periksa peta keserasian bagi tambahan dan tatar bahagian belakang anda dengan versi disokong." msgctxt "#30301" msgid "Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. The PIN code has to be configured in your backend to allow connection." msgstr "Gagal menyambung ke perkhidmatan API bagi bahagian belakang MythTV. Sila periksa kod PIN anda atau persediaan bahagian belakang. Kod pin telah dikonfigur dalam bahagian belakang anda untuk membenarkan sambungan." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Sambungan ke bahagian hadapan MythTV hilang" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Sambungan MythTV dipulihkan" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "Tiada respons dari bahagian belakang MythTV" msgctxt "#30305" msgid "Channel unavailable" msgstr "Saluran tidak tersedia" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Perakam tidak tersedia" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Membatalkan rakaman berkonflik: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Menghentikan TV Langsung kerana rakaman berkonflik: %s" msgctxt "#30309" msgid "Not recording" msgstr "Tidak merakam" msgctxt "#30310" msgid "Enabled" msgstr "Dibenarkan" msgctxt "#30311" msgid "Disabled" msgstr "Dilumpuhkan" msgctxt "#30312" msgid "No broadcast found" msgstr "Tiada siaran ditemui" msgctxt "#30411" msgid "Delete and re-record" msgstr "Padam dan rakam-semula" msgctxt "#30412" msgid "Keep recording" msgstr "Kekal merakam" msgctxt "#30421" msgid "Toggle display of alternative/recorded/expired" msgstr "Togol paparan bagi alternatif/dirakam/luput" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "Segar semula cache untuk ikon saluran" msgctxt "#30423" msgid "Trigger channels update" msgstr "Pemicu kemaskini saluran" msgctxt "#30424" msgid "Show status of scheduling" msgstr "Tunjuk status penjadualan" msgctxt "#30451" msgid "Unhandled" msgstr "Tidak dikendali" msgctxt "#30452" msgid "Upcoming" msgstr "Akan datang" msgctxt "#30453" msgid "Overriden" msgstr "Pembatal" msgctxt "#30454" msgid "Don't record" msgstr "Jangan rakam" msgctxt "#30455" msgid "Upcoming manual" msgstr "Manual akan datang" msgctxt "#30456" msgid "Zombie" msgstr "Zombi" msgctxt "#30457" msgid "Alternative" msgstr "Alternatif" msgctxt "#30458" msgid "Currently recorded" msgstr "Kini dirakam" msgctxt "#30459" msgid "Expired recording" msgstr "Rakaman luput" msgctxt "#30460" msgid "Manual" msgstr "Manual" msgctxt "#30461" msgid "Record one" msgstr "Rakam sekali" msgctxt "#30462" msgid "Record weekly" msgstr "Rakam mingguan" msgctxt "#30463" msgid "Record daily" msgstr "Rakam harian" msgctxt "#30464" msgid "Record all" msgstr "Rakam semua" msgctxt "#30465" msgid "Record this" msgstr "Rakam ini" msgctxt "#30466" msgid "Record series" msgstr "Rakam siri" msgctxt "#30467" msgid "Search keyword" msgstr "Gelintar kata kunci" msgctxt "#30468" msgid "Search people" msgstr "Gelintar individu" msgctxt "#30469" msgid "Rule disabled" msgstr "Peraturan dilumpuhkan" msgctxt "#30501" msgid "Don't match duplicates" msgstr "Jangan padankan pendua" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "Padankan pendua menggunakan sarikata" msgctxt "#30503" msgid "Match duplicates using description" msgstr "Padankan pendua menggunakan keterangan" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "Padankan pendua menggunakan sarikata & keterangan" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "Padankan pendua menggunakan sarikata kemudian keterangan" msgctxt "#30506" msgid "Recordings never expire" msgstr "Rakaman tidak sesekali luput" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Benarkan rakaman menjadi luput" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "Kekalkan sehingga %d rakaman" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "Kekalkan %d yang terbaharu dan luputkan yang lama" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.mt_mt/000077500000000000000000000000001360567320200273665ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.mt_mt/strings.po000066400000000000000000000023461360567320200314240ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Maltese (Malta) (http://www.transifex.com/projects/p/kodi-main/language/mt_MT/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: mt_MT\n" "Plural-Forms: nplurals=4; plural=(n==1 ? 0 : n==0 || ( n%100>1 && n%100<11) ? 1 : (n%100>10 && n%100<20 ) ? 2 : 3);\n" msgctxt "#30019" msgid "General" msgstr "Ä enerali" msgctxt "#30050" msgid "Advanced" msgstr "Avvanzat" msgctxt "#30055" msgid "Always" msgstr "Dejjem" msgctxt "#30057" msgid "Never" msgstr "Qatt" msgctxt "#30059" msgid "Always" msgstr "Dejjem" msgctxt "#30061" msgid "Never" msgstr "Qatt" msgctxt "#30305" msgid "Channel unavailable" msgstr "L-istazzjon mhux disponibbli" msgctxt "#30310" msgid "Enabled" msgstr "Jintuża" msgctxt "#30311" msgid "Disabled" msgstr "Mhux attiv" msgctxt "#30460" msgid "Manual" msgstr "Manwali" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.my_mm/000077500000000000000000000000001360567320200273645ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.my_mm/strings.po000066400000000000000000000035541360567320200314240ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Burmese (Myanmar) (http://www.transifex.com/projects/p/kodi-main/language/my_MM/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: my_MM\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "MythTV Backend Hostname သို့မဟုá€á€º IP" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "MythTV Backend Port" msgctxt "#30002" msgid "MythTV Database Username" msgstr "MythTV Database အသုံးပြုသူအမည်" msgctxt "#30003" msgid "MythTV Database Password" msgstr "MythTV Database စကားá€á€¾á€€á€º" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "MythTV Database Database အမည်" msgctxt "#30006" msgid "Enable Live TV" msgstr "Live TV ကိုဖွင့်ထားမည်" msgctxt "#30019" msgid "General" msgstr "ယေဘုယျ" msgctxt "#30050" msgid "Advanced" msgstr "အဆင့်မြင့်သော" msgctxt "#30055" msgid "Always" msgstr "အမြဲá€á€™á€ºá€¸" msgctxt "#30057" msgid "Never" msgstr "ဘယ်á€á€±á€¬á€·á€™á€¾" msgctxt "#30059" msgid "Always" msgstr "အမြဲá€á€™á€ºá€¸" msgctxt "#30061" msgid "Never" msgstr "ဘယ်á€á€±á€¬á€·á€™á€¾" msgctxt "#30310" msgid "Enabled" msgstr "ဖွင့်ထားမည်" msgctxt "#30311" msgid "Disabled" msgstr "ပိá€á€ºá€‘ားမည်" msgctxt "#30460" msgid "Manual" msgstr "စိá€á€ºá€€á€¼á€­á€¯á€€á€º" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.nb_no/000077500000000000000000000000001360567320200273415ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.nb_no/strings.po000066400000000000000000000230401360567320200313710ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Norwegian BokmÃ¥l (Norway) (http://www.transifex.com/projects/p/kodi-main/language/nb_NO/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: nb_NO\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "MythTV Backend Brukernavn eller IP" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "MythTV Backend Port" msgctxt "#30002" msgid "MythTV Database Username" msgstr "MythTV Database Brukernavn" msgctxt "#30003" msgid "MythTV Database Password" msgstr "MythTV Database Passord" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "MythTV Database Databasenavn" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Inkluder mer debug informasjon i logg filen" msgctxt "#30006" msgid "Enable Live TV" msgstr "Skru pÃ¥ direkte-TV" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Tillat at direkte-TV flytter avtalte programmer" msgctxt "#30008" msgid "Conflict handling" msgstr "KonflikthÃ¥ndtering" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Foretrekk direkte-TV nÃ¥r opptak er satt til senere" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Foretrekk opptak og stopp direkte-TV" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Foretrekk direkte-TV og avbryt motstridende opptak" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "MythTV Backend nettverksadresse (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "MythTV tjenerdel port for API-tjenester" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "MythTV Pin-kode for API-tjenester" msgctxt "#30019" msgid "General" msgstr "Generelt" msgctxt "#30020" msgid "Template provider" msgstr "Maltilbyder" msgctxt "#30021" msgid "Internal" msgstr "Intern" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "Intern mal" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Finn metadata automatisk" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Reklameflagg nye opptak" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Transcode nye opptak" msgctxt "#30029" msgid "Run User Job #1" msgstr "Kjør brukerjobb #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Kjør brukerjobb #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Kjør brukerjobb #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Kjør brukerjobb #4" msgctxt "#30033" msgid "Transcoder" msgstr "Transcoder" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Tillat opptak Ã¥ utløpe" msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "Spør før sletting av sette opptak" msgctxt "#30048" msgid "Show 'Original Airdate' instead of 'Recording Time'" msgstr "Vis 'Opprinnelig sendedato' i stedet for 'Opptakstid'" msgctxt "#30049" msgid "Recording template" msgstr "Opptaksmal" msgctxt "#30050" msgid "Advanced" msgstr "Avansert" msgctxt "#30051" msgid "Preferences" msgstr "Innstillinger" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Aktiver demuxing MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Justeringsforsinkelse (sekunder)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Grupper opptak etter tittel" msgctxt "#30055" msgid "Always" msgstr "Alltid" msgctxt "#30056" msgid "Only for series" msgstr "Bare for serier" msgctxt "#30057" msgid "Never" msgstr "Aldri" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Hopp over reklamer (EDL)" msgctxt "#30059" msgid "Always" msgstr "Alltid" msgctxt "#30060" msgid "Dialog" msgstr "Dialog" msgctxt "#30061" msgid "Never" msgstr "Aldri" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Tillate tjener i Ã¥ avslutte" msgctxt "#30063" msgid "Enable channel icons" msgstr "Aktiver kanal-ikoner" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Aktiver brukerkunstbidragminiatyrbilder for opptak" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "Begrens kanal justerings forsøk" msgctxt "#30066" msgid "Show inactive upcomings (alternative/recorded/expired)" msgstr "Vis kommende inaktive (alternativer/opptak/utgÃ¥tt)" msgctxt "#30067" msgid "Show LiveTV recordings" msgstr "Vis LiveTV-opptak" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Protokollversjon: %i - Databaseversjon: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "Aktiverer EDL" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "En kutt-liste eller reklame-hopper er funnet.\nVil du aktivere EDL-funksjonalitet for dette programmet?" msgctxt "#30112" msgid "Connection failed" msgstr "Tilkobling feilet" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "Ønsker du Ã¥ prøve pÃ¥ nytt ?" msgctxt "#30300" msgid "Failed to connect the MythTV backend with the known protocol versions. Please check the compatibility map of the addon and upgrade your backend to a supported version." msgstr "Tilkoblingen feilet til MythTV-tjenesten med kjent protokollversjon. Sjekk kompatibiliteten for tillegget og oppgrader din tjeneste til en støttet versjon." msgctxt "#30301" msgid "Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. The PIN code has to be configured in your backend to allow connection." msgstr "Tilkobling feilet til API-tjensten til MythTV-tjenste. Sjekk din PIN-kode eller tjenesteoppsett. PIN-koden mÃ¥ settes opp pÃ¥ din tjeneste for Ã¥ tillate tilkobling." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Tilkoblingen til MythTV tapt" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Tilkoblingen til MythTV gjenopprettet" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "Ingen respons fra MythTV backend" msgctxt "#30305" msgid "Channel unavailable" msgstr "Kanal utilgjengelig" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Opptaker utilgjengelig" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Avbryt motstridende opptak: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Stopper live TV grunnet motstridende opptak: %s" msgctxt "#30309" msgid "Not recording" msgstr "Tar ikke opp" msgctxt "#30310" msgid "Enabled" msgstr "Aktivert" msgctxt "#30311" msgid "Disabled" msgstr "Deaktivert" msgctxt "#30312" msgid "No broadcast found" msgstr "Ingen sending funnet" msgctxt "#30411" msgid "Delete and re-record" msgstr "Slett og ta opp pÃ¥ nytt" msgctxt "#30412" msgid "Keep recording" msgstr "Behold opptak" msgctxt "#30421" msgid "Toggle display of alternative/recorded/expired" msgstr "Veksle skjerm for alternativ/tatt opp/utgÃ¥tt" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "Oppdater minne for kanal ikoner" msgctxt "#30423" msgid "Trigger channels update" msgstr "Sjekk kanaloppdateringer" msgctxt "#30424" msgid "Show status of scheduling" msgstr "Vis status for planlegning" msgctxt "#30451" msgid "Unhandled" msgstr "UhÃ¥ndtert" msgctxt "#30452" msgid "Upcoming" msgstr "Kommende" msgctxt "#30453" msgid "Overriden" msgstr "Overskredet" msgctxt "#30454" msgid "Don't record" msgstr "Ikke ta opp" msgctxt "#30455" msgid "Upcoming manual" msgstr "Kommende manuell" msgctxt "#30456" msgid "Zombie" msgstr "Zombie" msgctxt "#30457" msgid "Alternative" msgstr "Alternativ" msgctxt "#30458" msgid "Currently recorded" msgstr "For øyeblikket tatt opp" msgctxt "#30459" msgid "Expired recording" msgstr "UtgÃ¥tte opptak" msgctxt "#30460" msgid "Manual" msgstr "Manuelt" msgctxt "#30461" msgid "Record one" msgstr "Ta opp 1" msgctxt "#30462" msgid "Record weekly" msgstr "Ta opp ukentlig" msgctxt "#30463" msgid "Record daily" msgstr "Ta opp daglig" msgctxt "#30464" msgid "Record all" msgstr "Ta opp alle" msgctxt "#30465" msgid "Record this" msgstr "Ta opp denne" msgctxt "#30466" msgid "Record series" msgstr "Ta opp serier" msgctxt "#30467" msgid "Search keyword" msgstr "Søk nøkkelord" msgctxt "#30468" msgid "Search people" msgstr "Søk personer" msgctxt "#30469" msgid "Rule disabled" msgstr "Regel utkoblet" msgctxt "#30501" msgid "Don't match duplicates" msgstr "Ikke gjenkjenn duplikater" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "Gjenkjen duplikater ved hjelp av undetekster" msgctxt "#30503" msgid "Match duplicates using description" msgstr "Gjenkjen duplikater ved hjelp av beskrivelse" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "Gjenkjen duplikater ved hjelp av undertekster og beskrivelse" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "Gjenkjenn duplikater ved hjelp av undertekster, dernest beskrivelse" msgctxt "#30506" msgid "Recordings never expire" msgstr "Opptak utløper aldri" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Tillat opptak Ã¥ utløpe" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "Behold opptil %d opptak" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "Behold %d nyeste og la eldre utløpe" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.nl_nl/000077500000000000000000000000001360567320200273505ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.nl_nl/strings.po000066400000000000000000000254141360567320200314070ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière # Translators: # Heimen Stoffels , 2018 # Jean-Luc Barrière , 2019 msgid "" msgstr "" "Project-Id-Version: pvr.mythtv\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: 2019-01-06 13:19+0000\n" "Last-Translator: Jean-Luc Barrière \n" "Language-Team: Dutch (Netherlands) (http://www.transifex.com/janbar/pvrmythtv/language/nl_NL/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: nl_NL\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" # Settings labels msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "MythTV Backend hostnaam of IP" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "MythTV Backend poort" msgctxt "#30002" msgid "MythTV Database Username" msgstr "MythTV Database Gebruikersnaam" msgctxt "#30003" msgid "MythTV Database Password" msgstr "MythTV Database Wachtwoord" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "MythTV Database Databasenaam" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Voeg meer debug-informatie toe aan het logbestand." msgctxt "#30006" msgid "Enable Live TV" msgstr "Zet Live TV aan" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Live TV toestaan geplande opnamen te verplaatsen" msgctxt "#30008" msgid "Conflict handling" msgstr "Conflict afhandeling" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Geef voorkeur aan Live TV indien opname later begint" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Geef voorkeur aan opname en stop Live TV" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Geef voorkeur aan Live TV en annuleer conflicterende opname" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "MythTV Backend ethernet adres (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "MythTV Backend poort voor API services" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "MythTV beveiliging wachtwoord voor API services" # empty strings from id 30015 to 30018 msgctxt "#30019" msgid "General" msgstr "Algemene instellingen" msgctxt "#30020" msgid "Template provider" msgstr "Template provider" msgctxt "#30021" msgid "Internal" msgstr "interne" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" # empty strings from id 30023 to 30024 msgctxt "#30025" msgid "Internal template" msgstr "Interne template" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Automatisch naar metadata zoeken" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Markeer reclames in nieuwe opnames" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Transcode nieuwe opnames" msgctxt "#30029" msgid "Run User Job #1" msgstr "Start Gebruikers Taak #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Start Gebruikers Taak #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Start Gebruikers Taak #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Start Gebruikers Taak #4" msgctxt "#30033" msgid "Transcoder" msgstr "Transcoder" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Sta opnames toe te expireren" # empty strings from id 30035 to 30046 msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "druk om de bekeken opname te verwijderen." msgctxt "#30048" msgid "Show 'Original Airdate' instead of 'Recording Time'" msgstr "Toon 'Orginele uitzenddatum' in plaats van 'opnametijd'" msgctxt "#30049" msgid "Recording template" msgstr "Opname template" msgctxt "#30050" msgid "Advanced" msgstr "Geavanceerd" msgctxt "#30051" msgid "Preferences" msgstr "Voorkeuren" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Activeer Demuxing MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Tuner vertraging (sec)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Groepeer opnamen via titel" msgctxt "#30055" msgid "Always" msgstr "Altijd" msgctxt "#30056" msgid "Only for series" msgstr "Alleen voor series" msgctxt "#30057" msgid "Never" msgstr "Nooit" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Activeer reclame skips (EDL)" msgctxt "#30059" msgid "Always" msgstr "Altijd" msgctxt "#30060" msgid "Dialog" msgstr "Dialoog" msgctxt "#30061" msgid "Never" msgstr "Nooit" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Toestaan backend afsluiten" msgctxt "#30063" msgid "Enable channel icons" msgstr "Activeer kanaaliconen" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Activeer opname fanart/miniaturen" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "Limiteer kanaal tuning pogingen" msgctxt "#30066" msgid "Show inactive upcomings (alternative/recorded/expired)" msgstr "Toon inactieve aankomende (alternatief/opgenomen/verlopen)" msgctxt "#30067" msgid "Show LiveTV recordings" msgstr "Toon LiveTV opnamen" msgctxt "#30068" msgid "Use bookmarks of the backend MythTV" msgstr "Gebruik bladwijzers van de backend MythTV" msgctxt "#30069" msgid "Show default recording group as root" msgstr "Toon standaard opnamegroep als root" # empty strings from id 30070 to 30099 # Systeminformation labels msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Protocol versie: %i - Database versie: %i" # empty strings from id 30101 to 30109 # Dialog labels msgctxt "#30110" msgid "Enabling EDL" msgstr "Activeren EDL" msgctxt "#30111" msgid "" "A cut list or commercial skips have been found.\n" "Do you want to activate EDL functionality for this show ?" msgstr "EEN knip lijst of reclame skips zijn gevonden.\nWil je de EDL functionaliteit activeren voor deze uitzending?" msgctxt "#30112" msgid "Connection failed" msgstr "Verbinden mislukt" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "Wilt u het opnieuw proberen?" msgctxt "#30114" msgid "Connected" msgstr "Verbonden" # empty strings from id 30114 to 30299 # Notifications msgctxt "#30300" msgid "" "Failed to connect the MythTV backend with the known protocol versions. " "Please check the compatibility map of the addon and upgrade your backend to " "a supported version." msgstr "Niet gelukt te verbinden met MythTV server met de vertrouwde protocol versies. Controleer de compabiliteitsmap van de add-on en werk de server bij naar een ondersteunende versie." msgctxt "#30301" msgid "" "Failed to connect the API services of MythTV backend. Please check your PIN " "code or backend setup. The PIN code has to be configured in your backend to " "allow connection." msgstr "Niet gelukt te verbinden met de API diensten van MythTV server. Controleer uw PIN code of server instellingen. De PIN code moet geconfigureerd zijn in uw server om verbinding toe te staan." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Verbinding met MythTV backend verbroken" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Verbinding met MythTV herstelt" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "Geen antwoord van de MythTV backend" msgctxt "#30305" msgid "Channel unavailable" msgstr "Kanaal niet beschikbaar" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Opnameapparaat niet beschikbaar" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Annuleer conflicterende opname: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Live TV gestopt in verband met conflicterende opname: %s" msgctxt "#30309" msgid "Not recording" msgstr "niet aan het opnemen" msgctxt "#30310" msgid "Enabled" msgstr "Geactiveerd" msgctxt "#30311" msgid "Disabled" msgstr "Uitgeschakeld" msgctxt "#30312" msgid "No broadcast found" msgstr "Geen uitzending gevonden" # empty strings from id 30313 to 30410 # Menu Hooks msgctxt "#30411" msgid "Delete and re-record" msgstr "Verwijder en her-opnemen" msgctxt "#30412" msgid "Keep recording" msgstr "Behoud opname" # empty strings from id 30413 to 30420 msgctxt "#30421" msgid "Toggle display of alternative/recorded/expired" msgstr "Schakel scherm van alternatie;/opgenomen/verlopen" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "Ververs geheugen voor de kanaaliconen" msgctxt "#30423" msgid "Trigger channels update" msgstr "Trigger update van kanalen" msgctxt "#30424" msgid "Show status of scheduling" msgstr "Toon status van inplanning" msgctxt "#30425" msgid "Show status of recording" msgstr "Toon status van opname" msgctxt "#30426" msgid "Show status of broadcast" msgstr "Toon status van uitzending" # empty strings from id 30427 to 30450 msgctxt "#30451" msgid "Unhandled" msgstr "Onafgehandeld" msgctxt "#30452" msgid "Upcoming" msgstr "Aankomend" msgctxt "#30453" msgid "Overriden" msgstr "Overschreven" msgctxt "#30454" msgid "Don't record" msgstr "Niet opgenomen" msgctxt "#30455" msgid "Upcoming manual" msgstr "Aankomend handmatig" msgctxt "#30456" msgid "Zombie" msgstr "Zombie" msgctxt "#30457" msgid "Alternative" msgstr "Alternatief" msgctxt "#30458" msgid "Currently recorded" msgstr "Huidig opgenomen" msgctxt "#30459" msgid "Expired recording" msgstr "Verlopen opname" msgctxt "#30460" msgid "Manual" msgstr "Handmatig" msgctxt "#30461" msgid "Record one" msgstr "Neem één op" msgctxt "#30462" msgid "Record weekly" msgstr "Neem wekelijks op" msgctxt "#30463" msgid "Record daily" msgstr "Neem dagelijks op" msgctxt "#30464" msgid "Record all" msgstr "Neem alles op" msgctxt "#30465" msgid "Record this" msgstr "Neem dit op" msgctxt "#30466" msgid "Record series" msgstr "Neem serie op" msgctxt "#30467" msgid "Search keyword" msgstr "Zoek op trefwoord" msgctxt "#30468" msgid "Search people" msgstr "Zoek personen" msgctxt "#30469" msgid "Rule disabled" msgstr "Regel gedeactiveerd" # empty strings from id 30470 to 30500 msgctxt "#30501" msgid "Don't match duplicates" msgstr "Niet duplicaten matchen" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "Match dubbelen op ondertitel" msgctxt "#30503" msgid "Match duplicates using description" msgstr "Match dubbelen op beschrijving" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "Match dubbelen op ondertitel & beschrijving" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "Match dubbelen op ondertitel daarna beschrijving" msgctxt "#30506" msgid "Recordings never expire" msgstr "Opnames verlopen nooit" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Sta opnames toe te expireren" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "Bewaar tot en met %d opnames" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "Bewaar %d nieuwste en ouden verlopen" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.pl_pl/000077500000000000000000000000001360567320200273545ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.pl_pl/strings.po000066400000000000000000000235471360567320200314200ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Polish (Poland) (http://www.transifex.com/projects/p/kodi-main/language/pl_PL/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: pl_PL\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "Nazwa lub adres serwera" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "Port serwera" msgctxt "#30002" msgid "MythTV Database Username" msgstr "Użytkownik bazy" msgctxt "#30003" msgid "MythTV Database Password" msgstr "HasÅ‚o użytkownika bazy" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "Nazwa bazy danych" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Rejestruj szczegółowe informacje w pliku dziennika" msgctxt "#30006" msgid "Enable Live TV" msgstr "Aktywuj menedżera telewizji" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Zezwalaj na przenoszenie zaplanowanych programów" msgctxt "#30008" msgid "Conflict handling" msgstr "ZarzÄ…dzanie konfliktami" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Preferuj odtwarzanie, gdy nagranie zaczyna siÄ™ później" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Preferuj nagrywanie i zatrzymuj odtwarzanie telewizji" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Preferuj odtwarzanie telewizji i anuluj konfliktowe nagrywanie" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "Adres MAC serwera (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "Port usÅ‚ug API" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "Kod bezpieczeÅ„stwa dla usÅ‚ug API" msgctxt "#30019" msgid "General" msgstr "Ogólne" msgctxt "#30020" msgid "Template provider" msgstr "Dostawca szablonów" msgctxt "#30021" msgid "Internal" msgstr "WewnÄ™trzny" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "Szablon wewnÄ™trzny" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Wyszukuj metadanych automatycznie" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Zaznaczaj reklamy w nowych nagraÅ„" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Transkoduj nowe nagrania" msgctxt "#30029" msgid "Run User Job #1" msgstr "Uruchom zadanie #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Uruchom zadanie #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Uruchom zadanie #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Uruchom zadanie #4" msgctxt "#30033" msgid "Transcoder" msgstr "Silnik transkodowania" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Zezwalaj na przedawnianie nagraÅ„" msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "Potwierdzaj usuniÄ™cie obejrzanych nagraÅ„" msgctxt "#30048" msgid "Show 'Original Airdate' instead of 'Recording Time'" msgstr "Pokazuj datÄ™ pierwszej emisji zamiast daty nagrania" msgctxt "#30049" msgid "Recording template" msgstr "Szablon nagrywania" msgctxt "#30050" msgid "Advanced" msgstr "Zaawansowane" msgctxt "#30051" msgid "Preferences" msgstr "Preferencje" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Używaj dekodowania MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Opóźnienie dostrajania (w sekundach)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Grupuj nagrania po tytule" msgctxt "#30055" msgid "Always" msgstr "Zawsze" msgctxt "#30056" msgid "Only for series" msgstr "Tylko dla seriali" msgctxt "#30057" msgid "Never" msgstr "Nigdy" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Używaj funkcji pomijania reklam (EDL)" msgctxt "#30059" msgid "Always" msgstr "Zawsze" msgctxt "#30060" msgid "Dialog" msgstr "Pytaj" msgctxt "#30061" msgid "Never" msgstr "Nigdy" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Zezwalaj wyłączaniu serwera" msgctxt "#30063" msgid "Enable channel icons" msgstr "Pokazuj ikony kanałów" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Pokazuj fototapety i miniatury nagraÅ„" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "Limit prób dostrajania kanaÅ‚u" msgctxt "#30066" msgid "Show inactive upcomings (alternative/recorded/expired)" msgstr "Pokazuj nieaktywne zadania (inne/nagrane/przeterminowane)" msgctxt "#30067" msgid "Show LiveTV recordings" msgstr "Pokazuj nagrania telewizyjne" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Wersja protokoÅ‚u: %i - wersja bazy danych: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "Używaj funkcji EDL" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "Odnaleziono listÄ™ wyciÄ™tych scen lub pomijania reklam.\nCzy chcesz użyć funkcji EDL dla tego serialu?" msgctxt "#30112" msgid "Connection failed" msgstr "Nieudane połączenie" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "Czy chcesz ponowić próbÄ™?" msgctxt "#30300" msgid "Failed to connect the MythTV backend with the known protocol versions. Please check the compatibility map of the addon and upgrade your backend to a supported version." msgstr "Nieudane połączenie z serwerem MythTV przy pomocy znanych wersji protokoÅ‚u.Zweryfikuj listÄ™ kompatybilnoÅ›ci dodatku i zaktualizuj serwer do obsÅ‚ugiwanej wersji." msgctxt "#30301" msgid "Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. The PIN code has to be configured in your backend to allow connection." msgstr "Nieudane połączenie z usÅ‚ugami API serwera MythTV. Zweryfikuj wprowadzony kod PIN lub konfiguracjÄ™ serwera. Kod Pin musi zostać najpierw skonfigurowany na serwerze, aby połączenie byÅ‚o możliwe." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Zerwane połączenie z serwerem MythTV" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Przywrócono połączenie z MythTV" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "Serwer MythTV nie odpowiada" msgctxt "#30305" msgid "Channel unavailable" msgstr "KanaÅ‚ niedostÄ™pny" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Funkcja nagrywania niedostÄ™pna" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Anulowanie zadania nagrywania powodujÄ…cego konflikt: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Zatrzymywanie odtwarzania z powodu konfliktowego nagrania: %s" msgctxt "#30309" msgid "Not recording" msgstr "Nagrywanie nieaktywne" msgctxt "#30310" msgid "Enabled" msgstr "Aktywne" msgctxt "#30311" msgid "Disabled" msgstr "Nieaktywny" msgctxt "#30312" msgid "No broadcast found" msgstr "Brak transmisji " msgctxt "#30411" msgid "Delete and re-record" msgstr "Skasuj i nagraj ponownie " msgctxt "#30412" msgid "Keep recording" msgstr "Zachowuj nagranie" msgctxt "#30421" msgid "Toggle display of alternative/recorded/expired" msgstr "Przełącz widok inne/nagrane/przeterminowane" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "OdÅ›wież bufor ikon kanałów" msgctxt "#30423" msgid "Trigger channels update" msgstr "Wymuszaj aktualizacjÄ™ kanałów" msgctxt "#30424" msgid "Show status of scheduling" msgstr "Pokazuj stan harmonogramu zadaÅ„" msgctxt "#30451" msgid "Unhandled" msgstr "NieobsÅ‚ugiwane" msgctxt "#30452" msgid "Upcoming" msgstr "Wkrótce" msgctxt "#30453" msgid "Overriden" msgstr "Nadpisane" msgctxt "#30454" msgid "Don't record" msgstr "Nie nagrywaj" msgctxt "#30455" msgid "Upcoming manual" msgstr "Wkrótce manualnie" msgctxt "#30456" msgid "Zombie" msgstr "Zombie" msgctxt "#30457" msgid "Alternative" msgstr "Inne" msgctxt "#30458" msgid "Currently recorded" msgstr "Aktualnie nagrywane" msgctxt "#30459" msgid "Expired recording" msgstr "Nagranie przeterminowane" msgctxt "#30460" msgid "Manual" msgstr "Manualnie" msgctxt "#30461" msgid "Record one" msgstr "Nagrywaj jednorazowo" msgctxt "#30462" msgid "Record weekly" msgstr "Nagrywaj co tydzieÅ„" msgctxt "#30463" msgid "Record daily" msgstr "Nagrywaj codziennie" msgctxt "#30464" msgid "Record all" msgstr "Nagrywaj wszystko" msgctxt "#30465" msgid "Record this" msgstr "Nagrywaj to" msgctxt "#30466" msgid "Record series" msgstr "Nagrywaj seryjnie" msgctxt "#30467" msgid "Search keyword" msgstr "Wyszukaj wg klucza" msgctxt "#30468" msgid "Search people" msgstr "Wyszukaj wg osób" msgctxt "#30469" msgid "Rule disabled" msgstr "ReguÅ‚a nieaktywna" msgctxt "#30501" msgid "Don't match duplicates" msgstr "Nie wyszukuj duplikatów" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "Wyszukuj duplikaty używajÄ…c podtytuÅ‚u" msgctxt "#30503" msgid "Match duplicates using description" msgstr "Wyszukuj duplikaty używajÄ…c opisu" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "Wyszukuj duplikaty używajÄ…c podtytuÅ‚u i opisu" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "Wyszukuj duplikaty używajÄ…c najpierw podtytuÅ‚u, a potem opisu" msgctxt "#30506" msgid "Recordings never expire" msgstr "Nagrania nie ulegajÄ… przedawnieniu" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Zezwalaj na przedawnienie nagraÅ„" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "Zachowuj %d nagraÅ„ " msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "Zachowuj %d najnowszy nagraÅ„, a resztÄ™ przedawniaj" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.pt_br/000077500000000000000000000000001360567320200273545ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.pt_br/strings.po000066400000000000000000000237521360567320200314160ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/kodi-main/language/pt_BR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: pt_BR\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "MythTV Backend Hostname ou IP" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "MythTV Backend Porta" msgctxt "#30002" msgid "MythTV Database Username" msgstr "MythTV Database Usuário" msgctxt "#30003" msgid "MythTV Database Password" msgstr "MythTV Database Senha" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "MythTV Database Nome do DataBase" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Incluir mais debug informações no arquivo de log" msgctxt "#30006" msgid "Enable Live TV" msgstr "Ativar TV ao Vivo" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Permitir TV ao Vivo mover-se para programação agendada" msgctxt "#30008" msgid "Conflict handling" msgstr "Tratamento de conflitos" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Preferir TV ao vivo quando gravando possuir slot para mais tarde" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Preferir gravar e interromper TV ao Vivo" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Preferir TV ao vivo e cancelar gravações conflitantes" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "Endereço Ethernet MythTV Backend (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "Porta do Backend MythTV para API de serviços" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "MythTV Pin de Segurança para serviços da API" msgctxt "#30019" msgid "General" msgstr "Geral" msgctxt "#30020" msgid "Template provider" msgstr "Fornecedor de Modelo" msgctxt "#30021" msgid "Internal" msgstr "Interno" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "Modelo interno" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Automaticamente procure pelos metadados" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Sinalizador de comercial em novas gravações" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Transcodifique novas gravações" msgctxt "#30029" msgid "Run User Job #1" msgstr "Executar o trabalho usuário #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Executar o trabalho usuário #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Executar o trabalho usuário #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Executar o trabalho usuário #4" msgctxt "#30033" msgid "Transcoder" msgstr "Transcoder" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Permitir gravações expirar" msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "Prompt para deletar gravação assistida" msgctxt "#30048" msgid "Show 'Original Airdate' instead of 'Recording Time'" msgstr "Mostrar 'Data Original em que foi ao ar' ao invés de 'Tempo de Gravação'" msgctxt "#30049" msgid "Recording template" msgstr "Gravando modelo" msgctxt "#30050" msgid "Advanced" msgstr "Avançado" msgctxt "#30051" msgid "Preferences" msgstr "Preferências" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Ativar demuxing MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Atraso de sintonia (seg)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Agrupar gravações por título" msgctxt "#30055" msgid "Always" msgstr "Sempre" msgctxt "#30056" msgid "Only for series" msgstr "Somente para seriados" msgctxt "#30057" msgid "Never" msgstr "Nunca" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Ativar pular comerciais (EDL)" msgctxt "#30059" msgid "Always" msgstr "Sempre" msgctxt "#30060" msgid "Dialog" msgstr "Diálogo" msgctxt "#30061" msgid "Never" msgstr "Nunca" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Permitir desligar backend" msgctxt "#30063" msgid "Enable channel icons" msgstr "Ativar Logos do Canais" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Ativar miniaturas/fanarts nas gravações" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "Limite de tentativas de sintonização dos canais" msgctxt "#30066" msgid "Show inactive upcomings (alternative/recorded/expired)" msgstr "Mostrar os por vir inativo (alternativo/gravado/expirado)" msgctxt "#30067" msgid "Show LiveTV recordings" msgstr "Mostrar gravações de Tv ao Vivo" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Versão do Protocolo: %i - Versão do Banco de Dados: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "Ativando EDL" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "Uma lista com cortes nos comerciais foi encontrada.\nDeseja ativar a funcionalidade de EDL para este programa ?" msgctxt "#30112" msgid "Connection failed" msgstr "Conexão falhou" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "Deseja tentar novamente?" msgctxt "#30300" msgid "Failed to connect the MythTV backend with the known protocol versions. Please check the compatibility map of the addon and upgrade your backend to a supported version." msgstr "Falha ao conectar ao backend do MythTV com a versão conhecida do protocolo. Por verifique o mapa de compatibilidade do addon e atualize o backend para uma versão suportada." msgctxt "#30301" msgid "Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. The PIN code has to be configured in your backend to allow connection." msgstr "Falha ao conectar a API de serviços do backend do MythTV. Por favor, verifique o seu código PIN ou instalação do backend. O código PIN tem de ser configurado em seu backend para permitir a conexão." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Conexão para Backend MythTV perdida" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Conexão para MythTV restaurada" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "Nenhuma resposta do backend do MythTV" msgctxt "#30305" msgid "Channel unavailable" msgstr "Canal indisponível" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Gravador indisponível" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Cancelando gravações conflitantes %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Interrompendo TV ao Vivo em função de conflitos na gravação %s" msgctxt "#30309" msgid "Not recording" msgstr "Não está gravando" msgctxt "#30310" msgid "Enabled" msgstr "Ativado" msgctxt "#30311" msgid "Disabled" msgstr "Desabilitado" msgctxt "#30312" msgid "No broadcast found" msgstr "Nenhuma transmissão encontrada" msgctxt "#30411" msgid "Delete and re-record" msgstr "Deletar e regravar" msgctxt "#30412" msgid "Keep recording" msgstr "Manter gravação" msgctxt "#30421" msgid "Toggle display of alternative/recorded/expired" msgstr "Alternar mostrar entre alternativo/gravado/expirado" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "Atualização de cache para logos de canais" msgctxt "#30423" msgid "Trigger channels update" msgstr "Disparar atualização de canais" msgctxt "#30424" msgid "Show status of scheduling" msgstr "Mostrar estatus dos agendamentos" msgctxt "#30451" msgid "Unhandled" msgstr "Sem tratamento" msgctxt "#30452" msgid "Upcoming" msgstr "Próximos por vir" msgctxt "#30453" msgid "Overriden" msgstr "Sobrepor" msgctxt "#30454" msgid "Don't record" msgstr "Não gravar" msgctxt "#30455" msgid "Upcoming manual" msgstr "Próximos por vir manual" msgctxt "#30456" msgid "Zombie" msgstr "Zumbie" msgctxt "#30457" msgid "Alternative" msgstr "Alternativo" msgctxt "#30458" msgid "Currently recorded" msgstr "Gravações atuais" msgctxt "#30459" msgid "Expired recording" msgstr "Gravações expiradas" msgctxt "#30460" msgid "Manual" msgstr "Manual" msgctxt "#30461" msgid "Record one" msgstr "Gravar um" msgctxt "#30462" msgid "Record weekly" msgstr "Gravações semanais" msgctxt "#30463" msgid "Record daily" msgstr "Gravações diárias" msgctxt "#30464" msgid "Record all" msgstr "Gravar todos" msgctxt "#30465" msgid "Record this" msgstr "Gravar este" msgctxt "#30466" msgid "Record series" msgstr "Gravações de seriados" msgctxt "#30467" msgid "Search keyword" msgstr "Procura por palavras chaves" msgctxt "#30468" msgid "Search people" msgstr "Procurar pessoas" msgctxt "#30469" msgid "Rule disabled" msgstr "Regras desabilitada" msgctxt "#30501" msgid "Don't match duplicates" msgstr "Duplicados não correspondentes" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "Duplicados correspondam baseados na legenda" msgctxt "#30503" msgid "Match duplicates using description" msgstr "Duplicados correspondam baseados na descrição" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "Duplicados correspondam baseados na legenda & descrição" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "Duplicados correspondam usando legenda então descrição" msgctxt "#30506" msgid "Recordings never expire" msgstr "Gravações nunca expiram" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Permitir gravações expirar" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "Manter até %d gravações" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "manter % mais novos e expirar os mais antigos" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.pt_pt/000077500000000000000000000000001360567320200273745ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.pt_pt/strings.po000066400000000000000000000230501360567320200314250ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Portuguese (Portugal) (http://www.transifex.com/projects/p/kodi-main/language/pt_PT/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: pt_PT\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "Nome ou IP do servidor MythTV" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "Porto da estrutura MythTV" msgctxt "#30002" msgid "MythTV Database Username" msgstr "Nome de utilizador da base de dados MythTV" msgctxt "#30003" msgid "MythTV Database Password" msgstr "Palavra-passe da base de dados MythTV" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "Nome da base de dados MythTV" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Incluir mais informação de depuração no ficheiro de registo" msgctxt "#30006" msgid "Enable Live TV" msgstr "Ativar TV em direto" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Permitir que a TV em direto mova programas agendados" msgctxt "#30008" msgid "Conflict handling" msgstr "Gestão de conflitos" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Preferir TV em direto se existir horário para gravar mais tarde" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Preferir gravação e parar TV em direto" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Preferir TV em direto e cancelar a gravação em conflito" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "Endereço ethernet da estrutura MythTV (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "Porto da estrutura MythTV para os serviços API" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "PIN de segurança MythTV para serviços da API" msgctxt "#30019" msgid "General" msgstr "Geral" msgctxt "#30020" msgid "Template provider" msgstr "Fornecedor de modelos" msgctxt "#30021" msgid "Internal" msgstr "Interno" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "Modelo interno" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Procurar meta-dados automaticamente" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Sinalizador de anúncios em novas gravações" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Transcodificar novas gravações" msgctxt "#30029" msgid "Run User Job #1" msgstr "Iniciar tarefa do utilizador #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Iniciar tarefa do utilizador #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Iniciar tarefa do utilizador #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Iniciar tarefa do utilizador #4" msgctxt "#30033" msgid "Transcoder" msgstr "Conversor" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Permitir que as gravações expirem" msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "Avisar para eliminar a gravação vista" msgctxt "#30049" msgid "Recording template" msgstr "Modelo da gravação" msgctxt "#30050" msgid "Advanced" msgstr "Avançado" msgctxt "#30051" msgid "Preferences" msgstr "Preferências" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Ativar 'demuxing' MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Atraso de ajuste (seg.)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Agrupar gravações por título" msgctxt "#30055" msgid "Always" msgstr "Sempre" msgctxt "#30056" msgid "Only for series" msgstr "Apenas para séries" msgctxt "#30057" msgid "Never" msgstr "Nunca" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Permitir ignorar anúncios (EDL)" msgctxt "#30059" msgid "Always" msgstr "Sempre" msgctxt "#30060" msgid "Dialog" msgstr "Janela" msgctxt "#30061" msgid "Never" msgstr "Nunca" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Permitir encerramento da estrutura" msgctxt "#30063" msgid "Enable channel icons" msgstr "Ativar ícones de canal" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Ativar gravação de fanart/miniaturas" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "Limitar tentativas de sintonização" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Versão do protocolo: %i - Versão da base de dados: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "A ativar EDL" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "Foi encontrada uma lista de cortes ou omissões comerciais.\nDeseja ativar a funcionalidade EDL para este programa?" msgctxt "#30112" msgid "Connection failed" msgstr "Falha de ligação" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "Deseja tentar novamente?" msgctxt "#30300" msgid "Failed to connect the MythTV backend with the known protocol versions. Please check the compatibility map of the addon and upgrade your backend to a supported version." msgstr "Não foi possível ligar-se à infraestrutura do MythTV com as versões conhecidas do protocolo. Verifique por favor o mapa de compatibilidades do add-on e atualize a sua infraestrutura para uma versão suportada." msgctxt "#30301" msgid "Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. The PIN code has to be configured in your backend to allow connection." msgstr "Não foi possível ligar-se aos serviços da API da infraestrutura do MythTV. Verifique por favor o seu código PIN ou configuração da infraestrutura. O código PIN tem de ser configurado na sua infraestrutura para permitir a ligação." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "A ligação ao MythTV foi perdida" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "A ligação ao MythTV foi restabelecida" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "Nenhuma resposta da infraestrutura do MythTV" msgctxt "#30305" msgid "Channel unavailable" msgstr "Canal não disponível" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Gravador não disponível" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Cancelar gravação em conflito: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "A parar a TV em direto devido a conflito com gravação: %s" msgctxt "#30309" msgid "Not recording" msgstr "Sem gravação" msgctxt "#30310" msgid "Enabled" msgstr "Ativado" msgctxt "#30311" msgid "Disabled" msgstr "Desativado" msgctxt "#30312" msgid "No broadcast found" msgstr "Emissão não encontrada" msgctxt "#30411" msgid "Delete and re-record" msgstr "Apagar e regravar" msgctxt "#30412" msgid "Keep recording" msgstr "Manter a gravação" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "Recarregar cache dos ícones de canal" msgctxt "#30423" msgid "Trigger channels update" msgstr "Ativar atualização de canais" msgctxt "#30424" msgid "Show status of scheduling" msgstr "Mostrar estado do agendamento" msgctxt "#30451" msgid "Unhandled" msgstr "Não geridos" msgctxt "#30452" msgid "Upcoming" msgstr "Brevemente" msgctxt "#30453" msgid "Overriden" msgstr "Substituídos" msgctxt "#30454" msgid "Don't record" msgstr "Não gravar" msgctxt "#30455" msgid "Upcoming manual" msgstr "Seguinte manual" msgctxt "#30456" msgid "Zombie" msgstr "Zombie" msgctxt "#30457" msgid "Alternative" msgstr "Alternativo" msgctxt "#30458" msgid "Currently recorded" msgstr "Atualmente gravado" msgctxt "#30459" msgid "Expired recording" msgstr "Gravação expirada" msgctxt "#30460" msgid "Manual" msgstr "Manual" msgctxt "#30461" msgid "Record one" msgstr "Gravar uma" msgctxt "#30462" msgid "Record weekly" msgstr "Gravar semanalmente" msgctxt "#30463" msgid "Record daily" msgstr "Gravar diariamente" msgctxt "#30464" msgid "Record all" msgstr "Gravar tudo" msgctxt "#30465" msgid "Record this" msgstr "Gravar esta" msgctxt "#30466" msgid "Record series" msgstr "Gravar série" msgctxt "#30467" msgid "Search keyword" msgstr "Pesquisa por palavra-chave" msgctxt "#30468" msgid "Search people" msgstr "Procurar pessoas" msgctxt "#30469" msgid "Rule disabled" msgstr "Regra desativada" msgctxt "#30501" msgid "Don't match duplicates" msgstr "Não corresponder os duplicados" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "Corresponder os duplicados pela legenda" msgctxt "#30503" msgid "Match duplicates using description" msgstr "Corresponder os duplicados pela descrição" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "Corresponder os duplicados pela legenda & descrição" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "Corresponder os duplicados pela legenda e depois descrição" msgctxt "#30506" msgid "Recordings never expire" msgstr "As gravações nunca expiram" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Permitir que as gravações expirem" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "Manter até %d gravações" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "Manter as %d mais recentes e expirar antigas" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.ro_ro/000077500000000000000000000000001360567320200273665ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.ro_ro/strings.po000066400000000000000000000246251360567320200314300ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Romanian (Romania) (http://www.transifex.com/projects/p/kodi-main/language/ro_RO/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ro_RO\n" "Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "Nume gazdă sau IP pentru furnizorul din spate MythTV" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "Port furnizor din spate MythTV" msgctxt "#30002" msgid "MythTV Database Username" msgstr "Utilizator bază de date MythTV" msgctxt "#30003" msgid "MythTV Database Password" msgstr "Parolă bază de date MythTV" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "Nume bază de date MythTV" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Include mai multe informaÈ›ii de depanare în fiÈ™ierul jurnal" msgctxt "#30006" msgid "Enable Live TV" msgstr "Activează televiziunea în direct" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Permite televiziunii în direct să mute serialele planificate" msgctxt "#30008" msgid "Conflict handling" msgstr "Conflict" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Preferă televiziunea în direct atunci când înregistrarea are slot pentru mai târziu" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Preferă înregistrarea È™i opreÈ™te televiziunea în direct" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Preferă televiziunea în direct È™i abandonează înregistrările conflictuale " msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "Adresă ethernet furnizor din spate MythTV (WOL) " msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "Port furnizor din spate MythTV pentru servicii API" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "PIN de securitate MythTV pentru servicii API" msgctxt "#30019" msgid "General" msgstr "General" msgctxt "#30020" msgid "Template provider" msgstr "Furnizor È™ablon" msgctxt "#30021" msgid "Internal" msgstr "Intern" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "Șablon intern" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Caută automat metadata" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Marchează înregistrările noi" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Transcode înregistrările noi" msgctxt "#30029" msgid "Run User Job #1" msgstr "Rulează sarcina utilizatorului # 1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Rulează sarcina utilizatorului # 2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Rulează sarcina utilizatorului # 3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Rulează sarcina utilizatorului # 4" msgctxt "#30033" msgid "Transcoder" msgstr "Transcoder" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Permite expirarea înregistrării" msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "Confirmare la È™tergerea înregistrării văzute" msgctxt "#30048" msgid "Show 'Original Airdate' instead of 'Recording Time'" msgstr "Arată 'Data lansării' în loc de 'Data înregistrării'" msgctxt "#30049" msgid "Recording template" msgstr "Șablon înregistrare" msgctxt "#30050" msgid "Advanced" msgstr "Avansat" msgctxt "#30051" msgid "Preferences" msgstr "PreferinÈ›e" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Activează demultiplicarea MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "întârziere prindere (sec)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Grupează înregistrările după nume" msgctxt "#30055" msgid "Always" msgstr "ÃŽntotdeauna" msgctxt "#30056" msgid "Only for series" msgstr "Doar pentru serii" msgctxt "#30057" msgid "Never" msgstr "Niciodată" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Activare sărire peste reclame (EDL)" msgctxt "#30059" msgid "Always" msgstr "ÃŽntotdeauna" msgctxt "#30060" msgid "Dialog" msgstr "Dialog" msgctxt "#30061" msgid "Never" msgstr "Niciodată" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Permite închiderea furnizorului din spate" msgctxt "#30063" msgid "Enable channel icons" msgstr "Activează pictograme canale" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Activează înregistrare decor/miniaturi" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "Limitează numărul de încercări de prindere a unui program" msgctxt "#30066" msgid "Show inactive upcomings (alternative/recorded/expired)" msgstr "Arată noutătile inactive (alternative/înregistrate/expirate)" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Versiunea protocolului: %i - Versiunea bazei de date: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "Activare EDL" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "A fost găsită o listă de tăieri sau de salturi peste reclame.\nDoriÈ›i să activaÈ›i funcÈ›ionalitatea EDL pentru această emisiune ?" msgctxt "#30112" msgid "Connection failed" msgstr "Conexiunea a eÈ™uat" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "DoriÈ›i să reîncercaÈ›i ?" msgctxt "#30300" msgid "Failed to connect the MythTV backend with the known protocol versions. Please check the compatibility map of the addon and upgrade your backend to a supported version." msgstr "EÈ™uare la conectare la furnizorul din spate MythTV cu versiunile de protocol cunoscute. VerificaÈ›i harta de compatibilitate a suplimentului È™i actualizaÈ›i furnizorul din spate la versiunea suportată." msgctxt "#30301" msgid "Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. The PIN code has to be configured in your backend to allow connection." msgstr "EÈ™uare la conectarea serviciilor API ale furnizorului din spate MythTV. VerificaÈ›i codul dumneavoastră PIN code sau configuraÈ›ia furnizorului din spate. Codul PIN trebuie să fie configurat în furnizorul din spate pentru a permite conexiunea." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Conexiunea la furnizorul din spate MythTV a fost pierdută " msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Conexiunea la MythTV backend restabilită " msgctxt "#30304" msgid "No response from MythTV backend" msgstr "Niciun răspuns de furnizorul din spate MythTV" msgctxt "#30305" msgid "Channel unavailable" msgstr "Canal indisponibil" msgctxt "#30306" msgid "Recorder unavailable" msgstr "ÃŽnregistrare indisponibila" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr " Anulează înregistrările conflictuale: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Se opreÈ™te televiziunea în direct din cauza înregistrărilor conflictuale: %s" msgctxt "#30309" msgid "Not recording" msgstr "Nu inregistraza" msgctxt "#30310" msgid "Enabled" msgstr "Activat" msgctxt "#30311" msgid "Disabled" msgstr "Dezactivat" msgctxt "#30312" msgid "No broadcast found" msgstr "Nu a fost găsit un canal de transmisie" msgctxt "#30411" msgid "Delete and re-record" msgstr "Sterge si reinregistraza" msgctxt "#30412" msgid "Keep recording" msgstr "Continu să înregistrezi" msgctxt "#30421" msgid "Toggle display of alternative/recorded/expired" msgstr "Comută afiÈ™area celor alternative/înregistrate/expirate" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "Reîmprospătează stocarea în avans a siglelor canalelor" msgctxt "#30423" msgid "Trigger channels update" msgstr "DeclanÈ™are actualizare canale" msgctxt "#30424" msgid "Show status of scheduling" msgstr "Arată starea planificării" msgctxt "#30451" msgid "Unhandled" msgstr "Fără gestionar" msgctxt "#30452" msgid "Upcoming" msgstr "Viitoare" msgctxt "#30453" msgid "Overriden" msgstr "Ignorat" msgctxt "#30454" msgid "Don't record" msgstr "Nu înregistra" msgctxt "#30455" msgid "Upcoming manual" msgstr "Viitoare manual" msgctxt "#30456" msgid "Zombie" msgstr "Zombi" msgctxt "#30457" msgid "Alternative" msgstr "Alternative" msgctxt "#30458" msgid "Currently recorded" msgstr "Momentan înregistrate" msgctxt "#30459" msgid "Expired recording" msgstr "ÃŽnregistrare expirată" msgctxt "#30460" msgid "Manual" msgstr "Manual" msgctxt "#30461" msgid "Record one" msgstr "ÃŽnregistrează unul" msgctxt "#30462" msgid "Record weekly" msgstr "ÃŽnregistrează săptămânal" msgctxt "#30463" msgid "Record daily" msgstr "ÃŽnregistrează zilnic" msgctxt "#30464" msgid "Record all" msgstr "ÃŽnregistrează toate" msgctxt "#30465" msgid "Record this" msgstr "ÃŽnregistrează asta" msgctxt "#30466" msgid "Record series" msgstr "ÃŽnregistrează seriile" msgctxt "#30467" msgid "Search keyword" msgstr "Căutare cuvânt cheie" msgctxt "#30468" msgid "Search people" msgstr "Căutare persoane" msgctxt "#30469" msgid "Rule disabled" msgstr "Regulă dezactivată" msgctxt "#30501" msgid "Don't match duplicates" msgstr "Nu potrivi cu duplicatele" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "PotriveÈ™te cu duplicatele folosind subtitlul" msgctxt "#30503" msgid "Match duplicates using description" msgstr "PotriveÈ™te cu duplicatele folosind descrierea" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "PotriveÈ™te cu duplicatele folosind subtitlul È™i descrierea" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "PotriveÈ™te cu duplicatele folosind subtitlul apoi descrierea" msgctxt "#30506" msgid "Recordings never expire" msgstr "ÃŽnregistrările nu expiră niciodată" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Permite expirarea înregistrării" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "Păstrează până la %d înregistrări" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "Păstrează %d cele mai noi È™i expiră pe cele vechi" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.ru_ru/000077500000000000000000000000001360567320200274025ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.ru_ru/strings.po000066400000000000000000000253371360567320200314450ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Russian (Russia) (http://www.transifex.com/projects/p/kodi-main/language/ru_RU/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ru_RU\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "Ð˜Ð¼Ñ Ñ…Ð¾Ñта бÑк-Ñнда MythTV" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "Порт бÑк-Ñнда MythTV" msgctxt "#30002" msgid "MythTV Database Username" msgstr "Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ MythTV" msgctxt "#30003" msgid "MythTV Database Password" msgstr "Пароль Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ MythTV" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "Ðазвание базы данных MythTV" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Включить в лог-файл отладочную информацию" msgctxt "#30006" msgid "Enable Live TV" msgstr "Включить Live TV" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Разрешить Live TV переключатьÑÑ Ð½Ð° запланированные шоу" msgctxt "#30008" msgid "Conflict handling" msgstr "Обработка конфликтов" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "ПредпочеÑть Live TV, при запиÑи через медленный Ñлот" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "ПредпочеÑть запиÑÑŒ и оÑтановку Live TV" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "ПредпочеÑть Live TV и отменить конфликтную запиÑÑŒ" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "Ethernet Ð°Ð´Ñ€ÐµÑ Ð¾Ð±Ð¾Ð»Ð¾Ñ‡ÐºÐ¸ MythTV (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "Порт бÑк-Ñнда MythTV Ð´Ð»Ñ API ÑервиÑов" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "MythTV код доÑтупа Ð´Ð»Ñ API ÑервиÑов" msgctxt "#30019" msgid "General" msgstr "ОÑновное" msgctxt "#30020" msgid "Template provider" msgstr "Шаблон поÑтавщика" msgctxt "#30021" msgid "Internal" msgstr "Внутренний" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "Внутренний шаблон" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "ÐвтопоиÑк метаданных" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Ðовые запиÑи отмечать как КоммерчеÑкие" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Перекодировать новые запиÑи" msgctxt "#30029" msgid "Run User Job #1" msgstr "ЗапуÑтить задачу â„–1" msgctxt "#30030" msgid "Run User Job #2" msgstr "ЗапуÑтить задачу â„–2" msgctxt "#30031" msgid "Run User Job #3" msgstr "ЗапуÑтить задачу â„–3" msgctxt "#30032" msgid "Run User Job #4" msgstr "ЗапуÑтить задачу â„–4" msgctxt "#30033" msgid "Transcoder" msgstr "Кодировщик" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Разрешить окончание запиÑи" msgctxt "#30049" msgid "Recording template" msgstr "Шаблон запиÑи" msgctxt "#30050" msgid "Advanced" msgstr "Дополнительно" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Включить демультиплекÑирование MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Регулировка задержки (Ñек)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Групповые запиÑи по названию" msgctxt "#30055" msgid "Always" msgstr "Ð’Ñегда" msgctxt "#30056" msgid "Only for series" msgstr "Только Ð´Ð»Ñ Ñериала" msgctxt "#30057" msgid "Never" msgstr "Ðикогда" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Включить пропуÑк рекламы (EDL)" msgctxt "#30059" msgid "Always" msgstr "Ð’Ñегда" msgctxt "#30060" msgid "Dialog" msgstr "Диалог" msgctxt "#30061" msgid "Never" msgstr "Ðикогда" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Разрешить выключение бÑк-Ñнда" msgctxt "#30063" msgid "Enable channel icons" msgstr "Включить логотипы каналов" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Включить фан-арт/ÑкÑкизы Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñей" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "Предел попыток наÑтройки канала" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "ВерÑÐ¸Ñ Ð¿Ñ€Ð¾Ñ‚Ð¾ÐºÐ¾Ð»Ð°: %i - верÑÐ¸Ñ Ð‘Ð°Ð·Ñ‹ данных: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "Включить EDL" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "Был найден ÑпиÑок вÑтавок или рекламы.\nВключить EDL Ð´Ð»Ñ Ñтого Ñериала?" msgctxt "#30112" msgid "Connection failed" msgstr "Ðе удалоÑÑŒ подключитьÑÑ" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "Повторить?" msgctxt "#30300" msgid "Failed to connect the MythTV backend with the known protocol versions. Please check the compatibility map of the addon and upgrade your backend to a supported version." msgstr "Ðе удалоÑÑŒ подключитьÑÑ Ðº Ñерверу MythTV Ñ Ð¸Ð·Ð²ÐµÑтными верÑиÑми протокола. ПожалуйÑта, проверьте карту ÑовмеÑтимоÑти Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¸ обновите Ñервер до поддерживаемой верÑии." msgctxt "#30301" msgid "Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. The PIN code has to be configured in your backend to allow connection." msgstr "Ðе удалоÑÑŒ подключитьÑÑ Ðº API Ñервера MythTV. ПожалуйÑта, проверьте ваш PIN-код или наÑтройки Ñервера. PIN-код код должен быть наÑтроен на Ñервере, чтобы обеÑпечить Ñоединение." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Разрыв ÑвÑзи Ñ Ð²Ð½ÑƒÑ‚Ñ€ÐµÐ½Ð½Ð¸Ð¼ интерфейÑом MythTV" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "СвÑзь Ñ MythTV воÑÑтановлена" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "Внутренний Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ MythTV не отвечает" msgctxt "#30305" msgid "Channel unavailable" msgstr "Канал недоÑтупен" msgctxt "#30306" msgid "Recorder unavailable" msgstr "УÑтройÑтво запиÑи недоÑтупно" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "ОтменÑетÑÑ ÐºÐ¾Ð½Ñ„Ð»Ð¸ÐºÑ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "ОÑтановка Live TV из-за конфликта запиÑи: %s" msgctxt "#30309" msgid "Not recording" msgstr "Ðе запиÑываетÑÑ" msgctxt "#30310" msgid "Enabled" msgstr "Вкл." msgctxt "#30311" msgid "Disabled" msgstr "Откл." msgctxt "#30312" msgid "No broadcast found" msgstr "Передачи не найдены" msgctxt "#30411" msgid "Delete and re-record" msgstr "Удалить и перезапиÑать" msgctxt "#30412" msgid "Keep recording" msgstr "СохранÑть запиÑÑŒ" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "Обновить кÑш Ð´Ð»Ñ Ð¸ÐºÐ¾Ð½Ð¾Ðº каналов" msgctxt "#30423" msgid "Trigger channels update" msgstr "Вызвать обновление каналов" msgctxt "#30424" msgid "Show status of scheduling" msgstr "Показать ÑÑ‚Ð°Ñ‚ÑƒÑ Ñ€Ð°ÑпиÑаниÑ" msgctxt "#30451" msgid "Unhandled" msgstr "ÐеизвеÑтное" msgctxt "#30452" msgid "Upcoming" msgstr "ПредÑтоÑщий" msgctxt "#30453" msgid "Overriden" msgstr "Переопределен" msgctxt "#30454" msgid "Don't record" msgstr "Ðе запиÑывать" msgctxt "#30455" msgid "Upcoming manual" msgstr "ПредÑтоÑщий" msgctxt "#30456" msgid "Zombie" msgstr "Зомби" msgctxt "#30460" msgid "Manual" msgstr "Вручную" msgctxt "#30461" msgid "Record one" msgstr "ЗапиÑать однажды" msgctxt "#30462" msgid "Record weekly" msgstr "ЗапиÑывать еденедельно" msgctxt "#30463" msgid "Record daily" msgstr "ЗапиÑывать ежедневно" msgctxt "#30464" msgid "Record all" msgstr "ЗапиÑать вÑе" msgctxt "#30465" msgid "Record this" msgstr "ЗапиÑать Ñто" msgctxt "#30466" msgid "Record series" msgstr "ЗапиÑать Ñерии" msgctxt "#30467" msgid "Search keyword" msgstr "ПоиÑк по ключевому Ñлову" msgctxt "#30468" msgid "Search people" msgstr "ПоиÑк людей" msgctxt "#30501" msgid "Don't match duplicates" msgstr "Ðе иÑкать дубликаты" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "ИÑкать дубликаты иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð¿Ð¾Ð´Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²Ð¾Ðº" msgctxt "#30503" msgid "Match duplicates using description" msgstr "ИÑкать дубликаты иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð¾Ð¿Ð¸Ñание" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "ИÑкать дубликаты иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð¿Ð¾Ð´Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²Ð¾Ðº и опиÑание" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "ИÑкать дубликаты иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð¿Ð¾Ð´Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²Ð¾Ðº затем опиÑание" msgctxt "#30506" msgid "Recordings never expire" msgstr "ЗапиÑи ни когда не уÑтаревают" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Разрешить окончание запиÑи" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "СохранÑть до %d запиÑей" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "СохранÑть %d новых и удалÑть Ñтарые" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.si_lk/000077500000000000000000000000001360567320200273475ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.si_lk/strings.po000066400000000000000000000022501360567320200313770ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Sinhala (Sri Lanka) (http://www.transifex.com/projects/p/kodi-main/language/si_LK/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: si_LK\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30019" msgid "General" msgstr "à·ƒà·à¶¸à·à¶±à·Šâ€à¶º" msgctxt "#30050" msgid "Advanced" msgstr "උසස්" msgctxt "#30057" msgid "Never" msgstr "කිසි විටෙකත් à¶±à·à¶­à·’ " msgctxt "#30061" msgid "Never" msgstr "කිසි විටෙකත් à¶±à·à¶­à·’ " msgctxt "#30310" msgid "Enabled" msgstr "à¶šà·Šâ€à¶»à·’යà·à¶­à·Šà¶¸à¶š à¶šà¶½à·" msgctxt "#30311" msgid "Disabled" msgstr "à¶…à¶šà·Šâ€à¶»à·’ය à¶šà¶» ඇත." msgctxt "#30460" msgid "Manual" msgstr "à¶šà·à¶º à·€à·à¶ºà·™à¶±à·Š" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.sk_sk/000077500000000000000000000000001360567320200273605ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.sk_sk/strings.po000066400000000000000000000242451360567320200314200ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Slovak (Slovakia) (http://www.transifex.com/projects/p/kodi-main/language/sk_SK/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: sk_SK\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "Názov hostiteľa alebo IP addresa MythTV backendu" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "SieÅ¥ový port MythTV backendu" msgctxt "#30002" msgid "MythTV Database Username" msgstr "Používateľské meno MythTV databázy" msgctxt "#30003" msgid "MythTV Database Password" msgstr "Heslo používateľa MythTV databázy" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "Názov databázy MythTV" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Zahrnúť viac ladiacich informácií do denníka" msgctxt "#30006" msgid "Enable Live TV" msgstr "PovoliÅ¥ Live TV" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "UmožniÅ¥ Live TV rozhraniu presunúť plánované relácie" msgctxt "#30008" msgid "Conflict handling" msgstr "RieÅ¡enie konfliktov" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Pokiaľ nahrávanie zaÄína neskôr, uprednostniÅ¥ živé TV vysielanie" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "UprednostňovaÅ¥ nahrávanie a zastaviÅ¥ živé TV vysielanie" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "UprednostniÅ¥ živé TV vysielanie a zruÅ¡iÅ¥ konfliktné plánované nahrávania" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "Ethernetová adresa backendu MythTV (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "SieÅ¥ový port MythTV backendu pre služby API" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "BezpeÄnostný kód PIN MythTV pre služby API" msgctxt "#30019" msgid "General" msgstr "VÅ¡eobecné" msgctxt "#30020" msgid "Template provider" msgstr "Poskytovateľ Å¡ablón" msgctxt "#30021" msgid "Internal" msgstr "Interný" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "Interná Å¡ablóna" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Automaticky vyhľadávaÅ¥ metadáta" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Automaticky oznaÄovaÅ¥ reklamy v nových nahrávkach" msgctxt "#30028" msgid "Transcode new recordings" msgstr "TranskódovaÅ¥ nové nahrávky" msgctxt "#30029" msgid "Run User Job #1" msgstr "SpustiÅ¥ používateľskú akciu 1" msgctxt "#30030" msgid "Run User Job #2" msgstr "SpustiÅ¥ používateľskú akciu 2" msgctxt "#30031" msgid "Run User Job #3" msgstr "SpustiÅ¥ používateľskú akciu 3" msgctxt "#30032" msgid "Run User Job #4" msgstr "SpustiÅ¥ používateľskú akciu 4" msgctxt "#30033" msgid "Transcoder" msgstr "Transkodér" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "PovoliÅ¥ expiráciu nahrávok" msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "Ponúkni vymazanie pozretej nahrávky" msgctxt "#30048" msgid "Show 'Original Airdate' instead of 'Recording Time'" msgstr "ZobraziÅ¥ 'Pôvodný Äas vysielania' namiesto 'ÄŒas nahrávania'" msgctxt "#30049" msgid "Recording template" msgstr "Å ablóna nahrávky" msgctxt "#30050" msgid "Advanced" msgstr "PokroÄilé" msgctxt "#30051" msgid "Preferences" msgstr "Preferencie" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "PovoliÅ¥ demultiplexovanie MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Oneskorenie ladenia (s)" msgctxt "#30054" msgid "Group recordings by title" msgstr "ZoskupiÅ¥ nahrávky podľa názvu" msgctxt "#30055" msgid "Always" msgstr "Vždy" msgctxt "#30056" msgid "Only for series" msgstr "Len pre seriály" msgctxt "#30057" msgid "Never" msgstr "Nikdy" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Zapnúť preskakovanie reklám (EDL)" msgctxt "#30059" msgid "Always" msgstr "Vždy" msgctxt "#30060" msgid "Dialog" msgstr "Dialóg" msgctxt "#30061" msgid "Never" msgstr "Nikdy" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "PovoliÅ¥ vypnutie na serveri" msgctxt "#30063" msgid "Enable channel icons" msgstr "AktivovaÅ¥ ikony kanálu" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "AktivovaÅ¥ náhľad/fanart nahrávok" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "ObmedziÅ¥ poÄet pokusov o ladenie kanálu" msgctxt "#30066" msgid "Show inactive upcomings (alternative/recorded/expired)" msgstr "Zobraz neaktívne nadchádzajúce (alternatívne/nahraté/vyprÅ¡ané)" msgctxt "#30067" msgid "Show LiveTV recordings" msgstr "ZobraziÅ¥ nahrávky televízie" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Verzia protokolu: %i - Verzia databázy: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "Aktivuje sa EDL" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "NaÅ¡iel sa zoznam vynechaných prvkov alebo preskoÄených reklám.\nChcete pre tento program aktivovaÅ¥ funkciu EDL?" msgctxt "#30112" msgid "Connection failed" msgstr "Spojenie zlyhalo" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "SkúsiÅ¥ znovu?" msgctxt "#30300" msgid "Failed to connect the MythTV backend with the known protocol versions. Please check the compatibility map of the addon and upgrade your backend to a supported version." msgstr "Pripojenie služby MythTV zo strany servera pomocou známych verzií protokolu zlyhalo. Skontrolujte kompatibilitu doplnku a aktualizujte softvér na strane servera na verziu, ktorá je podporovaná." msgctxt "#30301" msgid "Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. The PIN code has to be configured in your backend to allow connection." msgstr "Pripojenie služieb API zo strany serveru MythTV zlyhalo. Skontroluje kód PIN alebo nastavenie systému na strane servera. Aby bolo spojenie úspeÅ¡né, kód PIN musí byÅ¥ na strane servera vytvorený." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Spojenie k MythTV backendu bolo preruÅ¡ené" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Spojenie k MythTV bolo obnovené" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "MythTV backend neodpovedá" msgctxt "#30305" msgid "Channel unavailable" msgstr "Kanál nie je k dispozícii" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Rekordér nie je k dispozícii" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Ruší sa konfliktné nahrávanie: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Zastavuje sa živé TV vysielanie z dôvodu konfliktu s nahrávaním: %s" msgctxt "#30309" msgid "Not recording" msgstr "Nenahráva sa" msgctxt "#30310" msgid "Enabled" msgstr "Aktívne" msgctxt "#30311" msgid "Disabled" msgstr "Zakázaný" msgctxt "#30312" msgid "No broadcast found" msgstr "NenaÅ¡lo sa žiadne vysielanie" msgctxt "#30411" msgid "Delete and re-record" msgstr "VymazaÅ¥ a znova nahraÅ¥" msgctxt "#30412" msgid "Keep recording" msgstr "PonechaÅ¥ nahrávku" msgctxt "#30421" msgid "Toggle display of alternative/recorded/expired" msgstr "Prepnúť zobrazenie alternatívnych/nahratých/vyprÅ¡aných" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "ObnoviÅ¥ doÄasné úložisko pre ikony kanálov" msgctxt "#30423" msgid "Trigger channels update" msgstr "SpustiÅ¥ aktualizáciu kanálov" msgctxt "#30424" msgid "Show status of scheduling" msgstr "ZobraziÅ¥ stav plánovania" msgctxt "#30451" msgid "Unhandled" msgstr "NeoÅ¡etrené" msgctxt "#30452" msgid "Upcoming" msgstr "Nadchádzajúce" msgctxt "#30453" msgid "Overriden" msgstr "Nahradené" msgctxt "#30454" msgid "Don't record" msgstr "NenahrávaÅ¥" msgctxt "#30455" msgid "Upcoming manual" msgstr "Nadchádzajúce ruÄné" msgctxt "#30456" msgid "Zombie" msgstr "Zombia" msgctxt "#30457" msgid "Alternative" msgstr "Alternatívne" msgctxt "#30458" msgid "Currently recorded" msgstr "Aktuálne nahrané" msgctxt "#30459" msgid "Expired recording" msgstr "VyprÅ¡aná nahrávka" msgctxt "#30460" msgid "Manual" msgstr "Manuálne" msgctxt "#30461" msgid "Record one" msgstr "NahrávaÅ¥ raz" msgctxt "#30462" msgid "Record weekly" msgstr "NahrávaÅ¥ týždenne" msgctxt "#30463" msgid "Record daily" msgstr "NahrávaÅ¥ denne" msgctxt "#30464" msgid "Record all" msgstr "NahrávaÅ¥ vÅ¡etko" msgctxt "#30465" msgid "Record this" msgstr "NahraÅ¥ toto" msgctxt "#30466" msgid "Record series" msgstr "NahrávaÅ¥ seriál" msgctxt "#30467" msgid "Search keyword" msgstr "HľadaÅ¥ kľúÄové slovo" msgctxt "#30468" msgid "Search people" msgstr "HľadaÅ¥ ľudí" msgctxt "#30469" msgid "Rule disabled" msgstr "Pravidlo zakázané" msgctxt "#30501" msgid "Don't match duplicates" msgstr "NepárovaÅ¥ duplikáty" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "PárovaÅ¥ duplikáty na základe titulkov" msgctxt "#30503" msgid "Match duplicates using description" msgstr "PárovaÅ¥ duplikáty na základe popisu" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "PárovaÅ¥ duplikáty na základe titulkov a popisu" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "PárovaÅ¥ duplikáty na základe titulkov, potom popisu" msgctxt "#30506" msgid "Recordings never expire" msgstr "Nahrávky nikdy neexpirujú" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "PovoliÅ¥ expiráciu nahrávok" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "PonechaÅ¥ až do %d nahrávok" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "PonechaÅ¥ %d najnovších a expirovaÅ¥ staré" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.sl_si/000077500000000000000000000000001360567320200273575ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.sl_si/strings.po000066400000000000000000000142271360567320200314160ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Slovenian (Slovenia) (http://www.transifex.com/projects/p/kodi-main/language/sl_SI/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: sl_SI\n" "Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "Ime gostitelja ali IP hrbtenice MythTV" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "Vrata hrbtenice MythTV" msgctxt "#30002" msgid "MythTV Database Username" msgstr "UporabniÅ¡ko ime baze MythTV" msgctxt "#30003" msgid "MythTV Database Password" msgstr "Geslo baze MythTV" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "Ime baze MythTV" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "VkljuÄi veÄ razhroÅ¡Äevalnih informacij v zapisniku" msgctxt "#30006" msgid "Enable Live TV" msgstr "OmogoÄi TV v živo" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Dovoli TV v živo, da premika nastavljena snemanja" msgctxt "#30008" msgid "Conflict handling" msgstr "ReÅ¡evanje prekrivanj" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Predvajaj TV v živo, Äe se snemanje zaÄne kasneje" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "ZaÄni snemanje in ustavi TV v živo" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Predvajaj TV v živo in prekliÄi snemanje" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "Krajevni ethernet naslov hrbtenice MythTV (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "Vrata hrbtenice MythTV za API storitve" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "Varnostni pin MythTV za storitve API" msgctxt "#30019" msgid "General" msgstr "SploÅ¡no" msgctxt "#30020" msgid "Template provider" msgstr "Ponudnik predlog" msgctxt "#30021" msgid "Internal" msgstr "Notranji" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "Notranja predloga" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Samodejno poizvedi metapodatke" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "OznaÄi oglase v novih posnetkih" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Pretvori nove posnetke" msgctxt "#30029" msgid "Run User Job #1" msgstr "Zaženi uporabniÅ¡ko opravilo #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Zaženi uporabniÅ¡ko opravilo #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Zaženi uporabniÅ¡ko opravilo #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Zaženi uporabniÅ¡ko opravilo #4" msgctxt "#30033" msgid "Transcoder" msgstr "Pretvornik" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Dovoli posnetkom, da poteÄejo" msgctxt "#30049" msgid "Recording template" msgstr "Predloga snemanja" msgctxt "#30050" msgid "Advanced" msgstr "Napredno" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "OmogoÄi pretvarjanje MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Zakasnitev prilagajanja (s)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Združuj posnetke po naslovih" msgctxt "#30055" msgid "Always" msgstr "Vedno" msgctxt "#30056" msgid "Only for series" msgstr "Le za serije" msgctxt "#30057" msgid "Never" msgstr "Nikoli" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "OmogoÄi preskakovanje oglasov (EDL)" msgctxt "#30059" msgid "Always" msgstr "Vedno" msgctxt "#30060" msgid "Dialog" msgstr "Dialog" msgctxt "#30061" msgid "Never" msgstr "Nikoli" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Dovoli izklop hrbtenice" msgctxt "#30063" msgid "Enable channel icons" msgstr "OmogoÄi ikone programov" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "OmogoÄi snemanje grafike/sliÄic" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "Omeji poskuse uglaÅ¡evanja kanala" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "RazliÄica protokola: %i - RazliÄica baze: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "OmogoÄanje EDL" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "Obstaja seznam izrezanih delov in oglasov.\nAli želite aktivirati EDL za to oddajo?" msgctxt "#30112" msgid "Connection failed" msgstr "Povezava ni uspela" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "Želite poskusiti znova?" msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Povezava s hrbtenico MythTV je bila izgubljena" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Povezava z MythTv je obnovljena" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "Hrbtenica MythTV se ne odziva" msgctxt "#30305" msgid "Channel unavailable" msgstr "Program ni na voljo" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Snemalnik ni na voljo" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Preklic snemanja: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Ustavljam TV v živo zaradi prekrivanja: %s" msgctxt "#30309" msgid "Not recording" msgstr "Ne snemam" msgctxt "#30310" msgid "Enabled" msgstr "OmogoÄeno" msgctxt "#30311" msgid "Disabled" msgstr "OnemogoÄeno" msgctxt "#30312" msgid "No broadcast found" msgstr "Ni najdenega prenosa" msgctxt "#30411" msgid "Delete and re-record" msgstr "IzbriÅ¡i in ponovno snemaj" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "Osveži predpomnilnik za ikone programa" msgctxt "#30460" msgid "Manual" msgstr "RoÄno" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Dovoli posnetkom, da poteÄejo" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.sq_al/000077500000000000000000000000001360567320200273455ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.sq_al/strings.po000066400000000000000000000022611360567320200313770ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Albanian (Albania) (http://www.transifex.com/projects/p/kodi-main/language/sq_AL/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: sq_AL\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30019" msgid "General" msgstr "I përgjithsëm" msgctxt "#30050" msgid "Advanced" msgstr "Të shtuar" msgctxt "#30055" msgid "Always" msgstr "Gjithnjë" msgctxt "#30057" msgid "Never" msgstr "Kurrë" msgctxt "#30059" msgid "Always" msgstr "Gjithnjë" msgctxt "#30061" msgid "Never" msgstr "Kurrë" msgctxt "#30305" msgid "Channel unavailable" msgstr "Kanali i padisponueshëm" msgctxt "#30310" msgid "Enabled" msgstr "Aktivuar" msgctxt "#30311" msgid "Disabled" msgstr "Deaktivuar" msgctxt "#30460" msgid "Manual" msgstr "Udhëzuesi" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.sr_rs/000077500000000000000000000000001360567320200273765ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.sr_rs/strings.po000066400000000000000000000275771360567320200314510ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Serbian (Serbia) (http://www.transifex.com/projects/p/kodi-main/language/sr_RS/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: sr_RS\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "MythTV Hostname позадине или IP" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "MythTV Порт Позадине" msgctxt "#30002" msgid "MythTV Database Username" msgstr "КориÑничко Име MythTV Базе Података" msgctxt "#30003" msgid "MythTV Database Password" msgstr "Лозинка MythTV Базе Података" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "Име MythTV Базе Података" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Укључи више информација за откривање грешака у датотеку евиденције" msgctxt "#30006" msgid "Enable Live TV" msgstr "Омогући ТВ Уживо" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Дозволи да ТВ Уживо помера заказане емиÑије" msgctxt "#30008" msgid "Conflict handling" msgstr "Руковођење неуÑаглашеноÑтима" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Дати предноÑÑ‚ ТВ Уживо када Ñнимање има каÑнији Ñлот" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Дати предноÑÑ‚ Ñнимању и зауÑтавити ТВ Уживо" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Дати предноÑÑ‚ ТВ Уживо и отказати неуÑаглашено Ñнимање" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "Ethernet адреÑа MythTV Позадине (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "Порт MythTV Позадине за API ÑервиÑе" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "Pin MythTV Позадине за API ÑервиÑе" msgctxt "#30019" msgid "General" msgstr "Опште" msgctxt "#30020" msgid "Template provider" msgstr "Провајдер шаблона" msgctxt "#30021" msgid "Internal" msgstr "Унутрашњи" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "Унутрашњи шаблон" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "ÐутоматÑки Потражи Метаподатке" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Означи нове Ñнимке Ñа рекламама" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Прекодирај нове Ñнимке" msgctxt "#30029" msgid "Run User Job #1" msgstr "Покрени КориÑнички ПоÑао #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Покрени КориÑнички ПоÑао #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Покрени КориÑнички ПоÑао #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Покрени КориÑнички ПоÑао #4" msgctxt "#30033" msgid "Transcoder" msgstr "Прекодер" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Дозволи Ñнимцима да иÑтекну" msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "Питај за бриÑање одгледаног Ñнимка" msgctxt "#30048" msgid "Show 'Original Airdate' instead of 'Recording Time'" msgstr "Приказати 'Оригиналан Датум Емитовања' умеÑто 'Времена Снимања'" msgctxt "#30049" msgid "Recording template" msgstr "Шаблон Ñнимања" msgctxt "#30050" msgid "Advanced" msgstr "Ðапредно" msgctxt "#30051" msgid "Preferences" msgstr "Подешавања" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Омогући раздвајање MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Одлагање промене (Ñек)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Групиши Ñнимке по називу" msgctxt "#30055" msgid "Always" msgstr "Увек" msgctxt "#30056" msgid "Only for series" msgstr "Само за Ñерије" msgctxt "#30057" msgid "Never" msgstr "Ðикада" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Омогући преÑкакање реклама (EDL)" msgctxt "#30059" msgid "Always" msgstr "Увек" msgctxt "#30060" msgid "Dialog" msgstr "Дијалог" msgctxt "#30061" msgid "Never" msgstr "Ðикада" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "ДопуÑти гашење позадине" msgctxt "#30063" msgid "Enable channel icons" msgstr "Омогући иконе канала" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Омогући уметноÑÑ‚ љубитеља/Ñличице Ñнимака" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "Ограничи покушаје промене канала" msgctxt "#30066" msgid "Show inactive upcomings (alternative/recorded/expired)" msgstr "Прикажи неактивне надолаÑке (алтернативно/Ñнимљено/иÑтекло)" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Верзија протокола: %i - Верзија базе података: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "Омогућавање EDL" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "ЛиÑта Ñечења или преÑкакања реклама је пронађена.\nДа ли желите да активирате EDL функционалноÑÑ‚ за ову емиÑију?" msgctxt "#30112" msgid "Connection failed" msgstr "ÐеуÑпело повезивање" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "Да ли желите поново да покушате?" msgctxt "#30300" msgid "Failed to connect the MythTV backend with the known protocol versions. Please check the compatibility map of the addon and upgrade your backend to a supported version." msgstr "ÐеуÑпело повезивање MythTV позадине Ñа верзијом познатог протокола. Молимо, проверите мапу компатибилноÑти додатног програма и ажурирајте вашу позадину на подржану верзију." msgctxt "#30301" msgid "Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. The PIN code has to be configured in your backend to allow connection." msgstr "ÐеуÑпело повезивање API ÑервиÑа Ñа MythTV позадином. Молимо, проверите ваш PIN код или подешавања позадине. PIN код мора бити подешен у вашој позадини да би дозволио повезивање." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Изгубљена веза Ñа MythTV позадином" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Обновљена веза Ñа MythTV позадином" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "Ðема одзива од MythTV позадине" msgctxt "#30305" msgid "Channel unavailable" msgstr "Канал недоÑтупан" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Снимач недоÑтупан" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Отказивање неуÑаглашеног Ñнимања: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "ЗауÑтављање ТВ Уживо због неуÑаглашеног Ñнимања: %s" msgctxt "#30309" msgid "Not recording" msgstr "Ðе Ñнима Ñе" msgctxt "#30310" msgid "Enabled" msgstr "Омогућено" msgctxt "#30311" msgid "Disabled" msgstr "Онемогућено" msgctxt "#30312" msgid "No broadcast found" msgstr "Емитовање није пронађено" msgctxt "#30411" msgid "Delete and re-record" msgstr "Избриши и поново Ñними" msgctxt "#30412" msgid "Keep recording" msgstr "ÐаÑтави Ñа Ñнимањем" msgctxt "#30421" msgid "Toggle display of alternative/recorded/expired" msgstr "Мењај приказ алтернативно/Ñнимљено/иÑтекло" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "ОÑвежи кеш за иконе канала" msgctxt "#30423" msgid "Trigger channels update" msgstr "Ðктивирај ажурирање канала" msgctxt "#30424" msgid "Show status of scheduling" msgstr "Прикажи ÑÑ‚Ð°Ñ‚ÑƒÑ Ð·Ð°ÐºÐ°Ð·Ð¸Ð²Ð°ÑšÐ°" msgctxt "#30451" msgid "Unhandled" msgstr "Без руковања" msgctxt "#30452" msgid "Upcoming" msgstr "ПредÑтојеће" msgctxt "#30453" msgid "Overriden" msgstr "Премошћено" msgctxt "#30454" msgid "Don't record" msgstr "Ðемој да Ñнимаш" msgctxt "#30455" msgid "Upcoming manual" msgstr "ПредÑтојеће ручно" msgctxt "#30456" msgid "Zombie" msgstr "Зомби" msgctxt "#30457" msgid "Alternative" msgstr "Ðлтернативно" msgctxt "#30458" msgid "Currently recorded" msgstr "Тренутно Ñнимање" msgctxt "#30459" msgid "Expired recording" msgstr "ИÑтекло Ñнимање" msgctxt "#30460" msgid "Manual" msgstr "Ручно" msgctxt "#30461" msgid "Record one" msgstr "Сними једно" msgctxt "#30462" msgid "Record weekly" msgstr "Снимај недељно" msgctxt "#30463" msgid "Record daily" msgstr "Снимај дневно" msgctxt "#30464" msgid "Record all" msgstr "Сними Ñве" msgctxt "#30465" msgid "Record this" msgstr "Сними ово" msgctxt "#30466" msgid "Record series" msgstr "Сними Ñерију" msgctxt "#30467" msgid "Search keyword" msgstr "Претражи реч" msgctxt "#30468" msgid "Search people" msgstr "Претражи људе" msgctxt "#30469" msgid "Rule disabled" msgstr "Правило онемогућено" msgctxt "#30501" msgid "Don't match duplicates" msgstr "Ðеподударај дупликате" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "Подудари дупликате кориÑтећи титлове" msgctxt "#30503" msgid "Match duplicates using description" msgstr "Подудари дупликате кориÑтећи опиÑ" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "Подудари дупликате кориÑтећи титлове & опиÑ" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "Подудари дупликате кориÑтећи титлове па опиÑ" msgctxt "#30506" msgid "Recordings never expire" msgstr "Снимци никада не иÑтичу" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Дозволи Ñнимцима да иÑтекну" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "Задржи до %d Ñнимака" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "Задржи %d најновијих и Ñтари нека иÑтекну" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.sr_rs@latin/000077500000000000000000000000001360567320200305265ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.sr_rs@latin/strings.po000066400000000000000000000234101360567320200325570ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Serbian (Latin) (Serbia) (http://www.transifex.com/projects/p/kodi-main/language/sr_RS@latin/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: sr_RS@latin\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "MythTV hostname pozadine ili IP" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "MythTV Port Pozadine" msgctxt "#30002" msgid "MythTV Database Username" msgstr "KorisniÄko Ime MythTV Baze Podataka" msgctxt "#30003" msgid "MythTV Database Password" msgstr "Lozinka MythTV Baze Podataka" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "Ime MythTV Baze Podataka" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "UkljuÄi viÅ¡e informacija za otkrivanje greÅ¡aka u datoteku evidencije" msgctxt "#30006" msgid "Enable Live TV" msgstr "Omogući TV Uživo" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Dozvoli da TV Uživo pomera zakazane emisije" msgctxt "#30008" msgid "Conflict handling" msgstr "RukovoÄ‘enje neusaglaÅ¡enostima" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Dati prednost TV Uživo kada snimanje ima kasniji slot" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Dati prednost snimanju i zaustaviti TV Uživo" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Dati prednost TV Uživo i otkazati neusaglaÅ¡eno snimanje" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "Ethernet adresa MythTV Pozadine (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "Port MythTV Pozadine za API servise" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "PIN MythTV Pozadine za API servise" msgctxt "#30019" msgid "General" msgstr "OpÅ¡te" msgctxt "#30020" msgid "Template provider" msgstr "Provajder Å¡ablona" msgctxt "#30021" msgid "Internal" msgstr "UnutraÅ¡nji" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "UnutraÅ¡nji Å¡ablon" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Automatski Potraži Metapodatke" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "OznaÄi nove snimke sa reklamama" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Prekodiraj nove snimke" msgctxt "#30029" msgid "Run User Job #1" msgstr "Pokreni KorisniÄki Posao #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Pokreni KorisniÄki Posao #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Pokreni KorisniÄki Posao #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Pokreni KorisniÄki Posao #4" msgctxt "#30033" msgid "Transcoder" msgstr "Prekoder" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Dozvoli snimcima da isteknu" msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "Pitaj za brisanje odgledanog snimka" msgctxt "#30048" msgid "Show 'Original Airdate' instead of 'Recording Time'" msgstr "Prikazati 'Originalan Datum Emitovanja' umesto 'Vremena Snimanja'" msgctxt "#30049" msgid "Recording template" msgstr "Å ablon snimanja" msgctxt "#30050" msgid "Advanced" msgstr "Napredno" msgctxt "#30051" msgid "Preferences" msgstr "PodeÅ¡avanja" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Omogući razdvajanje MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Odlaganje promene (sek)" msgctxt "#30054" msgid "Group recordings by title" msgstr "GrupiÅ¡i snimke po nazivu" msgctxt "#30055" msgid "Always" msgstr "Uvek" msgctxt "#30056" msgid "Only for series" msgstr "Samo za serije" msgctxt "#30057" msgid "Never" msgstr "Nikada" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Omogući preskakanje reklama (EDL)" msgctxt "#30059" msgid "Always" msgstr "Uvek" msgctxt "#30060" msgid "Dialog" msgstr "Dijalog" msgctxt "#30061" msgid "Never" msgstr "Nikada" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Dopustiti gaÅ¡enje pozadine" msgctxt "#30063" msgid "Enable channel icons" msgstr "Omogući ikone kanala" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Omogući umetnost ljubitelja/sliÄice snimaka" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "OgraniÄi pokuÅ¡aje promene kanala" msgctxt "#30066" msgid "Show inactive upcomings (alternative/recorded/expired)" msgstr "Prikaži neaktivne nadolaske (alternativno/snimljeno/isteklo)" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Verzija protokola: %i - Verzija baze podataka: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "Omogućavanje EDL" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "Lista seÄenja ili preskakanja reklama je pronaÄ‘ena.\nDa li želite da aktivirate EDL funkcionalnost za ovu emisiju?" msgctxt "#30112" msgid "Connection failed" msgstr "Neuspelo povezivanje" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "Da li želite ponovo da pokuÅ¡ate?" msgctxt "#30300" msgid "Failed to connect the MythTV backend with the known protocol versions. Please check the compatibility map of the addon and upgrade your backend to a supported version." msgstr "Neuspelo povezivanje MythTV pozadine sa verzijom poznatog protokola. Molimo, proverite mapu kompatibilnosti dodatnog programa i ažurirajte vaÅ¡u pozadinu na podržanu verziju." msgctxt "#30301" msgid "Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. The PIN code has to be configured in your backend to allow connection." msgstr "Neuspelo povezivanje API servisa sa MythTV pozadinom. Molimo, proverite vaÅ¡ PIN kod ili podeÅ¡avanja pozadine. PIN kod mora biti podeÅ¡en u vaÅ¡oj pozadini da bi dozvolio povezivanje." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Izgubljena veza sa MythTV pozadinom" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Obnovljena veza sa MythTV pozadinom" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "Nema odziva od MythTV pozadine" msgctxt "#30305" msgid "Channel unavailable" msgstr "Kanal nedostupan" msgctxt "#30306" msgid "Recorder unavailable" msgstr "SnimaÄ nedostupan" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Otkazivanje neusaglaÅ¡enog snimanja: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Zaustavljanje TV Uživo zbog neusaglaÅ¡enog snimanja: %s" msgctxt "#30309" msgid "Not recording" msgstr "Ne snima se" msgctxt "#30310" msgid "Enabled" msgstr "Omogućeno" msgctxt "#30311" msgid "Disabled" msgstr "Onemogućeno" msgctxt "#30312" msgid "No broadcast found" msgstr "Emitovanje nije pronaÄ‘eno" msgctxt "#30411" msgid "Delete and re-record" msgstr "IzbriÅ¡i i ponovo snimi" msgctxt "#30412" msgid "Keep recording" msgstr "Nastavi sa snimanjem" msgctxt "#30421" msgid "Toggle display of alternative/recorded/expired" msgstr "Menjaj prikaz alternativno/snimljeno/isteklo" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "Osveži keÅ¡ za ikone kanala" msgctxt "#30423" msgid "Trigger channels update" msgstr "Aktiviraj ažuriranje kanala" msgctxt "#30424" msgid "Show status of scheduling" msgstr "Prikaži status zakazivanja" msgctxt "#30451" msgid "Unhandled" msgstr "Bez rukovanja" msgctxt "#30452" msgid "Upcoming" msgstr "Predstojeće" msgctxt "#30453" msgid "Overriden" msgstr "Premošćeno" msgctxt "#30454" msgid "Don't record" msgstr "Nemoj da snimaÅ¡" msgctxt "#30455" msgid "Upcoming manual" msgstr "Predstojeće ruÄno" msgctxt "#30456" msgid "Zombie" msgstr "Zombi" msgctxt "#30457" msgid "Alternative" msgstr "Alternativno" msgctxt "#30458" msgid "Currently recorded" msgstr "Trenutno snimanje" msgctxt "#30459" msgid "Expired recording" msgstr "Isteklo snimanje" msgctxt "#30460" msgid "Manual" msgstr "RuÄno" msgctxt "#30461" msgid "Record one" msgstr "Snimi jedno" msgctxt "#30462" msgid "Record weekly" msgstr "Snimaj nedeljno" msgctxt "#30463" msgid "Record daily" msgstr "Snimaj dnevno" msgctxt "#30464" msgid "Record all" msgstr "Snimi sve" msgctxt "#30465" msgid "Record this" msgstr "Snimi ovo" msgctxt "#30466" msgid "Record series" msgstr "Snimi seriju" msgctxt "#30467" msgid "Search keyword" msgstr "Pretraži reÄ" msgctxt "#30468" msgid "Search people" msgstr "Pretraži ljude" msgctxt "#30469" msgid "Rule disabled" msgstr "Pravilo onemogućeno" msgctxt "#30501" msgid "Don't match duplicates" msgstr "Nepodudaraj duplikate" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "Podudari duplikate koristeći titlove" msgctxt "#30503" msgid "Match duplicates using description" msgstr "Podudari duplikate koristeći opis" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "Podudari duplikate koristeći titlove & opis" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "Podudari duplikate koristeći titlove pa opis" msgctxt "#30506" msgid "Recordings never expire" msgstr "Snimci nikada ne istiÄu" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Dozvoli snimcima da isteknu" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "Zadrži do %d snimaka" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "Zadrži %d najnovijih i stari neka isteknu" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.sv_se/000077500000000000000000000000001360567320200273655ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.sv_se/strings.po000066400000000000000000000234111360567320200314170ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Swedish (Sweden) (http://www.transifex.com/projects/p/kodi-main/language/sv_SE/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: sv_SE\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "MythTV Backend Värdnamn eller IP" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "MythTV Backend Port" msgctxt "#30002" msgid "MythTV Database Username" msgstr "MythTV Databas Användarnamn" msgctxt "#30003" msgid "MythTV Database Password" msgstr "MythTV Databas Lösenord" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "MythTV Databas Namn" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Inkludera mer debugginformation i loggfilen" msgctxt "#30006" msgid "Enable Live TV" msgstr "Aktivera direktsänd TV" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "TillÃ¥t direktsänd TV att flytta schemalagda program" msgctxt "#30008" msgid "Conflict handling" msgstr "Konflikthantering" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Föredra direktsänd TV när inspelning har ett senare tillfälle" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Föredra inspelning och stoppa direktsänd TV" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Föredra direktsänd TV och avbryt inspelning i konflikt" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "MythTV Backend Nätverksadress (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "MythTV Backend Port för API-tjänster" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "MythTV Säkerhetspin för API-tjänster" msgctxt "#30019" msgid "General" msgstr "Allmänt" msgctxt "#30020" msgid "Template provider" msgstr "Mall-leverantör" msgctxt "#30021" msgid "Internal" msgstr "Intern" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "Intern mall" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "SlÃ¥ automatiskt upp metadata" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Raklamflagga nya inspelningar" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Omkoda nya inspelningar" msgctxt "#30029" msgid "Run User Job #1" msgstr "Kör användarjobb #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Kör användarjobb #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Kör användarjobb #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Kör användarjobb #4" msgctxt "#30033" msgid "Transcoder" msgstr "Omkodning" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "TillÃ¥t inspelningar att utgÃ¥" msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "Uppmaning att ta bort den sedda inspelningen" msgctxt "#30048" msgid "Show 'Original Airdate' instead of 'Recording Time'" msgstr "Visa 'Original Airdate' i stället för 'Recording Time'" msgctxt "#30049" msgid "Recording template" msgstr "Inspelningsmall" msgctxt "#30050" msgid "Advanced" msgstr "Avancerad" msgctxt "#30051" msgid "Preferences" msgstr "Inställningar" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Aktivera avmuxning av MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Tuningfördröjning (sek)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Gruppera inspelningar efter titel" msgctxt "#30055" msgid "Always" msgstr "Alltid" msgctxt "#30056" msgid "Only for series" msgstr "Endast för serier" msgctxt "#30057" msgid "Never" msgstr "Aldrig" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Aktivera reklamhopp (EDL)" msgctxt "#30059" msgid "Always" msgstr "Alltid" msgctxt "#30060" msgid "Dialog" msgstr "Dialog" msgctxt "#30061" msgid "Never" msgstr "Aldrig" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Medge avstägning av bakgrundsservern" msgctxt "#30063" msgid "Enable channel icons" msgstr "Aktivera kanalikoner" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Aktivera inspelnings-fanart/miniatyrbilder" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "Begränsa försök för justering av kanal" msgctxt "#30066" msgid "Show inactive upcomings (alternative/recorded/expired)" msgstr "Visa inaktiverade kommande (alternativ/inspelningar/utgÃ¥tt)" msgctxt "#30067" msgid "Show LiveTV recordings" msgstr "Visa direktsänd TV inspelningar" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Protokollversion: %i - Databasversion: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "Aktiverar EDL" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "Klipplista eller reklamhopp har hittats.\nVill du aktivera EDL-funktionalitet för denna visning?" msgctxt "#30112" msgid "Connection failed" msgstr "Anslutningen misslyckades" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "Vill du försöka igen?" msgctxt "#30300" msgid "Failed to connect the MythTV backend with the known protocol versions. Please check the compatibility map of the addon and upgrade your backend to a supported version." msgstr "Det gick inte att ansluta MythTV backend med de kända protokollversionerna. Kontrollera kompatibilitet med tillägg och uppgradera din backend till en version som stöds." msgctxt "#30301" msgid "Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. The PIN code has to be configured in your backend to allow connection." msgstr "Det gick inte att ansluta API tjänster MythTV backend. Kontrollera din PIN-kod eller backend inställningar. PIN-koden mÃ¥ste vara konfigurerade i backend för att möjliggöra anslutning." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Anslutning till MythTV backend förlorad" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Anslutning till MythTV Ã¥terställd" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "Inget svar frÃ¥n MythTV backend" msgctxt "#30305" msgid "Channel unavailable" msgstr "Kanal otillgänglig" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Inspelare inte tillgänglig" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Avbryter inspelning med konflikt: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Stoppar direktsänd TV pga konflikt med inspelning: %s" msgctxt "#30309" msgid "Not recording" msgstr "Spelar inte in" msgctxt "#30310" msgid "Enabled" msgstr "Aktiverad" msgctxt "#30311" msgid "Disabled" msgstr "Inaktiverad" msgctxt "#30312" msgid "No broadcast found" msgstr "Ingen sändning hittades" msgctxt "#30411" msgid "Delete and re-record" msgstr "Ta bort och spela in pÃ¥ nytt" msgctxt "#30412" msgid "Keep recording" msgstr "Fortsätt spela in" msgctxt "#30421" msgid "Toggle display of alternative/recorded/expired" msgstr "Växla skärm mellan alternativ/inspelningar/utgÃ¥tt" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "Förnya cache för kanalikoner" msgctxt "#30423" msgid "Trigger channels update" msgstr "Trigger kanaler uppdatering" msgctxt "#30424" msgid "Show status of scheduling" msgstr "Visa schemaläggningens status" msgctxt "#30451" msgid "Unhandled" msgstr "O-hanterad" msgctxt "#30452" msgid "Upcoming" msgstr "Kommande" msgctxt "#30453" msgid "Overriden" msgstr "Ã…sidosatt" msgctxt "#30454" msgid "Don't record" msgstr "Spela inte in" msgctxt "#30455" msgid "Upcoming manual" msgstr "Kommande manual" msgctxt "#30456" msgid "Zombie" msgstr "Zombie" msgctxt "#30457" msgid "Alternative" msgstr "Alternativ" msgctxt "#30458" msgid "Currently recorded" msgstr "För närvarande inspelad" msgctxt "#30459" msgid "Expired recording" msgstr "UtgÃ¥ende inspelning" msgctxt "#30460" msgid "Manual" msgstr "Manuell" msgctxt "#30461" msgid "Record one" msgstr "Spela in en" msgctxt "#30462" msgid "Record weekly" msgstr "Spela in veckovis" msgctxt "#30463" msgid "Record daily" msgstr "Spela in dagligen" msgctxt "#30464" msgid "Record all" msgstr "Spela in alla" msgctxt "#30465" msgid "Record this" msgstr "Spela on detta" msgctxt "#30466" msgid "Record series" msgstr "Sök serier" msgctxt "#30467" msgid "Search keyword" msgstr "Sök nyckelord" msgctxt "#30468" msgid "Search people" msgstr "Sök personer" msgctxt "#30469" msgid "Rule disabled" msgstr "Regel inaktiverad" msgctxt "#30501" msgid "Don't match duplicates" msgstr "Matcha inte dubbletter" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "Matcha dubbletter med hjälp av undertext" msgctxt "#30503" msgid "Match duplicates using description" msgstr "Matcha dubbletter med hjälp av beskrivning" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "Matcha dubbletter med hjälp av undertext & beskrivning" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "Matcha dubbletter med hjälp av undertext sedan beskrivning" msgctxt "#30506" msgid "Recordings never expire" msgstr "Inspelningen upphör aldrig" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "TillÃ¥t inspelningar att gÃ¥ ut" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "BehÃ¥ll upp till %d inspelningar" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "BehÃ¥ll %d nyaste och upphäv de gamla" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.szl/000077500000000000000000000000001360567320200270565ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.szl/strings.po000066400000000000000000000220241360567320200311070ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Silesian (http://www.transifex.com/projects/p/kodi-main/language/szl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: szl\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "Miano lebo adresa serwera" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "Port serwera" msgctxt "#30002" msgid "MythTV Database Username" msgstr "UżywÅcz bazy" msgctxt "#30003" msgid "MythTV Database Password" msgstr "HasÅ‚o używÅcza bazy" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "Miano bazy danych" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Registruj detajlowe informacyje we zbiorze dziynnika" msgctxt "#30006" msgid "Enable Live TV" msgstr "Aktywuj mynedżera telewizyje" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "PrzizwÅlej na przenoszynie nasztalowanych programÅw" msgctxt "#30008" msgid "Conflict handling" msgstr "Reskyrowanie kÅnfliktami" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Preferuj ôdtwÅrzanie, kej nagranie napoczynÅ sie niyskorzij" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Preferuj nagrować i zastÅwiej ôdtwÅrzanie telewizyje" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Preferuj ôdtwÅrzanie telewizyje i pociepnij konfliktowe nagrowania" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "Adresa MAC ôd serwera (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "Port posugÅw API" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "Kod bezpiyczyÅ„stwa dlÅ posugÅw API" msgctxt "#30019" msgid "General" msgstr "GÅ‚ÅwnÅ" msgctxt "#30020" msgid "Template provider" msgstr "Liferant szablÅn" msgctxt "#30021" msgid "Internal" msgstr "WnÅntrzny" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "WnÅntrznÅ szablÅna" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Zeszukuj metadaty autÅmatycznie" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Cechuj ryklamy w nowych nagraniach" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Transkoduj nowe nagrania" msgctxt "#30029" msgid "Run User Job #1" msgstr "Sztartnij auftrag #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Sztartnij auftrag #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Sztartnij auftrag #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Sztartnij auftrag #4" msgctxt "#30033" msgid "Transcoder" msgstr "Transkoder" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "PrzizwÅlej na przedÅwnianie nagraÅ„" msgctxt "#30049" msgid "Recording template" msgstr "SzablÅna nagrowaniÅ" msgctxt "#30050" msgid "Advanced" msgstr "Zaawansowane" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Używej dekodowaniÅ MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Zniyskorzynie dostrÅjaniÅ (w sekundach)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Zortuj nagrania po tytule" msgctxt "#30055" msgid "Always" msgstr "zawdy" msgctxt "#30056" msgid "Only for series" msgstr "Ino dlÅ seriolÅw" msgctxt "#30057" msgid "Never" msgstr "Nigdy" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Używej funkcyje pÅmijaniÅ ryklam (EDL)" msgctxt "#30059" msgid "Always" msgstr "zawdy" msgctxt "#30060" msgid "Dialog" msgstr "Dialog" msgctxt "#30061" msgid "Never" msgstr "Nigdy" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "zezwól na szaltrowanie serwera" msgctxt "#30063" msgid "Enable channel icons" msgstr "PokÅzuj ikÅny kanaÅ‚Åw" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "PokÅzuj fototapety i miniatury nagraÅ„" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "UkrÅcej prÅby dostrÅjaniÅ kanaÅ‚u" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "WersyjÅ protokoÅ‚u: %i - wersyjÅ bazy datÅw: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "Używej funkcyje EDL" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "ÔdnÅdniynto byÅ‚o wykÅz wytniyntych scyn abo pÅmijaniÅ ryklam.\nChcesz użyć funkcyje EDL dlÅ tego seriolu?" msgctxt "#30112" msgid "Connection failed" msgstr "NiypodarzÅne skuplowanie" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "Chcesz sprÅbować zaÅ›?" msgctxt "#30300" msgid "Failed to connect the MythTV backend with the known protocol versions. Please check the compatibility map of the addon and upgrade your backend to a supported version." msgstr "NiypodarzÅne skuplowanie z serwerym MythTV przi pÅmocy znanych wersyji protokoÅ‚u. Wybadej wykÅz kÅmpatybilnoÅ›ci przidÅwka i zaktualizuj serwer do dopÅmÅganyj wersyje." msgctxt "#30301" msgid "Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. The PIN code has to be configured in your backend to allow connection." msgstr "NiypodarzÅne skuplowanie z posugami API serwera MythTV. Wybadej wkludzÅny kod PIN lebo kÅnfiguracyjõ serwera. Kod PIN musi być nÅjprzÅd skÅnfigurowany na serwerze, coby skuplowanie byÅ‚o możebne." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Serwane skuplowanie z serwerym MythTV" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "WrÅcÅno byÅ‚o skuplowanie z MythTV" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "Serwer MythTV niy ôdpadÅ" msgctxt "#30305" msgid "Channel unavailable" msgstr "KanaÅ‚ je niydostympny" msgctxt "#30306" msgid "Recorder unavailable" msgstr "FunkcyjÅ nagrowaniÅ niydostympnÅ" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "PociepniyÅ„cie nagraniÅ, co sprÅwiÅ kÅnflikt: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "ZastÅwianie ôdtwÅrzaniÅ skiż konfliktowygo nagraniÅ: %s" msgctxt "#30309" msgid "Not recording" msgstr "Nagrowanie niyaktywne" msgctxt "#30310" msgid "Enabled" msgstr "Aktywny" msgctxt "#30311" msgid "Disabled" msgstr "ZastawiÅny" msgctxt "#30312" msgid "No broadcast found" msgstr "Niy ma transmisyje " msgctxt "#30411" msgid "Delete and re-record" msgstr "Skasuj i nagrej zaÅ› " msgctxt "#30412" msgid "Keep recording" msgstr "Spamiyntej nagranie" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "ÔdÅ›wiyż bufÅr ikÅn kanaÅ‚Åw" msgctxt "#30423" msgid "Trigger channels update" msgstr "Aktualizuj kanaÅ‚y" msgctxt "#30424" msgid "Show status of scheduling" msgstr "PokÅzuj stan harmÅnogramu auftragÅw" msgctxt "#30451" msgid "Unhandled" msgstr "Niypodpiyrane" msgctxt "#30452" msgid "Upcoming" msgstr "NÅjbliższe" msgctxt "#30453" msgid "Overriden" msgstr "PÅmiyniÅne" msgctxt "#30454" msgid "Don't record" msgstr "Niy nagrowej" msgctxt "#30455" msgid "Upcoming manual" msgstr "Manualnie nÅjbliższe" msgctxt "#30456" msgid "Zombie" msgstr "Zombie" msgctxt "#30460" msgid "Manual" msgstr "Manualnie" msgctxt "#30461" msgid "Record one" msgstr "Nagrej rÅz" msgctxt "#30462" msgid "Record weekly" msgstr "Nagrowej co tydziyÅ„" msgctxt "#30463" msgid "Record daily" msgstr "Nagrowej dziynnie" msgctxt "#30464" msgid "Record all" msgstr "Nagrowej wszyjsko" msgctxt "#30465" msgid "Record this" msgstr "Nagrej to" msgctxt "#30466" msgid "Record series" msgstr "Nagrowej seriol" msgctxt "#30467" msgid "Search keyword" msgstr "Zeszukej pdl. klucza" msgctxt "#30468" msgid "Search people" msgstr "Zeszukej pdl. ôsob" msgctxt "#30501" msgid "Don't match duplicates" msgstr "Niy zeszukuj tuplikatÅw" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "Zeszukuj tuplikaty przi używaniu podtytuÅ‚u" msgctxt "#30503" msgid "Match duplicates using description" msgstr "Zeszukuj tuplikaty przi używaniu ôpisu" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "Zeszukuj tuplikaty przi używaniu podtytuÅ‚u i ôpisu" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "Zeszukuj tuplikaty przi używaniu nÅjprzÅd podtytuÅ‚u, a potym ôpisu" msgctxt "#30506" msgid "Recordings never expire" msgstr "Nagrania sie nikej niy przedÅwniajÅm" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "PrzizwÅlej na przedÅwnianie nagraÅ„" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "Spamiyntuj do %d nagraÅ„ " msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "Spamiyntuj %d nÅjnowszych nagraÅ„, a stare przedÅwniej" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.ta_in/000077500000000000000000000000001360567320200273405ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.ta_in/strings.po000066400000000000000000000026251360567320200313760ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Tamil (India) (http://www.transifex.com/projects/p/kodi-main/language/ta_IN/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ta_IN\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30019" msgid "General" msgstr "பொதà¯à®µà®¾à®©à®¤à¯" msgctxt "#30050" msgid "Advanced" msgstr "மேமà¯à®ªà®Ÿà¯à®Ÿ" msgctxt "#30055" msgid "Always" msgstr "எபà¯à®ªà¯‡à®¾à®¤à¯à®®à¯" msgctxt "#30057" msgid "Never" msgstr "à®’à®°à¯à®ªà¯‹à®¤à¯à®®à¯" msgctxt "#30059" msgid "Always" msgstr "எபà¯à®ªà¯‡à®¾à®¤à¯à®®à¯" msgctxt "#30061" msgid "Never" msgstr "à®’à®°à¯à®ªà¯‹à®¤à¯à®®à¯" msgctxt "#30305" msgid "Channel unavailable" msgstr "சேனல௠கிடைகà¯à®•விலà¯à®²à¯ˆ" msgctxt "#30310" msgid "Enabled" msgstr "செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯" msgctxt "#30311" msgid "Disabled" msgstr "à®®à¯à®Ÿà®•à¯à®•பà¯à®ªà®Ÿà¯à®Ÿà®©" msgctxt "#30460" msgid "Manual" msgstr "கைமà¯à®±à¯ˆ" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.te_in/000077500000000000000000000000001360567320200273445ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.te_in/strings.po000066400000000000000000000014471360567320200314030ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Telugu (India) (http://www.transifex.com/projects/p/kodi-main/language/te_IN/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: te_IN\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30019" msgid "General" msgstr "సాధారణం" msgctxt "#30310" msgid "Enabled" msgstr "ఎనేబà±à°²à± చెయà±à°¯à°¬à°¡à°¿à°‚ది" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.tg_tj/000077500000000000000000000000001360567320200273555ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.tg_tj/strings.po000066400000000000000000000023401360567320200314050ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Tajik (Tajikistan) (http://www.transifex.com/projects/p/kodi-main/language/tg_TJ/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: tg_TJ\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30019" msgid "General" msgstr "Умумӣ" msgctxt "#30050" msgid "Advanced" msgstr "Иловагӣ" msgctxt "#30055" msgid "Always" msgstr "Ҳамеша" msgctxt "#30057" msgid "Never" msgstr "Ҳеҷ гоҳ" msgctxt "#30059" msgid "Always" msgstr "Ҳамеша" msgctxt "#30061" msgid "Never" msgstr "Ҳеҷ гоҳ" msgctxt "#30305" msgid "Channel unavailable" msgstr "Шабака даÑÑ‚Ð½Ð¾Ñ€Ð°Ñ Ð°ÑÑ‚" msgctxt "#30310" msgid "Enabled" msgstr "Фаъол" msgctxt "#30311" msgid "Disabled" msgstr "Ғайрифаъол" msgctxt "#30460" msgid "Manual" msgstr "ДаÑтур" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.th_th/000077500000000000000000000000001360567320200273545ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.th_th/strings.po000066400000000000000000000024471360567320200314140ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Thai (Thailand) (http://www.transifex.com/projects/p/kodi-main/language/th_TH/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: th_TH\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30019" msgid "General" msgstr "ทั่วไป" msgctxt "#30050" msgid "Advanced" msgstr "ขั้นสูง" msgctxt "#30055" msgid "Always" msgstr "เสมอ" msgctxt "#30057" msgid "Never" msgstr "ไม่เลย" msgctxt "#30059" msgid "Always" msgstr "เสมอ" msgctxt "#30061" msgid "Never" msgstr "ไม่เลย" msgctxt "#30305" msgid "Channel unavailable" msgstr "ช่อง ไม่พร้อมใช้งาน" msgctxt "#30310" msgid "Enabled" msgstr "ใช้งาน" msgctxt "#30311" msgid "Disabled" msgstr "ปิดà¸à¸²à¸£à¹ƒà¸Šà¹‰à¸‡à¸²à¸™" msgctxt "#30460" msgid "Manual" msgstr "ด้วยตนเอง" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.tr_tr/000077500000000000000000000000001360567320200274005ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.tr_tr/strings.po000066400000000000000000000241031360567320200314310ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Turkish (Turkey) (http://www.transifex.com/projects/p/kodi-main/language/tr_TR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: tr_TR\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "MythTV Arka Uç Ana Bilgisayar Adı veya IP'si" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "MythTV Arka Uç BaÄŸlantı Noktası" msgctxt "#30002" msgid "MythTV Database Username" msgstr "MythTV Veritabanı Kullanıcı Adı" msgctxt "#30003" msgid "MythTV Database Password" msgstr "MythTV Veritabanı Parolası" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "MythTV Veritabanı Adı" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Günlük dosyasına daha fazla hata ayıklama bilgisi ekle" msgctxt "#30006" msgid "Enable Live TV" msgstr "Canlı TV'yi etkinleÅŸtir" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Zamanlanmış ÅŸovları taşımak için Canlı TV'ye izin ver" msgctxt "#30008" msgid "Conflict handling" msgstr "Çakışma ele alma" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Kayıt daha sonra oynatılacaksa Canlı TV'yi tercih et" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Kaydı tercih et ve Live TV durdur" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Çakışan kaydı iptal et ve Canlı TV'yi tercih et" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "MythTV Arka Ucu Ethernet adresi (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "API hizmetleri için MythTV Arka Ucu Portu" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "API hizmetleri için MythTV Güvenlik Pin'i" msgctxt "#30019" msgid "General" msgstr "Genel" msgctxt "#30020" msgid "Template provider" msgstr "Åžablon saÄŸlayıcısı" msgctxt "#30021" msgid "Internal" msgstr "Dahili" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "Dahili ÅŸablon" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Metadata'ya Otomatik Olarak Bak" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Yeni kayıtlarda Reklam Bayrağı" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Yeni kayıtları dönüştür" msgctxt "#30029" msgid "Run User Job #1" msgstr "Kullanıcı çalışmaları #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Kullanıcı çalışmaları #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Kullanıcı çalışmaları #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Kullanıcı çalışmaları #4" msgctxt "#30033" msgid "Transcoder" msgstr "Dönüştürücü" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Kayıtların geçerliliÄŸini yitirmesine izin ver" msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "İzlenmiÅŸ kaydı silmeyi teklif et" msgctxt "#30048" msgid "Show 'Original Airdate' instead of 'Recording Time'" msgstr "'Kayıt Tarihi' yerine 'Yayın Tarihi'ni göster" msgctxt "#30049" msgid "Recording template" msgstr "Kaydetme ÅŸablonu" msgctxt "#30050" msgid "Advanced" msgstr "GeliÅŸmiÅŸ" msgctxt "#30051" msgid "Preferences" msgstr "Tercihler" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "MPEG-TS birleÅŸtirmesini etkinleÅŸtir" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Arama gecikmesi (sn)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Kayıtları baÅŸlığa göre grupla" msgctxt "#30055" msgid "Always" msgstr "Her zaman" msgctxt "#30056" msgid "Only for series" msgstr "Sadece diziler için" msgctxt "#30057" msgid "Never" msgstr "Asla" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Reklam atlamalarını etkinleÅŸtir (EDL)" msgctxt "#30059" msgid "Always" msgstr "Her zaman" msgctxt "#30060" msgid "Dialog" msgstr "İletiÅŸim Kutusu" msgctxt "#30061" msgid "Never" msgstr "Asla" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "Arka uç kapatmasını izin ver" msgctxt "#30063" msgid "Enable channel icons" msgstr "Kanal logolarını etkinleÅŸtir" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "Kayıt için fanart ve küçük resimleri etkinleÅŸtir " msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "Kanal düzeltme denemelerini sınırla" msgctxt "#30066" msgid "Show inactive upcomings (alternative/recorded/expired)" msgstr "Etkin olmayan yaklaÅŸanları göster (alternatif/kayıtlı/süresi dolan)" msgctxt "#30067" msgid "Show LiveTV recordings" msgstr "CanlıTV kayıtlarını göster" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Protokol sürümü: %i - Veritabanı sürümü: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "EDL EtkinleÅŸtirme" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "Bir kesinti listesi veya reklam atlamaları bulundu.\nBu ÅŸov için EDL özelliÄŸini etkinleÅŸtirmek istiyor musunuz?" msgctxt "#30112" msgid "Connection failed" msgstr "BaÄŸlantı baÅŸarısız" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "Yeniden denemek ister misiniz?" msgctxt "#30300" msgid "Failed to connect the MythTV backend with the known protocol versions. Please check the compatibility map of the addon and upgrade your backend to a supported version." msgstr "MythTV arka arayüzüne baÄŸlantı, bilinen protokol sürümleriyle baÅŸarısız oldu. Lütfen eklentinin uyumluluk haritasını kontrol edin ve arka arayüzünü desteklenen bir sürüme güncelleyin." msgctxt "#30301" msgid "Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. The PIN code has to be configured in your backend to allow connection." msgstr "MythTV arka arayüzünün uygulama hizmetlerine baÄŸlanılamadı. Arka arayüz kurulumunuzu veya PIN kodunuzu kontrol edin. BaÄŸlantıya izin vermek için PIN kodunun arka arayüzde yapılandırılması gerekir." msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "MythTV arka ucu baÄŸlantısı koptu" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "BaÄŸlantı düzenlendi." msgctxt "#30304" msgid "No response from MythTV backend" msgstr "MythTV arka ucundan cevap alınamıyor" msgctxt "#30305" msgid "Channel unavailable" msgstr "Kanal kullanılamıyor" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Kaydedici kullanılamıyor." msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Çakışan kayıt iptal ediliyor: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Çakışan kayıtlar nedeniyle Canlı TV durduruluyor: %s" msgctxt "#30309" msgid "Not recording" msgstr "Kaydedilemedi." msgctxt "#30310" msgid "Enabled" msgstr "Etkin" msgctxt "#30311" msgid "Disabled" msgstr "Devre dışı" msgctxt "#30312" msgid "No broadcast found" msgstr "Hiçbir yayın bulunamadı" msgctxt "#30411" msgid "Delete and re-record" msgstr "Sil ve yeniden kaydet" msgctxt "#30412" msgid "Keep recording" msgstr "Kayda devam et" msgctxt "#30421" msgid "Toggle display of alternative/recorded/expired" msgstr "Alternatif/kayıtlı/süresi dolan görünümleri arasında geçiÅŸ yap" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "Kanal logoları için önbelleÄŸi tazele" msgctxt "#30423" msgid "Trigger channels update" msgstr "Kanal güncellemelerini baÅŸlat" msgctxt "#30424" msgid "Show status of scheduling" msgstr "Zamanlamadaki son durumu göster" msgctxt "#30451" msgid "Unhandled" msgstr "İşlenmedi" msgctxt "#30452" msgid "Upcoming" msgstr "Gelecek" msgctxt "#30453" msgid "Overriden" msgstr "Üstüne yazılmış" msgctxt "#30454" msgid "Don't record" msgstr "Kaydetme" msgctxt "#30455" msgid "Upcoming manual" msgstr "Gelecek program kılavuzu" msgctxt "#30456" msgid "Zombie" msgstr "Zombi" msgctxt "#30457" msgid "Alternative" msgstr "Alternatif" msgctxt "#30458" msgid "Currently recorded" msgstr "Åžu an kaydedilen" msgctxt "#30459" msgid "Expired recording" msgstr "Süresi dolan kayıt" msgctxt "#30460" msgid "Manual" msgstr "El ile" msgctxt "#30461" msgid "Record one" msgstr "Bir tane kaydet" msgctxt "#30462" msgid "Record weekly" msgstr "Haftalık kaydet" msgctxt "#30463" msgid "Record daily" msgstr "Günlük kaydet" msgctxt "#30464" msgid "Record all" msgstr "Hepsini kaydet" msgctxt "#30465" msgid "Record this" msgstr "Bunu kaydet" msgctxt "#30466" msgid "Record series" msgstr "Diziyi kaydet" msgctxt "#30467" msgid "Search keyword" msgstr "Anahtar sözcük ara" msgctxt "#30468" msgid "Search people" msgstr "KiÅŸi ara" msgctxt "#30469" msgid "Rule disabled" msgstr "Kural devre dışı" msgctxt "#30501" msgid "Don't match duplicates" msgstr "Kopyaları eÅŸleÅŸtirme" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "Altyazı kullanarak kopyaları eÅŸleÅŸtir" msgctxt "#30503" msgid "Match duplicates using description" msgstr "Açıklama kullanarak kopyaları eÅŸleÅŸtir" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "Altyazı ve açıklama kullanarak kopyaları eÅŸleÅŸtir" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "Önce altyazı, sonra açıklama kullanarak kopyaları eÅŸleÅŸtir" msgctxt "#30506" msgid "Recordings never expire" msgstr "Kayıtların süresi dolmasın" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Kayıtların geçerliliÄŸini yitirmesine izin ver" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "%d kayda kadar sakla" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "%d en yeniyi sakla, eskilerin süresi dolsun" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.uk_ua/000077500000000000000000000000001360567320200273525ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.uk_ua/strings.po000066400000000000000000000136351360567320200314130ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Ukrainian (Ukraine) (http://www.transifex.com/projects/p/kodi-main/language/uk_UA/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: uk_UA\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "Ðазва Ñервера MythTV або IP" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "Порт MythTV" msgctxt "#30002" msgid "MythTV Database Username" msgstr "Ðазва кориÑтувача до бази даних MythTV" msgctxt "#30003" msgid "MythTV Database Password" msgstr "Пароль бази даних Myth TV" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "Логін до бази даних Myth TV" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Додати більше інформації в файл журналу" msgctxt "#30006" msgid "Enable Live TV" msgstr "Включити Live TV" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Дозволити Live TV переміщувати заплановані шоу" msgctxt "#30008" msgid "Conflict handling" msgstr "Ð’Ð¸Ñ€Ñ–ÑˆÐµÐ½Ð½Ñ ÐºÐ¾Ð½Ñ„Ð»Ñ–ÐºÑ‚Ñ–Ð²" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Ðадати перевагу Live TV, коли запиÑи Ñ” в пізнішому терміні" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Ðадати перевагу запиÑу Ñ– зупинки Live TV" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Ðадати перевагу Live TV Ñ– ÑкаÑувати Ñуперечливі запиÑи" msgctxt "#30019" msgid "General" msgstr "Загальні" msgctxt "#30020" msgid "Template provider" msgstr "ПоÑтачальник шаблонів" msgctxt "#30021" msgid "Internal" msgstr "Внутрішній" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "Внутрішній шаблон" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Ðвтоматичний пошук метаданих" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Перекодовувати нові запиÑи" msgctxt "#30029" msgid "Run User Job #1" msgstr "ЗапуÑк Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "ЗапуÑк Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "ЗапуÑк Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "ЗапуÑк Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача #4" msgctxt "#30033" msgid "Transcoder" msgstr "Перекодовувач" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Дозволити запиÑам згаÑати" msgctxt "#30049" msgid "Recording template" msgstr "Шаблон запиÑу" msgctxt "#30050" msgid "Advanced" msgstr "Більше" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "Ввімкнути демультиплекÑÑƒÐ²Ð°Ð½Ð½Ñ MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "Тонке Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ (Ñек)" msgctxt "#30054" msgid "Group recordings by title" msgstr "Групувати запиÑи за назвою" msgctxt "#30055" msgid "Always" msgstr "Завжди" msgctxt "#30056" msgid "Only for series" msgstr "Тільки Ð´Ð»Ñ Ñеріалів" msgctxt "#30057" msgid "Never" msgstr "Ðіколи" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "Включити пропуÑк реклами (EDL)" msgctxt "#30059" msgid "Always" msgstr "Завжди" msgctxt "#30061" msgid "Never" msgstr "Ðіколи" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "дозволÑти фонове вимиканнÑ" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "ВерÑÑ–Ñ Ð¿Ñ€Ð¾Ñ‚Ð¾ÐºÐ¾Ð»Ñƒ: %i - ВерÑÑ–Ñ Ð´Ð°Ð½Ð¸Ñ…: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "Ð’Ð²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð½Ñ EDL" msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Зв’Ñзок з MythTV втрачено" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Зв’Ñзок з MythTV відновлено" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "Ðемає відгуку від MythTV" msgctxt "#30305" msgid "Channel unavailable" msgstr "Канал недоÑтупний" msgctxt "#30306" msgid "Recorder unavailable" msgstr "ЗапиÑувач недоÑтупний" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "СкаÑÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ñ„Ð»Ñ–ÐºÑ‚Ð½Ð¸Ñ… запиÑів: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Зупинка Живого Ð¢ÐµÐ»ÐµÐ±Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ–Ð·-за конфліктних запиÑів: %s" msgctxt "#30309" msgid "Not recording" msgstr "Ðе запиÑувати" msgctxt "#30310" msgid "Enabled" msgstr "Увімкн." msgctxt "#30311" msgid "Disabled" msgstr "Вимкн." msgctxt "#30312" msgid "No broadcast found" msgstr "Ðе знайдено транÑлÑції" msgctxt "#30411" msgid "Delete and re-record" msgstr "Видалити Ñ– перезапиÑати" msgctxt "#30460" msgid "Manual" msgstr "Уручну" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Дозволити запиÑам згаÑати" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.uz_uz/000077500000000000000000000000001360567320200274225ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.uz_uz/strings.po000066400000000000000000000020521360567320200314520ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Uzbek (Uzbekistan) (http://www.transifex.com/projects/p/kodi-main/language/uz_UZ/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: uz_UZ\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30019" msgid "General" msgstr "Umumiy" msgctxt "#30055" msgid "Always" msgstr "Doim" msgctxt "#30057" msgid "Never" msgstr "Hech qachon" msgctxt "#30059" msgid "Always" msgstr "Doim" msgctxt "#30061" msgid "Never" msgstr "Hech qachon" msgctxt "#30305" msgid "Channel unavailable" msgstr "Kanal mavjud emas" msgctxt "#30310" msgid "Enabled" msgstr "Yoqilgan" msgctxt "#30460" msgid "Manual" msgstr "Qo‘lda" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.vi_vn/000077500000000000000000000000001360567320200273675ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.vi_vn/strings.po000066400000000000000000000106471360567320200314300ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Vietnamese (Viet Nam) (http://www.transifex.com/projects/p/kodi-main/language/vi_VN/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: vi_VN\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "Tên miá»n hoặc IP cá»§a MythTV" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "Cổng MythTV" msgctxt "#30002" msgid "MythTV Database Username" msgstr "Tài khoản truy cập cÆ¡ sở dữ liệu MythTV" msgctxt "#30003" msgid "MythTV Database Password" msgstr "Mật khẩu truy cập cÆ¡ sở dữ liệu MythTV" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "Tên cÆ¡ sở dữ liệu MythTV" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "Thêm thông tin sá»­a lá»—i chương trình vào báo cáo" msgctxt "#30006" msgid "Enable Live TV" msgstr "Sá»­ dụng Live TV" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "Cho phép Live TV thay đổi chương trình đã hẹn giá»" msgctxt "#30008" msgid "Conflict handling" msgstr "Giải quyết xung đột" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "Ưu tiên Live TV khi bản Ä‘ang thu có thể chiếu lại" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "Ưu tiên bản thu và dừng Live TV" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "Ưu tiên Live TV và há»§y xung đột bản thu" msgctxt "#30019" msgid "General" msgstr "Chung" msgctxt "#30020" msgid "Template provider" msgstr "Nguồn Template" msgctxt "#30021" msgid "Internal" msgstr "Äi kèm" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "Template Ä‘i kèm" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "Tá»± động tìm kiếm dữ liệu" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "Äánh dấu thương mại hóa cho các bản thu má»›i" msgctxt "#30028" msgid "Transcode new recordings" msgstr "Chuyển mã các bản thu má»›i" msgctxt "#30029" msgid "Run User Job #1" msgstr "Chạy tác vụ ngưá»i dùng #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "Chạy tác vụ ngưá»i dùng #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "Chạy tác vụ ngưá»i dùng #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "Chạy tác vụ ngưá»i dùng #4" msgctxt "#30033" msgid "Transcoder" msgstr "Bá»™ chuyển mã" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "Cho phép các bản thu hết hạn" msgctxt "#30049" msgid "Recording template" msgstr "Mẫu cho bản thu" msgctxt "#30050" msgid "Advanced" msgstr "Nâng cao" msgctxt "#30055" msgid "Always" msgstr "Luôn luôn" msgctxt "#30057" msgid "Never" msgstr "Không bao giá»" msgctxt "#30059" msgid "Always" msgstr "Luôn luôn" msgctxt "#30061" msgid "Never" msgstr "Không bao giá»" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "Protocol version: %i - Database version: %i" msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "Mất kết nối tá»›i MythTV" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "Äã khôi phục lại kết nối tá»›i MythTV" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "Không có tín hiệu từ MythTV" msgctxt "#30305" msgid "Channel unavailable" msgstr "Không có tín hiệu" msgctxt "#30306" msgid "Recorder unavailable" msgstr "Lá»—i đầu thu" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "Äang há»§y xung đột bản thu: %s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "Äang dừng Live TV vì lá»—i xung đột bản thu: %s" msgctxt "#30310" msgid "Enabled" msgstr "Äã bật" msgctxt "#30311" msgid "Disabled" msgstr "Äã tắt" msgctxt "#30460" msgid "Manual" msgstr "Thá»§ công" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "Cho phép các bản thu hết hạn" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.zh_cn/000077500000000000000000000000001360567320200273475ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.zh_cn/strings.po000066400000000000000000000217021360567320200314020ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Chinese (China) (http://www.transifex.com/projects/p/kodi-main/language/zh_CN/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: zh_CN\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "MythTV åŽç«¯ä¸»æœºå或 IP 地å€" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "MythTV åŽç«¯ç«¯å£" msgctxt "#30002" msgid "MythTV Database Username" msgstr "MythTV æ•°æ®åº“用户å" msgctxt "#30003" msgid "MythTV Database Password" msgstr "MythTV æ•°æ®åº“密ç " msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "MythTV æ•°æ®åº“库å" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "日志文件记录更多调试信æ¯" msgctxt "#30006" msgid "Enable Live TV" msgstr "å¯ç”¨ç›´æ’­ç”µè§†" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "å…许直播电视移动预定节目" msgctxt "#30008" msgid "Conflict handling" msgstr "冲çªå¤„ç†" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "å½“å½•åƒæŽ¨è¿Ÿæ—¶ç»§ç»­ç›´æ’­ç”µè§†" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "åœæ­¢ç›´æ’­ç”µè§†ä»¥ç»§ç»­å½•åƒ" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "å–æ¶ˆå†²çªå½•åƒä»¥ç»§ç»­ç›´æ’­ç”µè§†" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "MythTV åŽç«¯ç½‘络地å€ï¼ˆWOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "针对 API æœåŠ¡çš„ MythTV åŽç«¯ç«¯å£" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "针对 API æœåŠ¡çš„ MythTV 安全ç " msgctxt "#30019" msgid "General" msgstr "常规" msgctxt "#30020" msgid "Template provider" msgstr "æ¨¡æ¿æ¥æº" msgctxt "#30021" msgid "Internal" msgstr "内置" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "内置模æ¿" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "自动查找元数æ®" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "广告标记新录åƒ" msgctxt "#30028" msgid "Transcode new recordings" msgstr "è½¬ç æ–°å½•åƒ" msgctxt "#30029" msgid "Run User Job #1" msgstr "è¿è¡Œç”¨æˆ·ä»»åŠ¡ #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "è¿è¡Œç”¨æˆ·ä»»åŠ¡ #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "è¿è¡Œç”¨æˆ·ä»»åŠ¡ #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "è¿è¡Œç”¨æˆ·ä»»åŠ¡ #4" msgctxt "#30033" msgid "Transcoder" msgstr "转ç å™¨" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "å…许录åƒè¿‡æœŸ" msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "æç¤ºåˆ é™¤è§‚看过的录相" msgctxt "#30048" msgid "Show 'Original Airdate' instead of 'Recording Time'" msgstr "显示“原始播出时间â€è€Œä¸æ˜¯â€œå½•制时间â€" msgctxt "#30049" msgid "Recording template" msgstr "å½•åƒæ¨¡æ¿" msgctxt "#30050" msgid "Advanced" msgstr "高级" msgctxt "#30051" msgid "Preferences" msgstr "å好设置" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "å¯ç”¨åˆ†ç¦» MPEG-TS" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "æ¢å°å»¶è¿Ÿï¼ˆç§’)" msgctxt "#30054" msgid "Group recordings by title" msgstr "按标题分组录åƒ" msgctxt "#30055" msgid "Always" msgstr "总是" msgctxt "#30056" msgid "Only for series" msgstr "仅系列" msgctxt "#30057" msgid "Never" msgstr "从ä¸" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "å¯ç”¨è·³è¿‡å¹¿å‘Šï¼ˆEDL)" msgctxt "#30059" msgid "Always" msgstr "总是" msgctxt "#30060" msgid "Dialog" msgstr "对è¯" msgctxt "#30061" msgid "Never" msgstr "从ä¸" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "å…许åŽç«¯å…³æœº" msgctxt "#30063" msgid "Enable channel icons" msgstr "å¯ç”¨é¢‘é“图标" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "å¯ç”¨å½•åƒåŒäººç”»/缩略图" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "é™åˆ¶é¢‘é“è°ƒè°å°è¯•" msgctxt "#30066" msgid "Show inactive upcomings (alternative/recorded/expired)" msgstr "æ˜¾ç¤ºéžæ´»åŠ¨çš„å³æœŸäº‹é¡¹ï¼ˆæ›¿ä»£/已录制/已过期)" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "å议版本:%i - æ•°æ®åº“版本:%i" msgctxt "#30110" msgid "Enabling EDL" msgstr "EDL å¯ç”¨ä¸­" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "å‘现剪辑表或广告过滤,\n对此节目激活 EDL 功能å—?" msgctxt "#30112" msgid "Connection failed" msgstr "连接失败" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "è¦é‡è¯•å—?" msgctxt "#30300" msgid "Failed to connect the MythTV backend with the known protocol versions. Please check the compatibility map of the addon and upgrade your backend to a supported version." msgstr "用已知å议版本连接 MythTV åŽç«¯å¤±è´¥ã€‚请查看æ’件兼容信æ¯å¹¶å‡çº§åŽç«¯ä¸ºæ”¯æŒçš„版本。" msgctxt "#30301" msgid "Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. The PIN code has to be configured in your backend to allow connection." msgstr "连接 MythTV åŽç«¯çš„ API æœåŠ¡å¤±è´¥ã€‚è¯·æ£€æŸ¥ PIN ç æˆ–åŽç«¯è®¾ç½®ã€‚åŽç«¯éœ€è®¾ç½® PIN ç ä»¥å…许连接。" msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "MythTV åŽç«¯è¿žæŽ¥ä¸¢å¤±" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "MythTV 连接已æ¢å¤" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "MythTV åŽç«¯æ— å“应" msgctxt "#30305" msgid "Channel unavailable" msgstr "频é“ä¸å¯ç”¨" msgctxt "#30306" msgid "Recorder unavailable" msgstr "å½•åƒæœºä¸å¯ç”¨" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "æ­£å–æ¶ˆå†²çªå½•åƒï¼š%s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "åœæ­¢ç›´æ’­ç”µè§†äºŽå†²çªå½•åƒï¼š%s" msgctxt "#30309" msgid "Not recording" msgstr "未录制" msgctxt "#30310" msgid "Enabled" msgstr "å¯ç”¨" msgctxt "#30311" msgid "Disabled" msgstr "ç¦ç”¨" msgctxt "#30312" msgid "No broadcast found" msgstr "无播出" msgctxt "#30411" msgid "Delete and re-record" msgstr "åˆ é™¤é‡æ–°å½•åƒ" msgctxt "#30412" msgid "Keep recording" msgstr "ä¿ç•™å½•åƒ" msgctxt "#30421" msgid "Toggle display of alternative/recorded/expired" msgstr "åˆ‡æ¢æ˜¾ç¤ºæ›¿ä»£/已录制/已过期" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "刷新频é“图标缓存" msgctxt "#30423" msgid "Trigger channels update" msgstr "触å‘频铿›´æ–°" msgctxt "#30424" msgid "Show status of scheduling" msgstr "显示预约状æ€" msgctxt "#30451" msgid "Unhandled" msgstr "未处ç†" msgctxt "#30452" msgid "Upcoming" msgstr "å³å°†æ’­å‡º" msgctxt "#30453" msgid "Overriden" msgstr "覆盖" msgctxt "#30454" msgid "Don't record" msgstr "ä¸å½•制" msgctxt "#30455" msgid "Upcoming manual" msgstr "å³å°†æ’­å‡ºæ‰‹åЍ" msgctxt "#30456" msgid "Zombie" msgstr "僵尸" msgctxt "#30457" msgid "Alternative" msgstr "替代" msgctxt "#30458" msgid "Currently recorded" msgstr "当å‰å·²å½•制" msgctxt "#30459" msgid "Expired recording" msgstr "已过期录åƒ" msgctxt "#30460" msgid "Manual" msgstr "手动" msgctxt "#30461" msgid "Record one" msgstr "啿¬¡å½•åƒ" msgctxt "#30462" msgid "Record weekly" msgstr "æ¯å‘¨å½•åƒ" msgctxt "#30463" msgid "Record daily" msgstr "æ¯æ—¥å½•åƒ" msgctxt "#30464" msgid "Record all" msgstr "全部录制" msgctxt "#30465" msgid "Record this" msgstr "录制这个" msgctxt "#30466" msgid "Record series" msgstr "剧集录åƒ" msgctxt "#30467" msgid "Search keyword" msgstr "æœç´¢å…³é”®å­—" msgctxt "#30468" msgid "Search people" msgstr "æœç´¢äºº" msgctxt "#30469" msgid "Rule disabled" msgstr "å·²ç¦ç”¨è§„则" msgctxt "#30501" msgid "Don't match duplicates" msgstr "ä¸åŒ¹é…é‡å¤é¡¹" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "使用字幕匹é…é‡å¤" msgctxt "#30503" msgid "Match duplicates using description" msgstr "使用介ç»åŒ¹é…é‡å¤" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "使用字幕和介ç»åŒ¹é…é‡å¤" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "先用字幕然åŽç”¨ä»‹ç»åŒ¹é…é‡å¤" msgctxt "#30506" msgid "Recordings never expire" msgstr "å½•åƒæ°¸ä¸è¿‡æœŸ" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "å…许录åƒè¿‡æœŸ" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "ä¿ç•™ %d 录åƒ" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "ä¿ç•™ %d 新的并过期旧的" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.zh_tw/000077500000000000000000000000001360567320200274015ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/language/resource.language.zh_tw/strings.po000066400000000000000000000226231360567320200314370ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: MythTV PVR Client # Addon id: pvr.mythtv # Addon Provider: Christian Fetzer, Jean-Luc Barrière msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Chinese (Taiwan) (http://www.transifex.com/projects/p/kodi-main/language/zh_TW/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: zh_TW\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30000" msgid "MythTV Backend Hostname or IP" msgstr "MythTV的後端主機å稱或IP" msgctxt "#30001" msgid "MythTV Backend Port" msgstr "MythTV的後端端å£" msgctxt "#30002" msgid "MythTV Database Username" msgstr "MythTV 資料庫帳號" msgctxt "#30003" msgid "MythTV Database Password" msgstr "MythTV 資料庫密碼" msgctxt "#30004" msgid "MythTV Database Databasename" msgstr "MythTV 資料庫å稱" msgctxt "#30005" msgid "Include more debug information in the log file" msgstr "åœ¨æ—¥èªŒæª”æ¡ˆä¸­åŒ…å«æ›´å¤šé™¤éŒ¯è³‡è¨Š" msgctxt "#30006" msgid "Enable Live TV" msgstr "啟用電視直播" msgctxt "#30007" msgid "Allow Live TV to move scheduled shows" msgstr "å…許電視直播移動已排程節目" msgctxt "#30008" msgid "Conflict handling" msgstr "è¡çªè™•ç†" msgctxt "#30009" msgid "Prefer Live TV when recording has later slot" msgstr "ç•¶éŒ„å½±å»¶é²æ™‚繼續直播電視" msgctxt "#30010" msgid "Prefer recording and stop Live TV" msgstr "åœæ­¢ç›´æ’­é›»è¦–以繼續錄影" msgctxt "#30011" msgid "Prefer Live TV and cancel conflicting recording" msgstr "å–æ¶ˆè¡çªéŒ„影以繼續直播電視" msgctxt "#30012" msgid "MythTV Backend Ethernet address (WOL)" msgstr "MythTV 後端網路ä½å€ (WOL)" msgctxt "#30013" msgid "MythTV Backend Port for API services" msgstr "指定給APIæœå‹™çš„MythTV 後端連接埠" msgctxt "#30014" msgid "MythTV Security Pin for API services" msgstr "指定給APIæœå‹™çš„MythTV ä¿å…¨Pin碼" msgctxt "#30019" msgid "General" msgstr "一般設定" msgctxt "#30020" msgid "Template provider" msgstr "範本æä¾›è€…" msgctxt "#30021" msgid "Internal" msgstr "內部的" msgctxt "#30022" msgid "MythTV" msgstr "MythTV" msgctxt "#30025" msgid "Internal template" msgstr "內部的範本" msgctxt "#30026" msgid "Automatically Look Up Metadata" msgstr "自動查找數據資料" msgctxt "#30027" msgid "Commercial Flag new recordings" msgstr "åœ¨æ–°çš„éŒ„å½±ä¸­æ¨™ç¤ºå»£å‘Šå€æ®µ" msgctxt "#30028" msgid "Transcode new recordings" msgstr "å°æ–°éŒ„影進行轉碼" msgctxt "#30029" msgid "Run User Job #1" msgstr "執行使用者定義作業 #1" msgctxt "#30030" msgid "Run User Job #2" msgstr "執行使用者定義作業 #2" msgctxt "#30031" msgid "Run User Job #3" msgstr "執行使用者定義作業 #3" msgctxt "#30032" msgid "Run User Job #4" msgstr "執行使用者定義作業 #4" msgctxt "#30033" msgid "Transcoder" msgstr "轉碼器" msgctxt "#30034" msgid "Allow recordings to expire" msgstr "å…è¨±éŒ„å½±éŽæœŸ" msgctxt "#30047" msgid "Prompt to delete the watched recording" msgstr "刪除已看éŽçš„錄影å‰å…ˆæç¤º" msgctxt "#30048" msgid "Show 'Original Airdate' instead of 'Recording Time'" msgstr "顯示\"原始的播出時間\"è€Œä¸æ˜¯\"錄影當下時間\"" msgctxt "#30049" msgid "Recording template" msgstr "錄影範本" msgctxt "#30050" msgid "Advanced" msgstr "進階" msgctxt "#30051" msgid "Preferences" msgstr "喜好設定" msgctxt "#30052" msgid "Enable demuxing MPEG-TS" msgstr "開啟 MPEG-TS 影音分離處ç†" msgctxt "#30053" msgid "Tuning delay (sec)" msgstr "é¸å°å»¶é² (ç§’)" msgctxt "#30054" msgid "Group recordings by title" msgstr "ä¾å稱來歸類錄影檔" msgctxt "#30055" msgid "Always" msgstr "總是" msgctxt "#30056" msgid "Only for series" msgstr "僅é©ç”¨ç³»åˆ—影集" msgctxt "#30057" msgid "Never" msgstr "æ°¸ä¸" msgctxt "#30058" msgid "Enable commercial skips (EDL)" msgstr "開啟跳éŽå»£å‘Šå€æ®µåŠŸèƒ½ (EDL)" msgctxt "#30059" msgid "Always" msgstr "總是" msgctxt "#30060" msgid "Dialog" msgstr "å°è©±æ¡†" msgctxt "#30061" msgid "Never" msgstr "æ°¸ä¸" msgctxt "#30062" msgid "Allow backend shutdown" msgstr "å…許後端關機" msgctxt "#30063" msgid "Enable channel icons" msgstr "開啟頻é“圖示" msgctxt "#30064" msgid "Enable recording fanart/thumbnails" msgstr "開啟錄影檔的劇照/縮圖" msgctxt "#30065" msgid "Limit channel tuning attempts" msgstr "é™åˆ¶é¸å°å‹•作" msgctxt "#30066" msgid "Show inactive upcomings (alternative/recorded/expired)" msgstr "é¡¯ç¤ºå·²ä¸æ´»èºçš„下集é å‘Š(æœ‰å…¶ä»–é¸æ“‡/已錄製/éŽæœŸ)" msgctxt "#30067" msgid "Show LiveTV recordings" msgstr "顯示直播電視的錄影檔" msgctxt "#30100" msgid "Protocol version: %i - Database version: %i" msgstr "通訊å”定版本: %i - 資料庫版本: %i" msgctxt "#30110" msgid "Enabling EDL" msgstr "開啟 EDL" msgctxt "#30111" msgid "A cut list or commercial skips have been found.\nDo you want to activate EDL functionality for this show ?" msgstr "嵿¸¬åˆ°å‰ªæŽ¥è™•åˆ—è¡¨æˆ–å»£å‘Šå€æ®µæ¨™ç¤ºã€‚ä½ è¦ç‚ºæœ¬å½±ç‰‡å•Ÿç”¨EDL功能嗎?" msgctxt "#30112" msgid "Connection failed" msgstr "連接失敗" msgctxt "#30113" msgid "Do you want to retry ?" msgstr "您è¦é‡è©¦å—Žï¼Ÿ" msgctxt "#30300" msgid "Failed to connect the MythTV backend with the known protocol versions. Please check the compatibility map of the addon and upgrade your backend to a supported version." msgstr "無法使用已知的通訊å”定版本來連接MythTV後端。請查看附加元件中的支æ´åˆ—表並將您的後端å‡ç´šè‡³å¯æ”¯æ´çš„版本。" msgctxt "#30301" msgid "Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. The PIN code has to be configured in your backend to allow connection." msgstr "無法連接至MythTV後端的APIæœå‹™ã€‚請檢查您的PIN碼或後端設定。後端需設定PIN碼æ‰èƒ½å…許連接。" msgctxt "#30302" msgid "Connection to MythTV backend lost" msgstr "MythTV後端連線中斷" msgctxt "#30303" msgid "Connection to MythTV restored" msgstr "MythTV連線已æ¢å¾©" msgctxt "#30304" msgid "No response from MythTV backend" msgstr "MythTV後端無回應" msgctxt "#30305" msgid "Channel unavailable" msgstr "找ä¸åˆ°é »é“" msgctxt "#30306" msgid "Recorder unavailable" msgstr "錄影無法å–å¾—" msgctxt "#30307" msgid "Canceling conflicting recording: %s" msgstr "å–æ¶ˆè¡çªéŒ„影:%s" msgctxt "#30308" msgid "Stopping Live TV due to conflicting recording: %s" msgstr "正在終止電視直播,因為è¡çªåˆ°éŒ„影:%s" msgctxt "#30309" msgid "Not recording" msgstr "未執行錄影" msgctxt "#30310" msgid "Enabled" msgstr "啟用" msgctxt "#30311" msgid "Disabled" msgstr "關閉" msgctxt "#30312" msgid "No broadcast found" msgstr "未找到廣播" msgctxt "#30411" msgid "Delete and re-record" msgstr "åˆªé™¤ä¸¦é‡æ–°éŒ„製" msgctxt "#30412" msgid "Keep recording" msgstr "ä¿ç•™éŒ„影檔" msgctxt "#30421" msgid "Toggle display of alternative/recorded/expired" msgstr "切æ›é¡¯ç¤ºæœ‰å…¶ä»–鏿“‡çš„/已錄製的/éŽæœŸçš„" msgctxt "#30422" msgid "Refresh cache for channel icons" msgstr "æ›´æ–°é »é“圖示的快å–資料" msgctxt "#30423" msgid "Trigger channels update" msgstr "å•Ÿå‹•é »é“æ›´æ–°" msgctxt "#30424" msgid "Show status of scheduling" msgstr "顯示排程的狀態" msgctxt "#30451" msgid "Unhandled" msgstr "未å—管ç†" msgctxt "#30452" msgid "Upcoming" msgstr "新番é å‘Š" msgctxt "#30453" msgid "Overriden" msgstr "被覆蓋的" msgctxt "#30454" msgid "Don't record" msgstr "ä¸è¦éŒ„å½±" msgctxt "#30455" msgid "Upcoming manual" msgstr "手動更新新番" msgctxt "#30456" msgid "Zombie" msgstr "ä¸å†æ›´æ–°çš„çš„" msgctxt "#30457" msgid "Alternative" msgstr "æœ‰å…¶ä»–é¸æ“‡çš„" msgctxt "#30458" msgid "Currently recorded" msgstr "ç›®å‰éŒ„影的" msgctxt "#30459" msgid "Expired recording" msgstr "å·²éŽæœŸçš„錄影" msgctxt "#30460" msgid "Manual" msgstr "手動" msgctxt "#30461" msgid "Record one" msgstr "錄一次" msgctxt "#30462" msgid "Record weekly" msgstr "æ¯é€±éŒ„å½±" msgctxt "#30463" msgid "Record daily" msgstr "æ¯å¤©éŒ„å½±" msgctxt "#30464" msgid "Record all" msgstr "全部錄影" msgctxt "#30465" msgid "Record this" msgstr "錄製本集" msgctxt "#30466" msgid "Record series" msgstr "錄製系列影集" msgctxt "#30467" msgid "Search keyword" msgstr "æœå°‹é—œéµå­—" msgctxt "#30468" msgid "Search people" msgstr "æœå°‹äººå" msgctxt "#30469" msgid "Rule disabled" msgstr "è¦å‰‡å·²ç¦ç”¨" msgctxt "#30501" msgid "Don't match duplicates" msgstr "ä¸è¦åšé‡è¤‡æ¯”å°" msgctxt "#30502" msgid "Match duplicates using subtitle" msgstr "使用字幕內容進行é‡è¤‡æ¯”å°" msgctxt "#30503" msgid "Match duplicates using description" msgstr "使用æè¿°å…§å®¹é€²è¡Œé‡è¤‡æ¯”å°" msgctxt "#30504" msgid "Match duplicates using subtitle & description" msgstr "ä½¿ç”¨å­—å¹•åŠæè¿°å…§å®¹é€²è¡Œé‡è¤‡æ¯”å°" msgctxt "#30505" msgid "Match duplicates using subtitle then description" msgstr "先使用字幕,å†ç”¨æè¿°å…§å®¹é€²è¡Œé‡è¤‡æ¯”å°" msgctxt "#30506" msgid "Recordings never expire" msgstr "錄影檔永ä¸éŽæœŸ" msgctxt "#30507" msgid "Allow recordings to expire" msgstr "å…è¨±éŒ„å½±æª”éŽæœŸ" msgctxt "#30508" msgid "Keep up to %d recordings" msgstr "ä¿ç•™æœ€å¤š %d個錄影檔" msgctxt "#30509" msgid "Keep %d newest and expire old" msgstr "ä¿ç•™%då€‹æœ€æ–°çš„ä¸¦è®“èˆŠçš„éŽæœŸ" pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/recording.png000066400000000000000000000155001360567320200235360ustar00rootroot00000000000000‰PNG  IHDR¡(Ea™ pHYs  šœtIMEÞ  '4 Â/µtEXtCommentCreated with GIMPWºIDATxÚí{xå½Ç¿ïÌì., ·$D@TP©>-jÕSkESk­V ™Ù5ñ‚zŠOOO+DðXYBOÅ*X²3­E­µ6­ÖViÅ#>UðÈ].¹ ¹îμçì’„$€…wfv÷·ÿˆÉ‡÷òy÷½|÷†¯p8Œ@ €pظàyѨù5ƒEŽ0Æ:0÷â<âˆ#Îu\»¢H;éõ@@ý4ÖhǸ^Ñ0Œ‹9ÇËœã<˲’$õùñÇþGq ÃíØ MËß¡P1¤øwtÝx€sü ù‰#.I¹ó¾Õ0Œ;cÿïa]SãfÆð:˜&UqÄ%3óüæòòò?°•+ÿÊ23+, û/3F•EqÉ*?ç3UQ23+Š‘1v‚¿I•Jq‰-¿eY1Ï!ëºñà6λöOe®%‰>ÕÐÐ0µ  89Ôž:ùOµÝâò@ 0££©©)¬iêuû÷Wù:;#Eœc_ªœ 0]7øñ_L¦0çüo,(n=©Ï§ëÆ-V˜Dò÷‹í¶,sÁ¶mÿ÷ΰaÃÒcÕ"Ûc ®¨hî~Ã(Â9ÀõÉ*¿3€d‘ß4ÍÍ--G¯*(^ãù =}è뚦žkšÖM¦iV“üÝ“&Îq½¦©çVVúhøðáéNÉÛçÖš¦æIÆø Ùä'{ ñsÂïl5­­m·íÝ»÷–ææ£[ŽÛÁwL~¸ùæ› ûªªª¶íܹó"ÆØ©.?ç¸WÓÔ³*++ß…ŠÏ¶³=NÄišÿýökšú-Ó4¯³,«.9äç}gñ$`bw6þø_츨¡¡þ¿ßߨs­ç´üÇsC‡mµç+*FJ^KAù_«¬!꯻ö`xŽ[äïùRU56hÚ½k×® $‰-Jô$ Ð}ô/uO:|¸³³óÜÊW šæw[':7vl×4õV·¤ü·hšzëܹßånkqiiiGm!cl"€ºÄ[ÇåOª$ û­¦©Y55‡#²,ɉ$?äçç£kÊ©¾ÑÚÚ:Ò4̓I,ÿ^Ód隦¾áÖö8Î4ͽš¦Žðf"¶GŸMÀN.дüwÓÚñt¸úú†´ƒ|S’¤?&¡üÔ4u¢$ñ£‰,?ƒ†MSÀ9_Dw:óÎ?ã·¿ÝJùãœÇã­ Ôc«“E~ÆØ*MSo0 €šÐò¿7°oßþÕ‘HäGt' ½òOÿüó­o\vÙec“Iþ8WVVUÍ¿À²$xç_¦ªù÷w•)9äïÉy<e÷î=/0Ƨ'âŒ-“€×îܹóýŒŒa¹É(?äå塬¬ š¦ÎPœÀòkš:¿¬¬ yyyI'œ{òÉ'"𦽠°é‰v*hwÎúì³­ïûýþ¤•?þÊËË‹o΋FÍ (ÿ:MSç%»ü=9MË€š(ò÷;¸8 øóU«Ö¾2|øð³’]þž\(T|öž={$éï $ÿ&MS V®\™2òwj)ç|1%Ï,÷;MS¿ñÆëƦ’üq.=Ý$P¯p8ä¯Ñ4õßÂá0æÌ™“RòǹíÛw>Ã9'’€Ç> ÿ¢ Ã@Õ[¶l“sV*ÊçÖ­ CQ䱜ón^c2†±+WÕü””?ÎYVgå¸q*Œr“üÝw²î > ¸1`šÑ ªªª[SYþžß×uc6€U.]cÎÖ4õ…Tj¸©S§v466LäœïvÓŒ->Ãï³àFù-‹?Y^^ÙLò÷Zc®øfÊ¿™äïæn¼ñ¨jþÆð¸Ûfl}6Ý(?€êíÛ·?%˲Lòw¿–/_ákhh|À…L7’ü}9UUà%¿"×ÒÒzßСCýÔ‰zsœóœææ£u’Ä–¹HþEš¦Ö“ü}¹·Þz –eåSð«]æñAeeåGÔ‰úç$Iª ´ùÚ\Ðn­š¦.$ùûç¶nýÜ·{÷ž/8ç§$à)r­­-óÜ@è¤ÜOo7ö“eË–S{œ€óûýƒÌ¦;Oñ¿‚‚à5pø&ÃxÅÃyä2Æ0…s åœ{:;£~έzEQ>,(n€²²÷—w“§m9Ô‰Ú4Mõ;ù¬öööŽÇ{´:6.–$vçp€(chŠD¬]µµ‡Ë›ýþÁ <ÜéT¿Òu£ .¹cpÀÀé$ çüŠ‚‚à‡v7ÒÛoÿé`aaAšÇÃæpŽ;L>…r¼àך¦®uê&6ð„C70-*/¯x‘u*Û&ÿ¢E‹½>Ÿ/{Ô¨ì>Ÿ÷vÆpÅÉÊ!ËÒvk“žUÕYMk×n@AÁLå×È—ÖGnŸó®Íÿ^@÷uAŽ]ݽGÓÔIvÊošQ3''Wöù<+Ì8 ŠËË+Ÿa ¶ÊðÜs«Òü~³¨¢¢jç·³¼K—þÂ7zô¨§eYºÿ4Êñ2cìǪš_íÀŒm7€‰nx:0c.»±kØ%SSSë¸qã~æóyöžü€eñ¹¹¹£÷åæŽ¾¼¨hnÇêÕ«m)Gmm]çÖïín·H$ú»H¤3b‡4kÖ¬””è·“Ý~šòÀœóCá°¾¤¥åh†ÍË—Ý 8§ªWÙ%¿,KòL~1ö“3X&IÒÃ0^˜={6º¦}bËáñ(Š$I+í´#‘¨®(J­øwL………()Ñ_䜿zfËÁLœ8é½´´ôº‹/žjË æÐ¡Ú0Ý Ø?÷c—Û"ÿ A¾!99£?Ø"ÊË9îÑucSüjiÑÓÌ`0ð–ífÍž}÷Ñò‡Ãahš†pXßÄ9¿K̲Sž’™9ô`MM}º®Âû_KKS&çüJö匕+Ÿ.¿¢x¼#FŒÜÄ2—÷J]7ÞýÙŽ5æÛmý@ýåLµ[YYÂaý/–ůÜÿ2dû¢Q 2 Chÿóù|^Y– JöáØÆ9s¼æonÍε‘1dÚTÞï¼ôÒÚg£ÑhT¤üáðpŽ×íj7IÂÆõë× .çåå!Ö‹-‹_cCÿc†+ 6ÙqmcR©ó¾ p èÐ/S­ijŽØÝ~Ó7n샌±"»Ë ðïƒ÷úÛc9SåݰÁâ¨íÆ˜Í òÇnc°xñÂQƒ]08£Yt9¾üòKIÔ &ößI.X®Ö­+¹BÔ`·t鵌¡Ú‰Á®Ï& “I@õZÀ9Ÿìù»# %%¥£E–Wt9"‘NKÔ ¦¿ºq²Ý"óRÁƒ]ƒ“ò€r¢#›*¿C¤ Œa„e¹çBFYæ#T ”ß⒨χêEÍØ$ ÃÝ"lC|˜Ø½)´;]^7Ü ùNhYÜï¦ 9g~Áïü刈\®1¿[äÇÓ!8 uº¼nHúDî¶vvFd·Èû^“¨òÆvy}Ëá»|áÍn‘¿+ÁÉš/×|N–wÀ%€Í¿Ì ‘»­œóÃnºUQø!Qå­©©ñÛ݉Îðrí[–kŒœ[«‹š± ¢$ 0"ö_Qá˜ÍnºuÖ,µQÔ`7l؈Á‰*?äç«nZ®1&}.x¹6*å“€²~xÁHQ»­……Á-n‘Àf‘ƒÝر9ƒD—#^Ÿ+j³páâÎù?Ý2cÓ´Y;D.×LÓíŒü¼ï žt 4,¶C.r·u€«œß`âZ¶lù8Qƒ,{§‰.c||(T\!75 â²,½É.qÁ ý‘{S錱 çžÜcàô€“&;H”ü/¿üøµv—9òšÈ+´¢±,óQ3ÆXµ$IϺdÆö¢È½©ÜÜÜ1t'`Œóz=ˆZcÞqÇ÷ iêKNËošæ?kj— žéL³¡]euÁBÊ¡ªùU>rX~®ijXä·233ǸáZ0ÅiùcÜ7”‰ÝpáOZŸïÔSggçC† iœ7ï!‘çÊ—‰.cì’ùó‹Ô_Nÿz3Œágœã}§mưèñÇ—xEÉÏ9?$I,ßiùû=phä½Z¤ü¡P±¯¼¼òWÚzÜÙ‡³gßóª`ù ‚?»q‰(ù P¡ªêþêÐŒíèDzÄëõ޵WóðÃó:|Û Óny:ðt‘òÈa cP˜vuttüP¤4±wΩvµ›a‰>lkëPX®™&ÏÏÎÎ>K”ü=¸é.8•rÍ€Ã0ηáþüœã;ËË»å¾ûî­üÎÆØMöÅ™q“è[]]­'‰Ücó)Í ûöíÛ"ZþÒÒÒɶ<#8-< 䪧G£Ñ±wß]Xn‡4ðÒKk)Ëòƒgþ?oÚQŽeË–û²³³ç˲ü˜Í3¶y•••/Û°V†ñ}Îñ¦€wþe;vìz*-mˆpùËÊÊP__ŸešV5=¸Îçóý‡Ò„BžP¨øìÊÊÊeŒáJưÿ íöÿŲ"ÙvÉ ûšššÓ%I¾×vûqSSS lzª®ªª¿ooïÈ5Mó¯g¨{LÓ¼bÿþÏØ!?Ðõ´#Ó´þ‹ž< ÇÿÓi✢(µ¹¹cþ¡iêxw¨ý×–/æÖöööÛ ‚×ÞUc—ürÆ?û Y–Îràz³1S¦œw¾MÔŽ= ½Öûå—_ÎdŒMg ÿêg<¸KÓÔIUU‡ªEQ`ߣÁÁ9~LO˜¢ëƯ¾úªpùãÜôé×4M}IÓÔQŒI—qÎešæÞ“”ãCËâKŽ9réÞ½{¯ollüè£¾ã¹ŽŽŽN¿ðœûàŒ\dgy`ðàÁ_ÿúEïjš: `gqŽÇûÕ Ê±ÀÓŒáRMS³,/ …ŠÏ¶kù•”èù–eù 0ЀÏtp—òKMSϱCþ8˲²ÚÚÚ:/^Xcz¶e±ü;"Ifµªšbëïq"³ý'ã²³³¼g§Ãív¶eÉ‚Á™¶ ÚõÕ§ŸþŸ }>ß(¿ßß.Ir“$ñ:UÕªíj“ý~k׆+C®«î§p™ü0¡¤$<³²²êC'ä#I† r¤kí©UpE'êÉÍ= ëÆ.h·•Áà̸¡^ÚÛ;޶·wì~àûmo“q#GŽ,p›ü'œ8|-Sõ®]»¾–––vÄ ¹ÜÎ1ƪǎÍkYØéŠNÄØùåå8çÙ©Ø'ãZZZ2'Nœô™,KYn’¿×€‹ä€ìóÏ?ïvêDýsóæ=ÔnYØè–v³,þZcccÉß—ãœg?á~7Ê?à À©0ÐqçœV¹cÖ¬Y$N×K§¼@gwýqÙ4M&ËrÛ@':‚8GGg¨¡¡ám’¿7çñx½YY£vºQþ~—È•išú]’ÿ¤Llñâ%9Œº^Z½}û6Ën®­­½véÒÇ#ÔÝ\sssëäÉç¯wÏãÎz³Œ· ¿Щ$`?\žaªª®%ùOHVÑÜ£>Bò£×mÔ|òäó~èNù»’€½fñ‹õ}uvvN¨©9ÌI~â…ËÊÊ‘¼^y¯Ûäï¾uoº' Ø?'IÊæÎÎÎNêlÄ%·}û¶r¯Wþ‡ÛM\ùyß%€›“€_¡pÛîln>Z+IR u^âÎgšæ¨ŒŒ¡9™¯0†ñ êGŸ$ ÿñ[BUþwÑСŸdffÚ<ê¼Ä.·dÉ“^ÎyÖèÑ£îõzîMp?bŸõI°$àWçØ\]7Úu½ô'Ôɉûª\ ËÍÍ},77wŸÇ“øòǹ“ž$¶üýb766,kh82Ìãñ(ÔÉ‰ë ‡×#˜…uë ¿$ñÿvòiÒvqR ÈÎñhzzF˘1cWçæŽ¾0Þè†a )Î=óÌ3Ý2HÖuÝx[’Ð’ òŸpDò÷Ç™~°7, oƒùõßþöµÒ÷¾wÃ'où%N<Ç9ç>ºè`$ÒÂKK,ËÂMèzÖá÷S ß÷y))(?Èf|¦$ºn4E£æ˲¶z<ÊÿJû\××ï×´YõÇÿÌúúº4ËâÍÅÅ¡úÍžˆs÷ÜseÌ竉D.–ey¼Ïç³fÍê©®²,d¤X¿?µ@‚…ìà8ç°,Ëbœƒ+ŠÔ}¥Jÿ?8g9†w]¤’Ô©–´‹c–eÉ ËÒ)í™ç.Žús_6î$Ž8âÞ ¨ôübÏ„UqÄ%ŸüÝIÀK€$JGq'àR$ HqÄ Äõ|I$?qÄ¥¦ü½fTYÄ—zœDòG\êrUqĥ4ÐQUqÄ%·üý”$ޏä—?~+%‰#Ž’€”$Ž8JR€8â’š£$ qÄQ¨÷@òG\êÉßï)UqÄQ*‹8â( H•EqÉ|*@I@âˆ%½( HqÉ/?%‰#”¤$ qÄ’€ $ qÄ%?GI@∣0Pï€ä'Ž¸Ô“¿ßSª,∣$ UqÄQ*‹8â’ùT€’€Ä‡”Mr @SϯP8â’_þX°IðyÏw~ƨ²ˆ#.¹åçñ?n“lŒ‘1F•EqI,œ‹1¯ImmÊ/8‡Ù•¤0qÄ%+_ÞÇ<^u_!UUíæ–eÝHa âˆK .öº~üx ’×ëÁwÊC*‹8â’_~ÆÔ4õ= ö™ÀP¨EEsQRRz¡$ñRS©²ˆ#.鸛¡iùÛâŒEEs²Ì?WUõk†aL1M>Ã4ÍÉ (ÊÑÿîFM/qÄçVNþÀš¦n‡õ^ÜÿZùÛF>IEND®B`‚pvr.mythtv-5.10.15-Leia/pvr.mythtv/resources/settings.xml000066400000000000000000000072231360567320200234410ustar00rootroot00000000000000 pvr.mythtv-5.10.15-Leia/src/000077500000000000000000000000001360567320200154675ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/src/artworksmanager.cpp000066400000000000000000000050711360567320200214050ustar00rootroot00000000000000/* * Copyright (C) 2018 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "artworksmanager.h" #include "client.h" #include "private/os/os.h" #define FILEOPS_CHANNEL_DUMMY_ICON "channel.png" #define FILEOPS_RECORDING_DUMMY_ICON "recording.png" #define CHANNEL_ICON_WIDTH 300 using namespace ADDON; ArtworkManager::ArtworkManager(const std::string& server, unsigned wsapiport, const std::string& wsapiSecurityPin) : m_wsapi(NULL) , m_localBasePath(g_szUserPath.c_str()) { m_wsapi = new Myth::WSAPI(server, wsapiport, wsapiSecurityPin); } ArtworkManager::~ArtworkManager() { SAFE_DELETE(m_wsapi); } std::string ArtworkManager::GetChannelIconPath(const MythChannel& channel) { if (channel.IsNull() || channel.Icon().empty()) return ""; if (!g_bChannelIcons) return g_szClientPath + PATH_SEPARATOR_STRING + "resources" + PATH_SEPARATOR_STRING + FILEOPS_CHANNEL_DUMMY_ICON; return m_wsapi->GetChannelIconUrl(channel.ID(), CHANNEL_ICON_WIDTH); } std::string ArtworkManager::GetPreviewIconPath(const MythProgramInfo& recording) { if (recording.IsNull()) return ""; if (!g_bRecordingIcons) return g_szClientPath + PATH_SEPARATOR_STRING + "resources" + PATH_SEPARATOR_STRING + FILEOPS_RECORDING_DUMMY_ICON; return m_wsapi->GetPreviewImageUrl(recording.ChannelID(), recording.RecordingStartTime()); } std::string ArtworkManager::GetArtworkPath(const MythProgramInfo& recording, ArtworksType type) { if (recording.IsNull()) return ""; if (!g_bRecordingIcons) switch (type) { case AWTypeCoverart: return g_szClientPath + PATH_SEPARATOR_STRING + "resources" + PATH_SEPARATOR_STRING + FILEOPS_RECORDING_DUMMY_ICON; default: return ""; } return m_wsapi->GetRecordingArtworkUrl(GetTypeNameByArtworksType(type), recording.Inetref(), recording.Season()); } pvr.mythtv-5.10.15-Leia/src/artworksmanager.h000066400000000000000000000051671360567320200210600ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2018 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "cppmyth/MythChannel.h" #include "cppmyth/MythProgramInfo.h" #include #include class ArtworkManager { public: enum ArtworksType { AWTypeThumbnail, AWTypeCoverart, AWTypeFanart, AWTypeChannelIcon, AWTypeBanner, AWTypeScreenshot, AWTypePoster, AWTypeBackcover, AWTypeInsidecover, AWTypeCDImage }; static std::vector GetArtworksTypes() { std::vector ret; ret.push_back(AWTypeChannelIcon); ret.push_back(AWTypeThumbnail); ret.push_back(AWTypeCoverart); ret.push_back(AWTypeFanart); ret.push_back(AWTypeBanner); ret.push_back(AWTypeScreenshot); ret.push_back(AWTypePoster); ret.push_back(AWTypeBackcover); ret.push_back(AWTypeInsidecover); ret.push_back(AWTypeCDImage); return ret; } static const char *GetTypeNameByArtworksType(ArtworksType type) { switch(type) { case AWTypeChannelIcon: return "channelIcon"; case AWTypeThumbnail: return "thumbnail"; case AWTypeCoverart: return "coverart"; case AWTypeFanart: return "fanart"; case AWTypeBanner: return "banner"; case AWTypeScreenshot: return "screenshot"; case AWTypePoster: return "poster"; case AWTypeBackcover: return "backcover"; case AWTypeInsidecover: return "insidecover"; case AWTypeCDImage: return "cdimage"; default: return ""; } } ArtworkManager(const std::string& server, unsigned wsapiport, const std::string& wsapiSecurityPin); virtual ~ArtworkManager(); std::string GetChannelIconPath(const MythChannel& channel); std::string GetPreviewIconPath(const MythProgramInfo& recording); std::string GetArtworkPath(const MythProgramInfo& recording, ArtworksType type); Myth::WSAPI *m_wsapi; std::string m_localBasePath; }; pvr.mythtv-5.10.15-Leia/src/avinfo.cpp000066400000000000000000000205401360567320200174560ustar00rootroot00000000000000/* * Copyright (C) 2005-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include #include "avinfo.h" #include "demuxer/debug.h" #define LOGTAG "[AVINFO] " using namespace ADDON; void AVInfoLog(int level, char *msg) { if (msg && level != DEMUX_DBG_NONE) { bool doLog = g_bExtraDebug; addon_log_t loglevel = LOG_DEBUG; switch (level) { case DEMUX_DBG_ERROR: loglevel = LOG_ERROR; doLog = true; break; case DEMUX_DBG_WARN: case DEMUX_DBG_INFO: loglevel = LOG_INFO; break; case DEMUX_DBG_DEBUG: case DEMUX_DBG_PARSE: case DEMUX_DBG_ALL: loglevel = LOG_DEBUG; break; } if (XBMC && doLog) XBMC->Log(loglevel, LOGTAG "%s", msg); } } AVInfo::AVInfo(Myth::Stream* file) : m_file(file) , m_channel(1) , m_av_buf_size(AV_BUFFER_SIZE) , m_av_pos(0) , m_av_buf(NULL) , m_av_rbs(NULL) , m_av_rbe(NULL) , m_AVContext(NULL) , m_mainStreamPID(0xffff) , m_DTS(PTS_UNSET) , m_PTS(PTS_UNSET) , m_AVStatus(0) { m_av_buf = (unsigned char*)malloc(sizeof(*m_av_buf) * (m_av_buf_size + 1)); if (m_av_buf) { m_av_rbs = m_av_buf; m_av_rbe = m_av_buf; if (g_bExtraDebug) TSDemux::DBGLevel(DEMUX_DBG_DEBUG); else TSDemux::DBGLevel(DEMUX_DBG_ERROR); TSDemux::SetDBGMsgCallback(AVInfoLog); m_AVContext = new TSDemux::AVContext(this, m_av_pos, m_channel); Process(); } else { XBMC->Log(LOG_ERROR, LOGTAG "alloc AV buffer failed"); } } AVInfo::~AVInfo() { // Free AV context if (m_AVContext) SAFE_DELETE(m_AVContext); // Free AV buffer if (m_av_buf) { if (g_bExtraDebug) XBMC->Log(LOG_DEBUG, LOGTAG "free AV buffer: allocated size was %zu", m_av_buf_size); free(m_av_buf); m_av_buf = NULL; } } /* * Implement our AV reader */ const unsigned char* AVInfo::ReadAV(uint64_t pos, size_t n) { // out of range if (n > m_av_buf_size) return NULL; // Already read ? size_t sz = m_av_rbe - m_av_buf; if (pos < m_av_pos || pos > (m_av_pos + sz)) { // seek and reset buffer int64_t newpos = m_file->Seek((int64_t)pos, Myth::WHENCE_SET); if (newpos < 0) return NULL; m_av_pos = pos = (uint64_t)newpos; m_av_rbs = m_av_rbe = m_av_buf; } else { // move to the desired pos in buffer m_av_rbs = m_av_buf + (size_t)(pos - m_av_pos); } size_t dataread = m_av_rbe - m_av_rbs; if (dataread >= n) return m_av_rbs; // flush old data to free up space at the end memmove(m_av_buf, m_av_rbs, dataread); m_av_rbs = m_av_buf; m_av_rbe = m_av_rbs + dataread; m_av_pos = pos; // fill new data unsigned int len = (unsigned int)(m_av_buf_size - dataread); int retry = 5; while (retry > 0) { int ret = m_file->Read(m_av_rbe, len); if (ret > 0) { m_av_rbe += ret; dataread += ret; len -= ret; } if (dataread >= n || ret < 0) break; --retry; usleep(100000); } return dataread >= n ? m_av_rbs : NULL; } void AVInfo::Process() { if (!m_AVContext) { XBMC->Log(LOG_ERROR, LOGTAG "%s: no AVContext", __FUNCTION__); return; } int ret = 0; bool analyzed = false; // become true once all channel streams are parsed size_t throughput = 0; // to limit size of analyzed data while (!analyzed && throughput < ES_MAX_BUFFER_SIZE) { { ret = m_AVContext->TSResync(); } if (ret != TSDemux::AVCONTEXT_CONTINUE) break; ret = m_AVContext->ProcessTSPacket(); if (m_AVContext->HasPIDStreamData()) { TSDemux::STREAM_PKT pkt; while (get_stream_data(&pkt)) { throughput += pkt.size; if (pkt.streamChange) { // Update stream properties. Analyzing will be closed once setup is completed for all streams. if (update_pvr_stream(pkt.pid) && m_nosetup.empty()) analyzed = true; } } } if (m_AVContext->HasPIDPayload()) { ret = m_AVContext->ProcessTSPayload(); if (ret == TSDemux::AVCONTEXT_PROGRAM_CHANGE) { populate_pvr_streams(); } } if (ret < 0) XBMC->Log(LOG_NOTICE, LOGTAG "%s: error %d", __FUNCTION__, ret); if (ret == TSDemux::AVCONTEXT_TS_ERROR) throughput = static_cast(m_AVContext->Shift()); else m_AVContext->GoNext(); } m_AVStatus = ret; m_file->Seek(0, Myth::WHENCE_SET); XBMC->Log(LOG_DEBUG, LOGTAG "%s: terminated with status %d", __FUNCTION__, ret); } bool AVInfo::GetMainStream(STREAM_AVINFO *info) const { if (!m_AVContext || m_AVStatus < 0 || !m_nosetup.empty()) return false; TSDemux::ElementaryStream* found = m_AVContext->GetStream(m_mainStreamPID); if (found == NULL) return false; info->pid = found->pid; info->stream_type = found->stream_type; info->stream_info = found->stream_info; return true; } std::vector AVInfo::GetStreams() const { std::vector ret; if (!m_AVContext || m_AVStatus < 0 || !m_nosetup.empty()) return ret; std::vector streams = m_AVContext->GetStreams(); std::vector::const_iterator it; ret.reserve(streams.size()); for (it = streams.begin(); it < streams.end(); ++it) { STREAM_AVINFO info; info.pid = (*it)->pid; info.stream_type = (*it)->stream_type; info.stream_info = (*it)->stream_info; ret.push_back(info); } return ret; } bool AVInfo::get_stream_data(TSDemux::STREAM_PKT* pkt) { TSDemux::ElementaryStream* es = m_AVContext->GetPIDStream(); if (!es) return false; if (!es->GetStreamPacket(pkt)) return false; if (pkt->duration > 180000) { pkt->duration = 0; } else if (pkt->pid == m_mainStreamPID) { // Sync main DTS & PTS m_DTS = pkt->dts; m_PTS = pkt->pts; } return true; } void AVInfo::populate_pvr_streams() { uint16_t mainPid = 0xffff; int mainType = XBMC_CODEC_TYPE_UNKNOWN; const std::vector es_streams = m_AVContext->GetStreams(); for (std::vector::const_iterator it = es_streams.begin(); it != es_streams.end(); it++) { const char* codec_name = (*it)->GetStreamCodecName(); xbmc_codec_t codec = PVR->GetCodecByName(codec_name); if (codec.codec_type != XBMC_CODEC_TYPE_UNKNOWN) { // Find the main stream: // The best candidate would be the first video. Else the first audio switch (mainType) { case XBMC_CODEC_TYPE_VIDEO: break; case XBMC_CODEC_TYPE_AUDIO: if (codec.codec_type != XBMC_CODEC_TYPE_VIDEO) break; default: mainPid = (*it)->pid; mainType = codec.codec_type; } // Allow streaming for the PID m_AVContext->StartStreaming((*it)->pid); // Add stream to no setup set if (!(*it)->has_stream_info) m_nosetup.insert((*it)->pid); if (g_bExtraDebug) XBMC->Log(LOG_DEBUG, LOGTAG "%s: register PES %.4x %s", __FUNCTION__, (*it)->pid, codec_name); } } // Renew main stream m_mainStreamPID = mainPid; } bool AVInfo::update_pvr_stream(uint16_t pid) { TSDemux::ElementaryStream* es = m_AVContext->GetStream(pid); if (!es) return false; if (g_bExtraDebug) XBMC->Log(LOG_DEBUG, LOGTAG "%s: update info PES %.4x %s", __FUNCTION__, es->pid, es->GetStreamCodecName()); if (es->has_stream_info) { // Now stream is setup. Remove it from no setup set std::set::iterator it = m_nosetup.find(es->pid); if (it != m_nosetup.end()) { m_nosetup.erase(it); if (m_nosetup.empty()) XBMC->Log(LOG_DEBUG, LOGTAG "%s: setup is completed", __FUNCTION__); } } return true; } pvr.mythtv-5.10.15-Leia/src/avinfo.h000066400000000000000000000042501360567320200171230ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "demuxer/tsDemuxer.h" #include "client.h" #include #include #include #define AV_BUFFER_SIZE 131072 class AVInfo : public TSDemux::TSDemuxer { public: AVInfo(Myth::Stream *file); ~AVInfo(); const unsigned char* ReadAV(uint64_t pos, size_t n); typedef struct { uint16_t pid; TSDemux::STREAM_TYPE stream_type; TSDemux::STREAM_INFO stream_info; } STREAM_AVINFO; bool GetMainStream(STREAM_AVINFO *info) const; std::vector GetStreams() const; private: Myth::Stream *m_file; uint16_t m_channel; void Process(); bool get_stream_data(TSDemux::STREAM_PKT* pkt); void populate_pvr_streams(); bool update_pvr_stream(uint16_t pid); // AV raw buffer size_t m_av_buf_size; ///< size of av buffer uint64_t m_av_pos; ///< absolute position in av unsigned char* m_av_buf; ///< buffer unsigned char* m_av_rbs; ///< raw data start in buffer unsigned char* m_av_rbe; ///< raw data end in buffer // Playback context TSDemux::AVContext* m_AVContext; uint16_t m_mainStreamPID; ///< PID of main stream uint64_t m_DTS; ///< absolute decode time of main stream uint64_t m_PTS; ///< absolute presentation time of main stream std::set m_nosetup; int m_AVStatus; }; pvr.mythtv-5.10.15-Leia/src/categories.cpp000066400000000000000000000065041360567320200203250ustar00rootroot00000000000000/* * Copyright (C) 2005-2012 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "categories.h" #include "client.h" #include "private/os/os.h" #define CATEGORIES_FILENAME "eit_categories.txt" #define CATEGORIES_MAXLINESIZE 255 using namespace ADDON; Categories::Categories() : m_categoriesById() { std::string filePath; filePath = g_szClientPath + PATH_SEPARATOR_STRING + "resources" + PATH_SEPARATOR_STRING + CATEGORIES_FILENAME; LoadEITCategories(filePath.c_str()); filePath = g_szUserPath + CATEGORIES_FILENAME; LoadEITCategories(filePath.c_str()); // Copy over CategoryByIdMap::const_iterator it; for (it = m_categoriesById.begin(); it != m_categoriesById.end(); ++it) { m_categoriesByName[it->second] = it->first; } } std::string Categories::Category(int category) const { CategoryByIdMap::const_iterator it = m_categoriesById.find(category); if (it != m_categoriesById.end()) return it->second; return ""; } int Categories::Category(const std::string& category) const { CategoryByNameMap::const_iterator it = m_categoriesByName.find(category); if (it != m_categoriesByName.end()) return it->second; return 0; } void Categories::LoadEITCategories(const char *filePath) { if (XBMC->FileExists(filePath, false)) { XBMC->Log(LOG_DEBUG, "%s: Loading EIT categories from file '%s'", __FUNCTION__, filePath); void *file = XBMC->OpenFile(filePath, 0); char *line = new char[CATEGORIES_MAXLINESIZE + 1]; char *name = new char[CATEGORIES_MAXLINESIZE + 1]; while (XBMC->ReadFileString(file, line, CATEGORIES_MAXLINESIZE)) { char* end = line + strlen(line); char* pos = strchr(line, ';'); if (pos != NULL) { bool encaps = false; int catId; *pos = '\0'; if (sscanf(line, "%x", &catId) == 1) { unsigned p = 0; memset(name, 0, CATEGORIES_MAXLINESIZE + 1); do { ++pos; } while (isspace(*pos)); if (*pos == '"') encaps = true; while (++pos < end) { if (encaps && *pos == '"' && *(++pos) != '"') break; if (!iscntrl(*pos)) name[p++] = *pos; } m_categoriesById.insert(std::pair(catId, name)); XBMC->Log(LOG_DEBUG, "%s: Add name [%s] for category %.2X", __FUNCTION__, name, catId); } } } delete[] name; delete[] line; XBMC->CloseFile(file); } else { XBMC->Log(LOG_INFO, "%s: File '%s' not found", __FUNCTION__, filePath); } } pvr.mythtv-5.10.15-Leia/src/categories.h000066400000000000000000000024071360567320200177700ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2012 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include #include typedef std::multimap CategoryByIdMap; typedef std::map CategoryByNameMap; class Categories { public: Categories(); std::string Category(int category) const; int Category(const std::string& category) const; private: void LoadEITCategories(const char *filePath); CategoryByIdMap m_categoriesById; CategoryByNameMap m_categoriesByName; }; pvr.mythtv-5.10.15-Leia/src/client.cpp000066400000000000000000001127601360567320200174600ustar00rootroot00000000000000/* * Copyright (C) 2005-2014 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "client.h" #include "pvrclient-mythtv.h" #include "pvrclient-launcher.h" #include ///* undefined constants in pvr API */ #define SEEK_POSSIBLE 0x10 ///< flag used to check if protocol allows seeks using namespace ADDON; /* User adjustable settings are saved here. * Default values are defined inside client.h * and exported to the other source files. */ std::string g_szMythHostname = DEFAULT_HOST; ///< The Host name or IP of the mythtv server std::string g_szMythHostEther = ""; ///< The Host MAC address of the mythtv server int g_iProtoPort = DEFAULT_PROTO_PORT; ///< The mythtv protocol port (default is 6543) int g_iWSApiPort = DEFAULT_WSAPI_PORT; ///< The mythtv sevice API port (default is 6544) std::string g_szWSSecurityPin = DEFAULT_WSAPI_SECURITY_PIN; ///< The default security pin for the mythtv wsapi bool g_bExtraDebug = DEFAULT_EXTRA_DEBUG; ///< Output extensive debug information to the log bool g_bLiveTV = DEFAULT_LIVETV; ///< LiveTV support (or recordings only) bool g_bLiveTVPriority = DEFAULT_LIVETV_PRIORITY; ///< MythTV Backend setting to allow live TV to move scheduled shows int g_iLiveTVConflictStrategy = DEFAULT_LIVETV_CONFLICT_STRATEGY; ///< Conflict resolving strategy (0= bool g_bChannelIcons = DEFAULT_CHANNEL_ICONS; ///< Load Channel Icons bool g_bRecordingIcons = DEFAULT_RECORDING_ICONS; ///< Load Recording Icons (Fanart/Thumbnails) bool g_bLiveTVRecordings = DEFAULT_LIVETV_RECORDINGS; ///< Show LiveTV recordings int g_iRecTemplateType = DEFAULT_RECORD_TEMPLATE; ///< Template type for new record (0=Internal, 1=MythTV) bool g_bRecAutoMetadata = true; bool g_bRecAutoCommFlag = false; bool g_bRecAutoTranscode = false; bool g_bRecAutoRunJob1 = false; bool g_bRecAutoRunJob2 = false; bool g_bRecAutoRunJob3 = false; bool g_bRecAutoRunJob4 = false; bool g_bRecAutoExpire = false; int g_iRecTranscoder = 0; int g_iTuneDelay = DEFAULT_TUNE_DELAY; int g_iGroupRecordings = GROUP_RECORDINGS_ALWAYS; bool g_bUseAirdate = DEFAULT_USE_AIRDATE; int g_iEnableEDL = ENABLE_EDL_ALWAYS; bool g_bAllowMythShutdown = DEFAULT_ALLOW_SHUTDOWN; bool g_bLimitTuneAttempts = DEFAULT_LIMIT_TUNE_ATTEMPTS; bool g_bShowNotRecording = DEFAULT_SHOW_NOT_RECORDING; bool g_bPromptDeleteAtEnd = DEFAULT_PROMPT_DELETE; bool g_bUseBackendBookmarks = DEFAULT_BACKEND_BOOKMARKS; bool g_bRootDefaultGroup = DEFAULT_ROOT_DEFAULT_GROUP; std::string g_szDamagedColor = DEFAULT_DAMAGED_COLOR; ///* Client member variables */ ADDON_STATUS m_CurStatus = ADDON_STATUS_UNKNOWN; bool g_bCreated = false; int g_iClientID = -1; std::string g_szUserPath = ""; std::string g_szClientPath = ""; PVRClientMythTV *g_client = NULL; PVRClientLauncher *g_launcher = NULL; CHelper_libXBMC_addon *XBMC = NULL; CHelper_libXBMC_pvr *PVR = NULL; CHelper_libKODI_guilib *GUI = NULL; extern "C" { /*********************************************************** * Standard AddOn related public library functions ***********************************************************/ ADDON_STATUS ADDON_Create(void *hdl, void *props) { if (!hdl) return ADDON_STATUS_PERMANENT_FAILURE; SAFE_DELETE(g_launcher); // Register handles XBMC = new CHelper_libXBMC_addon; if (!XBMC->RegisterMe(hdl)) { SAFE_DELETE(XBMC); return ADDON_STATUS_PERMANENT_FAILURE; } XBMC->Log(LOG_NOTICE, "Creating MythTV PVR-Client"); XBMC->Log(LOG_NOTICE, "Addon compiled with PVR API version %s", STR(ADDON_INSTANCE_VERSION_PVR)); XBMC->Log(LOG_DEBUG, "Register handle @ libXBMC_addon...done"); XBMC->Log(LOG_DEBUG, "Checking props..."); if (!props) { SAFE_DELETE(XBMC); return ADDON_STATUS_PERMANENT_FAILURE; } XBMC->Log(LOG_DEBUG, "Checking props...done"); PVR_PROPERTIES* pvrprops = (PVR_PROPERTIES*)props; XBMC->Log(LOG_DEBUG, "Register handle @ libXBMC_pvr..."); PVR = new CHelper_libXBMC_pvr; if (!PVR->RegisterMe(hdl)) { SAFE_DELETE(PVR); SAFE_DELETE(XBMC); return ADDON_STATUS_PERMANENT_FAILURE; } XBMC->Log(LOG_DEBUG, "Register handle @ libXBMC_pvr...done"); XBMC->Log(LOG_DEBUG, "Register handle @ libXBMC_gui..."); GUI = new CHelper_libKODI_guilib; if (!GUI->RegisterMe(hdl)) { SAFE_DELETE(PVR); SAFE_DELETE(XBMC); SAFE_DELETE(GUI); return ADDON_STATUS_PERMANENT_FAILURE; } XBMC->Log(LOG_DEBUG, "Register handle @ libXBMC_gui...done"); m_CurStatus = ADDON_STATUS_UNKNOWN; g_szUserPath = pvrprops->strUserPath; g_szClientPath = pvrprops->strClientPath; // Read settings XBMC->Log(LOG_DEBUG, "Loading settings..."); char *buffer = new char [1024]; buffer[0] = 0; /* Set the end of string */ /* Read setting "host" from settings.xml */ if (XBMC->GetSetting("host", buffer)) g_szMythHostname = buffer; else { /* If setting is unknown fallback to defaults */ XBMC->Log(LOG_ERROR, "Couldn't get 'host' setting, falling back to '%s' as default", DEFAULT_HOST); g_szMythHostname = DEFAULT_HOST; } buffer[0] = 0; /* Read setting "port" from settings.xml */ if (!XBMC->GetSetting("port", &g_iProtoPort)) { /* If setting is unknown fallback to defaults */ XBMC->Log(LOG_ERROR, "Couldn't get 'port' setting, falling back to '%d' as default", DEFAULT_PROTO_PORT); g_iProtoPort = DEFAULT_PROTO_PORT; } /* Read setting "wsport" from settings.xml */ if (!XBMC->GetSetting("wsport", &g_iWSApiPort)) { /* If setting is unknown fallback to defaults */ XBMC->Log(LOG_ERROR, "Couldn't get 'wsport' setting, falling back to '%d' as default", DEFAULT_WSAPI_PORT); g_iWSApiPort = DEFAULT_WSAPI_PORT; } /* Read setting "wssecuritypin" from settings.xml */ if (XBMC->GetSetting("wssecuritypin", buffer)) g_szWSSecurityPin = buffer; else { /* If setting is unknown fallback to defaults */ XBMC->Log(LOG_ERROR, "Couldn't get 'wssecuritypin' setting, falling back to '%s' as default", DEFAULT_WSAPI_SECURITY_PIN); g_szWSSecurityPin = DEFAULT_WSAPI_SECURITY_PIN; } buffer[0] = 0; /* Read setting "extradebug" from settings.xml */ if (!XBMC->GetSetting("extradebug", &g_bExtraDebug)) { /* If setting is unknown fallback to defaults */ XBMC->Log(LOG_ERROR, "Couldn't get 'extradebug' setting, falling back to '%u' as default", DEFAULT_EXTRA_DEBUG); g_bExtraDebug = DEFAULT_EXTRA_DEBUG; } /* Read setting "LiveTV" from settings.xml */ if (!XBMC->GetSetting("livetv", &g_bLiveTV)) { /* If setting is unknown fallback to defaults */ XBMC->Log(LOG_ERROR, "Couldn't get 'livetv' setting, falling back to '%u' as default", DEFAULT_LIVETV); g_bLiveTV = DEFAULT_LIVETV; } /* Read settings "Record livetv_conflict_method" from settings.xml */ if (!XBMC->GetSetting("livetv_conflict_strategy", &g_iLiveTVConflictStrategy)) { /* If setting is unknown fallback to defaults */ XBMC->Log(LOG_ERROR, "Couldn't get 'livetv_conflict_method' setting, falling back to '%i' as default", DEFAULT_RECORD_TEMPLATE); g_iLiveTVConflictStrategy = DEFAULT_LIVETV_CONFLICT_STRATEGY; } /* Read settings "Record template" from settings.xml */ if (!XBMC->GetSetting("rec_template_provider", &g_iRecTemplateType)) { /* If setting is unknown fallback to defaults */ XBMC->Log(LOG_ERROR, "Couldn't get 'rec_template_provider' setting, falling back to '%i' as default", DEFAULT_RECORD_TEMPLATE); g_iRecTemplateType = DEFAULT_RECORD_TEMPLATE; } /* Get internal template settings */ if (!XBMC->GetSetting("rec_autometadata", &g_bRecAutoMetadata)) g_bRecAutoMetadata = true; if (!XBMC->GetSetting("rec_autocommflag", &g_bRecAutoCommFlag)) g_bRecAutoCommFlag = false; if (!XBMC->GetSetting("rec_autotranscode", &g_bRecAutoTranscode)) g_bRecAutoTranscode = false; if (!XBMC->GetSetting("rec_autorunjob1", &g_bRecAutoRunJob1)) g_bRecAutoRunJob1 = false; if (!XBMC->GetSetting("rec_autorunjob2", &g_bRecAutoRunJob2)) g_bRecAutoRunJob2 = false; if (!XBMC->GetSetting("rec_autorunjob3", &g_bRecAutoRunJob3)) g_bRecAutoRunJob3 = false; if (!XBMC->GetSetting("rec_autorunjob4", &g_bRecAutoRunJob4)) g_bRecAutoRunJob4 = false; if (!XBMC->GetSetting("rec_autoexpire", &g_bRecAutoExpire)) g_bRecAutoExpire = false; if (!XBMC->GetSetting("rec_transcoder", &g_iRecTranscoder)) g_iRecTranscoder = 0; /* Read setting "tunedelay" from settings.xml */ if (!XBMC->GetSetting("tunedelay", &g_iTuneDelay)) { /* If setting is unknown fallback to defaults */ XBMC->Log(LOG_ERROR, "Couldn't get 'tunedelay' setting, falling back to '%d' as default", DEFAULT_TUNE_DELAY); g_iTuneDelay = DEFAULT_TUNE_DELAY; } /* Read setting "host_ether" from settings.xml */ if (XBMC->GetSetting("host_ether", buffer)) g_szMythHostEther = buffer; else { /* If setting is unknown fallback to defaults */ g_szMythHostEther = ""; } buffer[0] = 0; /* Read settings "group_recordings" from settings.xml */ if (!XBMC->GetSetting("group_recordings", &g_iGroupRecordings)) { /* If setting is unknown fallback to defaults */ XBMC->Log(LOG_ERROR, "Couldn't get 'group_recordings' setting, falling back to '%i' as default", GROUP_RECORDINGS_ALWAYS); g_iGroupRecordings = GROUP_RECORDINGS_ALWAYS; } /* Read setting "use_airdate" from settings.xml */ if (!XBMC->GetSetting("use_airdate", &g_bUseAirdate)) { /* If setting is unknown fallback to defaults */ XBMC->Log(LOG_ERROR, "Couldn't get 'use_airdate' setting, falling back to '%u' as default", DEFAULT_USE_AIRDATE); g_bUseAirdate = DEFAULT_USE_AIRDATE; } /* Read setting "enable_edl" from settings.xml */ if (!XBMC->GetSetting("enable_edl", &g_iEnableEDL)) { /* If setting is unknown fallback to defaults */ XBMC->Log(LOG_ERROR, "Couldn't get 'enable_edl' setting, falling back to '%i' as default", ENABLE_EDL_ALWAYS); g_iEnableEDL = ENABLE_EDL_ALWAYS; } /* Read setting "allow_shutdown" from settings.xml */ if (!XBMC->GetSetting("allow_shutdown", &g_bAllowMythShutdown)) { /* If setting is unknown fallback to defaults */ XBMC->Log(LOG_ERROR, "Couldn't get 'allow_shutdown' setting, falling back to '%u' as default", DEFAULT_ALLOW_SHUTDOWN); g_bAllowMythShutdown = DEFAULT_ALLOW_SHUTDOWN; } /* Read setting "channel_icons" from settings.xml */ if (!XBMC->GetSetting("channel_icons", &g_bChannelIcons)) { /* If setting is unknown fallback to defaults */ XBMC->Log(LOG_ERROR, "Couldn't get 'channel_icons' setting, falling back to '%u' as default", DEFAULT_CHANNEL_ICONS); g_bChannelIcons = DEFAULT_CHANNEL_ICONS; } /* Read setting "recording_icons" from settings.xml */ if (!XBMC->GetSetting("recording_icons", &g_bRecordingIcons)) { /* If setting is unknown fallback to defaults */ XBMC->Log(LOG_ERROR, "Couldn't get 'recording_icons' setting, falling back to '%u' as default", DEFAULT_RECORDING_ICONS); g_bRecordingIcons = DEFAULT_RECORDING_ICONS; } /* Read setting "limit_tune_attempts" from settings.xml */ if (!XBMC->GetSetting("limit_tune_attempts", &g_bLimitTuneAttempts)) { /* If setting is unknown fallback to defaults */ XBMC->Log(LOG_ERROR, "Couldn't get 'limit_tune_attempts' setting, falling back to '%u' as default", DEFAULT_LIMIT_TUNE_ATTEMPTS); g_bLimitTuneAttempts = DEFAULT_LIMIT_TUNE_ATTEMPTS; } /* Read setting "inactive_upcomings" from settings.xml */ if (!XBMC->GetSetting("inactive_upcomings", &g_bShowNotRecording)) { /* If setting is unknown fallback to defaults */ XBMC->Log(LOG_ERROR, "Couldn't get 'inactive_upcomings' setting, falling back to '%u' as default", DEFAULT_SHOW_NOT_RECORDING); g_bShowNotRecording = DEFAULT_SHOW_NOT_RECORDING; } /* Read setting "prompt_delete" from settings.xml */ if (!XBMC->GetSetting("prompt_delete", &g_bPromptDeleteAtEnd)) { /* If setting is unknown fallback to defaults */ XBMC->Log(LOG_ERROR, "Couldn't get 'prompt_delete' setting, falling back to '%u' as default", DEFAULT_PROMPT_DELETE); g_bPromptDeleteAtEnd = DEFAULT_PROMPT_DELETE; } /* Read setting "livetv_recordings" from settings.xml */ if (!XBMC->GetSetting("livetv_recordings", &g_bLiveTVRecordings)) { /* If setting is unknown fallback to defaults */ XBMC->Log(LOG_ERROR, "Couldn't get 'livetv_recordings' setting, falling back to '%u' as default", DEFAULT_LIVETV_RECORDINGS); g_bLiveTVRecordings = DEFAULT_LIVETV_RECORDINGS; } /* Read setting "backend_bookmarks" from settings.xml */ if (!XBMC->GetSetting("backend_bookmarks", &g_bUseBackendBookmarks)) { /* If setting is unknown fallback to defaults */ XBMC->Log(LOG_ERROR, "Couldn't get 'backend_bookmarks' setting, falling back to '%u' as default", DEFAULT_BACKEND_BOOKMARKS); g_bUseBackendBookmarks = DEFAULT_BACKEND_BOOKMARKS; } /* Read setting "root_default_group" from settings.xml */ if (!XBMC->GetSetting("root_default_group", &g_bRootDefaultGroup)) { /* If setting is unknown fallback to defaults */ XBMC->Log(LOG_ERROR, "Couldn't get 'root_default_group' setting, falling back to '%u' as default", DEFAULT_ROOT_DEFAULT_GROUP); g_bRootDefaultGroup = DEFAULT_ROOT_DEFAULT_GROUP; } /* Read setting "damaged_color" from settings.xml */ if (XBMC->GetSetting("damaged_color", buffer)) { char* p = buffer; while (*p != '\0' && *p != ']') ++p; std::string s = std::string(buffer, p - buffer); if (sscanf(s.c_str(), "[COLOR %s", buffer) == 1) g_szDamagedColor = buffer; else g_szDamagedColor = ""; } else { /* If setting is unknown fallback to defaults */ XBMC->Log(LOG_ERROR, "Couldn't get 'damaged_color' setting, falling back to '%s' as default", DEFAULT_DAMAGED_COLOR); g_szDamagedColor = DEFAULT_DAMAGED_COLOR; } buffer[0] = 0; delete [] buffer; XBMC->Log(LOG_DEBUG, "Loading settings...done"); // Create menu hooks XBMC->Log(LOG_DEBUG, "Creating menu hooks..."); PVR_MENUHOOK menuHook; memset(&menuHook, 0, sizeof(PVR_MENUHOOK)); menuHook.category = PVR_MENUHOOK_RECORDING; menuHook.iHookId = MENUHOOK_REC_DELETE_AND_RERECORD; menuHook.iLocalizedStringId = 30411; PVR->AddMenuHook(&menuHook); memset(&menuHook, 0, sizeof(PVR_MENUHOOK)); menuHook.category = PVR_MENUHOOK_RECORDING; menuHook.iHookId = MENUHOOK_KEEP_RECORDING; menuHook.iLocalizedStringId = 30412; PVR->AddMenuHook(&menuHook); memset(&menuHook, 0, sizeof(PVR_MENUHOOK)); menuHook.category = PVR_MENUHOOK_RECORDING; menuHook.iHookId = MENUHOOK_INFO_RECORDING; menuHook.iLocalizedStringId = 30425; PVR->AddMenuHook(&menuHook); memset(&menuHook, 0, sizeof(PVR_MENUHOOK)); menuHook.category = PVR_MENUHOOK_TIMER; menuHook.iHookId = MENUHOOK_TIMER_BACKEND_INFO; menuHook.iLocalizedStringId = 30424; PVR->AddMenuHook(&menuHook); memset(&menuHook, 0, sizeof(PVR_MENUHOOK)); menuHook.category = PVR_MENUHOOK_TIMER; menuHook.iHookId = MENUHOOK_SHOW_HIDE_NOT_RECORDING; menuHook.iLocalizedStringId = 30421; PVR->AddMenuHook(&menuHook); memset(&menuHook, 0, sizeof(PVR_MENUHOOK)); menuHook.category = PVR_MENUHOOK_CHANNEL; menuHook.iHookId = MENUHOOK_TRIGGER_CHANNEL_UPDATE; menuHook.iLocalizedStringId = 30423; PVR->AddMenuHook(&menuHook); memset(&menuHook, 0, sizeof(PVR_MENUHOOK)); menuHook.category = PVR_MENUHOOK_EPG; menuHook.iHookId = MENUHOOK_INFO_EPG; menuHook.iLocalizedStringId = 30426; PVR->AddMenuHook(&menuHook); XBMC->Log(LOG_DEBUG, "Creating menu hooks...done"); // Create our addon XBMC->Log(LOG_DEBUG, "Starting the client..."); g_client = new PVRClientMythTV(); g_launcher = new PVRClientLauncher(g_client); g_bCreated = true; if (g_launcher->Start()) { XBMC->Log(LOG_NOTICE, "Addon started successfully"); return (m_CurStatus = ADDON_STATUS_OK); } XBMC->Log(LOG_ERROR, "Addon failed to start"); ADDON_Destroy(); return (m_CurStatus = ADDON_STATUS_PERMANENT_FAILURE); } void ADDON_Destroy() { if (g_bCreated) { g_bCreated = false; SAFE_DELETE(g_launcher); SAFE_DELETE(g_client); XBMC->Log(LOG_NOTICE, "Addon destroyed."); SAFE_DELETE(PVR); SAFE_DELETE(XBMC); SAFE_DELETE(GUI); } m_CurStatus = ADDON_STATUS_UNKNOWN; } ADDON_STATUS ADDON_GetStatus() { return m_CurStatus; } ADDON_STATUS ADDON_SetSetting(const char *settingName, const void *settingValue) { if (!g_bCreated) return ADDON_STATUS_OK; std::string str = settingName; if (str == "host") { std::string tmp_sHostname; XBMC->Log(LOG_INFO, "Changed Setting 'host' from %s to %s", g_szMythHostname.c_str(), (const char*)settingValue); tmp_sHostname = g_szMythHostname; g_szMythHostname = (const char*)settingValue; if (tmp_sHostname != g_szMythHostname) { return ADDON_STATUS_NEED_RESTART; } } else if (str == "port") { XBMC->Log(LOG_INFO, "Changed Setting 'port' from %u to %u", g_iProtoPort, *(int*)settingValue); if (g_iProtoPort != *(int*)settingValue) { g_iProtoPort = *(int*)settingValue; return ADDON_STATUS_NEED_RESTART; } } else if (str == "wsport") { XBMC->Log(LOG_INFO, "Changed Setting 'wsport' from %u to %u", g_iWSApiPort, *(int*)settingValue); if (g_iWSApiPort != *(int*)settingValue) { g_iWSApiPort = *(int*)settingValue; return ADDON_STATUS_NEED_RESTART; } } else if (str == "wssecuritypin") { std::string tmp_sWSSecurityPin; XBMC->Log(LOG_INFO, "Changed Setting 'wssecuritypin' from %s to %s", g_szWSSecurityPin.c_str(), (const char*)settingValue); tmp_sWSSecurityPin = g_szWSSecurityPin; g_szWSSecurityPin = (const char*)settingValue; if (tmp_sWSSecurityPin != g_szWSSecurityPin) return ADDON_STATUS_NEED_RESTART; } else if (str == "channel_icons") { XBMC->Log(LOG_INFO, "Changed Setting 'channel_icons' from %u to %u", g_bChannelIcons, *(bool*)settingValue); if (g_bChannelIcons != *(bool*)settingValue) return ADDON_STATUS_NEED_RESTART; } else if (str == "recording_icons") { XBMC->Log(LOG_INFO, "Changed Setting 'recording_icons' from %u to %u", g_bRecordingIcons, *(bool*)settingValue); if (g_bRecordingIcons != *(bool*)settingValue) return ADDON_STATUS_NEED_RESTART; } else if (str == "backend_bookmarks") { XBMC->Log(LOG_INFO, "Changed Setting 'backend_bookmarks' from %u to %u", g_bUseBackendBookmarks, *(bool*)settingValue); if (g_bUseBackendBookmarks != *(bool*)settingValue) return ADDON_STATUS_NEED_RESTART; } else if (str == "host_ether") { XBMC->Log(LOG_INFO, "Changed Setting 'host_ether' from %s to %s", g_szMythHostEther.c_str(), (const char*)settingValue); g_szMythHostEther = (const char*)settingValue; } else if (str == "extradebug") { XBMC->Log(LOG_INFO, "Changed Setting 'extra debug' from %u to %u", g_bExtraDebug, *(bool*)settingValue); if (g_bExtraDebug != *(bool*)settingValue) { g_bExtraDebug = *(bool*)settingValue; if (g_client) g_client->SetDebug(); } } else if (str == "livetv") { XBMC->Log(LOG_INFO, "Changed Setting 'livetv' from %u to %u", g_bLiveTV, *(bool*)settingValue); if (g_bLiveTV != *(bool*)settingValue) g_bLiveTV = *(bool*)settingValue; } else if (str == "livetv_priority") { XBMC->Log(LOG_INFO, "Changed Setting 'extra debug' from %u to %u", g_bLiveTVPriority, *(bool*)settingValue); if (g_bLiveTVPriority != *(bool*) settingValue && m_CurStatus != ADDON_STATUS_LOST_CONNECTION) { g_bLiveTVPriority = *(bool*)settingValue; if (g_client) g_client->SetLiveTVPriority(g_bLiveTVPriority); } } else if (str == "rec_template_provider") { XBMC->Log(LOG_INFO, "Changed Setting 'rec_template_provider' from %u to %u", g_iRecTemplateType, *(int*)settingValue); if (g_iRecTemplateType != *(int*)settingValue) g_iRecTemplateType = *(int*)settingValue; } else if (str == "rec_autometadata") { XBMC->Log(LOG_INFO, "Changed Setting 'rec_autometadata' from %u to %u", g_bRecAutoMetadata, *(bool*)settingValue); if (g_bRecAutoMetadata != *(bool*)settingValue) g_bRecAutoMetadata = *(bool*)settingValue; } else if (str == "rec_autocommflag") { XBMC->Log(LOG_INFO, "Changed Setting 'rec_autocommflag' from %u to %u", g_bRecAutoCommFlag, *(bool*)settingValue); if (g_bRecAutoCommFlag != *(bool*)settingValue) g_bRecAutoCommFlag = *(bool*)settingValue; } else if (str == "rec_autotranscode") { XBMC->Log(LOG_INFO, "Changed Setting 'rec_autotranscode' from %u to %u", g_bRecAutoTranscode, *(bool*)settingValue); if (g_bRecAutoTranscode != *(bool*)settingValue) g_bRecAutoTranscode = *(bool*)settingValue; } else if (str == "rec_transcoder") { XBMC->Log(LOG_INFO, "Changed Setting 'rec_transcoder' from %u to %u", g_iRecTranscoder, *(int*)settingValue); if (g_iRecTranscoder != *(int*)settingValue) g_iRecTranscoder = *(int*)settingValue; } else if (str == "rec_autorunjob1") { XBMC->Log(LOG_INFO, "Changed Setting 'rec_autorunjob1' from %u to %u", g_bRecAutoRunJob1, *(bool*)settingValue); if (g_bRecAutoRunJob1 != *(bool*)settingValue) g_bRecAutoRunJob1 = *(bool*)settingValue; } else if (str == "rec_autorunjob2") { XBMC->Log(LOG_INFO, "Changed Setting 'rec_autorunjob2' from %u to %u", g_bRecAutoRunJob2, *(bool*)settingValue); if (g_bRecAutoRunJob2 != *(bool*)settingValue) g_bRecAutoRunJob2 = *(bool*)settingValue; } else if (str == "rec_autorunjob3") { XBMC->Log(LOG_INFO, "Changed Setting 'rec_autorunjob3' from %u to %u", g_bRecAutoRunJob3, *(bool*)settingValue); if (g_bRecAutoRunJob3 != *(bool*)settingValue) g_bRecAutoRunJob3 = *(bool*)settingValue; } else if (str == "rec_autorunjob4") { XBMC->Log(LOG_INFO, "Changed Setting 'rec_autorunjob4' from %u to %u", g_bRecAutoRunJob4, *(bool*)settingValue); if (g_bRecAutoRunJob4 != *(bool*)settingValue) g_bRecAutoRunJob4 = *(bool*)settingValue; } else if (str == "rec_autoexpire") { XBMC->Log(LOG_INFO, "Changed Setting 'rec_autoexpire' from %u to %u", g_bRecAutoExpire, *(bool*)settingValue); if (g_bRecAutoExpire != *(bool*)settingValue) g_bRecAutoExpire = *(bool*)settingValue; } else if (str == "tunedelay") { XBMC->Log(LOG_INFO, "Changed Setting 'tunedelay' from %d to %d", g_iTuneDelay, *(int*)settingValue); if (g_iTuneDelay != *(int*)settingValue) g_iTuneDelay = *(int*)settingValue; } else if (str == "group_recordings") { XBMC->Log(LOG_INFO, "Changed Setting 'group_recordings' from %u to %u", g_iGroupRecordings, *(int*)settingValue); if (g_iGroupRecordings != *(int*)settingValue) { g_iGroupRecordings = *(int*)settingValue; PVR->TriggerRecordingUpdate(); } } else if (str == "use_airdate") { XBMC->Log(LOG_INFO, "Changed Setting 'use_airdate' from %u to %u", g_bUseAirdate, *(bool*)settingValue); if (g_bUseAirdate != *(bool*)settingValue) { g_bUseAirdate = *(bool*)settingValue; PVR->TriggerRecordingUpdate(); } } else if (str == "enable_edl") { XBMC->Log(LOG_INFO, "Changed Setting 'enable_edl' from %u to %u", g_iEnableEDL, *(int*)settingValue); if (g_iEnableEDL != *(int*)settingValue) g_iEnableEDL = *(int*)settingValue; } else if (str == "allow_shutdown") { XBMC->Log(LOG_INFO, "Changed Setting 'allow_shutdown' from %u to %u", g_bAllowMythShutdown, *(bool*)settingValue); if (g_bAllowMythShutdown != *(bool*)settingValue) g_bAllowMythShutdown = *(bool*)settingValue; } else if (str == "limit_tune_attempts") { XBMC->Log(LOG_INFO, "Changed Setting 'limit_tune_attempts' from %u to %u", g_bLimitTuneAttempts, *(bool*)settingValue); if (g_bLimitTuneAttempts != *(bool*)settingValue) g_bLimitTuneAttempts = *(bool*)settingValue; } else if (str == "inactive_upcomings") { XBMC->Log(LOG_INFO, "Changed Setting 'inactive_upcomings' from %u to %u", g_bShowNotRecording, *(bool*)settingValue); if (g_bShowNotRecording != *(bool*)settingValue) { g_bShowNotRecording = *(bool*)settingValue; if (g_client) g_client->HandleScheduleChange(); } } else if (str == "prompt_delete") { XBMC->Log(LOG_INFO, "Changed Setting 'prompt_delete' from %u to %u", g_bPromptDeleteAtEnd, *(bool*)settingValue); if (g_bPromptDeleteAtEnd != *(bool*)settingValue) g_bPromptDeleteAtEnd = *(bool*)settingValue; } else if (str == "livetv_recordings") { XBMC->Log(LOG_INFO, "Changed Setting 'livetv_recordings' from %u to %u", g_bLiveTVRecordings, *(bool*)settingValue); if (g_bLiveTVRecordings != *(bool*)settingValue) { g_bLiveTVRecordings = *(bool*)settingValue; PVR->TriggerRecordingUpdate(); } } else if (str == "root_default_group") { XBMC->Log(LOG_INFO, "Changed Setting 'root_default_group' from %u to %u", g_bRootDefaultGroup, *(bool*)settingValue); if (g_bRootDefaultGroup != *(bool*)settingValue) { g_bRootDefaultGroup = *(bool*)settingValue; PVR->TriggerRecordingUpdate(); } } else if (str == "damaged_color") { std::string tmp_sDamagedColor = g_szDamagedColor; char *buffer = new char [1024]; const char* v = (const char*)settingValue; const char* p = v; while (*p != '\0' && *p != ']') ++p; std::string s = std::string(v, p - v); if (sscanf(s.c_str(), "[COLOR %s", buffer) == 1) g_szDamagedColor = buffer; else g_szDamagedColor = ""; delete [] buffer; XBMC->Log(LOG_INFO, "Changed Setting 'damaged_color' from %s to %s", tmp_sDamagedColor.c_str(), g_szDamagedColor.c_str()); if (tmp_sDamagedColor != g_szDamagedColor) { PVR->TriggerRecordingUpdate(); } } return ADDON_STATUS_OK; } /*********************************************************** * PVR Client AddOn specific public library functions ***********************************************************/ PVR_ERROR GetAddonCapabilities(PVR_ADDON_CAPABILITIES *pCapabilities) { if (g_client != NULL) { unsigned version = g_client->GetBackendAPIVersion(); pCapabilities->bSupportsTV = g_bLiveTV; pCapabilities->bSupportsRadio = g_bLiveTV; pCapabilities->bSupportsChannelGroups = true; pCapabilities->bSupportsChannelScan = false; pCapabilities->bSupportsEPG = true; pCapabilities->bSupportsTimers = true; pCapabilities->bHandlesInputStream = true; pCapabilities->bHandlesDemuxing = false; pCapabilities->bSupportsRecordings = true; pCapabilities->bSupportsRecordingsUndelete = true; pCapabilities->bSupportsRecordingPlayCount = (version < 80 ? false : true); pCapabilities->bSupportsLastPlayedPosition = (version < 88 || !g_bUseBackendBookmarks ? false : true); pCapabilities->bSupportsRecordingEdl = true; pCapabilities->bSupportsRecordingsRename = false; pCapabilities->bSupportsRecordingsLifetimeChange = false; pCapabilities->bSupportsDescrambleInfo = false; return PVR_ERROR_NO_ERROR; } return PVR_ERROR_FAILED; } const char *GetBackendName() { return g_client->GetBackendName(); } const char *GetBackendVersion() { return g_client->GetBackendVersion(); } const char *GetConnectionString() { return g_client->GetConnectionString(); } const char *GetBackendHostname(void) { return g_szMythHostname.c_str(); } PVR_ERROR GetDriveSpace(long long *iTotal, long long *iUsed) { if (g_client == NULL) return PVR_ERROR_SERVER_ERROR; return g_client->GetDriveSpace(iTotal, iUsed); } PVR_ERROR OpenDialogChannelScan() { return PVR_ERROR_FAILED; } PVR_ERROR CallMenuHook(const PVR_MENUHOOK &menuhook, const PVR_MENUHOOK_DATA &item) { if (g_client == NULL) return PVR_ERROR_SERVER_ERROR; return g_client->CallMenuHook(menuhook, item); } void OnSystemSleep() { XBMC->Log(LOG_INFO, "Received event: %s", __FUNCTION__); if (g_client) g_client->OnSleep(); } void OnSystemWake() { XBMC->Log(LOG_INFO, "Received event: %s", __FUNCTION__); if (g_client) g_client->OnWake(); } void OnPowerSavingActivated() { XBMC->Log(LOG_INFO, "Received event: %s", __FUNCTION__); if (g_client) g_client->OnDeactivatedGUI(); } void OnPowerSavingDeactivated() { XBMC->Log(LOG_INFO, "Received event: %s", __FUNCTION__); if (g_client) g_client->OnActivatedGUI(); } /* * PVR EPG Functions */ PVR_ERROR GetEPGForChannel(ADDON_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd) { if (g_client == NULL) return PVR_ERROR_SERVER_ERROR; return g_client->GetEPGForChannel(handle, channel, iStart, iEnd); } /* * PVR Channel Functions */ int GetChannelsAmount() { if (g_client == NULL) return PVR_ERROR_SERVER_ERROR; return g_client->GetNumChannels(); } PVR_ERROR GetChannels(ADDON_HANDLE handle, bool bRadio) { if (g_client == NULL) return PVR_ERROR_SERVER_ERROR; return g_client->GetChannels(handle, bRadio); } PVR_ERROR DeleteChannel(const PVR_CHANNEL &channel) { (void)channel; return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR RenameChannel(const PVR_CHANNEL &channel) { (void)channel; return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR OpenDialogChannelSettings(const PVR_CHANNEL &channel) { (void)channel; return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR OpenDialogChannelAdd(const PVR_CHANNEL &channel) { (void)channel; return PVR_ERROR_NOT_IMPLEMENTED; } int GetChannelGroupsAmount(void) { if (g_client == NULL) return -1; return g_client->GetChannelGroupsAmount(); } PVR_ERROR GetChannelGroups(ADDON_HANDLE handle, bool bRadio) { if (g_client == NULL) return PVR_ERROR_SERVER_ERROR; return g_client->GetChannelGroups(handle, bRadio); } PVR_ERROR GetChannelGroupMembers(ADDON_HANDLE handle, const PVR_CHANNEL_GROUP &group){ if (g_client == NULL) return PVR_ERROR_SERVER_ERROR; return g_client->GetChannelGroupMembers(handle, group); } /* * PVR Recording Functions */ int GetRecordingsAmount(bool deleted) { if (g_client == NULL) return 0; if (deleted) return g_client->GetDeletedRecordingsAmount(); return g_client->GetRecordingsAmount(); } PVR_ERROR GetRecordings(ADDON_HANDLE handle, bool deleted) { if (g_client == NULL) return PVR_ERROR_SERVER_ERROR; if (deleted) return g_client->GetDeletedRecordings(handle); return g_client->GetRecordings(handle); } PVR_ERROR DeleteRecording(const PVR_RECORDING &recording) { if (g_client == NULL) return PVR_ERROR_SERVER_ERROR; return g_client->DeleteRecording(recording); } PVR_ERROR RenameRecording(const PVR_RECORDING &recording) { (void)recording; return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR SetRecordingPlayCount(const PVR_RECORDING &recording, int count) { if (g_client == NULL) return PVR_ERROR_SERVER_ERROR; return g_client->SetRecordingPlayCount(recording, count); } PVR_ERROR SetRecordingLastPlayedPosition(const PVR_RECORDING &recording, int lastplayedposition) { if (g_client == NULL) return PVR_ERROR_SERVER_ERROR; return g_client->SetRecordingLastPlayedPosition(recording, lastplayedposition); } int GetRecordingLastPlayedPosition(const PVR_RECORDING &recording) { if (g_client == NULL) return PVR_ERROR_SERVER_ERROR; return g_client->GetRecordingLastPlayedPosition(recording); } PVR_ERROR GetRecordingEdl(const PVR_RECORDING &recording, PVR_EDL_ENTRY entries[], int *size) { if (g_client == NULL) return PVR_ERROR_SERVER_ERROR; return g_client->GetRecordingEdl(recording, entries, size); } PVR_ERROR UndeleteRecording(const PVR_RECORDING& recording) { if (g_client == NULL) return PVR_ERROR_SERVER_ERROR; return g_client->UndeleteRecording(recording); } PVR_ERROR DeleteAllRecordingsFromTrash() { if (g_client == NULL) return PVR_ERROR_SERVER_ERROR; return g_client->PurgeDeletedRecordings(); } /* * PVR Timer Functions */ PVR_ERROR GetTimerTypes(PVR_TIMER_TYPE types[], int *size) { if (g_client == NULL) return PVR_ERROR_SERVER_ERROR; return g_client->GetTimerTypes(types, size); } int GetTimersAmount(void) { if (g_client == NULL) return PVR_ERROR_SERVER_ERROR; return g_client->GetTimersAmount(); } PVR_ERROR GetTimers(ADDON_HANDLE handle) { if (g_client == NULL) return PVR_ERROR_SERVER_ERROR; return g_client->GetTimers(handle); } PVR_ERROR AddTimer(const PVR_TIMER &timer) { if (g_client == NULL) return PVR_ERROR_SERVER_ERROR; return g_client->AddTimer(timer); } PVR_ERROR DeleteTimer(const PVR_TIMER &timer, bool bForceDelete) { if (g_client == NULL) return PVR_ERROR_SERVER_ERROR; return g_client->DeleteTimer(timer, bForceDelete); } PVR_ERROR UpdateTimer(const PVR_TIMER &timer) { if (g_client == NULL) return PVR_ERROR_SERVER_ERROR; return g_client->UpdateTimer(timer); } /* * PVR Live Stream Functions */ bool OpenLiveStream(const PVR_CHANNEL &channel) { if (g_client == NULL) return false; return g_client->OpenLiveStream(channel); } void CloseLiveStream(void) { if (g_client == NULL) return; g_client->CloseLiveStream(); } int ReadLiveStream(unsigned char *pBuffer, unsigned int iBufferSize) { if (g_client == NULL) return -1; int dataread = g_client->ReadLiveStream(pBuffer, iBufferSize); if (dataread < 0) { XBMC->Log(LOG_ERROR,"%s: Failed to read liveStream. Errorcode: %d!", __FUNCTION__, dataread); dataread = 0; } return dataread; } PVR_ERROR SignalStatus(PVR_SIGNAL_STATUS &signalStatus) { if (g_client == NULL) return PVR_ERROR_SERVER_ERROR; return g_client->SignalStatus(signalStatus); } void PauseStream(bool bPaused) { (void)bPaused; } bool CanPauseStream(void) { return true; } bool CanSeekStream(void) { return true; } long long SeekLiveStream(long long iPosition, int iWhence) { if (g_client == NULL) return -1; return g_client->SeekLiveStream(iPosition,iWhence); } long long LengthLiveStream(void) { if (g_client == NULL) return -1; return g_client->LengthLiveStream(); } bool IsRealTimeStream(void) { if (g_client == NULL) return false; return g_client->IsRealTimeStream(); } /* * PVR Recording Stream Functions */ bool OpenRecordedStream(const PVR_RECORDING &recinfo) { if (g_client == NULL) return false; return g_client->OpenRecordedStream(recinfo); } void CloseRecordedStream(void) { if (g_client == NULL) return; g_client->CloseRecordedStream(); } int ReadRecordedStream(unsigned char *pBuffer, unsigned int iBufferSize) { if (g_client == NULL) return -1; return g_client->ReadRecordedStream(pBuffer, iBufferSize); } long long SeekRecordedStream(long long iPosition, int iWhence) { if (g_client == NULL) return -1; if (iWhence == SEEK_POSSIBLE) return 1; return g_client->SeekRecordedStream(iPosition, iWhence); } long long LengthRecordedStream(void) { if (g_client == NULL) return -1; return g_client->LengthRecordedStream(); } /* * PVR Timeshift Functions */ bool IsTimeshifting(void) { return true; } /* * Unused API Functions */ PVR_ERROR GetStreamTimes(PVR_STREAM_TIMES *pStreamTimes) { if (g_client == NULL) return PVR_ERROR_SERVER_ERROR; return g_client->GetStreamTimes(pStreamTimes); } PVR_ERROR GetStreamProperties(PVR_STREAM_PROPERTIES *) { return PVR_ERROR_NOT_IMPLEMENTED; } void DemuxAbort(void) {} DemuxPacket* DemuxRead(void) { return NULL; } void DemuxFlush(void) {} bool SeekTime(double, bool, double *) { return false; } void DemuxReset() {} void SetSpeed(int) {}; PVR_ERROR SetEPGTimeFrame(int) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR GetDescrambleInfo(PVR_DESCRAMBLE_INFO*) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR SetRecordingLifetime(const PVR_RECORDING*) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR GetChannelStreamProperties(const PVR_CHANNEL*, PVR_NAMED_VALUE*, unsigned int*) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR GetRecordingStreamProperties(const PVR_RECORDING*, PVR_NAMED_VALUE*, unsigned int*) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR IsEPGTagRecordable(const EPG_TAG*, bool*) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR IsEPGTagPlayable(const EPG_TAG*, bool*) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR GetEPGTagStreamProperties(const EPG_TAG*, PVR_NAMED_VALUE*, unsigned int*) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR GetEPGTagEdl(const EPG_TAG* epgTag, PVR_EDL_ENTRY edl[], int *size) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR GetStreamReadChunkSize(int* chunksize) { return PVR_ERROR_NOT_IMPLEMENTED; } } //end extern "C" pvr.mythtv-5.10.15-Leia/src/client.h000066400000000000000000000135501360567320200171220ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2014 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef CLIENT_H #define CLIENT_H #include #include #include #include #define LIVETV_CONFLICT_STRATEGY_HASLATER 0 #define LIVETV_CONFLICT_STRATEGY_STOPTV 1 #define LIVETV_CONFLICT_STRATEGY_CANCELREC 2 #define DEFAULT_HOST "127.0.0.1" #define DEFAULT_EXTRA_DEBUG false #define DEFAULT_LIVETV_PRIORITY true #define DEFAULT_LIVETV_CONFLICT_STRATEGY LIVETV_CONFLICT_STRATEGY_HASLATER #define DEFAULT_LIVETV true #define DEFAULT_PROTO_PORT 6543 #define DEFAULT_WSAPI_PORT 6544 #define DEFAULT_WSAPI_SECURITY_PIN "0000" #define DEFAULT_CHANNEL_ICONS true #define DEFAULT_RECORDING_ICONS true #define DEFAULT_RECORD_TEMPLATE 1 #define MENUHOOK_REC_DELETE_AND_RERECORD 1 #define MENUHOOK_KEEP_RECORDING 2 #define MENUHOOK_TIMER_BACKEND_INFO 3 #define MENUHOOK_SHOW_HIDE_NOT_RECORDING 4 #define MENUHOOK_TRIGGER_CHANNEL_UPDATE 6 #define MENUHOOK_INFO_RECORDING 7 #define MENUHOOK_INFO_EPG 8 #define DEFAULT_TUNE_DELAY 5 #define GROUP_RECORDINGS_ALWAYS 0 #define GROUP_RECORDINGS_ONLY_FOR_SERIES 1 #define GROUP_RECORDINGS_NEVER 2 #define DEFAULT_USE_AIRDATE false #define ENABLE_EDL_ALWAYS 0 #define ENABLE_EDL_DIALOG 1 #define ENABLE_EDL_NEVER 2 #define ENABLE_EDL_SCENE 3 #define DEFAULT_ALLOW_SHUTDOWN true #define DEFAULT_LIMIT_TUNE_ATTEMPTS true #define DEFAULT_SHOW_NOT_RECORDING true #define DEFAULT_PROMPT_DELETE false #define DEFAULT_LIVETV_RECORDINGS true #define DEFAULT_BACKEND_BOOKMARKS true #define DEFAULT_ROOT_DEFAULT_GROUP false #define DEFAULT_DAMAGED_COLOR "yellow" /*! * @brief PVR macros for string exchange */ #define PVR_STRCPY(dest, source) do { strncpy(dest, source, sizeof(dest)-1); dest[sizeof(dest)-1] = '\0'; } while(0) #define PVR_STRCLR(dest) memset(dest, 0, sizeof(dest)) /** Delete macros that make the pointer NULL again */ #define SAFE_DELETE(p) if ((p) != NULL) { delete (p); (p) = NULL; } #define SAFE_DELETE_ARRAY(p) if ((p) != NULL) { delete[] (p); (p) = NULL; } extern bool g_bCreated; ///< Shows that the Create function was successfully called extern int g_iClientID; ///< The PVR client ID used by XBMC for this driver extern std::string g_szUserPath; ///< The Path to the user directory inside user profile extern std::string g_szClientPath; ///< The Path where this driver is located /* Client Settings */ extern std::string g_szMythHostname; ///< The Host name or IP of the mythtv server extern std::string g_szMythHostEther; ///< The Host MAC address of the mythtv server extern int g_iProtoPort; ///< The mythtv protocol port (default is 6543) extern int g_iWSApiPort; ///< The mythtv service API port (default is 6544) extern std::string g_szWSSecurityPin; ///< The default security pin for the mythtv wsapi extern bool g_bExtraDebug; ///< Debug logging extern bool g_bLiveTV; ///< LiveTV support (or recordings only) extern bool g_bLiveTVPriority; ///< MythTV Backend setting to allow live TV to move scheduled shows extern int g_iLiveTVConflictStrategy; ///< Live TV conflict resolving strategy (0=Has later, 1=Stop TV, 2=Cancel recording) extern bool g_bChannelIcons; ///< Load Channel Icons extern bool g_bRecordingIcons; ///< Load Recording Icons (Fanart/Thumbnails) extern bool g_bLiveTVRecordings; ///< Show LiveTV recordings extern int g_iRecTemplateType; ///< Template type for new record (0=Internal, 1=MythTV) ///@{ /// Internal Record template extern bool g_bRecAutoMetadata; extern bool g_bRecAutoCommFlag; extern bool g_bRecAutoTranscode; extern bool g_bRecAutoRunJob1; extern bool g_bRecAutoRunJob2; extern bool g_bRecAutoRunJob3; extern bool g_bRecAutoRunJob4; extern bool g_bRecAutoExpire; extern int g_iRecTranscoder; ///@} extern int g_iTuneDelay; extern int g_iGroupRecordings; extern bool g_bUseAirdate; extern int g_iEnableEDL; extern bool g_bAllowMythShutdown; extern bool g_bLimitTuneAttempts; ///< Limit channel tuning attempts to first card extern bool g_bShowNotRecording; extern bool g_bPromptDeleteAtEnd; extern bool g_bUseBackendBookmarks; extern bool g_bRootDefaultGroup; extern std::string g_szDamagedColor; extern ADDON::CHelper_libXBMC_addon *XBMC; extern CHelper_libXBMC_pvr *PVR; extern CHelper_libKODI_guilib *GUI; #endif /* CLIENT_H */ pvr.mythtv-5.10.15-Leia/src/cppmyth.h000066400000000000000000000003461360567320200173270ustar00rootroot00000000000000#pragma once #include "cppmyth/MythPrivate.h" #include "cppmyth/MythChannel.h" #include "cppmyth/MythEPGInfo.h" #include "cppmyth/MythProgramInfo.h" #include "cppmyth/MythRecordingRule.h" #include "cppmyth/MythScheduleManager.h" pvr.mythtv-5.10.15-Leia/src/cppmyth/000077500000000000000000000000001360567320200171535ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/src/cppmyth/MythChannel.cpp000066400000000000000000000055241360567320200220770ustar00rootroot00000000000000/* * Copyright (C) 2005-2014 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ #include "MythChannel.h" #include #include #include #define CHANNUM_STR_SIZE 10 MythChannel::MythChannel() : m_channel() , m_numMajor(0) , m_numMinor(0) { } MythChannel::MythChannel(Myth::ChannelPtr channel) : m_channel() { m_channel.swap(channel); if (m_channel) { BreakNumber(m_channel->chanNum.c_str(), &m_numMajor, &m_numMinor); } else { m_numMajor = 0; m_numMinor = 0; } } void MythChannel::BreakNumber(const char *numstr, unsigned *major, unsigned *minor) { // ATSC channel number use "_" or "." for major and minor separator char str[CHANNUM_STR_SIZE + 1]; char *p1 = str; char *p2 = str; strncpy(str, numstr, CHANNUM_STR_SIZE); str[CHANNUM_STR_SIZE] = '\0'; while(isspace(*p1)) ++p1; p2 = p1; while (isdigit(*p2)) ++p2; *p2++ = '\0'; *major = (unsigned)atoi(p1); p1 = p2; while (isdigit(*p2)) ++p2; *p2 = '\0'; *minor = (unsigned)atoi(p1); } bool MythChannel::IsNull() const { if (!m_channel) return true; return m_channel.get() == NULL; } Myth::ChannelPtr MythChannel::GetPtr() const { return m_channel; } uint32_t MythChannel::ID() const { return (m_channel ? m_channel->chanId : 0); } std::string MythChannel::Name() const { return (m_channel ? m_channel->channelName : ""); } std::string MythChannel::Number() const { return (m_channel ? m_channel->chanNum : ""); } std::string MythChannel::Callsign() const { return (m_channel ? m_channel->callSign : ""); } std::string MythChannel::Icon() const { return (m_channel ? m_channel->iconURL : ""); } bool MythChannel::Visible() const { return (m_channel ? m_channel->visible : false); } bool MythChannel::IsRadio() const { // Check for keyword to move channel to "Radio" group in the channel's callsign // If "[RADIO]" is found then return true else return false return (m_channel ? ((m_channel->callSign.find("[RADIO]") != std::string::npos) ? true : false) : false); } uint32_t MythChannel::SourceID() const { return (m_channel ? m_channel->sourceId : 0); } uint32_t MythChannel::MultiplexID() const { return (m_channel ? m_channel->mplexId : 0); } pvr.mythtv-5.10.15-Leia/src/cppmyth/MythChannel.h000066400000000000000000000026561360567320200215470ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2014 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ #include class MythChannel { public: MythChannel(); MythChannel(Myth::ChannelPtr channel); bool IsNull() const; Myth::ChannelPtr GetPtr() const; uint32_t ID() const; std::string Name() const; std::string Number() const; std::string Callsign() const; std::string Icon() const; bool Visible() const; bool IsRadio() const; uint32_t SourceID() const; uint32_t MultiplexID() const; unsigned NumberMajor() const { return m_numMajor; } unsigned NumberMinor() const { return m_numMinor; } private: Myth::ChannelPtr m_channel; unsigned m_numMajor; unsigned m_numMinor; static void BreakNumber(const char *numstr, unsigned *major, unsigned *minor); }; pvr.mythtv-5.10.15-Leia/src/cppmyth/MythEPGInfo.cpp000066400000000000000000000100021360567320200217410ustar00rootroot00000000000000/* * Copyright (C) 2005-2014 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ #include "MythEPGInfo.h" #include "../tools.h" MythEPGInfo::MythEPGInfo() : m_epginfo() { } MythEPGInfo::MythEPGInfo(const Myth::ProgramPtr& epginfo) : m_epginfo(epginfo) { } MythEPGInfo::MythEPGInfo(unsigned chanid, time_t starttime, time_t endtime) : m_epginfo() { m_epginfo.reset(new Myth::Program()); m_epginfo->channel.chanId = chanid; m_epginfo->startTime = starttime; m_epginfo->endTime = endtime; } bool MythEPGInfo::IsNull() const { if (!m_epginfo) return true; return m_epginfo.get() == NULL; } Myth::ProgramPtr MythEPGInfo::GetPtr() const { return m_epginfo; } uint32_t MythEPGInfo::ChannelID() const { return (m_epginfo ? m_epginfo->channel.chanId : 0); } std::string MythEPGInfo::ChannelName() const { return (m_epginfo ? m_epginfo->channel.channelName : "" ); } std::string MythEPGInfo::Callsign() const { return (m_epginfo ? m_epginfo->channel.callSign : ""); } uint32_t MythEPGInfo::SourceID() const { return (m_epginfo ? m_epginfo->channel.sourceId : 0); } std::string MythEPGInfo::Title() const { return (m_epginfo ? m_epginfo->title : ""); } std::string MythEPGInfo::Subtitle() const { return (m_epginfo ? m_epginfo->subTitle : ""); } std::string MythEPGInfo::Description() const { return (m_epginfo ? m_epginfo->description : ""); } time_t MythEPGInfo::StartTime() const { return (m_epginfo ? m_epginfo->startTime : 0); } time_t MythEPGInfo::EndTime() const { return (m_epginfo ? m_epginfo->endTime : 0); } std::string MythEPGInfo::ProgramID() const { return (m_epginfo ? m_epginfo->programId : ""); } std::string MythEPGInfo::SeriesID() const { return (m_epginfo ? m_epginfo->seriesId : ""); } std::string MythEPGInfo::Category() const { return (m_epginfo ? m_epginfo->category : ""); } std::string MythEPGInfo::CategoryType() const { return (m_epginfo ? m_epginfo->catType : ""); } std::string MythEPGInfo::ChannelNumber() const { return (m_epginfo ? m_epginfo->channel.chanNum : ""); } // Broacast ID is 32 bits integer and allows to identify a EPG item. // MythTV backend doesn't provide one. So we make it encoding time and channel // as below: // 31. . . . . . . . . . . . . . . 15. . . . . . . . . . . . . . 0 // [ timecode (self-relative) ][ channel Id ] // Timecode is the count of minutes since epoch modulo 0xFFFF. Now therefore it // is usable for a period of +/- 32767 minutes (+/-22 days) around itself. int MythEPGInfo::MakeBroadcastID(unsigned int chanid, time_t starttime) { int timecode = (int)(difftime(starttime, 0) / INTERVAL_MINUTE) & 0xFFFF; return (int)((timecode << 16) | (chanid & 0xFFFF)); } void MythEPGInfo::BreakBroadcastID(int broadcastid, unsigned int *chanid, time_t *attime) { time_t now; int ntc, ptc, distance; struct tm epgtm; now = time(NULL); ntc = (int)(difftime(now, 0) / INTERVAL_MINUTE) & 0xFFFF; ptc = (broadcastid >> 16) & 0xFFFF; // removes arithmetic bits if (ptc > ntc) distance = (ptc - ntc) < 0x8000 ? ptc - ntc : ptc - ntc - 0xFFFF; else distance = (ntc - ptc) < 0x8000 ? ptc - ntc : ptc - ntc + 0xFFFF; localtime_r(&now, &epgtm); epgtm.tm_min += distance; // Time precision is minute, so we are looking for program started before next minute. epgtm.tm_sec = INTERVAL_MINUTE - 1; *attime = mktime(&epgtm); *chanid = (unsigned int)broadcastid & 0xFFFF; } pvr.mythtv-5.10.15-Leia/src/cppmyth/MythEPGInfo.h000066400000000000000000000032641360567320200214220ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2014 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ #include class MythEPGInfo { public: MythEPGInfo(); MythEPGInfo(const Myth::ProgramPtr& epginfo); MythEPGInfo(unsigned chanid, time_t starttime, time_t endtime); bool IsNull() const; Myth::ProgramPtr GetPtr() const; uint32_t ChannelID() const; std::string ChannelName() const; std::string Callsign() const; uint32_t SourceID() const; std::string Title() const; std::string Subtitle() const; std::string Description() const; time_t StartTime() const; time_t EndTime() const; std::string ProgramID() const; std::string SeriesID() const; std::string Category() const; std::string CategoryType() const; std::string ChannelNumber() const; /** * * \brief Handle broadcast UID for MythTV program */ static int MakeBroadcastID(unsigned int chanid, time_t starttime); static void BreakBroadcastID(int broadcastid, unsigned int *chanid, time_t *starttime); private: Myth::ProgramPtr m_epginfo; }; pvr.mythtv-5.10.15-Leia/src/cppmyth/MythPrivate.h000066400000000000000000000002511360567320200215760ustar00rootroot00000000000000#ifndef MYTHPRIVATE_H #define MYTHPRIVATE_H namespace Myth { namespace OS { class CMutex; class CThread; class CTimeout; class CEvent; } } #endif /* MYTHPRIVATE_H */ pvr.mythtv-5.10.15-Leia/src/cppmyth/MythProgramInfo.cpp000066400000000000000000000211471360567320200227510ustar00rootroot00000000000000/* * Copyright (C) 2005-2014 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ #include "MythProgramInfo.h" #include // for sprintf #include // for difftime enum { FLAGS_INITIALIZED = 0x80000000, FLAGS_HAS_COVERART = 0x00000001, FLAGS_HAS_FANART = 0x00000002, FLAGS_HAS_BANNER = 0x00000004, FLAGS_IS_VISIBLE = 0x00000008, FLAGS_IS_LIVETV = 0x00000010, FLAGS_IS_DELETED = 0x00000020, }; MythProgramInfo::MythProgramInfo() : m_proginfo() , m_flags(0) , m_props(new Props()) { } MythProgramInfo::MythProgramInfo(Myth::ProgramPtr proginfo) : m_proginfo() , m_flags(0) , m_props(new Props()) { m_proginfo.swap(proginfo); } bool MythProgramInfo::IsNull() const { if (!m_proginfo) return true; return m_proginfo.get() == NULL; } Myth::ProgramPtr MythProgramInfo::GetPtr() const { return m_proginfo; } bool MythProgramInfo::operator ==(const MythProgramInfo &other) { if (!this->IsNull() && !other.IsNull()) { if (this->m_proginfo->channel.chanId == other.m_proginfo->channel.chanId && this->m_proginfo->recording.startTs == other.m_proginfo->recording.startTs) return true; } return false; } bool MythProgramInfo::operator !=(const MythProgramInfo &other) { return !(*this == other); } bool MythProgramInfo::IsSetup() const { if (m_flags) return true; m_flags |= FLAGS_INITIALIZED; if (m_proginfo) { // Has Artworks ? for (std::vector::const_iterator it = m_proginfo->artwork.begin(); it != m_proginfo->artwork.end(); ++it) { if (it->type == "coverart") m_flags |= FLAGS_HAS_COVERART; else if (it->type == "fanart") m_flags |= FLAGS_HAS_FANART; else if (it->type == "banner") m_flags |= FLAGS_HAS_BANNER; } // Is Visible ? // Filter out recording of special storage group Deleted // Filter out recording with duration less than 5 seconds // When deleting a recording, it might not be deleted immediately but marked as 'pending delete'. // Depending on the protocol version the recording is moved to the group Deleted or // the 'delete pending' flag is set if (Duration() >= 5) { if (RecordingGroup() == "Deleted" || IsDeletePending()) m_flags |= FLAGS_IS_DELETED; else m_flags |= FLAGS_IS_VISIBLE; } // Is LiveTV ? if (RecordingGroup() == "LiveTV") m_flags |= FLAGS_IS_LIVETV; } return true; } bool MythProgramInfo::IsVisible() const { if (IsSetup() && (m_flags & FLAGS_IS_VISIBLE)) return true; return false; } bool MythProgramInfo::IsDeleted() const { if (IsSetup() && (m_flags & FLAGS_IS_DELETED)) return true; return false; } bool MythProgramInfo::IsLiveTV() const { if (IsSetup() && (m_flags & FLAGS_IS_LIVETV)) return true; return false; } bool MythProgramInfo::HasCoverart() const { if (IsSetup() && (m_flags & FLAGS_HAS_COVERART)) return true; return false; } bool MythProgramInfo::HasFanart() const { if (IsSetup() && (m_flags & FLAGS_HAS_FANART)) return true; return false; } void MythProgramInfo::SetPropsVideoFrameRate(float fps) { m_props->m_videoFrameRate = fps; } float MythProgramInfo::GetPropsVideoFrameRate() const { return m_props->m_videoFrameRate; } void MythProgramInfo::SetPropsVideoAspec(float aspec) { m_props->m_videoAspec = aspec; } float MythProgramInfo::GetPropsVideoAspec() const { return m_props->m_videoAspec; } void MythProgramInfo::SetPropsSerie(bool flag) { m_props->m_serie = flag; } bool MythProgramInfo::GetPropsSerie() const { return m_props->m_serie; } std::string MythProgramInfo::UID() const { char buf[48] = ""; sprintf(buf, "%u_%ld_%.3x", (unsigned)m_proginfo->channel.chanId, (long)m_proginfo->recording.startTs, (unsigned)m_proginfo->recording.recordedId & 0xfff); return std::string(buf); } std::string MythProgramInfo::ProgramID() const { return (m_proginfo ? m_proginfo->programId : ""); } std::string MythProgramInfo::SerieID() const { return (m_proginfo ? m_proginfo->seriesId : ""); } std::string MythProgramInfo::Title() const { return (m_proginfo ? m_proginfo->title : ""); } std::string MythProgramInfo::Subtitle() const { return (m_proginfo ? m_proginfo->subTitle : ""); } std::string MythProgramInfo::HostName() const { return (m_proginfo ? m_proginfo->hostName : ""); } std::string MythProgramInfo::FileName() const { return (m_proginfo ? m_proginfo->fileName : ""); } std::string MythProgramInfo::Description() const { return (m_proginfo ? m_proginfo->description : ""); } int MythProgramInfo::Duration() const { return (m_proginfo ? (int)difftime(m_proginfo->recording.endTs, m_proginfo->recording.startTs) : 0); } std::string MythProgramInfo::Category() const { return (m_proginfo ? m_proginfo->category : ""); } time_t MythProgramInfo::StartTime() const { return (m_proginfo ? m_proginfo->startTime : (time_t)(-1)); } time_t MythProgramInfo::EndTime() const { return (m_proginfo ? m_proginfo->endTime : (time_t)(-1)); } bool MythProgramInfo::IsWatched() const { return ((m_proginfo && (m_proginfo->programFlags & 0x00000200)) ? true : false); } bool MythProgramInfo::IsDeletePending() const { return ((m_proginfo && (m_proginfo->programFlags & 0x00000080)) ? true : false); } bool MythProgramInfo::HasBookmark() const { return ((m_proginfo && (m_proginfo->programFlags & 0x00000010)) ? true : false); } uint32_t MythProgramInfo::ChannelID() const { return (m_proginfo ? m_proginfo->channel.chanId : 0); } std::string MythProgramInfo::ChannelName() const { return (m_proginfo ? m_proginfo->channel.channelName : ""); } std::string MythProgramInfo::Callsign() const { return (m_proginfo ? m_proginfo->channel.callSign : ""); } Myth::RS_t MythProgramInfo::Status() const { return (m_proginfo ? (Myth::RS_t)m_proginfo->recording.status : Myth::RS_UNKNOWN); } std::string MythProgramInfo::RecordingGroup() const { return (m_proginfo ? m_proginfo->recording.recGroup : ""); } uint32_t MythProgramInfo::RecordID() const { return (m_proginfo ? m_proginfo->recording.recordId : 0); } time_t MythProgramInfo::RecordingStartTime() const { return (m_proginfo ? m_proginfo->recording.startTs : (time_t)(-1)); } time_t MythProgramInfo::RecordingEndTime() const { return (m_proginfo ? m_proginfo->recording.endTs : (time_t)(-1)); } int MythProgramInfo::Priority() const { return (m_proginfo ? m_proginfo->recording.priority : 0); } std::string MythProgramInfo::StorageGroup() const { return (m_proginfo ? m_proginfo->recording.storageGroup : ""); } std::string MythProgramInfo::Inetref() const { return (m_proginfo ? m_proginfo->inetref : ""); } uint16_t MythProgramInfo::Season() const { return (m_proginfo ? m_proginfo->season : 0); } uint16_t MythProgramInfo::Episode() const { return (m_proginfo ? m_proginfo->episode : 0); } time_t MythProgramInfo::Airdate() const { return (m_proginfo ? m_proginfo->airdate : 0); } bool MythProgramInfo::IsDamaged() const { return ((m_proginfo && (m_proginfo->videoProps & 0x0020)) ? true : false); } std::string MythProgramInfo::GroupingTitle() const { if (!m_proginfo || !m_groupingTitle.empty()) return m_groupingTitle; // UTF-8 is safe when interpreting 7-bit ASCII characters. Therefore, the following // treatments do not require special care about locale std::string& sin = m_proginfo->title; // truncate title at the first left parenthesis // i.e: "Ad Vitam (1/6)" => "Ad Vitam " size_t p = sin.find('\x28'); if (p == std::string::npos || p == 0) p = sin.length(); // clean special characters std::string buf; for (size_t i = 0; i < p; ++i) { char c = sin[i]; if (c != '\x2f' // slash && c != '\x5c' // back-slash && c != '\x5b' // [ && c != '\x5d' // ] ) buf.push_back(c); else buf.push_back('\x20'); } // trim trailing spaces p = buf.length(); while (p > 0 && isspace((int)(buf[p - 1]))) --p; buf.resize(p); return m_groupingTitle = buf; } pvr.mythtv-5.10.15-Leia/src/cppmyth/MythProgramInfo.h000066400000000000000000000061071360567320200224150ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2014 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ #include class MythProgramInfo; typedef std::map ProgramInfoMap; class MythProgramInfo { public: MythProgramInfo(); MythProgramInfo(Myth::ProgramPtr proginfo); bool IsNull() const; Myth::ProgramPtr GetPtr() const; bool operator ==(const MythProgramInfo &other); bool operator !=(const MythProgramInfo &other); /// Reset custom flags and properties void ResetProps() { m_flags = 0; m_props.reset(new Props()); } /// Copy reference of properties from other void CopyProps(const MythProgramInfo &other) { m_props = other.m_props; } // Custom flags bool IsVisible() const; bool IsDeleted() const; bool IsLiveTV() const; bool HasCoverart() const; bool HasFanart() const; // Custom props void SetPropsVideoFrameRate(float fps); float GetPropsVideoFrameRate() const; void SetPropsVideoAspec(float aspec); float GetPropsVideoAspec() const; void SetPropsSerie(bool flag); bool GetPropsSerie() const; // Program fields std::string UID() const; std::string ProgramID() const; std::string SerieID() const; std::string Title() const; std::string Subtitle() const; std::string HostName() const; std::string FileName() const; std::string Description() const; int Duration() const; std::string Category() const; time_t StartTime() const; time_t EndTime() const; bool IsWatched() const; bool IsDeletePending() const; bool HasBookmark() const; uint32_t ChannelID() const; std::string ChannelName() const; std::string Callsign() const; Myth::RS_t Status() const; std::string RecordingGroup() const; uint32_t RecordID() const; time_t RecordingStartTime() const; time_t RecordingEndTime() const; int Priority() const; std::string StorageGroup() const; std::string Inetref() const; uint16_t Season() const; uint16_t Episode() const; time_t Airdate() const; bool IsDamaged() const; std::string GroupingTitle() const; private: Myth::ProgramPtr m_proginfo; mutable int32_t m_flags; mutable std::string m_groupingTitle; class Props { public: Props() : m_videoFrameRate(0) , m_videoAspec(0) , m_serie(false) {} ~Props() {} float m_videoFrameRate; float m_videoAspec; bool m_serie; ///< true if program is serie else false }; MYTH_SHARED_PTR m_props; bool IsSetup() const; }; pvr.mythtv-5.10.15-Leia/src/cppmyth/MythRecordingRule.cpp000066400000000000000000000221071360567320200232670ustar00rootroot00000000000000/* * Copyright (C) 2005-2014 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ #include "MythRecordingRule.h" MythRecordingRule::MythRecordingRule() : m_recordSchedule(new Myth::RecordSchedule()) { } MythRecordingRule::MythRecordingRule(Myth::RecordSchedulePtr recordschedule) : m_recordSchedule(new Myth::RecordSchedule()) { if (recordschedule) m_recordSchedule.swap(recordschedule); } Myth::RecordSchedulePtr MythRecordingRule::GetPtr() { return m_recordSchedule; } MythRecordingRule MythRecordingRule::DuplicateRecordingRule() const { Myth::RecordSchedulePtr copy(new Myth::RecordSchedule()); *copy = *m_recordSchedule; return MythRecordingRule(copy); } uint32_t MythRecordingRule::RecordID() const { return m_recordSchedule->recordId; } void MythRecordingRule::SetRecordID(uint32_t recordid) { m_recordSchedule->recordId = recordid; } uint32_t MythRecordingRule::ChannelID() const { return m_recordSchedule->chanId; } void MythRecordingRule::SetChannelID(uint32_t chanid) { m_recordSchedule->chanId = chanid; } std::string MythRecordingRule::Callsign() const { return m_recordSchedule->callSign; } void MythRecordingRule::SetCallsign(const std::string& channame) { m_recordSchedule->callSign = channame; } time_t MythRecordingRule::StartTime() const { return m_recordSchedule->startTime; } void MythRecordingRule::SetStartTime(time_t starttime) { m_recordSchedule->startTime = starttime; } time_t MythRecordingRule::EndTime() const { return m_recordSchedule->endTime; } void MythRecordingRule::SetEndTime(time_t endtime) { m_recordSchedule->endTime = endtime; } std::string MythRecordingRule::Title() const { return m_recordSchedule->title; } void MythRecordingRule::SetTitle(const std::string& title) { m_recordSchedule->title = title; } std::string MythRecordingRule::Subtitle() const { return m_recordSchedule->subtitle; } void MythRecordingRule::SetSubtitle(const std::string& subtitle) { m_recordSchedule->subtitle = subtitle; } std::string MythRecordingRule::Description() const { return m_recordSchedule->description; } void MythRecordingRule::SetDescription(const std::string& description) { m_recordSchedule->description = description; } Myth::RT_t MythRecordingRule::Type() const { return m_recordSchedule->type_t; } void MythRecordingRule::SetType(Myth::RT_t type) { m_recordSchedule->type_t = type; } std::string MythRecordingRule::Category() const { return m_recordSchedule->category; } void MythRecordingRule::SetCategory(const std::string& category) { m_recordSchedule->category = category; } uint8_t MythRecordingRule::StartOffset() const { return m_recordSchedule->startOffset; } void MythRecordingRule::SetStartOffset(uint8_t startoffset) { m_recordSchedule->startOffset = startoffset; } uint8_t MythRecordingRule::EndOffset() const { return m_recordSchedule->endOffset; } void MythRecordingRule::SetEndOffset(uint8_t endoffset) { m_recordSchedule->endOffset = endoffset; } int8_t MythRecordingRule::Priority() const { return m_recordSchedule->recPriority; } void MythRecordingRule::SetPriority(int8_t priority) { m_recordSchedule->recPriority = priority; } bool MythRecordingRule::Inactive() const { return m_recordSchedule->inactive; } void MythRecordingRule::SetInactive(bool inactive) { m_recordSchedule->inactive = inactive; } Myth::ST_t MythRecordingRule::SearchType() const { return m_recordSchedule->searchType_t; } void MythRecordingRule::SetSearchType(Myth::ST_t searchtype) { m_recordSchedule->searchType_t = searchtype; } Myth::DM_t MythRecordingRule::DuplicateControlMethod() const { return m_recordSchedule->dupMethod_t; } void MythRecordingRule::SetDuplicateControlMethod(Myth::DM_t method) { m_recordSchedule->dupMethod_t = method; } Myth::DI_t MythRecordingRule::CheckDuplicatesInType() const { return m_recordSchedule->dupIn_t; } void MythRecordingRule::SetCheckDuplicatesInType(Myth::DI_t in) { m_recordSchedule->dupIn_t = in; } std::string MythRecordingRule::RecordingGroup() const { return m_recordSchedule->recGroup; } void MythRecordingRule::SetRecordingGroup(const std::string& group) { m_recordSchedule->recGroup = group; } std::string MythRecordingRule::StorageGroup() const { return m_recordSchedule->storageGroup; } void MythRecordingRule::SetStorageGroup(const std::string& group) { m_recordSchedule->storageGroup = group; } std::string MythRecordingRule::PlaybackGroup() const { return m_recordSchedule->playGroup; } void MythRecordingRule::SetPlaybackGroup(const std::string& group) { m_recordSchedule->playGroup = group; } bool MythRecordingRule::AutoTranscode() const { return m_recordSchedule->autoTranscode; } void MythRecordingRule::SetAutoTranscode(bool enable) { m_recordSchedule->autoTranscode = enable; } bool MythRecordingRule::UserJob(int jobnumber) const { switch (jobnumber) { case 1: return m_recordSchedule->autoUserJob1; case 2: return m_recordSchedule->autoUserJob2; case 3: return m_recordSchedule->autoUserJob3; case 4: return m_recordSchedule->autoUserJob4; default: break; } return false; } void MythRecordingRule::SetUserJob(int jobnumber, bool enable) { switch (jobnumber) { case 1: m_recordSchedule->autoUserJob1 = enable; break; case 2: m_recordSchedule->autoUserJob2 = enable; break; case 3: m_recordSchedule->autoUserJob3 = enable; break; case 4: m_recordSchedule->autoUserJob4 = enable; break; default: break; } } bool MythRecordingRule::AutoMetadata() const { return m_recordSchedule->autoMetaLookup; } void MythRecordingRule::SetAutoMetadata(bool enable) { m_recordSchedule->autoMetaLookup = enable; } bool MythRecordingRule::AutoCommFlag() const { return m_recordSchedule->autoCommflag; } void MythRecordingRule::SetAutoCommFlag(bool enable) { m_recordSchedule->autoCommflag = enable; } bool MythRecordingRule::AutoExpire() const { return m_recordSchedule->autoExpire; } void MythRecordingRule::SetAutoExpire(bool enable) { m_recordSchedule->autoExpire = enable; } uint32_t MythRecordingRule::MaxEpisodes() const { return m_recordSchedule->maxEpisodes; } void MythRecordingRule::SetMaxEpisodes(uint32_t max) { m_recordSchedule->maxEpisodes = max; } bool MythRecordingRule::NewExpiresOldRecord() const { return m_recordSchedule->maxNewest; } void MythRecordingRule::SetNewExpiresOldRecord(bool enable) { m_recordSchedule->maxNewest = enable; } uint32_t MythRecordingRule::Transcoder() const { return m_recordSchedule->transcoder; } void MythRecordingRule::SetTranscoder(uint32_t transcoder) { m_recordSchedule->transcoder = transcoder; } uint32_t MythRecordingRule::ParentID() const { return m_recordSchedule->parentId; } void MythRecordingRule::SetParentID(uint32_t parentid) { m_recordSchedule->parentId = parentid; } uint32_t MythRecordingRule::Filter() const { return m_recordSchedule->filter; } void MythRecordingRule::SetFilter(uint32_t filter) { m_recordSchedule->filter = filter; } std::string MythRecordingRule::ProgramID() const { return m_recordSchedule->programId; } void MythRecordingRule::SetProgramID(const std::string& programid) { m_recordSchedule->programId = programid; } std::string MythRecordingRule::SeriesID() const { return m_recordSchedule->seriesId; } void MythRecordingRule::SetSeriesID(const std::string& seriesid) { m_recordSchedule->seriesId = seriesid; } std::string MythRecordingRule::RecordingProfile() const { return m_recordSchedule->recProfile; } void MythRecordingRule::SetRecordingProfile(const std::string& profile) { m_recordSchedule->recProfile = profile; } std::string MythRecordingRule::InetRef() const { return m_recordSchedule->inetref; } void MythRecordingRule::SetInerRef(const std::string& inetref) { m_recordSchedule->inetref = inetref; } uint16_t MythRecordingRule::Season() const { return m_recordSchedule->season; } void MythRecordingRule::SetSeason(uint16_t season) { m_recordSchedule->season = season; } uint16_t MythRecordingRule::Episode() const { return m_recordSchedule->episode; } void MythRecordingRule::SetEpisode(uint16_t episode) { m_recordSchedule->episode = episode; } time_t MythRecordingRule::NextRecording() const { return m_recordSchedule->nextRecording; } time_t MythRecordingRule::LastRecorded() const { return m_recordSchedule->lastRecorded; } time_t MythRecordingRule::LastDeleted() const { return m_recordSchedule->lastDeleted; } uint32_t MythRecordingRule::AverageDelay() const { return m_recordSchedule->averageDelay; } pvr.mythtv-5.10.15-Leia/src/cppmyth/MythRecordingRule.h000066400000000000000000000075011360567320200227350ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2014 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ #include class MythRecordingRule { public: MythRecordingRule(); MythRecordingRule(Myth::RecordSchedulePtr recordschedule); Myth::RecordSchedulePtr GetPtr(); MythRecordingRule DuplicateRecordingRule() const; uint32_t RecordID() const; void SetRecordID(uint32_t recordid); uint32_t ChannelID() const; void SetChannelID(uint32_t channelid); std::string Callsign() const; void SetCallsign(const std::string& callsign); time_t StartTime() const; void SetStartTime(time_t starttime); time_t EndTime() const; void SetEndTime(time_t endtime); std::string Title() const; void SetTitle(const std::string& title); std::string Subtitle() const; void SetSubtitle(const std::string& subtitle); std::string Description() const; void SetDescription(const std::string& description); Myth::RT_t Type() const; void SetType(Myth::RT_t type); std::string Category() const; void SetCategory(const std::string& category); uint8_t StartOffset() const; void SetStartOffset(uint8_t startoffset); uint8_t EndOffset() const; void SetEndOffset(uint8_t endoffset); int8_t Priority() const; void SetPriority(int8_t priority); bool Inactive() const; void SetInactive(bool inactive); Myth::ST_t SearchType() const; void SetSearchType(Myth::ST_t searchtype); Myth::DM_t DuplicateControlMethod() const; void SetDuplicateControlMethod(Myth::DM_t method); Myth::DI_t CheckDuplicatesInType() const; void SetCheckDuplicatesInType(Myth::DI_t in); std::string RecordingGroup() const; void SetRecordingGroup(const std::string& group); std::string StorageGroup() const; void SetStorageGroup(const std::string& group); std::string PlaybackGroup() const; void SetPlaybackGroup(const std::string& group); bool AutoTranscode() const; void SetAutoTranscode(bool enable); bool UserJob(int jobnumber) const; void SetUserJob(int jobnumber, bool enable); bool AutoMetadata() const; void SetAutoMetadata(bool enable); bool AutoCommFlag() const; void SetAutoCommFlag(bool enable); bool AutoExpire() const; void SetAutoExpire(bool enable); uint32_t MaxEpisodes() const; void SetMaxEpisodes(uint32_t max); bool NewExpiresOldRecord() const; void SetNewExpiresOldRecord(bool enable); uint32_t Transcoder() const; void SetTranscoder(uint32_t transcoder); uint32_t ParentID() const; void SetParentID(uint32_t parentid); uint32_t Filter() const; void SetFilter(uint32_t filter); std::string ProgramID() const; void SetProgramID(const std::string& programid); std::string SeriesID() const; void SetSeriesID(const std::string& seriesid); std::string RecordingProfile() const; void SetRecordingProfile(const std::string& profile); std::string InetRef() const; void SetInerRef(const std::string& inetref); uint16_t Season() const; void SetSeason(uint16_t season); uint16_t Episode() const; void SetEpisode(uint16_t episode); time_t NextRecording() const; time_t LastRecorded() const; time_t LastDeleted() const; uint32_t AverageDelay() const; private: Myth::RecordSchedulePtr m_recordSchedule; }; pvr.mythtv-5.10.15-Leia/src/cppmyth/MythScheduleHelper75.cpp000066400000000000000000001524731360567320200236050ustar00rootroot00000000000000/* * Copyright (C) 2005-2015 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ /////////////////////////////////////////////////////////////////////////////// //// //// Version helper for backend version 75 (0.26) //// #include "MythScheduleHelper75.h" #include "../client.h" #include "../tools.h" #include "private/os/threads/mutex.h" #include #include using namespace ADDON; MythTimerTypeList MythScheduleHelper75::GetTimerTypes() const { Myth::OS::CLockGuard lock(*m_lock); if (!m_timerTypeListInit) { m_timerTypeListInit = true; // Empty list MythTimerType::AttributeList emptyList; // Simple expiration list for no repeating rule MythTimerType::AttributeList autoExpireList; int autoExpire0 = GetRuleExpirationId(RuleExpiration(false, 0, false)); int autoExpire1 = GetRuleExpirationId(RuleExpiration(true, 0, false)); autoExpireList.push_back(std::make_pair(autoExpire0, XBMC->GetLocalizedString(30506))); // Recordings never expire autoExpireList.push_back(std::make_pair(autoExpire1, XBMC->GetLocalizedString(30507))); // Allow recordings to expire m_timerTypeList.push_back(MythTimerTypePtr(new MythTimerType(TIMER_TYPE_MANUAL_SEARCH, PVR_TIMER_TYPE_IS_MANUAL | PVR_TIMER_TYPE_SUPPORTS_ENABLE_DISABLE | PVR_TIMER_TYPE_SUPPORTS_CHANNELS | PVR_TIMER_TYPE_SUPPORTS_START_TIME | PVR_TIMER_TYPE_SUPPORTS_END_TIME | PVR_TIMER_TYPE_SUPPORTS_START_END_MARGIN | PVR_TIMER_TYPE_SUPPORTS_PRIORITY | PVR_TIMER_TYPE_SUPPORTS_LIFETIME | PVR_TIMER_TYPE_SUPPORTS_RECORDING_GROUP, XBMC->GetLocalizedString(30460), // Manual GetRulePriorityList(), GetRulePriorityDefaultId(), emptyList, Myth::DM_CheckNone, autoExpireList, autoExpire1, GetRuleRecordingGroupList(), GetRuleRecordingGroupDefaultId()))); m_timerTypeList.push_back(MythTimerTypePtr(new MythTimerType(TIMER_TYPE_THIS_SHOWING, PVR_TIMER_TYPE_SUPPORTS_ENABLE_DISABLE | PVR_TIMER_TYPE_SUPPORTS_CHANNELS | PVR_TIMER_TYPE_SUPPORTS_START_TIME | PVR_TIMER_TYPE_SUPPORTS_END_TIME | PVR_TIMER_TYPE_REQUIRES_EPG_TAG_ON_CREATE | PVR_TIMER_TYPE_SUPPORTS_START_END_MARGIN | PVR_TIMER_TYPE_SUPPORTS_PRIORITY | PVR_TIMER_TYPE_SUPPORTS_LIFETIME | PVR_TIMER_TYPE_SUPPORTS_RECORDING_GROUP, XBMC->GetLocalizedString(30465), // Record this GetRulePriorityList(), GetRulePriorityDefaultId(), emptyList, Myth::DM_CheckNone, autoExpireList, autoExpire1, GetRuleRecordingGroupList(), GetRuleRecordingGroupDefaultId()))); m_timerTypeList.push_back(MythTimerTypePtr(new MythTimerType(TIMER_TYPE_RECORD_ONE, PVR_TIMER_TYPE_IS_REPEATING | PVR_TIMER_TYPE_SUPPORTS_ENABLE_DISABLE | PVR_TIMER_TYPE_SUPPORTS_TITLE_EPG_MATCH | PVR_TIMER_TYPE_SUPPORTS_CHANNELS | PVR_TIMER_TYPE_SUPPORTS_ANY_CHANNEL | PVR_TIMER_TYPE_SUPPORTS_RECORD_ONLY_NEW_EPISODES | PVR_TIMER_TYPE_SUPPORTS_START_END_MARGIN | PVR_TIMER_TYPE_SUPPORTS_PRIORITY | PVR_TIMER_TYPE_SUPPORTS_LIFETIME | PVR_TIMER_TYPE_SUPPORTS_RECORDING_GROUP, XBMC->GetLocalizedString(30461), // Record one GetRulePriorityList(), GetRulePriorityDefaultId(), GetRuleDupMethodList(), GetRuleDupMethodDefaultId(), autoExpireList, autoExpire1, GetRuleRecordingGroupList(), GetRuleRecordingGroupDefaultId()))); m_timerTypeList.push_back(MythTimerTypePtr(new MythTimerType(TIMER_TYPE_RECORD_WEEKLY, PVR_TIMER_TYPE_IS_REPEATING | PVR_TIMER_TYPE_SUPPORTS_ENABLE_DISABLE | PVR_TIMER_TYPE_SUPPORTS_TITLE_EPG_MATCH | PVR_TIMER_TYPE_SUPPORTS_CHANNELS | PVR_TIMER_TYPE_SUPPORTS_ANY_CHANNEL | PVR_TIMER_TYPE_SUPPORTS_START_TIME | PVR_TIMER_TYPE_SUPPORTS_END_TIME | PVR_TIMER_TYPE_SUPPORTS_FIRST_DAY | PVR_TIMER_TYPE_SUPPORTS_START_END_MARGIN | PVR_TIMER_TYPE_SUPPORTS_PRIORITY | PVR_TIMER_TYPE_SUPPORTS_LIFETIME | PVR_TIMER_TYPE_SUPPORTS_RECORDING_GROUP, XBMC->GetLocalizedString(30462), // Record weekly GetRulePriorityList(), GetRulePriorityDefaultId(), emptyList, Myth::DM_CheckNone, GetRuleExpirationNameList(), GetRuleExpirationDefaultId(), GetRuleRecordingGroupList(), GetRuleRecordingGroupDefaultId()))); m_timerTypeList.push_back(MythTimerTypePtr(new MythTimerType(TIMER_TYPE_RECORD_DAILY, PVR_TIMER_TYPE_IS_REPEATING | PVR_TIMER_TYPE_SUPPORTS_ENABLE_DISABLE | PVR_TIMER_TYPE_SUPPORTS_TITLE_EPG_MATCH | PVR_TIMER_TYPE_SUPPORTS_CHANNELS | PVR_TIMER_TYPE_SUPPORTS_ANY_CHANNEL | PVR_TIMER_TYPE_SUPPORTS_START_TIME | PVR_TIMER_TYPE_SUPPORTS_END_TIME | PVR_TIMER_TYPE_SUPPORTS_FIRST_DAY | PVR_TIMER_TYPE_SUPPORTS_RECORD_ONLY_NEW_EPISODES | PVR_TIMER_TYPE_SUPPORTS_START_END_MARGIN | PVR_TIMER_TYPE_SUPPORTS_PRIORITY | PVR_TIMER_TYPE_SUPPORTS_LIFETIME | PVR_TIMER_TYPE_SUPPORTS_RECORDING_GROUP, XBMC->GetLocalizedString(30463), // Record daily GetRulePriorityList(), GetRulePriorityDefaultId(), GetRuleDupMethodList(), GetRuleDupMethodDefaultId(), GetRuleExpirationNameList(), GetRuleExpirationDefaultId(), GetRuleRecordingGroupList(), GetRuleRecordingGroupDefaultId()))); m_timerTypeList.push_back(MythTimerTypePtr(new MythTimerType(TIMER_TYPE_RECORD_ALL, PVR_TIMER_TYPE_IS_REPEATING | PVR_TIMER_TYPE_SUPPORTS_ENABLE_DISABLE | PVR_TIMER_TYPE_SUPPORTS_TITLE_EPG_MATCH | PVR_TIMER_TYPE_SUPPORTS_CHANNELS | PVR_TIMER_TYPE_SUPPORTS_ANY_CHANNEL | PVR_TIMER_TYPE_SUPPORTS_RECORD_ONLY_NEW_EPISODES | PVR_TIMER_TYPE_SUPPORTS_START_END_MARGIN | PVR_TIMER_TYPE_SUPPORTS_PRIORITY | PVR_TIMER_TYPE_SUPPORTS_LIFETIME | PVR_TIMER_TYPE_SUPPORTS_RECORDING_GROUP, XBMC->GetLocalizedString(30464), // Record all GetRulePriorityList(), GetRulePriorityDefaultId(), GetRuleDupMethodList(), GetRuleDupMethodDefaultId(), GetRuleExpirationNameList(), GetRuleExpirationDefaultId(), GetRuleRecordingGroupList(), GetRuleRecordingGroupDefaultId()))); m_timerTypeList.push_back(MythTimerTypePtr(new MythTimerType(TIMER_TYPE_RECORD_SERIES, PVR_TIMER_TYPE_IS_REPEATING | PVR_TIMER_TYPE_REQUIRES_EPG_SERIES_ON_CREATE | PVR_TIMER_TYPE_SUPPORTS_ENABLE_DISABLE | PVR_TIMER_TYPE_SUPPORTS_RECORD_ONLY_NEW_EPISODES | PVR_TIMER_TYPE_SUPPORTS_START_END_MARGIN | PVR_TIMER_TYPE_SUPPORTS_PRIORITY | PVR_TIMER_TYPE_SUPPORTS_LIFETIME | PVR_TIMER_TYPE_SUPPORTS_RECORDING_GROUP, XBMC->GetLocalizedString(30466), // Record series GetRulePriorityList(), GetRulePriorityDefaultId(), GetRuleDupMethodList(), GetRuleDupMethodDefaultId(), GetRuleExpirationNameList(), GetRuleExpirationDefaultId(), GetRuleRecordingGroupList(), GetRuleRecordingGroupDefaultId()))); m_timerTypeList.push_back(MythTimerTypePtr(new MythTimerType(TIMER_TYPE_SEARCH_KEYWORD, PVR_TIMER_TYPE_IS_REPEATING | PVR_TIMER_TYPE_SUPPORTS_ENABLE_DISABLE | PVR_TIMER_TYPE_SUPPORTS_TITLE_EPG_MATCH | PVR_TIMER_TYPE_SUPPORTS_CHANNELS | PVR_TIMER_TYPE_SUPPORTS_ANY_CHANNEL | PVR_TIMER_TYPE_SUPPORTS_RECORD_ONLY_NEW_EPISODES | PVR_TIMER_TYPE_SUPPORTS_START_END_MARGIN | PVR_TIMER_TYPE_SUPPORTS_PRIORITY | PVR_TIMER_TYPE_SUPPORTS_LIFETIME | PVR_TIMER_TYPE_SUPPORTS_RECORDING_GROUP, XBMC->GetLocalizedString(30467), // Search keyword GetRulePriorityList(), GetRulePriorityDefaultId(), GetRuleDupMethodList(), GetRuleDupMethodDefaultId(), GetRuleExpirationNameList(), GetRuleExpirationDefaultId(), GetRuleRecordingGroupList(), GetRuleRecordingGroupDefaultId()))); m_timerTypeList.push_back(MythTimerTypePtr(new MythTimerType(TIMER_TYPE_SEARCH_PEOPLE, PVR_TIMER_TYPE_IS_REPEATING | PVR_TIMER_TYPE_SUPPORTS_ENABLE_DISABLE | PVR_TIMER_TYPE_SUPPORTS_TITLE_EPG_MATCH | PVR_TIMER_TYPE_SUPPORTS_CHANNELS | PVR_TIMER_TYPE_SUPPORTS_ANY_CHANNEL | PVR_TIMER_TYPE_SUPPORTS_RECORD_ONLY_NEW_EPISODES | PVR_TIMER_TYPE_SUPPORTS_START_END_MARGIN | PVR_TIMER_TYPE_SUPPORTS_PRIORITY | PVR_TIMER_TYPE_SUPPORTS_LIFETIME | PVR_TIMER_TYPE_SUPPORTS_RECORDING_GROUP, XBMC->GetLocalizedString(30468), // Search people GetRulePriorityList(), GetRulePriorityDefaultId(), GetRuleDupMethodList(), GetRuleDupMethodDefaultId(), GetRuleExpirationNameList(), GetRuleExpirationDefaultId(), GetRuleRecordingGroupList(), GetRuleRecordingGroupDefaultId()))); /////////////////////////////////////////////////////////////////////////// //// KEEP LAST /////////////////////////////////////////////////////////////////////////// m_timerTypeList.push_back(MythTimerTypePtr(new MythTimerType(TIMER_TYPE_UNHANDLED, PVR_TIMER_TYPE_IS_REPEATING | PVR_TIMER_TYPE_FORBIDS_NEW_INSTANCES | PVR_TIMER_TYPE_SUPPORTS_PRIORITY | PVR_TIMER_TYPE_SUPPORTS_LIFETIME | PVR_TIMER_TYPE_SUPPORTS_RECORDING_GROUP, XBMC->GetLocalizedString(30451), // Unhandled GetRulePriorityList(), GetRulePriorityDefaultId(), GetRuleDupMethodList(), GetRuleDupMethodDefaultId(), GetRuleExpirationNameList(), GetRuleExpirationDefaultId(), GetRuleRecordingGroupList(), GetRuleRecordingGroupDefaultId()))); m_timerTypeList.push_back(MythTimerTypePtr(new MythTimerType(TIMER_TYPE_RULE_INACTIVE, PVR_TIMER_TYPE_FORBIDS_NEW_INSTANCES | PVR_TIMER_TYPE_SUPPORTS_ENABLE_DISABLE | PVR_TIMER_TYPE_SUPPORTS_START_END_MARGIN | PVR_TIMER_TYPE_SUPPORTS_PRIORITY | PVR_TIMER_TYPE_SUPPORTS_LIFETIME | PVR_TIMER_TYPE_SUPPORTS_RECORDING_GROUP, XBMC->GetLocalizedString(30469), // Rule Disabled GetRulePriorityList(), GetRulePriorityDefaultId(), emptyList, 0, // n&v autoExpireList, autoExpire1, GetRuleRecordingGroupList(), GetRuleRecordingGroupDefaultId()))); m_timerTypeList.push_back(MythTimerTypePtr(new MythTimerType(TIMER_TYPE_UPCOMING, PVR_TIMER_TYPE_FORBIDS_NEW_INSTANCES | PVR_TIMER_TYPE_SUPPORTS_ENABLE_DISABLE | PVR_TIMER_TYPE_SUPPORTS_START_END_MARGIN | PVR_TIMER_TYPE_SUPPORTS_PRIORITY | PVR_TIMER_TYPE_SUPPORTS_LIFETIME | PVR_TIMER_TYPE_SUPPORTS_RECORDING_GROUP, XBMC->GetLocalizedString(30452), // Upcoming GetRulePriorityList(), GetRulePriorityDefaultId(), emptyList, 0, // n&v autoExpireList, autoExpire1, GetRuleRecordingGroupList(), GetRuleRecordingGroupDefaultId()))); m_timerTypeList.push_back(MythTimerTypePtr(new MythTimerType(TIMER_TYPE_UPCOMING_ALTERNATE, PVR_TIMER_TYPE_FORBIDS_NEW_INSTANCES | PVR_TIMER_TYPE_SUPPORTS_ENABLE_DISABLE | PVR_TIMER_TYPE_SUPPORTS_START_END_MARGIN | PVR_TIMER_TYPE_SUPPORTS_PRIORITY | PVR_TIMER_TYPE_SUPPORTS_LIFETIME | PVR_TIMER_TYPE_SUPPORTS_RECORDING_GROUP, XBMC->GetLocalizedString(30457), // Alternative GetRulePriorityList(), GetRulePriorityDefaultId(), emptyList, 0, // n&v autoExpireList, autoExpire1, GetRuleRecordingGroupList(), GetRuleRecordingGroupDefaultId()))); m_timerTypeList.push_back(MythTimerTypePtr(new MythTimerType(TIMER_TYPE_UPCOMING_RECORDED, PVR_TIMER_TYPE_FORBIDS_NEW_INSTANCES | PVR_TIMER_TYPE_SUPPORTS_ENABLE_DISABLE | PVR_TIMER_TYPE_SUPPORTS_START_END_MARGIN | PVR_TIMER_TYPE_SUPPORTS_PRIORITY | PVR_TIMER_TYPE_SUPPORTS_LIFETIME | PVR_TIMER_TYPE_SUPPORTS_RECORDING_GROUP, XBMC->GetLocalizedString(30458), // Currently recorded GetRulePriorityList(), GetRulePriorityDefaultId(), emptyList, 0, // n&v autoExpireList, autoExpire1, GetRuleRecordingGroupList(), GetRuleRecordingGroupDefaultId()))); m_timerTypeList.push_back(MythTimerTypePtr(new MythTimerType(TIMER_TYPE_UPCOMING_EXPIRED, PVR_TIMER_TYPE_FORBIDS_NEW_INSTANCES | PVR_TIMER_TYPE_SUPPORTS_ENABLE_DISABLE | PVR_TIMER_TYPE_SUPPORTS_START_END_MARGIN | PVR_TIMER_TYPE_SUPPORTS_PRIORITY | PVR_TIMER_TYPE_SUPPORTS_LIFETIME | PVR_TIMER_TYPE_SUPPORTS_RECORDING_GROUP, XBMC->GetLocalizedString(30459), // Expired recording GetRulePriorityList(), GetRulePriorityDefaultId(), emptyList, 0, // n&v autoExpireList, autoExpire1, GetRuleRecordingGroupList(), GetRuleRecordingGroupDefaultId()))); m_timerTypeList.push_back(MythTimerTypePtr(new MythTimerType(TIMER_TYPE_OVERRIDE, PVR_TIMER_TYPE_FORBIDS_NEW_INSTANCES | PVR_TIMER_TYPE_SUPPORTS_ENABLE_DISABLE | PVR_TIMER_TYPE_SUPPORTS_START_END_MARGIN | PVR_TIMER_TYPE_SUPPORTS_PRIORITY | PVR_TIMER_TYPE_SUPPORTS_LIFETIME | PVR_TIMER_TYPE_SUPPORTS_RECORDING_GROUP, XBMC->GetLocalizedString(30453), // Overriden GetRulePriorityList(), GetRulePriorityDefaultId(), emptyList, 0, // n&v autoExpireList, autoExpire1, GetRuleRecordingGroupList(), GetRuleRecordingGroupDefaultId()))); m_timerTypeList.push_back(MythTimerTypePtr(new MythTimerType(TIMER_TYPE_DONT_RECORD, PVR_TIMER_TYPE_FORBIDS_NEW_INSTANCES | PVR_TIMER_TYPE_SUPPORTS_ENABLE_DISABLE | PVR_TIMER_TYPE_SUPPORTS_CHANNELS | PVR_TIMER_TYPE_SUPPORTS_START_TIME | PVR_TIMER_TYPE_SUPPORTS_END_TIME, XBMC->GetLocalizedString(30454), // Don't record emptyList, 0, // n&v emptyList, 0, // n&v emptyList, 0, // n&v emptyList, RECGROUP_DFLT_ID))); m_timerTypeList.push_back(MythTimerTypePtr(new MythTimerType(TIMER_TYPE_UPCOMING_MANUAL, PVR_TIMER_TYPE_IS_READONLY, XBMC->GetLocalizedString(30455), // Upcoming manual emptyList, 0, // n&v emptyList, 0, // n&v emptyList, 0, // n&v emptyList, RECGROUP_DFLT_ID))); m_timerTypeList.push_back(MythTimerTypePtr(new MythTimerType(TIMER_TYPE_ZOMBIE, PVR_TIMER_TYPE_IS_READONLY, XBMC->GetLocalizedString(30456), // Zombie emptyList, 0, // n&v emptyList, 0, // n&v emptyList, 0, // n&v emptyList, RECGROUP_DFLT_ID))); } return m_timerTypeList; } bool MythScheduleHelper75::SameTimeslot(const MythRecordingRule& first, const MythRecordingRule& second) const { time_t first_st = first.StartTime(); time_t second_st = second.StartTime(); switch (first.Type()) { case Myth::RT_NotRecording: case Myth::RT_SingleRecord: case Myth::RT_OverrideRecord: case Myth::RT_DontRecord: return second_st == first_st && second.EndTime() == first.EndTime() && second.ChannelID() == first.ChannelID() && second.Filter() == first.Filter(); case Myth::RT_OneRecord: // FindOneRecord return second.Title() == first.Title() && second.ChannelID() == first.ChannelID() && second.Filter() == first.Filter(); case Myth::RT_DailyRecord: // TimeslotRecord return second.Title() == first.Title() && daytime(&first_st) == daytime(&second_st) && second.ChannelID() == first.ChannelID() && second.Filter() == first.Filter(); case Myth::RT_WeeklyRecord: // WeekslotRecord return second.Title() == first.Title() && daytime(&first_st) == daytime(&second_st) && weekday(&first_st) == weekday(&second_st) && second.ChannelID() == first.ChannelID() && second.Filter() == first.Filter(); case Myth::RT_FindDailyRecord: return second.Title() == first.Title() && second.ChannelID() == first.ChannelID() && second.Filter() == first.Filter(); case Myth::RT_FindWeeklyRecord: return second.Title() == first.Title() && weekday(&first_st) == weekday(&second_st) && second.ChannelID() == first.ChannelID() && second.Filter() == first.Filter(); case Myth::RT_ChannelRecord: return second.Title() == first.Title() && second.ChannelID() == first.ChannelID() && second.Filter() == first.Filter(); case Myth::RT_AllRecord: return second.Title() == first.Title() && second.Filter() == first.Filter(); default: break; } return false; } bool MythScheduleHelper75::FillTimerEntryWithRule(MythTimerEntry& entry, const MythRecordingRuleNode& node) const { // Assign timer type regarding rule attributes. The match SHOULD be opposite to // that which is applied in function 'NewFromTimer' // Check rule flag for this entry entry.isRule = true; MythRecordingRule rule = node.GetRule(); if (g_bExtraDebug) XBMC->Log(LOG_DEBUG, "75::%s: Rule %u", __FUNCTION__, rule.RecordID()); switch (rule.Type()) { case Myth::RT_SingleRecord: { // Fill recording status from its upcoming. MythScheduleList recordings = m_manager->FindUpComingByRuleId(rule.RecordID()); MythScheduleList::const_reverse_iterator it = recordings.rbegin(); if (it != recordings.rend()) entry.recordingStatus = it->second->Status(); else return false; // Don't transfer single without upcoming } if (rule.SearchType() == Myth::ST_ManualSearch) entry.timerType = TIMER_TYPE_MANUAL_SEARCH; else entry.timerType = TIMER_TYPE_THIS_SHOWING; entry.chanid = rule.ChannelID(); entry.callsign = rule.Callsign(); break; case Myth::RT_OneRecord: entry.timerType = TIMER_TYPE_RECORD_ONE; break; case Myth::RT_FindDailyRecord: entry.timerType = TIMER_TYPE_RECORD_DAILY; break; case Myth::RT_DailyRecord: entry.timerType = TIMER_TYPE_RECORD_DAILY; entry.chanid = rule.ChannelID(); entry.callsign = rule.Callsign(); break; case Myth::RT_FindWeeklyRecord: entry.timerType = TIMER_TYPE_RECORD_WEEKLY; break; case Myth::RT_WeeklyRecord: entry.timerType = TIMER_TYPE_RECORD_WEEKLY; entry.chanid = rule.ChannelID(); entry.callsign = rule.Callsign(); break; case Myth::RT_ChannelRecord: if ((rule.Filter() & Myth::FM_ThisSeries)) entry.timerType = TIMER_TYPE_RECORD_SERIES; else entry.timerType = TIMER_TYPE_RECORD_ALL; entry.chanid = rule.ChannelID(); entry.callsign = rule.Callsign(); break; case Myth::RT_AllRecord: entry.timerType = TIMER_TYPE_RECORD_ALL; break; case Myth::RT_OverrideRecord: entry.timerType = TIMER_TYPE_OVERRIDE; entry.chanid = rule.ChannelID(); entry.callsign = rule.Callsign(); break; case Myth::RT_DontRecord: entry.timerType = TIMER_TYPE_DONT_RECORD; entry.chanid = rule.ChannelID(); entry.callsign = rule.Callsign(); break; default: entry.timerType = TIMER_TYPE_UNHANDLED; entry.chanid = rule.ChannelID(); entry.callsign = rule.Callsign(); break; } switch (rule.SearchType()) { case Myth::ST_TitleSearch: entry.epgSearch = rule.Description(); break; case Myth::ST_KeywordSearch: entry.epgSearch = rule.Description(); entry.timerType = TIMER_TYPE_SEARCH_KEYWORD; break; case Myth::ST_PeopleSearch: entry.epgSearch = rule.Description(); entry.timerType = TIMER_TYPE_SEARCH_PEOPLE; break; case Myth::ST_PowerSearch: entry.epgSearch = rule.Description(); entry.timerType = TIMER_TYPE_UNHANDLED; break; case Myth::ST_NoSearch: // EPG based entry.epgCheck = true; entry.epgSearch = rule.Title(); break; case Myth::ST_ManualSearch: // Manual entry.chanid = rule.ChannelID(); entry.callsign = rule.Callsign(); entry.startTime = rule.StartTime(); entry.endTime = rule.EndTime(); break; default: break; } switch (entry.timerType) { case TIMER_TYPE_RECORD_ONE: case TIMER_TYPE_RECORD_WEEKLY: case TIMER_TYPE_RECORD_DAILY: case TIMER_TYPE_RECORD_ALL: case TIMER_TYPE_RECORD_SERIES: case TIMER_TYPE_SEARCH_KEYWORD: case TIMER_TYPE_SEARCH_PEOPLE: case TIMER_TYPE_UNHANDLED: entry.startTime = rule.StartTime(); entry.endTime = rule.EndTime(); // For all repeating fix timeslot as needed if (!entry.HasTimeSlot()) { if (difftime(rule.NextRecording(), 0) > 0) { // fill timeslot starting at next recording entry.startTime = rule.NextRecording(); // it includes offset correction // WARNING: if next recording has been overriden then offset could be different timeadd(&entry.startTime, INTERVAL_MINUTE * rule.StartOffset()); // remove start offset entry.endTime = 0; // any time } else if (difftime(rule.LastRecorded(), 0) > 0) { // fill timeslot starting at last recorded entry.startTime = rule.LastRecorded(); // it includes offset correction // WARNING: if last recorded has been overriden then offset could be different timeadd(&entry.startTime, INTERVAL_MINUTE * rule.StartOffset()); // remove start offset entry.endTime = 0; // any time } } // For all repeating set summary status if (node.HasConflict()) entry.recordingStatus = Myth::RS_CONFLICT; else if (node.IsRecording()) entry.recordingStatus = Myth::RS_RECORDING; // break; default: entry.startTime = rule.StartTime(); entry.endTime = rule.EndTime(); } // fill others entry.epgInfo = MythEPGInfo(rule.ChannelID(), rule.StartTime(), rule.EndTime()); entry.title = rule.Title(); entry.category = rule.Category(); entry.startOffset = rule.StartOffset(); entry.endOffset = rule.EndOffset(); entry.dupMethod = rule.DuplicateControlMethod(); entry.priority = rule.Priority(); entry.expiration = GetRuleExpirationId(RuleExpiration(rule.AutoExpire(), rule.MaxEpisodes(), rule.NewExpiresOldRecord())); entry.isInactive = rule.Inactive(); entry.firstShowing = (rule.Filter() & Myth::FM_FirstShowing ? true : false); entry.recordingGroup = GetRuleRecordingGroupId(rule.RecordingGroup()); entry.entryIndex = MythScheduleManager::MakeIndex(rule); // rule index if (node.IsOverrideRule()) entry.parentIndex = MythScheduleManager::MakeIndex(node.GetMainRule()); else entry.parentIndex = 0; return true; } bool MythScheduleHelper75::FillTimerEntryWithUpcoming(MythTimerEntry& entry, const MythProgramInfo& recording) const { //Only include timers which have an inactive status if the user has requested it (flag m_showNotRecording) switch (recording.Status()) { //Upcoming recordings which are disabled due to being lower priority duplicates or already recorded case Myth::RS_EARLIER_RECORDING: //will record earlier case Myth::RS_LATER_SHOWING: //will record later case Myth::RS_CURRENT_RECORDING: //Already in the current library case Myth::RS_PREVIOUS_RECORDING: //Previoulsy recorded but no longer in the library if (!m_manager->ShowNotRecording()) { if (g_bExtraDebug) XBMC->Log(LOG_DEBUG, "75::%s: Skipping %s:%s on %s because status %d", __FUNCTION__, recording.Title().c_str(), recording.Subtitle().c_str(), recording.ChannelName().c_str(), recording.Status()); return false; } default: break; } MythRecordingRuleNodePtr node = m_manager->FindRuleById(recording.RecordID()); if (node) { MythRecordingRule rule = node->GetRule(); // Relate the main rule as parent entry.parentIndex = MythScheduleManager::MakeIndex(node->GetMainRule()); switch (rule.Type()) { case Myth::RT_SingleRecord: return false; // Discard upcoming. We show only main rule. // API Dvr/1.9: Type OverrideRecord is use to qualify all modifers. // So I use the recording status to choose the right type case Myth::RT_DontRecord: case Myth::RT_OverrideRecord: switch (recording.Status()) { case Myth::RS_DONT_RECORD: case Myth::RS_NEVER_RECORD: entry.recordingStatus = recording.Status(); entry.timerType = TIMER_TYPE_DONT_RECORD; entry.isInactive = rule.Inactive(); break; default: entry.recordingStatus = recording.Status(); entry.timerType = TIMER_TYPE_OVERRIDE; entry.isInactive = rule.Inactive(); } break; default: entry.recordingStatus = recording.Status(); if (node->GetMainRule().SearchType() == Myth::ST_ManualSearch) entry.timerType = TIMER_TYPE_UPCOMING_MANUAL; else { switch (recording.Status()) { case Myth::RS_EARLIER_RECORDING: //will record earlier case Myth::RS_LATER_SHOWING: //will record later entry.timerType = TIMER_TYPE_UPCOMING_ALTERNATE; break; case Myth::RS_CURRENT_RECORDING: //Already in the current library entry.timerType = TIMER_TYPE_UPCOMING_RECORDED; break; case Myth::RS_PREVIOUS_RECORDING: //Previoulsy recorded but no longer in the library entry.timerType = TIMER_TYPE_UPCOMING_EXPIRED; break; case Myth::RS_INACTIVE: entry.timerType = TIMER_TYPE_RULE_INACTIVE; break; default: entry.timerType = TIMER_TYPE_UPCOMING; break; } } } entry.startOffset = rule.StartOffset(); entry.endOffset = rule.EndOffset(); entry.priority = rule.Priority(); entry.expiration = GetRuleExpirationId(RuleExpiration(rule.AutoExpire(), 0, false)); } else entry.timerType = TIMER_TYPE_ZOMBIE; switch (entry.timerType) { case TIMER_TYPE_UPCOMING: case TIMER_TYPE_RULE_INACTIVE: case TIMER_TYPE_UPCOMING_ALTERNATE: case TIMER_TYPE_UPCOMING_RECORDED: case TIMER_TYPE_UPCOMING_EXPIRED: case TIMER_TYPE_OVERRIDE: case TIMER_TYPE_UPCOMING_MANUAL: entry.epgCheck = true; break; default: entry.epgCheck = false; } entry.epgInfo = MythEPGInfo(recording.ChannelID(), recording.StartTime(), recording.EndTime()); entry.description = ""; entry.chanid = recording.ChannelID(); entry.callsign = recording.Callsign(); entry.startTime = recording.StartTime(); entry.endTime = recording.EndTime(); entry.title.assign(recording.Title()); if (!recording.Subtitle().empty()) entry.title.append(" (").append(recording.Subtitle()).append(")"); if (recording.Season() && recording.Episode()) entry.title.append(" - ").append(Myth::IntToString(recording.Season())).append(".").append(Myth::IntToString(recording.Episode())); else if (recording.Episode()) entry.title.append(" - S").append(Myth::IntToString(recording.Episode())); entry.recordingGroup = GetRuleRecordingGroupId(recording.RecordingGroup()); entry.entryIndex = MythScheduleManager::MakeIndex(recording); // upcoming index return true; } MythRecordingRule MythScheduleHelper75::NewFromTemplate(const MythEPGInfo& epgInfo) { MythRecordingRule rule; // Load rule template from selected provider switch (g_iRecTemplateType) { case 1: // Template provider is 'MythTV', then load the template from backend. if (!epgInfo.IsNull()) { MythRecordingRuleList templates = m_manager->GetTemplateRules(); MythRecordingRuleList::const_iterator tplIt = templates.end(); for (MythRecordingRuleList::const_iterator it = templates.begin(); it != templates.end(); ++it) { if (it->Category() == epgInfo.Category()) { tplIt = it; break; } if (it->Category() == epgInfo.CategoryType()) { tplIt = it; continue; } if (it->Category() == "Default" && tplIt == templates.end()) tplIt = it; } if (tplIt != templates.end()) { XBMC->Log(LOG_INFO, "75::%s: Overriding the rule with template %u '%s'", __FUNCTION__, (unsigned)tplIt->RecordID(), tplIt->Title().c_str()); rule.SetPriority(tplIt->Priority()); rule.SetStartOffset(tplIt->StartOffset()); rule.SetEndOffset(tplIt->EndOffset()); rule.SetSearchType(tplIt->SearchType()); rule.SetDuplicateControlMethod(tplIt->DuplicateControlMethod()); rule.SetCheckDuplicatesInType(tplIt->CheckDuplicatesInType()); rule.SetRecordingGroup(tplIt->RecordingGroup()); rule.SetRecordingProfile(tplIt->RecordingProfile()); rule.SetStorageGroup(tplIt->StorageGroup()); rule.SetPlaybackGroup(tplIt->PlaybackGroup()); rule.SetUserJob(1, tplIt->UserJob(1)); rule.SetUserJob(2, tplIt->UserJob(2)); rule.SetUserJob(3, tplIt->UserJob(3)); rule.SetUserJob(4, tplIt->UserJob(4)); rule.SetAutoTranscode(tplIt->AutoTranscode()); rule.SetAutoCommFlag(tplIt->AutoCommFlag()); rule.SetAutoExpire(tplIt->AutoExpire()); rule.SetAutoMetadata(tplIt->AutoMetadata()); rule.SetMaxEpisodes(tplIt->MaxEpisodes()); rule.SetNewExpiresOldRecord(tplIt->NewExpiresOldRecord()); rule.SetFilter(tplIt->Filter()); rule.SetCategory(tplIt->Category()); } else XBMC->Log(LOG_INFO, "75::%s: No template found for the category '%s'", __FUNCTION__, epgInfo.Category().c_str()); } break; case 0: // Template provider is 'Internal', then set rule with settings rule.SetAutoCommFlag(g_bRecAutoCommFlag); rule.SetAutoMetadata(g_bRecAutoMetadata); rule.SetAutoTranscode(g_bRecAutoTranscode); rule.SetUserJob(1, g_bRecAutoRunJob1); rule.SetUserJob(2, g_bRecAutoRunJob2); rule.SetUserJob(3, g_bRecAutoRunJob3); rule.SetUserJob(4, g_bRecAutoRunJob4); rule.SetAutoExpire(g_bRecAutoExpire); rule.SetTranscoder(g_iRecTranscoder); // set defaults rule.SetPriority(GetRulePriorityDefaultId()); rule.SetDuplicateControlMethod(static_cast(GetRuleDupMethodDefaultId())); rule.SetCheckDuplicatesInType(Myth::DI_InAll); rule.SetRecordingGroup(GetRuleRecordingGroupName(GetRuleRecordingGroupDefaultId())); } // Category override if (!epgInfo.IsNull()) { Myth::SettingPtr overTimeCategory = m_control->GetSetting("OverTimeCategory", false); if (overTimeCategory && (overTimeCategory->value == epgInfo.Category() || overTimeCategory->value == epgInfo.CategoryType())) { Myth::SettingPtr categoryOverTime = m_control->GetSetting("CategoryOverTime", false); if (categoryOverTime && !categoryOverTime->value.empty()) { int offset = atoi(categoryOverTime->value.c_str()); XBMC->Log(LOG_DEBUG, "75::%s: Overriding end offset for category %s: +%d", __FUNCTION__, overTimeCategory->value.c_str(), offset); rule.SetEndOffset(offset); } } } return rule; } MythRecordingRule MythScheduleHelper75::NewFromTimer(const MythTimerEntry& entry, bool withTemplate) { // Create a recording rule regarding timer attributes. The match SHOULD be opposite to // that which is applied in function 'FillTimerEntry' MythRecordingRule rule; XBMC->Log(LOG_DEBUG, "75::%s", __FUNCTION__); // default required fields start, end time time_t now = time(0); rule.SetStartTime(now); rule.SetEndTime(now); if (withTemplate) { // Base on template rule = NewFromTemplate(entry.epgInfo); // Override template with timer settings rule.SetStartOffset(rule.StartOffset() + entry.startOffset); rule.SetEndOffset(rule.EndOffset() + entry.endOffset); if (entry.dupMethod != GetRuleDupMethodDefaultId()) { rule.SetDuplicateControlMethod(entry.dupMethod); rule.SetCheckDuplicatesInType(Myth::DI_InAll); } if (entry.priority != GetRulePriorityDefaultId()) rule.SetPriority(entry.priority); if (entry.expiration != GetRuleExpirationDefaultId()) { RuleExpiration exr = GetRuleExpiration(entry.expiration); rule.SetAutoExpire(exr.autoExpire); rule.SetMaxEpisodes(exr.maxEpisodes); rule.SetNewExpiresOldRecord(exr.maxNewest); } if (entry.recordingGroup != RECGROUP_DFLT_ID) rule.SetRecordingGroup(GetRuleRecordingGroupName(entry.recordingGroup)); } else { rule.SetCategory(entry.category); rule.SetStartOffset(entry.startOffset); rule.SetEndOffset(entry.endOffset); rule.SetDuplicateControlMethod(entry.dupMethod); rule.SetPriority(entry.priority); RuleExpiration exr = GetRuleExpiration(entry.expiration); rule.SetAutoExpire(exr.autoExpire); rule.SetMaxEpisodes(exr.maxEpisodes); rule.SetNewExpiresOldRecord(exr.maxNewest); rule.SetRecordingGroup(GetRuleRecordingGroupName(entry.recordingGroup)); } switch (entry.timerType) { case TIMER_TYPE_MANUAL_SEARCH: { if (entry.HasChannel() && entry.HasTimeSlot()) { rule.SetType(Myth::RT_SingleRecord); rule.SetSearchType(Myth::ST_ManualSearch); // Using timeslot rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); rule.SetStartTime(entry.startTime); rule.SetEndTime(entry.endTime); rule.SetTitle(entry.title); rule.SetDescription(entry.description); rule.SetInactive(entry.isInactive); return rule; } break; } case TIMER_TYPE_THIS_SHOWING: { if (!entry.epgInfo.IsNull()) { rule.SetType(Myth::RT_SingleRecord); rule.SetSearchType(Myth::ST_NoSearch); rule.SetChannelID(entry.epgInfo.ChannelID()); rule.SetStartTime(entry.epgInfo.StartTime()); rule.SetEndTime(entry.epgInfo.EndTime()); rule.SetTitle(entry.epgInfo.Title()); rule.SetSubtitle(entry.epgInfo.Subtitle()); rule.SetDescription(entry.description); rule.SetCallsign(entry.epgInfo.Callsign()); rule.SetCategory(entry.epgInfo.Category()); rule.SetProgramID(entry.epgInfo.ProgramID()); rule.SetSeriesID(entry.epgInfo.SeriesID()); rule.SetInactive(entry.isInactive); return rule; } break; } case TIMER_TYPE_RECORD_ONE: { if (!entry.epgInfo.IsNull()) { rule.SetType(Myth::RT_OneRecord); rule.SetSearchType(Myth::ST_NoSearch); rule.SetChannelID(entry.epgInfo.ChannelID()); rule.SetStartTime(entry.epgInfo.StartTime()); rule.SetEndTime(entry.epgInfo.EndTime()); rule.SetTitle(entry.epgInfo.Title()); rule.SetSubtitle(entry.epgInfo.Subtitle()); rule.SetDescription(entry.description); rule.SetCallsign(entry.epgInfo.Callsign()); rule.SetCategory(entry.epgInfo.Category()); rule.SetProgramID(entry.epgInfo.ProgramID()); rule.SetSeriesID(entry.epgInfo.SeriesID()); rule.SetInactive(entry.isInactive); return rule; } if (!entry.epgSearch.empty()) { if (entry.HasChannel()) { rule.SetType(Myth::RT_ChannelRecord); rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); } else rule.SetType(Myth::RT_OneRecord); rule.SetSearchType(Myth::ST_TitleSearch); // Search title rule.SetTitle(entry.title); // Backend use the subtitle/description to find program by keywords or title rule.SetSubtitle(""); rule.SetDescription(entry.epgSearch); rule.SetInactive(entry.isInactive); return rule; } break; } case TIMER_TYPE_RECORD_WEEKLY: { if (!entry.epgInfo.IsNull()) { rule.SetType(Myth::RT_WeeklyRecord); rule.SetSearchType(Myth::ST_NoSearch); rule.SetChannelID(entry.epgInfo.ChannelID()); rule.SetStartTime(entry.epgInfo.StartTime()); rule.SetEndTime(entry.epgInfo.EndTime()); rule.SetTitle(entry.epgInfo.Title()); rule.SetSubtitle(entry.epgInfo.Subtitle()); rule.SetDescription(entry.description); rule.SetCallsign(entry.epgInfo.Callsign()); rule.SetCategory(entry.epgInfo.Category()); rule.SetProgramID(entry.epgInfo.ProgramID()); rule.SetSeriesID(entry.epgInfo.SeriesID()); rule.SetInactive(entry.isInactive); rule.SetDuplicateControlMethod(Myth::DM_CheckNone); return rule; } if (!entry.epgSearch.empty()) { if (entry.HasChannel()) { rule.SetType(Myth::RT_WeeklyRecord); rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); } else rule.SetType(Myth::RT_FindWeeklyRecord); rule.SetSearchType(Myth::ST_TitleSearch); // Search title rule.SetTitle(entry.title); // Backend use the subtitle/description to find program by keywords or title rule.SetSubtitle(""); rule.SetDescription(entry.epgSearch); rule.SetInactive(entry.isInactive); rule.SetDuplicateControlMethod(Myth::DM_CheckNone); return rule; } if (entry.HasChannel() && entry.HasTimeSlot()) { rule.SetType(Myth::RT_WeeklyRecord); rule.SetSearchType(Myth::ST_ManualSearch); // Using timeslot rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); rule.SetStartTime(entry.startTime); rule.SetEndTime(entry.endTime); rule.SetTitle(entry.title); rule.SetDescription(entry.description); rule.SetInactive(entry.isInactive); rule.SetDuplicateControlMethod(Myth::DM_CheckNone); return rule; } break; } case TIMER_TYPE_RECORD_DAILY: { if (!entry.epgInfo.IsNull()) { rule.SetType(Myth::RT_DailyRecord); rule.SetSearchType(Myth::ST_NoSearch); rule.SetChannelID(entry.epgInfo.ChannelID()); rule.SetStartTime(entry.epgInfo.StartTime()); rule.SetEndTime(entry.epgInfo.EndTime()); rule.SetTitle(entry.epgInfo.Title()); rule.SetSubtitle(entry.epgInfo.Subtitle()); rule.SetDescription(entry.description); rule.SetCallsign(entry.epgInfo.Callsign()); rule.SetCategory(entry.epgInfo.Category()); rule.SetProgramID(entry.epgInfo.ProgramID()); rule.SetSeriesID(entry.epgInfo.SeriesID()); rule.SetInactive(entry.isInactive); rule.SetDuplicateControlMethod(Myth::DM_CheckNone); return rule; } if (!entry.epgSearch.empty()) { if (entry.HasChannel()) { rule.SetType(Myth::RT_DailyRecord); rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); } else rule.SetType(Myth::RT_FindDailyRecord); rule.SetSearchType(Myth::ST_TitleSearch); // Search title rule.SetTitle(entry.title); // Backend use the subtitle/description to find program by keywords or title rule.SetSubtitle(""); rule.SetDescription(entry.epgSearch); rule.SetInactive(entry.isInactive); return rule; } if (entry.HasChannel() && entry.HasTimeSlot()) { rule.SetType(Myth::RT_DailyRecord); rule.SetSearchType(Myth::ST_ManualSearch); // Using timeslot rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); rule.SetStartTime(entry.startTime); rule.SetEndTime(entry.endTime); rule.SetTitle(entry.title); rule.SetDescription(entry.description); rule.SetInactive(entry.isInactive); rule.SetDuplicateControlMethod(Myth::DM_CheckNone); return rule; } break; } case TIMER_TYPE_RECORD_ALL: { if (!entry.epgInfo.IsNull()) { rule.SetType(Myth::RT_ChannelRecord); rule.SetSearchType(Myth::ST_NoSearch); rule.SetChannelID(entry.epgInfo.ChannelID()); rule.SetStartTime(entry.epgInfo.StartTime()); rule.SetEndTime(entry.epgInfo.EndTime()); rule.SetTitle(entry.epgInfo.Title()); rule.SetSubtitle(entry.epgInfo.Subtitle()); rule.SetDescription(entry.description); rule.SetCallsign(entry.epgInfo.Callsign()); rule.SetCategory(entry.epgInfo.Category()); rule.SetProgramID(entry.epgInfo.ProgramID()); rule.SetSeriesID(entry.epgInfo.SeriesID()); rule.SetInactive(entry.isInactive); return rule; } if (!entry.epgSearch.empty()) { if (entry.HasChannel()) { rule.SetType(Myth::RT_ChannelRecord); rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); } else rule.SetType(Myth::RT_AllRecord); rule.SetSearchType(Myth::ST_TitleSearch); // Search title rule.SetTitle(entry.title); // Backend use the subtitle/description to find program by keywords or title rule.SetSubtitle(""); rule.SetDescription(entry.epgSearch); rule.SetInactive(entry.isInactive); return rule; } break; } case TIMER_TYPE_RECORD_SERIES: { if (!entry.epgInfo.IsNull()) { rule.SetType(Myth::RT_ChannelRecord); rule.SetFilter(Myth::FM_ThisSeries); rule.SetSearchType(Myth::ST_NoSearch); rule.SetChannelID(entry.epgInfo.ChannelID()); rule.SetStartTime(entry.epgInfo.StartTime()); rule.SetEndTime(entry.epgInfo.EndTime()); rule.SetTitle(entry.epgInfo.Title()); rule.SetSubtitle(entry.epgInfo.Subtitle()); rule.SetDescription(entry.description); rule.SetCallsign(entry.epgInfo.Callsign()); rule.SetCategory(entry.epgInfo.Category()); rule.SetProgramID(entry.epgInfo.ProgramID()); rule.SetSeriesID(entry.epgInfo.SeriesID()); rule.SetInactive(entry.isInactive); return rule; } break; } case TIMER_TYPE_SEARCH_KEYWORD: { if (!entry.epgSearch.empty()) { if (entry.HasChannel()) { rule.SetType(Myth::RT_ChannelRecord); rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); } else rule.SetType(Myth::RT_AllRecord); rule.SetSearchType(Myth::ST_KeywordSearch); // Search keyword rule.SetTitle(entry.title); // Backend use the subtitle/description to find program by keywords or title rule.SetSubtitle(""); rule.SetDescription(entry.epgSearch); rule.SetInactive(entry.isInactive); return rule; } break; } case TIMER_TYPE_SEARCH_PEOPLE: { if (!entry.epgSearch.empty()) { if (entry.HasChannel()) { rule.SetType(Myth::RT_ChannelRecord); rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); } else rule.SetType(Myth::RT_AllRecord); rule.SetSearchType(Myth::ST_PeopleSearch); // Search People rule.SetTitle(entry.title); // Backend use the subtitle/description to find program by keywords or title rule.SetSubtitle(""); rule.SetDescription(entry.epgSearch); rule.SetInactive(entry.isInactive); return rule; } break; } case TIMER_TYPE_DONT_RECORD: rule.SetType(Myth::RT_DontRecord); rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); rule.SetStartTime(entry.startTime); rule.SetEndTime(entry.endTime); rule.SetTitle(entry.title); rule.SetDescription(entry.description); rule.SetInactive(entry.isInactive); return rule; case TIMER_TYPE_OVERRIDE: rule.SetType(Myth::RT_OverrideRecord); rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); rule.SetStartTime(entry.startTime); rule.SetEndTime(entry.endTime); rule.SetTitle(entry.title); rule.SetDescription(entry.description); rule.SetInactive(entry.isInactive); return rule; case TIMER_TYPE_UPCOMING: case TIMER_TYPE_RULE_INACTIVE: case TIMER_TYPE_UPCOMING_ALTERNATE: case TIMER_TYPE_UPCOMING_RECORDED: case TIMER_TYPE_UPCOMING_EXPIRED: case TIMER_TYPE_UPCOMING_MANUAL: case TIMER_TYPE_ZOMBIE: rule.SetType(Myth::RT_SingleRecord); rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); rule.SetStartTime(entry.startTime); rule.SetEndTime(entry.endTime); rule.SetTitle(entry.title); rule.SetDescription(entry.description); rule.SetInactive(entry.isInactive); return rule; default: break; } rule.SetType(Myth::RT_UNKNOWN); XBMC->Log(LOG_ERROR, "75::%s: Invalid timer %u: TYPE=%d CHANID=%u SIGN=%s ST=%u ET=%u", __FUNCTION__, entry.entryIndex, entry.timerType, entry.chanid, entry.callsign.c_str(), (unsigned)entry.startTime, (unsigned)entry.endTime); return rule; } MythRecordingRule MythScheduleHelper75::MakeDontRecord(const MythRecordingRule& rule, const MythProgramInfo& recording) { MythRecordingRule modifier = rule.DuplicateRecordingRule(); // Do the same as backend even we know the modifier will be rejected for manual rule: // Don't know if this behavior is a bug issue or desired: cf libmythtv/recordingrule.cpp if (modifier.SearchType() != Myth::ST_ManualSearch) modifier.SetSearchType(Myth::ST_NoSearch); modifier.SetType(Myth::RT_DontRecord); modifier.SetParentID(modifier.RecordID()); modifier.SetRecordID(0); modifier.SetInactive(false); // Assign recording info modifier.SetTitle(recording.Title()); modifier.SetSubtitle(recording.Subtitle()); modifier.SetDescription(recording.Description()); modifier.SetChannelID(recording.ChannelID()); modifier.SetCallsign(recording.Callsign()); modifier.SetStartTime(recording.StartTime()); modifier.SetEndTime(recording.EndTime()); modifier.SetSeriesID(recording.SerieID()); modifier.SetProgramID(recording.ProgramID()); modifier.SetCategory(recording.Category()); if (rule.InetRef().empty()) { modifier.SetInerRef(recording.Inetref()); modifier.SetSeason(recording.Season()); modifier.SetEpisode(recording.Episode()); } return modifier; } MythRecordingRule MythScheduleHelper75::MakeOverride(const MythRecordingRule& rule, const MythProgramInfo& recording) { MythRecordingRule modifier = rule.DuplicateRecordingRule(); // Do the same as backend even we know the modifier will be rejected for manual rule: // Don't know if this behavior is a bug issue or desired: cf libmythtv/recordingrule.cpp if (modifier.SearchType() != Myth::ST_ManualSearch) modifier.SetSearchType(Myth::ST_NoSearch); modifier.SetType(Myth::RT_OverrideRecord); modifier.SetParentID(modifier.RecordID()); modifier.SetRecordID(0); modifier.SetInactive(false); // Assign recording info modifier.SetTitle(recording.Title()); modifier.SetSubtitle(recording.Subtitle()); modifier.SetDescription(recording.Description()); modifier.SetChannelID(recording.ChannelID()); modifier.SetCallsign(recording.Callsign()); modifier.SetStartTime(recording.StartTime()); modifier.SetEndTime(recording.EndTime()); modifier.SetSeriesID(recording.SerieID()); modifier.SetProgramID(recording.ProgramID()); modifier.SetCategory(recording.Category()); if (rule.InetRef().empty()) { modifier.SetInerRef(recording.Inetref()); modifier.SetSeason(recording.Season()); modifier.SetEpisode(recording.Episode()); } return modifier; } const MythTimerType::AttributeList& MythScheduleHelper75::GetRulePriorityList() const { if (!m_priorityListInit) { char buf[5]; m_priorityListInit = true; m_priorityList.reserve(200); memset(buf, 0, sizeof(buf)); for (int i = -99; i <= 99; ++i) { if (i) { snprintf(buf, sizeof(buf), "%+2d", i); m_priorityList.push_back(std::make_pair(i, buf)); } else m_priorityList.push_back(std::make_pair(0, "0")); } } return m_priorityList; } const MythTimerType::AttributeList& MythScheduleHelper75::GetRuleDupMethodList() const { if (!m_dupMethodListInit) { m_dupMethodListInit = true; m_dupMethodList.push_back(std::make_pair(static_cast(Myth::DM_CheckNone), XBMC->GetLocalizedString(30501))); m_dupMethodList.push_back(std::make_pair(static_cast(Myth::DM_CheckSubtitle), XBMC->GetLocalizedString(30502))); m_dupMethodList.push_back(std::make_pair(static_cast(Myth::DM_CheckDescription), XBMC->GetLocalizedString(30503))); m_dupMethodList.push_back(std::make_pair(static_cast(Myth::DM_CheckSubtitleAndDescription), XBMC->GetLocalizedString(30504))); m_dupMethodList.push_back(std::make_pair(static_cast(Myth::DM_CheckSubtitleThenDescription), XBMC->GetLocalizedString(30505))); } return m_dupMethodList; } const MythScheduleHelperNoHelper::RuleExpirationMap& MythScheduleHelper75::GetRuleExpirationMap() const { if (!m_expirationMapInit) { m_expirationMapInit = true; char buf[256]; memset(buf, 0, sizeof(buf)); // Insert cases 'keep newest' int index = (EXPIRATION_NEVER_EXPIRE_ID < EXPIRATION_ALLOW_EXPIRE_ID ? EXPIRATION_NEVER_EXPIRE_ID : EXPIRATION_ALLOW_EXPIRE_ID) - 100; for (int i = 100; i >= 1; --i) { snprintf(buf, sizeof(buf), XBMC->GetLocalizedString(30509), i); // Keep %d newest and expire old m_expirationMap.insert(std::make_pair(index++, std::make_pair(RuleExpiration(false,i,true), buf))); } // Insert cases 'auto expire' m_expirationMap.insert(std::make_pair(EXPIRATION_NEVER_EXPIRE_ID, std::make_pair(RuleExpiration(false, 0, false), XBMC->GetLocalizedString(30506)))); // Recordings never expire m_expirationMap.insert(std::make_pair(EXPIRATION_ALLOW_EXPIRE_ID, std::make_pair(RuleExpiration(true, 0, false), XBMC->GetLocalizedString(30507)))); // Allow recordings to expire // Insert cases 'keep up' index = (EXPIRATION_ALLOW_EXPIRE_ID > EXPIRATION_NEVER_EXPIRE_ID ? EXPIRATION_ALLOW_EXPIRE_ID : EXPIRATION_NEVER_EXPIRE_ID) + 1; for (int i = 2; i <= 100; ++i) { snprintf(buf, sizeof(buf), XBMC->GetLocalizedString(30508), i); // Keep up to %d recordings m_expirationMap.insert(std::make_pair(index++, std::make_pair(RuleExpiration(false,i,false), buf))); } } return m_expirationMap; } const MythTimerType::AttributeList& MythScheduleHelper75::GetRuleRecordingGroupList() const { if (!m_recGroupListInit && m_control) { int count = 0, index = RECGROUP_DFLT_ID; m_recGroupListInit = true; Myth::StringListPtr strl = m_control->GetRecGroupList(); // First add default group for (Myth::StringList::const_iterator it = strl->begin(); it != strl->end(); ++it) { if (*it == RECGROUP_DFLT_NAME) { m_recGroupList.push_back(std::make_pair(index++, RECGROUP_DFLT_NAME)); ++count; } } // Then others for (Myth::StringList::const_iterator it = strl->begin(); it != strl->end(); ++it) { if (*it != RECGROUP_DFLT_NAME) { if (count == PVR_ADDON_TIMERTYPE_VALUES_ARRAY_SIZE) { XBMC->Log(LOG_NOTICE, "75::%s: List overflow (%d): %u remaining value(s) are not loaded", __FUNCTION__, count, (unsigned)(strl->size() - count)); break; } m_recGroupList.push_back(std::make_pair(index++, *it)); ++count; } } } return m_recGroupList; } pvr.mythtv-5.10.15-Leia/src/cppmyth/MythScheduleHelper75.h000066400000000000000000000046041360567320200232420ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2015 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ #include "MythScheduleHelperNoHelper.h" // MythTV 0.26 class MythScheduleHelper75 : public MythScheduleHelperNoHelper { public: MythScheduleHelper75(MythScheduleManager *manager, Myth::Control *control) : m_manager(manager) , m_control(control) { } virtual MythTimerTypeList GetTimerTypes() const; virtual bool SameTimeslot(const MythRecordingRule& first, const MythRecordingRule& second) const; virtual bool FillTimerEntryWithRule(MythTimerEntry& entry, const MythRecordingRuleNode& node) const; virtual bool FillTimerEntryWithUpcoming(MythTimerEntry& entry, const MythProgramInfo& recording) const; virtual MythRecordingRule NewFromTemplate(const MythEPGInfo& epgInfo); virtual MythRecordingRule NewFromTimer(const MythTimerEntry& entry, bool withTemplate); virtual MythRecordingRule MakeDontRecord(const MythRecordingRule& rule, const MythProgramInfo& recording); virtual MythRecordingRule MakeOverride(const MythRecordingRule& rule, const MythProgramInfo& recording); // Members return default id for setting virtual int GetRuleDupMethodDefaultId() const { return Myth::DM_CheckSubtitleThenDescription; } virtual int GetRuleExpirationDefaultId() const { return EXPIRATION_ALLOW_EXPIRE_ID; } protected: // Following members aren't thread safe: SHOULD be called by a locked method virtual const MythTimerType::AttributeList& GetRulePriorityList() const; virtual const MythTimerType::AttributeList& GetRuleDupMethodList() const; virtual const RuleExpirationMap& GetRuleExpirationMap() const; virtual const MythTimerType::AttributeList& GetRuleRecordingGroupList() const; MythScheduleManager *m_manager; Myth::Control *m_control; }; pvr.mythtv-5.10.15-Leia/src/cppmyth/MythScheduleHelper76.cpp000066400000000000000000000542651360567320200236060ustar00rootroot00000000000000/* * Copyright (C) 2005-2015 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ /////////////////////////////////////////////////////////////////////////////// //// //// Version helper for database up to 1309 (0.27) //// //// Remove the Timeslot and Weekslot recording rule types. These rule //// types are too rigid and don't work when a broadcaster shifts the //// starting time of a program by a few minutes. Users should now use //// Channel recording rules in place of Timeslot and Weekslot rules. To //// approximate the old functionality, two new schedule filters have been //// added. In addition, the new "This time" and "This day and time" //// filters are less strict and match any program starting within 10 //// minutes of the recording rule time. //// Restrict the use of the FindDaily? and FindWeekly? recording rule types //// (now simply called Daily and Weekly) to search and manual recording //// rules. These rule types are rarely needed and limiting their use to //// the most powerful cases simplifies the user interface for the more //// common cases. Users should now use Daily and Weekly, custom search //// rules in place of FindDaily? and FindWeekly? rules. //// Any existing recording rules using the no longer supported or allowed //// types are automatically converted to the suggested alternatives. //// #include "MythScheduleHelper76.h" #include "../client.h" #include "../tools.h" #include #include using namespace ADDON; bool MythScheduleHelper76::FillTimerEntryWithRule(MythTimerEntry& entry, const MythRecordingRuleNode& node) const { // Assign timer type regarding rule attributes. The match SHOULD be opposite to // that which is applied in function 'NewFromTimer' // Check rule flag for this entry entry.isRule = true; MythRecordingRule rule = node.GetRule(); if (g_bExtraDebug) XBMC->Log(LOG_DEBUG, "76::%s: RecordID %u", __FUNCTION__, rule.RecordID()); switch (rule.Type()) { case Myth::RT_SingleRecord: { // Fill recording status from its upcoming MythScheduleList recordings = m_manager->FindUpComingByRuleId(rule.RecordID()); MythScheduleList::const_reverse_iterator it = recordings.rbegin(); if (it != recordings.rend()) entry.recordingStatus = it->second->Status(); else return false; // Don't transfer single without upcoming } if (rule.SearchType() == Myth::ST_ManualSearch) entry.timerType = TIMER_TYPE_MANUAL_SEARCH; else entry.timerType = TIMER_TYPE_THIS_SHOWING; entry.chanid = rule.ChannelID(); entry.callsign = rule.Callsign(); break; case Myth::RT_OneRecord: entry.timerType = TIMER_TYPE_RECORD_ONE; if (rule.Filter() & Myth::FM_ThisChannel) { entry.chanid = rule.ChannelID(); entry.callsign = rule.Callsign(); } break; case Myth::RT_DailyRecord: entry.timerType = TIMER_TYPE_RECORD_DAILY; if (rule.Filter() & Myth::FM_ThisChannel) { entry.chanid = rule.ChannelID(); entry.callsign = rule.Callsign(); } break; case Myth::RT_WeeklyRecord: entry.timerType = TIMER_TYPE_RECORD_WEEKLY; if (rule.Filter() & Myth::FM_ThisChannel) { entry.chanid = rule.ChannelID(); entry.callsign = rule.Callsign(); } break; case Myth::RT_AllRecord: if ((rule.Filter() & Myth::FM_ThisDayAndTime)) entry.timerType = TIMER_TYPE_RECORD_WEEKLY; else if ((rule.Filter() & Myth::FM_ThisTime)) entry.timerType = TIMER_TYPE_RECORD_DAILY; else if ((rule.Filter() & Myth::FM_ThisSeries)) entry.timerType = TIMER_TYPE_RECORD_SERIES; else entry.timerType = TIMER_TYPE_RECORD_ALL; if (rule.Filter() & Myth::FM_ThisChannel) { entry.chanid = rule.ChannelID(); entry.callsign = rule.Callsign(); } break; case Myth::RT_OverrideRecord: entry.timerType = TIMER_TYPE_OVERRIDE; entry.chanid = rule.ChannelID(); entry.callsign = rule.Callsign(); break; case Myth::RT_DontRecord: entry.timerType = TIMER_TYPE_DONT_RECORD; entry.chanid = rule.ChannelID(); entry.callsign = rule.Callsign(); break; default: entry.timerType = TIMER_TYPE_UNHANDLED; entry.chanid = rule.ChannelID(); entry.callsign = rule.Callsign(); break; } switch (rule.SearchType()) { case Myth::ST_TitleSearch: entry.epgSearch = rule.Description(); break; case Myth::ST_KeywordSearch: entry.epgSearch = rule.Description(); entry.timerType = TIMER_TYPE_SEARCH_KEYWORD; break; case Myth::ST_PeopleSearch: entry.epgSearch = rule.Description(); entry.timerType = TIMER_TYPE_SEARCH_PEOPLE; break; case Myth::ST_PowerSearch: entry.epgSearch = rule.Description(); entry.timerType = TIMER_TYPE_UNHANDLED; break; case Myth::ST_NoSearch: // EPG based entry.epgCheck = true; entry.epgSearch = rule.Title(); break; case Myth::ST_ManualSearch: // Manual entry.chanid = rule.ChannelID(); entry.callsign = rule.Callsign(); entry.startTime = rule.StartTime(); entry.endTime = rule.EndTime(); break; default: break; } switch (entry.timerType) { case TIMER_TYPE_RECORD_ONE: case TIMER_TYPE_RECORD_WEEKLY: case TIMER_TYPE_RECORD_DAILY: case TIMER_TYPE_RECORD_ALL: case TIMER_TYPE_RECORD_SERIES: case TIMER_TYPE_SEARCH_KEYWORD: case TIMER_TYPE_SEARCH_PEOPLE: case TIMER_TYPE_UNHANDLED: entry.startTime = rule.StartTime(); entry.endTime = rule.EndTime(); // For all repeating fix timeslot as needed if (!entry.HasTimeSlot()) { if (difftime(rule.NextRecording(), 0) > 0) { // fill timeslot starting at next recording entry.startTime = rule.NextRecording(); // it includes offset correction // WARNING: if next recording has been overriden then offset could be different timeadd(&entry.startTime, INTERVAL_MINUTE * rule.StartOffset()); // remove start offset entry.endTime = 0; // any time } else if (difftime(rule.LastRecorded(), 0) > 0) { // fill timeslot starting at last recorded entry.startTime = rule.LastRecorded(); // it includes offset correction // WARNING: if last recorded has been overriden then offset could be different timeadd(&entry.startTime, INTERVAL_MINUTE * rule.StartOffset()); // remove start offset entry.endTime = 0; // any time } } // For all repeating set summary status if (node.HasConflict()) entry.recordingStatus = Myth::RS_CONFLICT; else if (node.IsRecording()) entry.recordingStatus = Myth::RS_RECORDING; // break; default: entry.startTime = rule.StartTime(); entry.endTime = rule.EndTime(); } // fill others entry.epgInfo = MythEPGInfo(rule.ChannelID(), rule.StartTime(), rule.EndTime()); entry.title = rule.Title(); entry.category = rule.Category(); entry.startOffset = rule.StartOffset(); entry.endOffset = rule.EndOffset(); entry.dupMethod = rule.DuplicateControlMethod(); entry.priority = rule.Priority(); entry.expiration = GetRuleExpirationId(RuleExpiration(rule.AutoExpire(), rule.MaxEpisodes(), rule.NewExpiresOldRecord())); entry.isInactive = rule.Inactive(); entry.firstShowing = (rule.Filter() & Myth::FM_FirstShowing ? true : false); entry.recordingGroup = GetRuleRecordingGroupId(rule.RecordingGroup()); entry.entryIndex = MythScheduleManager::MakeIndex(rule); // rule index if (node.IsOverrideRule()) entry.parentIndex = MythScheduleManager::MakeIndex(node.GetMainRule()); else entry.parentIndex = 0; return true; } MythRecordingRule MythScheduleHelper76::NewFromTimer(const MythTimerEntry& entry, bool withTemplate) { // Create a recording rule regarding timer attributes. The match SHOULD be opposite to // that which is applied in function 'FillTimerEntry' MythRecordingRule rule; XBMC->Log(LOG_DEBUG, "76::%s", __FUNCTION__); // default required fields start, end time time_t now = time(0); rule.SetStartTime(now); rule.SetEndTime(now); if (withTemplate) { // Base on template rule = NewFromTemplate(entry.epgInfo); // Override template with timer settings rule.SetStartOffset(rule.StartOffset() + entry.startOffset); rule.SetEndOffset(rule.EndOffset() + entry.endOffset); if (entry.dupMethod != GetRuleDupMethodDefaultId()) { rule.SetDuplicateControlMethod(entry.dupMethod); rule.SetCheckDuplicatesInType(Myth::DI_InAll); } if (entry.priority != GetRulePriorityDefaultId()) rule.SetPriority(entry.priority); if (entry.expiration != GetRuleExpirationDefaultId()) { RuleExpiration exr = GetRuleExpiration(entry.expiration); rule.SetAutoExpire(exr.autoExpire); rule.SetMaxEpisodes(exr.maxEpisodes); rule.SetNewExpiresOldRecord(exr.maxNewest); } if (entry.recordingGroup != RECGROUP_DFLT_ID) rule.SetRecordingGroup(GetRuleRecordingGroupName(entry.recordingGroup)); } else { rule.SetCategory(entry.category); rule.SetStartOffset(entry.startOffset); rule.SetEndOffset(entry.endOffset); rule.SetDuplicateControlMethod(entry.dupMethod); rule.SetPriority(entry.priority); RuleExpiration exr = GetRuleExpiration(entry.expiration); rule.SetAutoExpire(exr.autoExpire); rule.SetMaxEpisodes(exr.maxEpisodes); rule.SetNewExpiresOldRecord(exr.maxNewest); rule.SetRecordingGroup(GetRuleRecordingGroupName(entry.recordingGroup)); } switch (entry.timerType) { case TIMER_TYPE_MANUAL_SEARCH: { if (entry.HasChannel() && entry.HasTimeSlot()) { rule.SetType(Myth::RT_SingleRecord); rule.SetSearchType(Myth::ST_ManualSearch); // Using timeslot rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); rule.SetStartTime(entry.startTime); rule.SetEndTime(entry.endTime); rule.SetTitle(entry.title); rule.SetDescription(entry.description); rule.SetInactive(entry.isInactive); return rule; } break; } case TIMER_TYPE_THIS_SHOWING: { if (!entry.epgInfo.IsNull()) { rule.SetType(Myth::RT_SingleRecord); rule.SetSearchType(Myth::ST_NoSearch); rule.SetChannelID(entry.epgInfo.ChannelID()); rule.SetStartTime(entry.epgInfo.StartTime()); rule.SetEndTime(entry.epgInfo.EndTime()); rule.SetTitle(entry.epgInfo.Title()); rule.SetSubtitle(entry.epgInfo.Subtitle()); rule.SetDescription(entry.description); rule.SetCallsign(entry.epgInfo.Callsign()); rule.SetCategory(entry.epgInfo.Category()); rule.SetProgramID(entry.epgInfo.ProgramID()); rule.SetSeriesID(entry.epgInfo.SeriesID()); rule.SetInactive(entry.isInactive); return rule; } break; } case TIMER_TYPE_RECORD_ONE: { if (!entry.epgInfo.IsNull()) { rule.SetType(Myth::RT_OneRecord); rule.SetSearchType(Myth::ST_NoSearch); rule.SetChannelID(entry.epgInfo.ChannelID()); rule.SetStartTime(entry.epgInfo.StartTime()); rule.SetEndTime(entry.epgInfo.EndTime()); rule.SetTitle(entry.epgInfo.Title()); rule.SetSubtitle(entry.epgInfo.Subtitle()); rule.SetDescription(entry.description); rule.SetCallsign(entry.epgInfo.Callsign()); rule.SetCategory(entry.epgInfo.Category()); rule.SetProgramID(entry.epgInfo.ProgramID()); rule.SetSeriesID(entry.epgInfo.SeriesID()); rule.SetInactive(entry.isInactive); return rule; } if (!entry.epgSearch.empty()) { rule.SetType(Myth::RT_OneRecord); rule.SetSearchType(Myth::ST_TitleSearch); // Search title if (entry.HasChannel()) { rule.SetFilter(Myth::FM_ThisChannel); rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); } rule.SetTitle(entry.title); // Backend use the subtitle/description to find program by keywords or title rule.SetSubtitle(""); rule.SetDescription(entry.epgSearch); rule.SetInactive(entry.isInactive); return rule; } break; } case TIMER_TYPE_RECORD_WEEKLY: { if (!entry.epgInfo.IsNull()) { rule.SetType(Myth::RT_AllRecord); rule.SetFilter(Myth::FM_ThisChannel + Myth::FM_ThisDayAndTime); rule.SetSearchType(Myth::ST_NoSearch); rule.SetChannelID(entry.epgInfo.ChannelID()); rule.SetStartTime(entry.epgInfo.StartTime()); rule.SetEndTime(entry.epgInfo.EndTime()); rule.SetTitle(entry.epgInfo.Title()); rule.SetSubtitle(entry.epgInfo.Subtitle()); rule.SetDescription(entry.description); rule.SetCallsign(entry.epgInfo.Callsign()); rule.SetCategory(entry.epgInfo.Category()); rule.SetProgramID(entry.epgInfo.ProgramID()); rule.SetSeriesID(entry.epgInfo.SeriesID()); rule.SetInactive(entry.isInactive); rule.SetDuplicateControlMethod(Myth::DM_CheckNone); return rule; } if (!entry.epgSearch.empty()) { rule.SetType(Myth::RT_WeeklyRecord); rule.SetSearchType(Myth::ST_TitleSearch); // Search title if (entry.HasChannel()) { rule.SetFilter(Myth::FM_ThisChannel); rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); } rule.SetTitle(entry.title); // Backend use the subtitle/description to find program by keywords or title rule.SetSubtitle(""); rule.SetDescription(entry.epgSearch); rule.SetInactive(entry.isInactive); rule.SetDuplicateControlMethod(Myth::DM_CheckNone); return rule; } if (entry.HasChannel() && entry.HasTimeSlot()) { rule.SetType(Myth::RT_WeeklyRecord); rule.SetSearchType(Myth::ST_ManualSearch); // Using timeslot rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); rule.SetStartTime(entry.startTime); rule.SetEndTime(entry.endTime); rule.SetTitle(entry.title); rule.SetDescription(entry.description); rule.SetInactive(entry.isInactive); rule.SetDuplicateControlMethod(Myth::DM_CheckNone); return rule; } break; } case TIMER_TYPE_RECORD_DAILY: { if (!entry.epgInfo.IsNull()) { rule.SetType(Myth::RT_AllRecord); rule.SetFilter(Myth::FM_ThisChannel + Myth::FM_ThisTime); rule.SetSearchType(Myth::ST_NoSearch); rule.SetChannelID(entry.epgInfo.ChannelID()); rule.SetStartTime(entry.epgInfo.StartTime()); rule.SetEndTime(entry.epgInfo.EndTime()); rule.SetTitle(entry.epgInfo.Title()); rule.SetSubtitle(entry.epgInfo.Subtitle()); rule.SetDescription(entry.description); rule.SetCallsign(entry.epgInfo.Callsign()); rule.SetCategory(entry.epgInfo.Category()); rule.SetProgramID(entry.epgInfo.ProgramID()); rule.SetSeriesID(entry.epgInfo.SeriesID()); rule.SetInactive(entry.isInactive); rule.SetDuplicateControlMethod(Myth::DM_CheckNone); return rule; } if (!entry.epgSearch.empty()) { rule.SetType(Myth::RT_DailyRecord); rule.SetSearchType(Myth::ST_TitleSearch); // Search title if (entry.HasChannel()) { rule.SetFilter(Myth::FM_ThisChannel); rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); } rule.SetTitle(entry.title); // Backend use the subtitle/description to find program by keywords or title rule.SetSubtitle(""); rule.SetDescription(entry.epgSearch); rule.SetInactive(entry.isInactive); return rule; } if (entry.HasChannel() && entry.HasTimeSlot()) { rule.SetType(Myth::RT_DailyRecord); rule.SetSearchType(Myth::ST_ManualSearch); // Using timeslot rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); rule.SetStartTime(entry.startTime); rule.SetEndTime(entry.endTime); rule.SetTitle(entry.title); rule.SetDescription(entry.description); rule.SetInactive(entry.isInactive); rule.SetDuplicateControlMethod(Myth::DM_CheckNone); return rule; } break; } case TIMER_TYPE_RECORD_ALL: { if (!entry.epgInfo.IsNull()) { rule.SetType(Myth::RT_AllRecord); rule.SetFilter(Myth::FM_ThisChannel); rule.SetSearchType(Myth::ST_NoSearch); rule.SetChannelID(entry.epgInfo.ChannelID()); rule.SetStartTime(entry.epgInfo.StartTime()); rule.SetEndTime(entry.epgInfo.EndTime()); rule.SetTitle(entry.epgInfo.Title()); rule.SetSubtitle(entry.epgInfo.Subtitle()); rule.SetDescription(entry.description); rule.SetCallsign(entry.epgInfo.Callsign()); rule.SetCategory(entry.epgInfo.Category()); rule.SetProgramID(entry.epgInfo.ProgramID()); rule.SetSeriesID(entry.epgInfo.SeriesID()); rule.SetInactive(entry.isInactive); return rule; } if (!entry.epgSearch.empty()) { rule.SetType(Myth::RT_AllRecord); rule.SetSearchType(Myth::ST_TitleSearch); // Search title if (entry.HasChannel()) { rule.SetFilter(Myth::FM_ThisChannel); rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); } rule.SetTitle(entry.title); // Backend use the subtitle/description to find program by keywords or title rule.SetSubtitle(""); rule.SetDescription(entry.epgSearch); rule.SetInactive(entry.isInactive); return rule; } break; } case TIMER_TYPE_RECORD_SERIES: { if (!entry.epgInfo.IsNull()) { rule.SetType(Myth::RT_AllRecord); rule.SetFilter(Myth::FM_ThisChannel | Myth::FM_ThisSeries); rule.SetSearchType(Myth::ST_NoSearch); rule.SetChannelID(entry.epgInfo.ChannelID()); rule.SetStartTime(entry.epgInfo.StartTime()); rule.SetEndTime(entry.epgInfo.EndTime()); rule.SetTitle(entry.epgInfo.Title()); rule.SetSubtitle(entry.epgInfo.Subtitle()); rule.SetDescription(entry.description); rule.SetCallsign(entry.epgInfo.Callsign()); rule.SetCategory(entry.epgInfo.Category()); rule.SetProgramID(entry.epgInfo.ProgramID()); rule.SetSeriesID(entry.epgInfo.SeriesID()); rule.SetInactive(entry.isInactive); return rule; } break; } case TIMER_TYPE_SEARCH_KEYWORD: { if (!entry.epgSearch.empty()) { rule.SetType(Myth::RT_AllRecord); rule.SetSearchType(Myth::ST_KeywordSearch); // Search keyword if (entry.HasChannel()) { rule.SetFilter(Myth::FM_ThisChannel); rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); } rule.SetTitle(entry.title); // Backend use the subtitle/description to find program by keywords or title rule.SetSubtitle(""); rule.SetDescription(entry.epgSearch); rule.SetInactive(entry.isInactive); return rule; } break; } case TIMER_TYPE_SEARCH_PEOPLE: { if (!entry.epgSearch.empty()) { rule.SetType(Myth::RT_AllRecord); rule.SetSearchType(Myth::ST_PeopleSearch); // Search people if (entry.HasChannel()) { rule.SetFilter(Myth::FM_ThisChannel); rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); } rule.SetTitle(entry.title); // Backend use the subtitle/description to find program by keywords or title rule.SetSubtitle(""); rule.SetDescription(entry.epgSearch); rule.SetInactive(entry.isInactive); return rule; } break; } case TIMER_TYPE_DONT_RECORD: rule.SetType(Myth::RT_DontRecord); rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); rule.SetStartTime(entry.startTime); rule.SetEndTime(entry.endTime); rule.SetTitle(entry.title); rule.SetDescription(entry.description); rule.SetInactive(entry.isInactive); return rule; case TIMER_TYPE_OVERRIDE: rule.SetType(Myth::RT_OverrideRecord); rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); rule.SetStartTime(entry.startTime); rule.SetEndTime(entry.endTime); rule.SetTitle(entry.title); rule.SetDescription(entry.description); rule.SetInactive(entry.isInactive); return rule; case TIMER_TYPE_UPCOMING: case TIMER_TYPE_RULE_INACTIVE: case TIMER_TYPE_UPCOMING_ALTERNATE: case TIMER_TYPE_UPCOMING_RECORDED: case TIMER_TYPE_UPCOMING_EXPIRED: case TIMER_TYPE_UPCOMING_MANUAL: case TIMER_TYPE_ZOMBIE: rule.SetType(Myth::RT_SingleRecord); rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); rule.SetStartTime(entry.startTime); rule.SetEndTime(entry.endTime); rule.SetTitle(entry.title); rule.SetDescription(entry.description); rule.SetInactive(entry.isInactive); return rule; default: break; } rule.SetType(Myth::RT_UNKNOWN); XBMC->Log(LOG_ERROR, "76::%s: Invalid timer %u: TYPE=%d CHANID=%u SIGN=%s ST=%u ET=%u", __FUNCTION__, entry.entryIndex, entry.timerType, entry.chanid, entry.callsign.c_str(), (unsigned)entry.startTime, (unsigned)entry.endTime); return rule; } pvr.mythtv-5.10.15-Leia/src/cppmyth/MythScheduleHelper76.h000066400000000000000000000024131360567320200232370ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2015 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ #include "MythScheduleHelper75.h" // News in 0.27 class MythScheduleHelper76 : public MythScheduleHelper75 { public: MythScheduleHelper76(MythScheduleManager *manager, Myth::Control *control) : MythScheduleHelper75(manager, control) { } virtual bool FillTimerEntryWithRule(MythTimerEntry& entry, const MythRecordingRuleNode& node) const; //virtual bool FillTimerEntry(MythTimerEntry& entry, const MythProgramInfo& recording) const; virtual MythRecordingRule NewFromTimer(const MythTimerEntry& entry, bool withTemplate); }; pvr.mythtv-5.10.15-Leia/src/cppmyth/MythScheduleHelper85.cpp000066400000000000000000000124341360567320200235760ustar00rootroot00000000000000/* * Copyright (C) 2005-2015 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ /////////////////////////////////////////////////////////////////////////////// //// //// Version helper for backend version 85 (0.28-pre) //// #include "MythScheduleHelper85.h" #include "../client.h" #include "../tools.h" #include #include using namespace ADDON; bool MythScheduleHelper85::FillTimerEntryWithUpcoming(MythTimerEntry& entry, const MythProgramInfo& recording) const { //Only include timers which have an inactive status if the user has requested it (flag m_showNotRecording) switch (recording.Status()) { //Upcoming recordings which are disabled due to being lower priority duplicates or already recorded case Myth::RS_EARLIER_RECORDING: //will record earlier case Myth::RS_LATER_SHOWING: //will record later case Myth::RS_CURRENT_RECORDING: //Already in the current library case Myth::RS_PREVIOUS_RECORDING: //Previoulsy recorded but no longer in the library if (!m_manager->ShowNotRecording()) { if (g_bExtraDebug) XBMC->Log(LOG_DEBUG, "85::%s: Skipping %s:%s on %s because status %d", __FUNCTION__, recording.Title().c_str(), recording.Subtitle().c_str(), recording.ChannelName().c_str(), recording.Status()); return false; } default: break; } MythRecordingRuleNodePtr node = m_manager->FindRuleById(recording.RecordID()); if (node) { MythRecordingRule rule = node->GetRule(); // Relate the main rule as parent entry.parentIndex = MythScheduleManager::MakeIndex(node->GetMainRule()); switch (rule.Type()) { case Myth::RT_SingleRecord: return false; // Discard upcoming. We show only main rule. case Myth::RT_DontRecord: entry.recordingStatus = recording.Status(); entry.timerType = TIMER_TYPE_DONT_RECORD; entry.isInactive = rule.Inactive(); break; case Myth::RT_OverrideRecord: entry.recordingStatus = recording.Status(); entry.timerType = TIMER_TYPE_OVERRIDE; entry.isInactive = rule.Inactive(); break; default: entry.recordingStatus = recording.Status(); if (node->GetMainRule().SearchType() == Myth::ST_ManualSearch) entry.timerType = TIMER_TYPE_UPCOMING_MANUAL; else { switch (recording.Status()) { case Myth::RS_EARLIER_RECORDING: //will record earlier case Myth::RS_LATER_SHOWING: //will record later entry.timerType = TIMER_TYPE_UPCOMING_ALTERNATE; break; case Myth::RS_CURRENT_RECORDING: //Already in the current library entry.timerType = TIMER_TYPE_UPCOMING_RECORDED; break; case Myth::RS_PREVIOUS_RECORDING: //Previoulsy recorded but no longer in the library entry.timerType = TIMER_TYPE_UPCOMING_EXPIRED; break; case Myth::RS_INACTIVE: //Parent rule is disabled entry.timerType = TIMER_TYPE_RULE_INACTIVE; break; default: entry.timerType = TIMER_TYPE_UPCOMING; break; } } } entry.startOffset = rule.StartOffset(); entry.endOffset = rule.EndOffset(); entry.priority = rule.Priority(); entry.expiration = GetRuleExpirationId(RuleExpiration(rule.AutoExpire(), 0, false)); } else entry.timerType = TIMER_TYPE_ZOMBIE; switch (entry.timerType) { case TIMER_TYPE_UPCOMING: case TIMER_TYPE_RULE_INACTIVE: case TIMER_TYPE_UPCOMING_ALTERNATE: case TIMER_TYPE_UPCOMING_RECORDED: case TIMER_TYPE_UPCOMING_EXPIRED: case TIMER_TYPE_OVERRIDE: case TIMER_TYPE_UPCOMING_MANUAL: entry.epgCheck = true; break; default: entry.epgCheck = false; } entry.epgInfo = MythEPGInfo(recording.ChannelID(), recording.StartTime(), recording.EndTime()); entry.description = ""; entry.chanid = recording.ChannelID(); entry.callsign = recording.Callsign(); entry.startTime = recording.StartTime(); entry.endTime = recording.EndTime(); entry.title.assign(recording.Title()); if (!recording.Subtitle().empty()) entry.title.append(" (").append(recording.Subtitle()).append(")"); if (recording.Season() || recording.Episode()) entry.title.append(" - ").append(Myth::IntToString(recording.Season())).append(".").append(Myth::IntToString(recording.Episode())); entry.recordingGroup = GetRuleRecordingGroupId(recording.RecordingGroup()); entry.entryIndex = MythScheduleManager::MakeIndex(recording); // upcoming index return true; } pvr.mythtv-5.10.15-Leia/src/cppmyth/MythScheduleHelper85.h000066400000000000000000000021241360567320200232360ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2015 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ #include "MythScheduleHelper76.h" // News in 0.28 class MythScheduleHelper85 : public MythScheduleHelper76 { public: MythScheduleHelper85(MythScheduleManager *manager, Myth::Control *control) : MythScheduleHelper76(manager, control) { } virtual bool FillTimerEntryWithUpcoming(MythTimerEntry& entry, const MythProgramInfo& recording) const; }; pvr.mythtv-5.10.15-Leia/src/cppmyth/MythScheduleHelper91.cpp000066400000000000000000000354701360567320200236000ustar00rootroot00000000000000/* * Copyright (C) 2018 Team Kodi * http://kodi.tv * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ /////////////////////////////////////////////////////////////////////////////// //// //// Version helper for database up to 1348 (29.0) //// //// Because they aren't required for SearchTypes other than None and Manual, //// the start/end date/time can be empty. //// #include "MythScheduleHelper91.h" #include "../client.h" #include "../tools.h" #include #include using namespace ADDON; MythRecordingRule MythScheduleHelper91::NewFromTimer(const MythTimerEntry& entry, bool withTemplate) { // Create a recording rule regarding timer attributes. The match SHOULD be opposite to // that which is applied in function 'FillTimerEntry' MythRecordingRule rule; XBMC->Log(LOG_DEBUG, "91::%s", __FUNCTION__); if (withTemplate) { // Base on template rule = NewFromTemplate(entry.epgInfo); // Override template with timer settings rule.SetStartOffset(rule.StartOffset() + entry.startOffset); rule.SetEndOffset(rule.EndOffset() + entry.endOffset); if (entry.dupMethod != GetRuleDupMethodDefaultId()) { rule.SetDuplicateControlMethod(entry.dupMethod); rule.SetCheckDuplicatesInType(Myth::DI_InAll); } if (entry.priority != GetRulePriorityDefaultId()) rule.SetPriority(entry.priority); if (entry.expiration != GetRuleExpirationDefaultId()) { RuleExpiration exr = GetRuleExpiration(entry.expiration); rule.SetAutoExpire(exr.autoExpire); rule.SetMaxEpisodes(exr.maxEpisodes); rule.SetNewExpiresOldRecord(exr.maxNewest); } if (entry.recordingGroup != RECGROUP_DFLT_ID) rule.SetRecordingGroup(GetRuleRecordingGroupName(entry.recordingGroup)); } else { rule.SetCategory(entry.category); rule.SetStartOffset(entry.startOffset); rule.SetEndOffset(entry.endOffset); rule.SetDuplicateControlMethod(entry.dupMethod); rule.SetPriority(entry.priority); RuleExpiration exr = GetRuleExpiration(entry.expiration); rule.SetAutoExpire(exr.autoExpire); rule.SetMaxEpisodes(exr.maxEpisodes); rule.SetNewExpiresOldRecord(exr.maxNewest); rule.SetRecordingGroup(GetRuleRecordingGroupName(entry.recordingGroup)); } switch (entry.timerType) { case TIMER_TYPE_MANUAL_SEARCH: { if (entry.HasChannel() && entry.HasTimeSlot()) { rule.SetType(Myth::RT_SingleRecord); rule.SetSearchType(Myth::ST_ManualSearch); // Using timeslot rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); rule.SetStartTime(entry.startTime); rule.SetEndTime(entry.endTime); rule.SetTitle(entry.title); rule.SetDescription(entry.description); rule.SetInactive(entry.isInactive); return rule; } break; } case TIMER_TYPE_THIS_SHOWING: { if (!entry.epgInfo.IsNull()) { rule.SetType(Myth::RT_SingleRecord); rule.SetSearchType(Myth::ST_NoSearch); rule.SetChannelID(entry.epgInfo.ChannelID()); rule.SetStartTime(entry.epgInfo.StartTime()); rule.SetEndTime(entry.epgInfo.EndTime()); rule.SetTitle(entry.epgInfo.Title()); rule.SetSubtitle(entry.epgInfo.Subtitle()); rule.SetDescription(entry.description); rule.SetCallsign(entry.epgInfo.Callsign()); rule.SetCategory(entry.epgInfo.Category()); rule.SetProgramID(entry.epgInfo.ProgramID()); rule.SetSeriesID(entry.epgInfo.SeriesID()); rule.SetInactive(entry.isInactive); return rule; } break; } case TIMER_TYPE_RECORD_ONE: { if (!entry.epgInfo.IsNull()) { rule.SetType(Myth::RT_OneRecord); rule.SetSearchType(Myth::ST_NoSearch); rule.SetChannelID(entry.epgInfo.ChannelID()); rule.SetStartTime(entry.epgInfo.StartTime()); rule.SetEndTime(entry.epgInfo.EndTime()); rule.SetTitle(entry.epgInfo.Title()); rule.SetSubtitle(entry.epgInfo.Subtitle()); rule.SetDescription(entry.description); rule.SetCallsign(entry.epgInfo.Callsign()); rule.SetCategory(entry.epgInfo.Category()); rule.SetProgramID(entry.epgInfo.ProgramID()); rule.SetSeriesID(entry.epgInfo.SeriesID()); rule.SetInactive(entry.isInactive); return rule; } if (!entry.epgSearch.empty()) { rule.SetType(Myth::RT_OneRecord); rule.SetSearchType(Myth::ST_TitleSearch); // Search title if (entry.HasChannel()) { rule.SetFilter(Myth::FM_ThisChannel); rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); } rule.SetTitle(entry.title); // Backend use the subtitle/description to find program by keywords or title rule.SetSubtitle(""); rule.SetDescription(entry.epgSearch); rule.SetInactive(entry.isInactive); return rule; } break; } case TIMER_TYPE_RECORD_WEEKLY: { if (!entry.epgInfo.IsNull()) { rule.SetType(Myth::RT_AllRecord); rule.SetFilter(Myth::FM_ThisChannel + Myth::FM_ThisDayAndTime); rule.SetSearchType(Myth::ST_NoSearch); rule.SetChannelID(entry.epgInfo.ChannelID()); rule.SetStartTime(entry.epgInfo.StartTime()); rule.SetEndTime(entry.epgInfo.EndTime()); rule.SetTitle(entry.epgInfo.Title()); rule.SetSubtitle(entry.epgInfo.Subtitle()); rule.SetDescription(entry.description); rule.SetCallsign(entry.epgInfo.Callsign()); rule.SetCategory(entry.epgInfo.Category()); rule.SetProgramID(entry.epgInfo.ProgramID()); rule.SetSeriesID(entry.epgInfo.SeriesID()); rule.SetInactive(entry.isInactive); rule.SetDuplicateControlMethod(Myth::DM_CheckNone); return rule; } if (!entry.epgSearch.empty()) { rule.SetType(Myth::RT_WeeklyRecord); rule.SetSearchType(Myth::ST_TitleSearch); // Search title if (entry.HasChannel()) { rule.SetFilter(Myth::FM_ThisChannel); rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); } rule.SetTitle(entry.title); // Backend use the subtitle/description to find program by keywords or title rule.SetSubtitle(""); rule.SetDescription(entry.epgSearch); rule.SetInactive(entry.isInactive); rule.SetDuplicateControlMethod(Myth::DM_CheckNone); return rule; } if (entry.HasChannel() && entry.HasTimeSlot()) { rule.SetType(Myth::RT_WeeklyRecord); rule.SetSearchType(Myth::ST_ManualSearch); // Using timeslot rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); rule.SetStartTime(entry.startTime); rule.SetEndTime(entry.endTime); rule.SetTitle(entry.title); rule.SetDescription(entry.description); rule.SetInactive(entry.isInactive); rule.SetDuplicateControlMethod(Myth::DM_CheckNone); return rule; } break; } case TIMER_TYPE_RECORD_DAILY: { if (!entry.epgInfo.IsNull()) { rule.SetType(Myth::RT_AllRecord); rule.SetFilter(Myth::FM_ThisChannel + Myth::FM_ThisTime); rule.SetSearchType(Myth::ST_NoSearch); rule.SetChannelID(entry.epgInfo.ChannelID()); rule.SetStartTime(entry.epgInfo.StartTime()); rule.SetEndTime(entry.epgInfo.EndTime()); rule.SetTitle(entry.epgInfo.Title()); rule.SetSubtitle(entry.epgInfo.Subtitle()); rule.SetDescription(entry.description); rule.SetCallsign(entry.epgInfo.Callsign()); rule.SetCategory(entry.epgInfo.Category()); rule.SetProgramID(entry.epgInfo.ProgramID()); rule.SetSeriesID(entry.epgInfo.SeriesID()); rule.SetInactive(entry.isInactive); rule.SetDuplicateControlMethod(Myth::DM_CheckNone); return rule; } if (!entry.epgSearch.empty()) { rule.SetType(Myth::RT_DailyRecord); rule.SetSearchType(Myth::ST_TitleSearch); // Search title if (entry.HasChannel()) { rule.SetFilter(Myth::FM_ThisChannel); rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); } rule.SetTitle(entry.title); // Backend use the subtitle/description to find program by keywords or title rule.SetSubtitle(""); rule.SetDescription(entry.epgSearch); rule.SetInactive(entry.isInactive); return rule; } if (entry.HasChannel() && entry.HasTimeSlot()) { rule.SetType(Myth::RT_DailyRecord); rule.SetSearchType(Myth::ST_ManualSearch); // Using timeslot rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); rule.SetStartTime(entry.startTime); rule.SetEndTime(entry.endTime); rule.SetTitle(entry.title); rule.SetDescription(entry.description); rule.SetInactive(entry.isInactive); rule.SetDuplicateControlMethod(Myth::DM_CheckNone); return rule; } break; } case TIMER_TYPE_RECORD_ALL: { if (!entry.epgInfo.IsNull()) { rule.SetType(Myth::RT_AllRecord); rule.SetFilter(Myth::FM_ThisChannel); rule.SetSearchType(Myth::ST_NoSearch); rule.SetChannelID(entry.epgInfo.ChannelID()); rule.SetStartTime(entry.epgInfo.StartTime()); rule.SetEndTime(entry.epgInfo.EndTime()); rule.SetTitle(entry.epgInfo.Title()); rule.SetSubtitle(entry.epgInfo.Subtitle()); rule.SetDescription(entry.description); rule.SetCallsign(entry.epgInfo.Callsign()); rule.SetCategory(entry.epgInfo.Category()); rule.SetProgramID(entry.epgInfo.ProgramID()); rule.SetSeriesID(entry.epgInfo.SeriesID()); rule.SetInactive(entry.isInactive); return rule; } if (!entry.epgSearch.empty()) { rule.SetType(Myth::RT_AllRecord); rule.SetSearchType(Myth::ST_TitleSearch); // Search title if (entry.HasChannel()) { rule.SetFilter(Myth::FM_ThisChannel); rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); } rule.SetTitle(entry.title); // Backend use the subtitle/description to find program by keywords or title rule.SetSubtitle(""); rule.SetDescription(entry.epgSearch); rule.SetInactive(entry.isInactive); return rule; } break; } case TIMER_TYPE_RECORD_SERIES: { if (!entry.epgInfo.IsNull()) { rule.SetType(Myth::RT_AllRecord); rule.SetFilter(Myth::FM_ThisChannel | Myth::FM_ThisSeries); rule.SetSearchType(Myth::ST_NoSearch); rule.SetChannelID(entry.epgInfo.ChannelID()); rule.SetStartTime(entry.epgInfo.StartTime()); rule.SetEndTime(entry.epgInfo.EndTime()); rule.SetTitle(entry.epgInfo.Title()); rule.SetSubtitle(entry.epgInfo.Subtitle()); rule.SetDescription(entry.description); rule.SetCallsign(entry.epgInfo.Callsign()); rule.SetCategory(entry.epgInfo.Category()); rule.SetProgramID(entry.epgInfo.ProgramID()); rule.SetSeriesID(entry.epgInfo.SeriesID()); rule.SetInactive(entry.isInactive); return rule; } break; } case TIMER_TYPE_SEARCH_KEYWORD: { if (!entry.epgSearch.empty()) { rule.SetType(Myth::RT_AllRecord); rule.SetSearchType(Myth::ST_KeywordSearch); // Search keyword if (entry.HasChannel()) { rule.SetFilter(Myth::FM_ThisChannel); rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); } rule.SetTitle(entry.title); // Backend use the subtitle/description to find program by keywords or title rule.SetSubtitle(""); rule.SetDescription(entry.epgSearch); rule.SetInactive(entry.isInactive); return rule; } break; } case TIMER_TYPE_SEARCH_PEOPLE: { if (!entry.epgSearch.empty()) { rule.SetType(Myth::RT_AllRecord); rule.SetSearchType(Myth::ST_PeopleSearch); // Search people if (entry.HasChannel()) { rule.SetFilter(Myth::FM_ThisChannel); rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); } rule.SetTitle(entry.title); // Backend use the subtitle/description to find program by keywords or title rule.SetSubtitle(""); rule.SetDescription(entry.epgSearch); rule.SetInactive(entry.isInactive); return rule; } break; } case TIMER_TYPE_DONT_RECORD: rule.SetType(Myth::RT_DontRecord); rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); rule.SetStartTime(entry.startTime); rule.SetEndTime(entry.endTime); rule.SetTitle(entry.title); rule.SetDescription(entry.description); rule.SetInactive(entry.isInactive); return rule; case TIMER_TYPE_OVERRIDE: rule.SetType(Myth::RT_OverrideRecord); rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); rule.SetStartTime(entry.startTime); rule.SetEndTime(entry.endTime); rule.SetTitle(entry.title); rule.SetDescription(entry.description); rule.SetInactive(entry.isInactive); return rule; case TIMER_TYPE_UPCOMING: case TIMER_TYPE_RULE_INACTIVE: case TIMER_TYPE_UPCOMING_ALTERNATE: case TIMER_TYPE_UPCOMING_RECORDED: case TIMER_TYPE_UPCOMING_EXPIRED: case TIMER_TYPE_UPCOMING_MANUAL: case TIMER_TYPE_ZOMBIE: rule.SetType(Myth::RT_SingleRecord); rule.SetChannelID(entry.chanid); rule.SetCallsign(entry.callsign); rule.SetStartTime(entry.startTime); rule.SetEndTime(entry.endTime); rule.SetTitle(entry.title); rule.SetDescription(entry.description); rule.SetInactive(entry.isInactive); return rule; default: break; } rule.SetType(Myth::RT_UNKNOWN); XBMC->Log(LOG_ERROR, "91::%s: Invalid timer %u: TYPE=%d CHANID=%u SIGN=%s ST=%u ET=%u", __FUNCTION__, entry.entryIndex, entry.timerType, entry.chanid, entry.callsign.c_str(), (unsigned)entry.startTime, (unsigned)entry.endTime); return rule; } pvr.mythtv-5.10.15-Leia/src/cppmyth/MythScheduleHelper91.h000066400000000000000000000020721360567320200232350ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2018 Team Kodi * http://kodi.tv * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ #include "MythScheduleHelper85.h" // News in 29.0 class MythScheduleHelper91 : public MythScheduleHelper85 { public: MythScheduleHelper91(MythScheduleManager *manager, Myth::Control *control) : MythScheduleHelper85(manager, control) { } virtual MythRecordingRule NewFromTimer(const MythTimerEntry& entry, bool withTemplate); }; pvr.mythtv-5.10.15-Leia/src/cppmyth/MythScheduleHelperNoHelper.cpp000066400000000000000000000163461360567320200250640ustar00rootroot00000000000000/* * Copyright (C) 2005-2015 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ /////////////////////////////////////////////////////////////////////////////// //// //// Version Helper for unknown version (no helper) //// #include "MythScheduleHelperNoHelper.h" #include "../client.h" #include "private/os/threads/mutex.h" MythScheduleHelperNoHelper::MythScheduleHelperNoHelper() : m_lock(new Myth::OS::CMutex) , m_timerTypeListInit(false) , m_priorityListInit(false) , m_dupMethodListInit(false) , m_expirationMapInit(false) , m_expirationListInit(false) , m_expirationByKeyInit(false) , m_recGroupListInit(false) , m_recGroupByNameInit(false) , m_recGroupByIdInit(false) { } MythScheduleHelperNoHelper::~MythScheduleHelperNoHelper() { delete m_lock; } MythTimerTypeList MythScheduleHelperNoHelper::GetTimerTypes() const { Myth::OS::CLockGuard lock(*m_lock); return m_timerTypeList; } bool MythScheduleHelperNoHelper::SameTimeslot(const MythRecordingRule &first, const MythRecordingRule &second) const { (void)first; (void)second; return false; } bool MythScheduleHelperNoHelper::FillTimerEntryWithRule(MythTimerEntry& entry, const MythRecordingRuleNode& node) const { (void)node; entry.isRule = true; entry.timerType = TIMER_TYPE_UNHANDLED; return true; } bool MythScheduleHelperNoHelper::FillTimerEntryWithUpcoming(MythTimerEntry& entry, const MythProgramInfo& recording) const { (void)recording; entry.timerType = TIMER_TYPE_UNHANDLED; return true; } MythRecordingRule MythScheduleHelperNoHelper::NewFromTemplate(const MythEPGInfo& epgInfo) { (void)epgInfo; return MythRecordingRule(); } MythRecordingRule MythScheduleHelperNoHelper::NewFromTimer(const MythTimerEntry& entry, bool withTemplate) { (void)entry; (void)withTemplate; return MythRecordingRule(); } MythRecordingRule MythScheduleHelperNoHelper::MakeDontRecord(const MythRecordingRule& rule, const MythProgramInfo& recording) { MythRecordingRule modifier; modifier.SetType(Myth::RT_NotRecording); return modifier; } MythRecordingRule MythScheduleHelperNoHelper::MakeOverride(const MythRecordingRule& rule, const MythProgramInfo& recording) { MythRecordingRule modifier; modifier.SetType(Myth::RT_NotRecording); return modifier; } static inline uint32_t expiration_key(const MythScheduleHelperNoHelper::RuleExpiration& expiration) { if (expiration.maxEpisodes > 0 && expiration.maxEpisodes < 0x100) return (expiration.maxEpisodes & 0xFF) | (expiration.maxNewest ? 0x100 : 0x0); else return (expiration.autoExpire ? 0x200 : 0x0); } int MythScheduleHelperNoHelper::GetRuleExpirationId(const RuleExpiration& expiration) const { Myth::OS::CLockGuard lock(*m_lock); if (!m_expirationByKeyInit) { m_expirationByKeyInit = true; const RuleExpirationMap& expirationMap = GetRuleExpirationMap(); for (RuleExpirationMap::const_iterator it = expirationMap.begin(); it != expirationMap.end(); ++it) m_expirationByKey.insert(std::make_pair(expiration_key(it->second.first), it->first)); } std::map::const_iterator it = m_expirationByKey.find(expiration_key(expiration)); if (it != m_expirationByKey.end()) return it->second; return GetRuleExpirationDefaultId(); } MythScheduleHelperNoHelper::RuleExpiration MythScheduleHelperNoHelper::GetRuleExpiration(int id) const { Myth::OS::CLockGuard lock(*m_lock); static RuleExpiration _empty(false, 0, false); RuleExpirationMap::const_iterator it = GetRuleExpirationMap().find(id); if (it != m_expirationMap.end()) return it->second.first; return _empty; } int MythScheduleHelperNoHelper::GetRuleRecordingGroupId(const std::string& name) const { Myth::OS::CLockGuard lock(*m_lock); if (!m_recGroupByNameInit) { m_recGroupByNameInit = true; const MythTimerType::AttributeList& groupList = GetRuleRecordingGroupList(); for (MythTimerType::AttributeList::const_iterator it = groupList.begin(); it != groupList.end(); ++it) m_recGroupByName.insert(std::make_pair(it->second, it->first)); } std::map::const_iterator it = m_recGroupByName.find(name); if (it != m_recGroupByName.end()) return it->second; return RECGROUP_DFLT_ID; } std::string MythScheduleHelperNoHelper::GetRuleRecordingGroupName(int id) const { Myth::OS::CLockGuard lock(*m_lock); static std::string _empty = ""; if (!m_recGroupByIdInit) { m_recGroupByIdInit = true; const MythTimerType::AttributeList& groupList = GetRuleRecordingGroupList(); for (MythTimerType::AttributeList::const_iterator it = groupList.begin(); it != groupList.end(); ++it) { m_recGroupById.insert(std::make_pair(it->first, it->second)); } } std::map::const_iterator it = m_recGroupById.find(id); if (it != m_recGroupById.end()) return it->second; return _empty; } const MythTimerType::AttributeList& MythScheduleHelperNoHelper::GetRulePriorityList() const { if (!m_priorityListInit) { m_priorityListInit = true; m_priorityList.push_back(std::make_pair(0, "0")); } return m_priorityList; } const MythTimerType::AttributeList& MythScheduleHelperNoHelper::GetRuleDupMethodList() const { if (!m_dupMethodListInit) { m_dupMethodListInit = true; m_dupMethodList.push_back(std::make_pair(static_cast(Myth::DM_CheckNone), XBMC->GetLocalizedString(30501))); // Don't match duplicates } return m_dupMethodList; } const MythScheduleHelperNoHelper::RuleExpirationMap& MythScheduleHelperNoHelper::GetRuleExpirationMap() const { if (!m_expirationMapInit) { m_expirationMapInit = true; m_expirationMap.insert(std::make_pair(EXPIRATION_NEVER_EXPIRE_ID, std::make_pair(RuleExpiration(false, 0, false), XBMC->GetLocalizedString(30506)))); // Allow recordings to expire m_expirationMap.insert(std::make_pair(EXPIRATION_ALLOW_EXPIRE_ID, std::make_pair(RuleExpiration(true, 0, false), XBMC->GetLocalizedString(30507)))); // Allow recordings to expire } return m_expirationMap; } const MythTimerType::AttributeList& MythScheduleHelperNoHelper::GetRuleExpirationNameList() const { if (!m_expirationListInit) { m_expirationListInit = true; const RuleExpirationMap& expirationMap = GetRuleExpirationMap(); for (RuleExpirationMap::const_iterator it = expirationMap.begin(); it != expirationMap.end(); ++it) m_expirationList.push_back(std::make_pair(it->first, it->second.second)); } return m_expirationList; } const MythTimerType::AttributeList& MythScheduleHelperNoHelper::GetRuleRecordingGroupList() const { if (!m_recGroupListInit) { m_recGroupListInit = true; m_recGroupList.push_back(std::make_pair(RECGROUP_DFLT_ID, RECGROUP_DFLT_NAME)); } return m_recGroupList; } pvr.mythtv-5.10.15-Leia/src/cppmyth/MythScheduleHelperNoHelper.h000066400000000000000000000106441360567320200245240ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2015 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ #include "MythScheduleManager.h" #define RECGROUP_DFLT_ID 0 #define RECGROUP_DFLT_NAME "Default" #define EXPIRATION_NEVER_EXPIRE_ID 0 #define EXPIRATION_ALLOW_EXPIRE_ID 1 // No helper class MythScheduleHelperNoHelper : public MythScheduleManager::VersionHelper { public: MythScheduleHelperNoHelper(); virtual ~MythScheduleHelperNoHelper(); // Implements VersionHelper virtual MythTimerTypeList GetTimerTypes() const; virtual bool SameTimeslot(const MythRecordingRule& first, const MythRecordingRule& second) const; virtual bool FillTimerEntryWithRule(MythTimerEntry& entry, const MythRecordingRuleNode& node) const; virtual bool FillTimerEntryWithUpcoming(MythTimerEntry& entry, const MythProgramInfo& recording) const; virtual MythRecordingRule NewFromTemplate(const MythEPGInfo& epgInfo); virtual MythRecordingRule NewFromTimer(const MythTimerEntry& entry, bool withTemplate); virtual MythRecordingRule MakeDontRecord(const MythRecordingRule& rule, const MythProgramInfo& recording); virtual MythRecordingRule MakeOverride(const MythRecordingRule& rule, const MythProgramInfo& recording); struct RuleExpiration { bool autoExpire; int maxEpisodes; bool maxNewest; RuleExpiration(bool autoexpire, int maxepisodes, bool newest) : autoExpire(autoexpire), maxEpisodes(maxepisodes), maxNewest(newest) { } }; // Members return default id for setting virtual int GetRulePriorityDefaultId() const { return 0; } virtual int GetRuleDupMethodDefaultId() const { return static_cast(Myth::DM_CheckNone); } virtual int GetRuleExpirationDefaultId() const { return EXPIRATION_NEVER_EXPIRE_ID; } virtual int GetRuleRecordingGroupDefaultId() const { return RECGROUP_DFLT_ID; } // Members convert id to/from data virtual int GetRuleExpirationId(const RuleExpiration& expiration) const; virtual RuleExpiration GetRuleExpiration(int id) const; virtual int GetRuleRecordingGroupId(const std::string& name) const; virtual std::string GetRuleRecordingGroupName(int id) const; protected: typedef std::map > RuleExpirationMap; // Following members aren't thread safe: SHOULD be called by a locked method virtual const MythTimerType::AttributeList& GetRulePriorityList() const; virtual const MythTimerType::AttributeList& GetRuleDupMethodList() const; virtual const RuleExpirationMap& GetRuleExpirationMap() const; virtual const MythTimerType::AttributeList& GetRuleExpirationNameList() const; virtual const MythTimerType::AttributeList& GetRuleRecordingGroupList() const; mutable Myth::OS::CMutex *m_lock; mutable bool m_timerTypeListInit; mutable MythTimerTypeList m_timerTypeList; mutable bool m_priorityListInit; mutable MythTimerType::AttributeList m_priorityList; mutable bool m_dupMethodListInit; mutable MythTimerType::AttributeList m_dupMethodList; mutable bool m_expirationMapInit; mutable RuleExpirationMap m_expirationMap; mutable bool m_expirationListInit; mutable MythTimerType::AttributeList m_expirationList; mutable bool m_expirationByKeyInit; mutable std::map m_expirationByKey; mutable bool m_recGroupListInit; mutable MythTimerType::AttributeList m_recGroupList; mutable bool m_recGroupByNameInit; mutable std::map m_recGroupByName; mutable bool m_recGroupByIdInit; mutable std::map m_recGroupById; }; pvr.mythtv-5.10.15-Leia/src/cppmyth/MythScheduleManager.cpp000066400000000000000000001061351360567320200235560ustar00rootroot00000000000000/* * Copyright (C) 2005-2015 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ #include "MythScheduleManager.h" #include "MythScheduleHelperNoHelper.h" #include "MythScheduleHelper75.h" #include "MythScheduleHelper76.h" #include "MythScheduleHelper85.h" #include "MythScheduleHelper91.h" #include "../client.h" #include "../tools.h" #include "private/cppdef.h" #include "private/os/threads/mutex.h" #include #include #include using namespace ADDON; enum { METHOD_UNKNOWN = 0, METHOD_NOOP = 1, METHOD_UPDATE_INACTIVE, METHOD_CREATE_OVERRIDE, METHOD_CREATE_DONTRECORD, METHOD_DELETE, METHOD_DISCREET_UPDATE, }; static uint_fast32_t hashvalue(uint_fast32_t maxsize, const char *value) { uint_fast32_t h = 0, g; while (*value) { h = (h << 4) + *value++; if ((g = h & 0xF0000000L)) { h ^= g >> 24; } h &= ~g; } return h % maxsize; } /////////////////////////////////////////////////////////////////////////////// //// //// MythRecordingRuleNode //// MythRecordingRuleNode::MythRecordingRuleNode(const MythRecordingRule &rule) : m_rule(rule) , m_mainRule() , m_overrideRules() , m_hasConflict(false) , m_isRecording(false) { } bool MythRecordingRuleNode::IsOverrideRule() const { return (m_rule.Type() == Myth::RT_DontRecord || m_rule.Type() == Myth::RT_OverrideRecord); } MythRecordingRule MythRecordingRuleNode::GetRule() const { return m_rule; } MythRecordingRule MythRecordingRuleNode::GetMainRule() const { if (IsOverrideRule()) return m_mainRule; return m_rule; } bool MythRecordingRuleNode::HasOverrideRules() const { return (!m_overrideRules.empty()); } MythRecordingRuleList MythRecordingRuleNode::GetOverrideRules() const { return m_overrideRules; } bool MythRecordingRuleNode::IsInactiveRule() const { return m_rule.Inactive(); } bool MythRecordingRuleNode::HasConflict() const { return m_hasConflict; } bool MythRecordingRuleNode::IsRecording() const { return m_isRecording; } /////////////////////////////////////////////////////////////////////////////// //// //// MythScheduleManager //// MythScheduleManager::MythScheduleManager(const std::string& server, unsigned protoPort, unsigned wsapiPort, const std::string& wsapiSecurityPin) : m_lock(new Myth::OS::CMutex) , m_control(NULL) , m_protoVersion(0) , m_versionHelper(NULL) , m_rules(NULL) , m_rulesById(NULL) , m_rulesByIndex(NULL) , m_recordings(NULL) , m_recordingIndexByRuleId(NULL) , m_templates(NULL) { m_control = new Myth::Control(server, protoPort, wsapiPort, wsapiSecurityPin); this->Update(); } MythScheduleManager::~MythScheduleManager() { Myth::OS::CLockGuard lock(*m_lock); SAFE_DELETE(m_recordingIndexByRuleId); SAFE_DELETE(m_recordings); SAFE_DELETE(m_templates); SAFE_DELETE(m_rulesByIndex); SAFE_DELETE(m_rulesById); SAFE_DELETE(m_rules); SAFE_DELETE(m_versionHelper); SAFE_DELETE(m_control); delete m_lock; } void MythScheduleManager::Setup() { Myth::OS::CLockGuard lock(*m_lock); int old = m_protoVersion; m_protoVersion = m_control->CheckService(); // On new connection the protocol version could change if (m_protoVersion != old) { SAFE_DELETE(m_versionHelper); if (m_protoVersion >= 91) { m_versionHelper = new MythScheduleHelper91(this, m_control); XBMC->Log(LOG_DEBUG, "Using MythScheduleHelper91 and inherited functions"); } else if (m_protoVersion >= 85) { m_versionHelper = new MythScheduleHelper85(this, m_control); XBMC->Log(LOG_DEBUG, "Using MythScheduleHelper85 and inherited functions"); } else if (m_protoVersion >= 76) { m_versionHelper = new MythScheduleHelper76(this, m_control); XBMC->Log(LOG_DEBUG, "Using MythScheduleHelper76 and inherited functions"); } else if (m_protoVersion >= 75) { m_versionHelper = new MythScheduleHelper75(this, m_control); XBMC->Log(LOG_DEBUG, "Using MythScheduleHelper75 and inherited functions"); } else { m_versionHelper = new MythScheduleHelperNoHelper(); XBMC->Log(LOG_DEBUG, "Using MythScheduleHelperNoHelper"); } } } uint32_t MythScheduleManager::MakeIndex(const MythProgramInfo& recording) { // Recordings must keep same identifier even after refreshing cache (cf Update). // Numeric hash of UID is used to make the constant numeric identifier. // Since client share index range with 'node', I exclusively reserve the range // of values 0x80000000 - 0xFFFFFFFF for indexing of upcoming. uint32_t index = 0x80000000L | (recording.RecordID() << 16) | hashvalue(0xFFFF, recording.UID().c_str()); return index; } uint32_t MythScheduleManager::MakeIndex(const MythRecordingRule& rule) { // The range of values 0x0 - 0x7FFFFFFF is reserved for indexing of rule. return rule.RecordID() & 0x7FFFFFFFL; } unsigned MythScheduleManager::GetUpcomingCount() const { Myth::OS::CLockGuard lock(*m_lock); return (unsigned)m_recordings->size(); } MythTimerEntryList MythScheduleManager::GetTimerEntries() { Myth::OS::CLockGuard lock(*m_lock); MythTimerEntryList entries; for (NodeList::iterator it = m_rules->begin(); it != m_rules->end(); ++it) { if ((*it)->IsOverrideRule()) continue; MythTimerEntryPtr entry = MythTimerEntryPtr(new MythTimerEntry()); if (m_versionHelper->FillTimerEntryWithRule(*entry, **it)) entries.push_back(entry); } for (RecordingList::iterator it = m_recordings->begin(); it != m_recordings->end(); ++it) { MythTimerEntryPtr entry = MythTimerEntryPtr(new MythTimerEntry()); if (m_versionHelper->FillTimerEntryWithUpcoming(*entry, *(it->second))) entries.push_back(entry); } return entries; } MythScheduleManager::MSM_ERROR MythScheduleManager::SubmitTimer(const MythTimerEntry& entry) { Myth::OS::CLockGuard lock(*m_lock); switch (entry.timerType) { case TIMER_TYPE_MANUAL_SEARCH: case TIMER_TYPE_THIS_SHOWING: case TIMER_TYPE_RECORD_ONE: case TIMER_TYPE_RECORD_WEEKLY: case TIMER_TYPE_RECORD_DAILY: case TIMER_TYPE_RECORD_ALL: case TIMER_TYPE_RECORD_SERIES: case TIMER_TYPE_SEARCH_KEYWORD: case TIMER_TYPE_SEARCH_PEOPLE: break; default: return MSM_ERROR_NOT_IMPLEMENTED; } MythRecordingRule rule = m_versionHelper->NewFromTimer(entry, true); MSM_ERROR ret = AddRecordingRule(rule); return ret; } MythScheduleManager::MSM_ERROR MythScheduleManager::UpdateTimer(const MythTimerEntry& entry) { Myth::OS::CLockGuard lock(*m_lock); switch (entry.timerType) { case TIMER_TYPE_UPCOMING: case TIMER_TYPE_RULE_INACTIVE: case TIMER_TYPE_UPCOMING_ALTERNATE: case TIMER_TYPE_UPCOMING_RECORDED: case TIMER_TYPE_UPCOMING_EXPIRED: case TIMER_TYPE_DONT_RECORD: case TIMER_TYPE_OVERRIDE: { MythRecordingRule newrule = m_versionHelper->NewFromTimer(entry, false); return UpdateRecording(entry.entryIndex, newrule); } case TIMER_TYPE_MANUAL_SEARCH: case TIMER_TYPE_THIS_SHOWING: case TIMER_TYPE_RECORD_ONE: case TIMER_TYPE_RECORD_WEEKLY: case TIMER_TYPE_RECORD_DAILY: case TIMER_TYPE_RECORD_ALL: case TIMER_TYPE_RECORD_SERIES: case TIMER_TYPE_SEARCH_KEYWORD: case TIMER_TYPE_SEARCH_PEOPLE: { if (entry.epgCheck && entry.epgInfo.IsNull()) { XBMC->Log(LOG_ERROR, "%s: index %u requires valid EPG info", __FUNCTION__, entry.entryIndex); return MSM_ERROR_NOT_IMPLEMENTED; } MythRecordingRule newrule = m_versionHelper->NewFromTimer(entry, false); return UpdateRecordingRule(entry.entryIndex, newrule); } default: break; } return MSM_ERROR_NOT_IMPLEMENTED; } MythScheduleManager::MSM_ERROR MythScheduleManager::DeleteTimer(const MythTimerEntry& entry) { switch (entry.timerType) { case TIMER_TYPE_UPCOMING: case TIMER_TYPE_RULE_INACTIVE: case TIMER_TYPE_UPCOMING_ALTERNATE: case TIMER_TYPE_UPCOMING_RECORDED: case TIMER_TYPE_UPCOMING_EXPIRED: return DisableRecording(entry.entryIndex); case TIMER_TYPE_DONT_RECORD: case TIMER_TYPE_OVERRIDE: return DeleteModifier(entry.entryIndex); case TIMER_TYPE_THIS_SHOWING: case TIMER_TYPE_MANUAL_SEARCH: return DeleteRecordingRule(entry.entryIndex); case TIMER_TYPE_RECORD_ONE: case TIMER_TYPE_RECORD_WEEKLY: case TIMER_TYPE_RECORD_DAILY: case TIMER_TYPE_RECORD_ALL: case TIMER_TYPE_RECORD_SERIES: case TIMER_TYPE_SEARCH_KEYWORD: case TIMER_TYPE_SEARCH_PEOPLE: return DeleteRecordingRule(entry.entryIndex); default: break; } return MSM_ERROR_NOT_IMPLEMENTED; } MythScheduleManager::MSM_ERROR MythScheduleManager::DeleteModifier(uint32_t index) { Myth::OS::CLockGuard lock(*m_lock); MythScheduledPtr recording = FindUpComingByIndex(index); if (!recording) return MSM_ERROR_FAILED; MythRecordingRuleNodePtr node = FindRuleById(recording->RecordID()); if (node && node->IsOverrideRule()) { XBMC->Log(LOG_DEBUG, "%s: Deleting modifier rule %u relates recording %u", __FUNCTION__, node->m_rule.RecordID(), index); return DeleteRecordingRule(node->m_rule.RecordID()); } return MSM_ERROR_FAILED; } MythScheduleManager::MSM_ERROR MythScheduleManager::DisableRecording(uint32_t index) { Myth::OS::CLockGuard lock(*m_lock); MythScheduledPtr recording = FindUpComingByIndex(index); if (!recording) return MSM_ERROR_FAILED; if (recording->Status() == Myth::RS_INACTIVE) return MSM_ERROR_SUCCESS; MythRecordingRuleNodePtr node = FindRuleById(recording->RecordID()); if (node) { XBMC->Log(LOG_DEBUG, "%s: %u : %s:%s on channel %s program %s", __FUNCTION__, index, recording->Title().c_str(), recording->Subtitle().c_str(), recording->Callsign().c_str(), recording->UID().c_str()); XBMC->Log(LOG_DEBUG, "%s: %u : Found rule %u type %d with recording status %d", __FUNCTION__, index, (unsigned)node->m_rule.RecordID(), (int)node->m_rule.Type(), recording->Status()); int method = METHOD_UNKNOWN; MythRecordingRule handle = node->m_rule.DuplicateRecordingRule(); // Method depends of its rule type switch (node->m_rule.Type()) { case Myth::RT_SingleRecord: switch (recording->Status()) { case Myth::RS_RECORDING: case Myth::RS_TUNING: method = METHOD_DELETE; break; case Myth::RS_PREVIOUS_RECORDING: case Myth::RS_EARLIER_RECORDING: method = METHOD_CREATE_DONTRECORD; break; default: method = METHOD_UPDATE_INACTIVE; break; } break; case Myth::RT_DontRecord: case Myth::RT_OverrideRecord: method = METHOD_DELETE; break; case Myth::RT_OneRecord: case Myth::RT_ChannelRecord: case Myth::RT_AllRecord: case Myth::RT_DailyRecord: case Myth::RT_WeeklyRecord: case Myth::RT_FindDailyRecord: case Myth::RT_FindWeeklyRecord: method = METHOD_CREATE_DONTRECORD; break; default: method = METHOD_UNKNOWN; break; } XBMC->Log(LOG_DEBUG, "%s: %u : Dealing with the problem using method %d", __FUNCTION__, index, method); switch (method) { case METHOD_UPDATE_INACTIVE: handle.SetInactive(true); if (!m_control->UpdateRecordSchedule(*(handle.GetPtr()))) return MSM_ERROR_FAILED; node->m_rule = handle; // sync node return MSM_ERROR_SUCCESS; case METHOD_CREATE_DONTRECORD: handle = m_versionHelper->MakeDontRecord(handle, *recording); XBMC->Log(LOG_DEBUG, "%s: %u : Creating Override for %u (%s: %s) on %u (%s)" , __FUNCTION__, index, (unsigned)handle.ParentID(), handle.Title().c_str(), handle.Subtitle().c_str(), handle.ChannelID(), handle.Callsign().c_str()); // If currently recording then stop it without overriding if (recording->Status() == Myth::RS_RECORDING || recording->Status() == Myth::RS_TUNING) { XBMC->Log(LOG_DEBUG, "%s: Stop recording %s", __FUNCTION__, recording->UID().c_str()); m_control->StopRecording(*(recording->GetPtr())); } else { if (!m_control->AddRecordSchedule(*(handle.GetPtr()))) return MSM_ERROR_FAILED; node->m_overrideRules.push_back(handle); // sync node } return MSM_ERROR_SUCCESS; case METHOD_DELETE: return DeleteRecordingRule(handle.RecordID()); default: return MSM_ERROR_NOT_IMPLEMENTED; } } return MSM_ERROR_FAILED; } MythScheduleManager::MSM_ERROR MythScheduleManager::EnableRecording(uint32_t index) { Myth::OS::CLockGuard lock(*m_lock); MythScheduledPtr recording = FindUpComingByIndex(index); if (!recording) return MSM_ERROR_FAILED; MythRecordingRuleNodePtr node = FindRuleById(recording->RecordID()); if (node) { XBMC->Log(LOG_DEBUG, "%s: %u : %s:%s on channel %s program %s", __FUNCTION__, index, recording->Title().c_str(), recording->Subtitle().c_str(), recording->Callsign().c_str(), recording->UID().c_str()); XBMC->Log(LOG_DEBUG, "%s: %u : Found rule %u type %d disabled by status %d", __FUNCTION__, index, (unsigned)node->m_rule.RecordID(), (int)node->m_rule.Type(), recording->Status()); int method = METHOD_UNKNOWN; MythRecordingRule handle = node->m_rule.DuplicateRecordingRule(); switch (recording->Status()) { case Myth::RS_NEVER_RECORD: case Myth::RS_PREVIOUS_RECORDING: case Myth::RS_EARLIER_RECORDING: case Myth::RS_CURRENT_RECORDING: // Add override to record anyway method = METHOD_CREATE_OVERRIDE; break; default: // Enable parent rule method = METHOD_UPDATE_INACTIVE; break; } XBMC->Log(LOG_DEBUG, "%s: %u : Dealing with the problem using method %d", __FUNCTION__, index, method); switch (method) { case METHOD_UPDATE_INACTIVE: handle.SetInactive(false); if (!m_control->UpdateRecordSchedule(*(handle.GetPtr()))) return MSM_ERROR_FAILED; node->m_rule = handle; // sync node return MSM_ERROR_SUCCESS; case METHOD_CREATE_OVERRIDE: handle = m_versionHelper->MakeOverride(handle, *recording); XBMC->Log(LOG_DEBUG, "%s: %u : Creating Override for %u (%s:%s) on %u (%s)" , __FUNCTION__, index, (unsigned)handle.ParentID(), handle.Title().c_str(), handle.Subtitle().c_str(), handle.ChannelID(), handle.Callsign().c_str()); if (!m_control->AddRecordSchedule(*(handle.GetPtr()))) return MSM_ERROR_FAILED; node->m_overrideRules.push_back(handle); // sync node return MSM_ERROR_SUCCESS; default: return MSM_ERROR_NOT_IMPLEMENTED; } } return MSM_ERROR_FAILED; } MythScheduleManager::MSM_ERROR MythScheduleManager::UpdateRecording(uint32_t index, MythRecordingRule& newrule) { Myth::OS::CLockGuard lock(*m_lock); if (newrule.Type() == Myth::RT_UNKNOWN) return MSM_ERROR_FAILED; MythScheduledPtr recording = FindUpComingByIndex(index); if (!recording) return MSM_ERROR_FAILED; MythRecordingRuleNodePtr node = FindRuleById(recording->RecordID()); if (node) { XBMC->Log(LOG_DEBUG, "%s: %u : Found rule %u type %d and recording status %d", __FUNCTION__, index, (unsigned)node->m_rule.RecordID(), (int)node->m_rule.Type(), recording->Status()); // Prior handle inactive if (!node->m_rule.Inactive() && newrule.Inactive()) { XBMC->Log(LOG_DEBUG, "%s: Disable recording", __FUNCTION__); return DisableRecording(index); } int method = METHOD_UNKNOWN; MythRecordingRule handle = node->m_rule.DuplicateRecordingRule(); switch (node->m_rule.Type()) { case Myth::RT_NotRecording: case Myth::RT_TemplateRecord: method = METHOD_UNKNOWN; break; case Myth::RT_DontRecord: method = METHOD_NOOP; break; case Myth::RT_OverrideRecord: method = METHOD_DISCREET_UPDATE; handle.SetInactive(newrule.Inactive()); handle.SetPriority(newrule.Priority()); handle.SetAutoExpire(newrule.AutoExpire()); handle.SetStartOffset(newrule.StartOffset()); handle.SetEndOffset(newrule.EndOffset()); handle.SetRecordingGroup(newrule.RecordingGroup()); break; case Myth::RT_SingleRecord: switch (recording->Status()) { case Myth::RS_RECORDING: case Myth::RS_TUNING: method = METHOD_DISCREET_UPDATE; handle.SetEndOffset(newrule.EndOffset()); break; case Myth::RS_NEVER_RECORD: case Myth::RS_PREVIOUS_RECORDING: case Myth::RS_EARLIER_RECORDING: case Myth::RS_CURRENT_RECORDING: // Add override to record anyway method = METHOD_CREATE_OVERRIDE; handle.SetPriority(newrule.Priority()); handle.SetAutoExpire(newrule.AutoExpire()); handle.SetStartOffset(newrule.StartOffset()); handle.SetEndOffset(newrule.EndOffset()); handle.SetRecordingGroup(newrule.RecordingGroup()); break; default: method = METHOD_DISCREET_UPDATE; handle.SetInactive(newrule.Inactive()); handle.SetPriority(newrule.Priority()); handle.SetAutoExpire(newrule.AutoExpire()); handle.SetStartOffset(newrule.StartOffset()); handle.SetEndOffset(newrule.EndOffset()); handle.SetRecordingGroup(newrule.RecordingGroup()); break; } break; default: method = METHOD_CREATE_OVERRIDE; handle.SetPriority(newrule.Priority()); handle.SetAutoExpire(newrule.AutoExpire()); handle.SetStartOffset(newrule.StartOffset()); handle.SetEndOffset(newrule.EndOffset()); handle.SetRecordingGroup(newrule.RecordingGroup()); break; } XBMC->Log(LOG_DEBUG, "%s: %u : Dealing with the problem using method %d", __FUNCTION__, index, method); switch (method) { case METHOD_NOOP: return MSM_ERROR_SUCCESS; case METHOD_DISCREET_UPDATE: if (!m_control->UpdateRecordSchedule(*(handle.GetPtr()))) return MSM_ERROR_FAILED; node->m_rule = handle; // sync node return MSM_ERROR_SUCCESS; case METHOD_CREATE_OVERRIDE: handle = m_versionHelper->MakeOverride(handle, *recording); XBMC->Log(LOG_DEBUG, "%s: %u : Creating Override for %u (%s: %s) on %u (%s)" , __FUNCTION__, index, (unsigned)node->m_rule.RecordID(), node->m_rule.Title().c_str(), node->m_rule.Subtitle().c_str(), recording->ChannelID(), recording->Callsign().c_str()); if (!m_control->AddRecordSchedule(*(handle.GetPtr()))) return MSM_ERROR_FAILED; node->m_overrideRules.push_back(handle); // sync node return MSM_ERROR_SUCCESS; default: return MSM_ERROR_NOT_IMPLEMENTED; } } return MSM_ERROR_FAILED; } MythScheduleManager::MSM_ERROR MythScheduleManager::AddRecordingRule(MythRecordingRule &rule) { if (rule.Type() == Myth::RT_UNKNOWN || rule.Type() == Myth::RT_NotRecording) return MSM_ERROR_FAILED; if (!m_control->AddRecordSchedule(*(rule.GetPtr()))) return MSM_ERROR_FAILED; return MSM_ERROR_SUCCESS; } MythScheduleManager::MSM_ERROR MythScheduleManager::DeleteRecordingRule(uint32_t index) { Myth::OS::CLockGuard lock(*m_lock); MythRecordingRuleNodePtr node = FindRuleByIndex(index); if (node) { XBMC->Log(LOG_DEBUG, "%s: Found rule %u type %d", __FUNCTION__, (unsigned)node->m_rule.RecordID(), (int)node->m_rule.Type()); // Delete overrides and their related recording if (node->HasOverrideRules()) { for (MythRecordingRuleList::iterator ito = node->m_overrideRules.begin(); ito != node->m_overrideRules.end(); ++ito) { XBMC->Log(LOG_DEBUG, "%s: Found override rule %u type %d", __FUNCTION__, (unsigned)ito->RecordID(), (int)ito->Type()); MythScheduleList rec = FindUpComingByRuleId(ito->RecordID()); for (MythScheduleList::iterator itr = rec.begin(); itr != rec.end(); ++itr) { XBMC->Log(LOG_DEBUG, "%s: Found overriden recording %s status %d", __FUNCTION__, itr->second->UID().c_str(), itr->second->Status()); if (itr->second->Status() == Myth::RS_RECORDING || itr->second->Status() == Myth::RS_TUNING) { XBMC->Log(LOG_DEBUG, "%s: Stop recording %s", __FUNCTION__, itr->second->UID().c_str()); m_control->StopRecording(*(itr->second->GetPtr())); } } XBMC->Log(LOG_DEBUG, "%s: Deleting recording rule %u (modifier of rule %u)", __FUNCTION__, (unsigned)ito->RecordID(), (unsigned)node->m_rule.RecordID()); if (!m_control->RemoveRecordSchedule(ito->RecordID())) XBMC->Log(LOG_ERROR, "%s: Deleting recording rule failed", __FUNCTION__); } } // Delete related recordings MythScheduleList rec = FindUpComingByRuleId(node->m_rule.RecordID()); for (MythScheduleList::iterator itr = rec.begin(); itr != rec.end(); ++itr) { XBMC->Log(LOG_DEBUG, "%s: Found recording %s status %d", __FUNCTION__, itr->second->UID().c_str(), itr->second->Status()); if (itr->second->Status() == Myth::RS_RECORDING || itr->second->Status() == Myth::RS_TUNING) { XBMC->Log(LOG_DEBUG, "%s: Stop recording %s", __FUNCTION__, itr->second->UID().c_str()); m_control->StopRecording(*(itr->second->GetPtr())); } } // Delete rule XBMC->Log(LOG_DEBUG, "%s: Deleting recording rule %u", __FUNCTION__, node->m_rule.RecordID()); if (!m_control->RemoveRecordSchedule(node->m_rule.RecordID())) XBMC->Log(LOG_ERROR, "%s: Deleting recording rule failed", __FUNCTION__); } // Another client could delete the rule at the same time. Therefore always SUCCESS even if database delete fails. return MSM_ERROR_SUCCESS; } MythScheduleManager::MSM_ERROR MythScheduleManager::UpdateRecordingRule(uint32_t index, MythRecordingRule& newrule) { Myth::OS::CLockGuard lock(*m_lock); if (newrule.Type() == Myth::RT_UNKNOWN) return MSM_ERROR_FAILED; MythRecordingRuleNodePtr node = FindRuleByIndex(index); if (node) { XBMC->Log(LOG_DEBUG, "%s: Found rule %u type %d", __FUNCTION__, (unsigned)node->m_rule.RecordID(), (int)node->m_rule.Type()); int method = METHOD_UNKNOWN; MythRecordingRule handle = node->m_rule.DuplicateRecordingRule(); switch (node->m_rule.Type()) { case Myth::RT_NotRecording: case Myth::RT_TemplateRecord: method = METHOD_UNKNOWN; break; case Myth::RT_DontRecord: method = METHOD_NOOP; break; case Myth::RT_OverrideRecord: method = METHOD_DISCREET_UPDATE; handle.SetInactive(newrule.Inactive()); handle.SetPriority(newrule.Priority()); handle.SetAutoExpire(newrule.AutoExpire()); handle.SetStartOffset(newrule.StartOffset()); handle.SetEndOffset(newrule.EndOffset()); handle.SetRecordingGroup(newrule.RecordingGroup()); break; case Myth::RT_SingleRecord: { MythScheduleList recordings = FindUpComingByRuleId(handle.RecordID()); MythScheduleList::const_reverse_iterator it = recordings.rbegin(); if (it != recordings.rend()) return UpdateRecording(MakeIndex(*(it->second)), newrule); method = METHOD_UNKNOWN; } break; default: method = METHOD_DISCREET_UPDATE; switch (node->m_rule.SearchType()) { case Myth::ST_NoSearch: case Myth::ST_ManualSearch: break; default: handle.SetDescription(newrule.Description()); } handle.SetInactive(newrule.Inactive()); handle.SetPriority(newrule.Priority()); handle.SetAutoExpire(newrule.AutoExpire()); handle.SetMaxEpisodes(newrule.MaxEpisodes()); handle.SetNewExpiresOldRecord(newrule.NewExpiresOldRecord()); handle.SetStartOffset(newrule.StartOffset()); handle.SetEndOffset(newrule.EndOffset()); handle.SetRecordingGroup(newrule.RecordingGroup()); handle.SetCheckDuplicatesInType(newrule.CheckDuplicatesInType()); handle.SetDuplicateControlMethod(newrule.DuplicateControlMethod()); } XBMC->Log(LOG_DEBUG, "%s: Dealing with the problem using method %d", __FUNCTION__, method); switch (method) { case METHOD_NOOP: return MSM_ERROR_SUCCESS; case METHOD_DISCREET_UPDATE: if (!m_control->UpdateRecordSchedule(*(handle.GetPtr()))) return MSM_ERROR_FAILED; node->m_rule = handle; // sync node return MSM_ERROR_SUCCESS; default: return MSM_ERROR_NOT_IMPLEMENTED; } } return MSM_ERROR_FAILED; } MythRecordingRuleNodePtr MythScheduleManager::FindRuleById(uint32_t recordid) const { Myth::OS::CLockGuard lock(*m_lock); NodeById::const_iterator it = m_rulesById->find(recordid); if (it != m_rulesById->end()) return it->second; return MythRecordingRuleNodePtr(); } MythRecordingRuleNodePtr MythScheduleManager::FindRuleByIndex(uint32_t index) const { Myth::OS::CLockGuard lock(*m_lock); NodeByIndex::const_iterator it = m_rulesByIndex->find(index); if (it != m_rulesByIndex->end()) return it->second; return MythRecordingRuleNodePtr(); } MythScheduleList MythScheduleManager::FindUpComingByRuleId(uint32_t recordid) const { Myth::OS::CLockGuard lock(*m_lock); MythScheduleList found; std::pair range = m_recordingIndexByRuleId->equal_range(recordid); if (range.first != m_recordingIndexByRuleId->end()) { for (RecordingIndexByRuleId::const_iterator it = range.first; it != range.second; ++it) { RecordingList::const_iterator recordingIt = m_recordings->find(it->second); if (recordingIt != m_recordings->end()) found.push_back(std::make_pair(it->second, recordingIt->second)); } } return found; } MythScheduledPtr MythScheduleManager::FindUpComingByIndex(uint32_t index) const { Myth::OS::CLockGuard lock(*m_lock); RecordingList::const_iterator it = m_recordings->find(index); if (it != m_recordings->end()) return it->second; return MythScheduledPtr(); } bool MythScheduleManager::OpenControl() { if (m_control) return m_control->Open(); return false; } void MythScheduleManager::CloseControl() { if (m_control) m_control->Close(); } void MythScheduleManager::Update() { // Setup VersionHelper for the new set this->Setup(); // Allocate containers NodeList* new_rules = new NodeList; NodeById* new_rulesById = new NodeById; NodeByIndex* new_rulesByIndex = new NodeByIndex; MythRecordingRuleList* new_templates = new MythRecordingRuleList; RecordingList* new_recordings = new RecordingList; RecordingIndexByRuleId* new_recordingIndexByRuleId = new RecordingIndexByRuleId; Myth::RecordScheduleListPtr records = m_control->GetRecordScheduleList(); for (Myth::RecordScheduleList::iterator it = records->begin(); it != records->end(); ++it) { MythRecordingRule rule(*it); if (rule.Type() == Myth::RT_TemplateRecord) { new_templates->push_back(rule); } else { MythRecordingRuleNodePtr node = MythRecordingRuleNodePtr(new MythRecordingRuleNode(rule)); new_rules->push_back(node); new_rulesById->insert(NodeById::value_type(rule.RecordID(), node)); new_rulesByIndex->insert(NodeByIndex::value_type(MakeIndex(rule), node)); } } for (NodeList::iterator it = new_rules->begin(); it != new_rules->end(); ++it) { // Is override rule ? Then find main rule and link to it if ((*it)->IsOverrideRule()) { // First check parentid. Then fallback searching the same timeslot NodeById::iterator itp = new_rulesById->find((*it)->m_rule.ParentID()); if (itp != new_rulesById->end() && (*it)->m_rule.ParentID() != (*it)->m_rule.RecordID()) { itp->second->m_overrideRules.push_back((*it)->m_rule); (*it)->m_mainRule = itp->second->m_rule; } else { for (NodeList::iterator itm = new_rules->begin(); itm != new_rules->end(); ++itm) if (!(*itm)->IsOverrideRule() && m_versionHelper->SameTimeslot((*it)->m_rule, (*itm)->m_rule)) { (*itm)->m_overrideRules.push_back((*it)->m_rule); (*it)->m_mainRule = (*itm)->m_rule; } } } } // Add upcoming recordings Myth::ProgramListPtr recordings = m_control->GetUpcomingList(); for (Myth::ProgramList::iterator it = recordings->begin(); it != recordings->end(); ++it) { MythScheduledPtr scheduled = MythScheduledPtr(new MythProgramInfo(*it)); uint32_t index = MakeIndex(*scheduled); (*new_recordings)[index] = scheduled; // Fix 0.27: Override by last upcoming with this index new_recordingIndexByRuleId->insert(RecordingIndexByRuleId::value_type(scheduled->RecordID(), index)); // Update summary status of related rule switch (scheduled->Status()) { case Myth::RS_RECORDING: case Myth::RS_TUNING: { NodeById::const_iterator rit = new_rulesById->find(scheduled->RecordID()); if (rit != new_rulesById->end()) rit->second->m_isRecording = true; break; } case Myth::RS_CONFLICT: { NodeById::const_iterator rit = new_rulesById->find(scheduled->RecordID()); if (rit != new_rulesById->end()) rit->second->m_hasConflict = true; break; } default: break; } } if (g_bExtraDebug) { for (NodeList::iterator it = new_rules->begin(); it != new_rules->end(); ++it) XBMC->Log(LOG_DEBUG, "%s: Rule node - recordid: %u, parentid: %u, type: %d, overriden: %s", __FUNCTION__, (unsigned)(*it)->m_rule.RecordID(), (unsigned)(*it)->m_rule.ParentID(), (int)(*it)->m_rule.Type(), ((*it)->HasOverrideRules() ? "Yes" : "No")); for (RecordingList::iterator it = new_recordings->begin(); it != new_recordings->end(); ++it) XBMC->Log(LOG_DEBUG, "%s: Recording - recordid: %u, index: %u, status: %d, title: %s", __FUNCTION__, (unsigned)it->second->RecordID(), (unsigned)it->first, it->second->Status(), it->second->Title().c_str()); } { Myth::OS::CLockGuard lock(*m_lock); SAFE_DELETE(m_recordingIndexByRuleId); SAFE_DELETE(m_recordings); SAFE_DELETE(m_templates); SAFE_DELETE(m_rulesByIndex); SAFE_DELETE(m_rulesById); SAFE_DELETE(m_rules); m_rules = new_rules; m_rulesById = new_rulesById; m_rulesByIndex = new_rulesByIndex; m_templates = new_templates; m_recordings = new_recordings; m_recordingIndexByRuleId = new_recordingIndexByRuleId; } } MythTimerTypeList MythScheduleManager::GetTimerTypes() { Myth::OS::CLockGuard lock(*m_lock); return m_versionHelper->GetTimerTypes(); } bool MythScheduleManager::FillTimerEntryWithRule(MythTimerEntry& entry, const MythRecordingRuleNode& node) const { Myth::OS::CLockGuard lock(*m_lock); return m_versionHelper->FillTimerEntryWithRule(entry, node); } bool MythScheduleManager::FillTimerEntryWithUpcoming(MythTimerEntry& entry, const MythProgramInfo& recording) const { Myth::OS::CLockGuard lock(*m_lock); return m_versionHelper->FillTimerEntryWithUpcoming(entry, recording); } MythRecordingRule MythScheduleManager::NewFromTimer(const MythTimerEntry& entry, bool withTemplate) { Myth::OS::CLockGuard lock(*m_lock); return m_versionHelper->NewFromTimer(entry, withTemplate); } MythRecordingRuleList MythScheduleManager::GetTemplateRules() const { Myth::OS::CLockGuard lock(*m_lock); return *m_templates; } bool MythScheduleManager::ToggleShowNotRecording() { g_bShowNotRecording ^= true; return g_bShowNotRecording; } bool MythScheduleManager::ShowNotRecording() { return g_bShowNotRecording; } /////////////////////////////////////////////////////////////////////////////// //// //// MythTimerType //// MythTimerType::MythTimerType(TimerTypeId id, unsigned attributes, const std::string& description, const AttributeList& priorityList, int priorityDefault, const AttributeList& dupMethodList, int dupMethodDefault, const AttributeList& expirationList, int expirationDefault, const AttributeList& recGroupList, int recGroupDefault) : m_id(id) , m_attributes(attributes) , m_description(description) , m_priorityList(priorityList) , m_priorityDefault(priorityDefault) , m_dupMethodList(dupMethodList) , m_dupMethodDefault(dupMethodDefault) , m_expirationList(expirationList) , m_expirationDefault(expirationDefault) , m_recGroupList(recGroupList) , m_recGroupDefault(recGroupDefault) { } void MythTimerType::Fill(PVR_TIMER_TYPE* type) const { memset(type, 0, sizeof(PVR_TIMER_TYPE)); type->iId = m_id; type->iAttributes = m_attributes; PVR_STRCPY(type->strDescription, m_description.c_str()); // Fill priorities type->iPrioritiesSize = m_priorityList.size(); assert(type->iPrioritiesSize <= PVR_ADDON_TIMERTYPE_VALUES_ARRAY_SIZE); unsigned index = 0; for (AttributeList::const_iterator it = m_priorityList.begin(); it != m_priorityList.end(); ++it, ++index) { type->priorities[index].iValue = it->first; PVR_STRCPY(type->priorities[index].strDescription, it->second.c_str()); } type->iPrioritiesDefault = m_priorityDefault; // Fill duplicate methodes type->iPreventDuplicateEpisodesSize = m_dupMethodList.size(); assert(type->iPreventDuplicateEpisodesSize <= PVR_ADDON_TIMERTYPE_VALUES_ARRAY_SIZE); index = 0; for (AttributeList::const_iterator it = m_dupMethodList.begin(); it != m_dupMethodList.end(); ++it, ++index) { type->preventDuplicateEpisodes[index].iValue = it->first; PVR_STRCPY(type->preventDuplicateEpisodes[index].strDescription, it->second.c_str()); } type->iPreventDuplicateEpisodesDefault = m_dupMethodDefault; // Fill expirations type->iLifetimesSize = m_expirationList.size(); assert(type->iLifetimesSize <= PVR_ADDON_TIMERTYPE_VALUES_ARRAY_SIZE); index = 0; for (AttributeList::const_iterator it = m_expirationList.begin(); it != m_expirationList.end(); ++it, ++index) { type->lifetimes[index].iValue = it->first; PVR_STRCPY(type->lifetimes[index].strDescription, it->second.c_str()); } type->iLifetimesDefault = m_expirationDefault; // Fill recording groups type->iRecordingGroupSize = m_recGroupList.size(); assert(type->iRecordingGroupSize <= PVR_ADDON_TIMERTYPE_VALUES_ARRAY_SIZE); index = 0; for (AttributeList::const_iterator it = m_recGroupList.begin(); it != m_recGroupList.end(); ++it, ++index) { type->recordingGroup[index].iValue = it->first; PVR_STRCPY(type->recordingGroup[index].strDescription, it->second.c_str()); } type->iRecordingGroupDefault = m_recGroupDefault; } pvr.mythtv-5.10.15-Leia/src/cppmyth/MythScheduleManager.h000066400000000000000000000220771360567320200232250ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2015 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ #include #include "MythRecordingRule.h" #include "MythProgramInfo.h" #include "MythEPGInfo.h" #include "MythChannel.h" #include "MythPrivate.h" #include #include #include #include typedef enum { TIMER_TYPE_MANUAL_SEARCH = 1, // Manual record TIMER_TYPE_THIS_SHOWING = 2, // Record This showing TIMER_TYPE_RECORD_ONE, // Record one showing TIMER_TYPE_RECORD_WEEKLY, // Record one showing every week TIMER_TYPE_RECORD_DAILY, // Record one showing every day TIMER_TYPE_RECORD_ALL, // Record all showings TIMER_TYPE_RECORD_SERIES, // Record series TIMER_TYPE_SEARCH_KEYWORD, // Search keyword TIMER_TYPE_SEARCH_PEOPLE, // Search people // Keep last TIMER_TYPE_UPCOMING, // Upcoming TIMER_TYPE_RULE_INACTIVE, // Parent Rule is disable TIMER_TYPE_UPCOMING_ALTERNATE, // Upcoming will record at another time TIMER_TYPE_UPCOMING_RECORDED, // Upcoming currently recorded TIMER_TYPE_UPCOMING_EXPIRED, // Upcoming previously recorded and expired TIMER_TYPE_OVERRIDE, // Override TIMER_TYPE_DONT_RECORD, // Don't record TIMER_TYPE_UNHANDLED, // Unhandled rule TIMER_TYPE_UPCOMING_MANUAL, // Upcoming manual TIMER_TYPE_ZOMBIE, // Zombie } TimerTypeId; struct MythTimerEntry { bool isRule; bool isInactive; TimerTypeId timerType; bool epgCheck; MythEPGInfo epgInfo; uint32_t chanid; std::string callsign; time_t startTime; time_t endTime; std::string epgSearch; std::string title; std::string description; std::string category; int startOffset; int endOffset; int priority; Myth::DM_t dupMethod; int expiration; bool firstShowing; unsigned recordingGroup; uint32_t entryIndex; uint32_t parentIndex; Myth::RS_t recordingStatus; MythTimerEntry() : isRule(false) , isInactive(false) , timerType(TIMER_TYPE_UNHANDLED) , epgCheck(false) , chanid(0) , startTime(0) , endTime(0) , startOffset(0) , endOffset(0) , priority(0) , dupMethod(Myth::DM_CheckNone) , expiration(0) , firstShowing(false) , recordingGroup(0) , entryIndex(0) , parentIndex(0) , recordingStatus(Myth::RS_UNKNOWN) { } bool HasChannel() const { return (chanid > 0 && !callsign.empty() ? true : false); } bool HasTimeSlot() const { return (startTime > 0 && endTime >= startTime ? true : false); } }; class MythRecordingRuleNode; typedef MYTH_SHARED_PTR MythRecordingRuleNodePtr; typedef std::vector MythRecordingRuleList; typedef MYTH_SHARED_PTR MythScheduledPtr; typedef std::vector > MythScheduleList; typedef MYTH_SHARED_PTR MythTimerEntryPtr; typedef std::vector MythTimerEntryList; class MythTimerType; typedef MYTH_SHARED_PTR MythTimerTypePtr; typedef std::vector MythTimerTypeList; class MythRecordingRuleNode { public: friend class MythScheduleManager; MythRecordingRuleNode(const MythRecordingRule &rule); bool IsOverrideRule() const; MythRecordingRule GetRule() const; MythRecordingRule GetMainRule() const; bool HasOverrideRules() const; MythRecordingRuleList GetOverrideRules() const; bool IsInactiveRule() const; bool HasConflict() const; bool IsRecording() const; private: MythRecordingRule m_rule; MythRecordingRule m_mainRule; MythRecordingRuleList m_overrideRules; bool m_hasConflict; //!< @brief Has upcoming recording in conflict status bool m_isRecording; //!< @brief Is currently recording }; class MythScheduleManager { public: enum MSM_ERROR { MSM_ERROR_FAILED = -1, MSM_ERROR_NOT_IMPLEMENTED = 0, MSM_ERROR_SUCCESS = 1 }; MythScheduleManager(const std::string& server, unsigned protoPort, unsigned wsapiPort, const std::string& wsapiSecurityPin); ~MythScheduleManager(); // Called by GetTimers unsigned GetUpcomingCount() const; MythTimerEntryList GetTimerEntries(); MSM_ERROR SubmitTimer(const MythTimerEntry& entry); MSM_ERROR UpdateTimer(const MythTimerEntry& entry); MSM_ERROR DeleteTimer(const MythTimerEntry& entry); MSM_ERROR DeleteModifier(uint32_t index); MSM_ERROR DisableRecording(uint32_t index); MSM_ERROR EnableRecording(uint32_t index); MSM_ERROR UpdateRecording(uint32_t index, MythRecordingRule &newrule); // Called by AddTimer MSM_ERROR AddRecordingRule(MythRecordingRule &rule); MSM_ERROR DeleteRecordingRule(uint32_t index); MSM_ERROR UpdateRecordingRule(uint32_t index, MythRecordingRule &newrule); MythRecordingRuleNodePtr FindRuleById(uint32_t recordid) const; MythRecordingRuleNodePtr FindRuleByIndex(uint32_t index) const; MythScheduleList FindUpComingByRuleId(uint32_t recordid) const; MythScheduledPtr FindUpComingByIndex(uint32_t index) const; bool OpenControl(); void CloseControl(); void Update(); MythTimerTypeList GetTimerTypes(); bool FillTimerEntryWithRule(MythTimerEntry& entry, const MythRecordingRuleNode& node) const; bool FillTimerEntryWithUpcoming(MythTimerEntry& entry, const MythProgramInfo& recording) const; MythRecordingRule NewFromTimer(const MythTimerEntry& entry, bool withTemplate); MythRecordingRuleList GetTemplateRules() const; bool ToggleShowNotRecording(); bool ShowNotRecording(); class VersionHelper { public: friend class MythScheduleManager; VersionHelper() { } virtual ~VersionHelper() { } virtual MythTimerTypeList GetTimerTypes() const = 0; virtual bool SameTimeslot(const MythRecordingRule& first, const MythRecordingRule& second) const = 0; virtual bool FillTimerEntryWithRule(MythTimerEntry& entry, const MythRecordingRuleNode& node) const = 0; virtual bool FillTimerEntryWithUpcoming(MythTimerEntry& entry, const MythProgramInfo& recording) const = 0; virtual MythRecordingRule NewFromTemplate(const MythEPGInfo& epgInfo) = 0; virtual MythRecordingRule NewFromTimer(const MythTimerEntry& entry, bool withTemplate) = 0; virtual MythRecordingRule MakeDontRecord(const MythRecordingRule& rule, const MythProgramInfo& recording) = 0; virtual MythRecordingRule MakeOverride(const MythRecordingRule& rule, const MythProgramInfo& recording) = 0; }; static uint32_t MakeIndex(const MythProgramInfo& recording); static uint32_t MakeIndex(const MythRecordingRule& rule); private: mutable Myth::OS::CMutex *m_lock; Myth::Control *m_control; int m_protoVersion; VersionHelper *m_versionHelper; void Setup(); // The list of rule nodes typedef std::list NodeList; // To find a rule node by its key (recordId) typedef std::map NodeById; // To find a rule node by its key (recordId) typedef std::map NodeByIndex; // Store and find up coming recordings by index typedef std::map RecordingList; // To find all indexes of schedule by rule Id : pair < Rule Id , index of schedule > typedef std::multimap RecordingIndexByRuleId; NodeList* m_rules; NodeById* m_rulesById; NodeByIndex* m_rulesByIndex; RecordingList* m_recordings; RecordingIndexByRuleId* m_recordingIndexByRuleId; MythRecordingRuleList* m_templates; }; /////////////////////////////////////////////////////////////////////////////// //// //// MythTimerType //// class MythTimerType { public: typedef std::vector > AttributeList; MythTimerType(TimerTypeId id, unsigned attributes, const std::string& description, const AttributeList& priorityList, int priorityDefault, const AttributeList& dupMethodList, int dupMethodDefault, const AttributeList& expirationList, int expirationDefault, const AttributeList& recGroupList, int recGroupDefault); virtual ~MythTimerType() {} void Fill(PVR_TIMER_TYPE* type) const; private: TimerTypeId m_id; unsigned m_attributes; std::string m_description; AttributeList m_priorityList; int m_priorityDefault; AttributeList m_dupMethodList; int m_dupMethodDefault; AttributeList m_expirationList; int m_expirationDefault; AttributeList m_recGroupList; int m_recGroupDefault; }; pvr.mythtv-5.10.15-Leia/src/demuxer/000077500000000000000000000000001360567320200171405ustar00rootroot00000000000000pvr.mythtv-5.10.15-Leia/src/demuxer/ES_AAC.cpp000066400000000000000000000147201360567320200206230ustar00rootroot00000000000000/* * Copyright (C) 2005-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ #include "ES_AAC.h" #include "bitstream.h" using namespace TSDemux; static int aac_sample_rates[16] = { 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350, 0, 0, 0 }; ES_AAC::ES_AAC(uint16_t pes_pid) : ElementaryStream(pes_pid) { m_Configured = false; m_FrameLengthType = 0; m_PTS = 0; m_DTS = 0; m_FrameSize = 0; m_SampleRate = 0; m_Channels = 0; m_BitRate = 0; m_AudioMuxVersion_A = 0; es_alloc_init = 1920*2; Reset(); } ES_AAC::~ES_AAC() { } void ES_AAC::Parse(STREAM_PKT* pkt) { int p = es_parsed; int l; while ((l = es_len - p) > 8) { if (FindHeaders(es_buf + p, l) < 0) break; p++; } es_parsed = p; if (es_found_frame && l >= m_FrameSize) { bool streamChange = SetAudioInformation(m_Channels, m_SampleRate, m_BitRate, 0, 0); pkt->pid = pid; pkt->data = &es_buf[p]; pkt->size = m_FrameSize; pkt->duration = 1024 * 90000 / (!m_SampleRate ? aac_sample_rates[4] : m_SampleRate); pkt->dts = m_DTS; pkt->pts = m_PTS; pkt->streamChange = streamChange; es_consumed = p + m_FrameSize; es_parsed = es_consumed; es_found_frame = false; } } int ES_AAC::FindHeaders(uint8_t *buf, int buf_size) { if (es_found_frame) return -1; uint8_t *buf_ptr = buf; if (stream_type == STREAM_TYPE_AUDIO_AAC) { if (buf_ptr[0] == 0xFF && (buf_ptr[1] & 0xF0) == 0xF0) stream_type = STREAM_TYPE_AUDIO_AAC_ADTS; else if (buf_ptr[0] == 0x56 && (buf_ptr[1] & 0xE0) == 0xE0) stream_type = STREAM_TYPE_AUDIO_AAC_LATM; } // STREAM_TYPE_AUDIO_AAC_LATM if (stream_type == STREAM_TYPE_AUDIO_AAC_LATM) { if ((buf_ptr[0] == 0x56 && (buf_ptr[1] & 0xE0) == 0xE0)) { // TODO if (buf_size < 16) return -1; CBitstream bs(buf_ptr, 16 * 8); bs.skipBits(11); m_FrameSize = bs.readBits(13) + 3; if (!ParseLATMAudioMuxElement(&bs)) return 0; es_found_frame = true; m_DTS = c_pts; m_PTS = c_pts; c_pts += 90000 * 1024 / (!m_SampleRate ? aac_sample_rates[4] : m_SampleRate); return -1; } } // STREAM_TYPE_AUDIO_AAC_ADTS else if (stream_type == STREAM_TYPE_AUDIO_AAC_ADTS) { if(buf_ptr[0] == 0xFF && (buf_ptr[1] & 0xF0) == 0xF0) { // need at least 7 bytes for header if (buf_size < 7) return -1; CBitstream bs(buf_ptr, 9 * 8); bs.skipBits(15); // check if CRC is present, means header is 9 byte long int noCrc = bs.readBits(1); if (!noCrc && (buf_size < 9)) return -1; bs.skipBits(2); // profile int SampleRateIndex = bs.readBits(4); bs.skipBits(1); // private m_Channels = bs.readBits(3); bs.skipBits(4); m_FrameSize = bs.readBits(13); m_SampleRate = aac_sample_rates[SampleRateIndex & 0x0F]; es_found_frame = true; m_DTS = c_pts; m_PTS = c_pts; c_pts += 90000 * 1024 / (!m_SampleRate ? aac_sample_rates[4] : m_SampleRate); return -1; } } return 0; } bool ES_AAC::ParseLATMAudioMuxElement(CBitstream *bs) { if (!bs->readBits1()) ReadStreamMuxConfig(bs); if (!m_Configured) return false; return true; } void ES_AAC::ReadStreamMuxConfig(CBitstream *bs) { int AudioMuxVersion = bs->readBits(1); m_AudioMuxVersion_A = 0; if (AudioMuxVersion) // audioMuxVersion m_AudioMuxVersion_A = bs->readBits(1); if(m_AudioMuxVersion_A) return; if (AudioMuxVersion) LATMGetValue(bs); // taraFullness bs->skipBits(1); // allStreamSameTimeFraming = 1 bs->skipBits(6); // numSubFrames = 0 bs->skipBits(4); // numPrograms = 0 // for each program (which there is only on in DVB) bs->skipBits(3); // numLayer = 0 // for each layer (which there is only on in DVB) if (!AudioMuxVersion) ReadAudioSpecificConfig(bs); else return; // these are not needed... perhaps m_FrameLengthType = bs->readBits(3); switch (m_FrameLengthType) { case 0: bs->readBits(8); break; case 1: bs->readBits(9); break; case 3: case 4: case 5: bs->readBits(6); // celp_table_index break; case 6: case 7: bs->readBits(1); // hvxc_table_index break; } if (bs->readBits(1)) { // other data? int esc; do { esc = bs->readBits(1); bs->skipBits(8); } while (esc); } if (bs->readBits(1)) // crc present? bs->skipBits(8); // config_crc m_Configured = true; } void ES_AAC::ReadAudioSpecificConfig(CBitstream *bs) { int aot = bs->readBits(5); if (aot == 31) aot = 32 + bs->readBits(6); int SampleRateIndex = bs->readBits(4); if (SampleRateIndex == 0xf) m_SampleRate = bs->readBits(24); else m_SampleRate = aac_sample_rates[SampleRateIndex & 0xf]; m_Channels = bs->readBits(4); if (aot == 5) { // AOT_SBR if (bs->readBits(4) == 0xf) { // extensionSamplingFrequencyIndex bs->skipBits(24); } aot = bs->readBits(5); // this is the main object type (i.e. non-extended) if (aot == 31) aot = 32 + bs->readBits(6); } if(aot != 2) return; bs->skipBits(1); //framelen_flag if (bs->readBits1()) // depends_on_coder bs->skipBits(14); if (bs->readBits(1)) // ext_flag bs->skipBits(1); // ext3_flag } void ES_AAC::Reset() { ElementaryStream::Reset(); m_Configured = false; } pvr.mythtv-5.10.15-Leia/src/demuxer/ES_AAC.h000066400000000000000000000032561360567320200202720ustar00rootroot00000000000000/* * Copyright (C) 2005-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ #ifndef ES_AAC_H #define ES_AAC_H #include "elementaryStream.h" #include "bitstream.h" namespace TSDemux { class ES_AAC : public ElementaryStream { private: int m_SampleRate; int m_Channels; int m_BitRate; int m_FrameSize; int64_t m_PTS; /* pts of the current frame */ int64_t m_DTS; /* dts of the current frame */ bool m_Configured; int m_AudioMuxVersion_A; int m_FrameLengthType; int FindHeaders(uint8_t *buf, int buf_size); bool ParseLATMAudioMuxElement(CBitstream *bs); void ReadStreamMuxConfig(CBitstream *bs); void ReadAudioSpecificConfig(CBitstream *bs); uint32_t LATMGetValue(CBitstream *bs) { return bs->readBits(bs->readBits(2) * 8); } public: ES_AAC(uint16_t pes_pid); virtual ~ES_AAC(); virtual void Parse(STREAM_PKT* pkt); virtual void Reset(); }; } #endif /* ES_AAC_H */ pvr.mythtv-5.10.15-Leia/src/demuxer/ES_AC3.cpp000066400000000000000000000137511360567320200206100ustar00rootroot00000000000000/* * Copyright (C) 2005-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ #include "ES_AC3.h" #include "bitstream.h" #include // for max using namespace TSDemux; #define AC3_HEADER_SIZE 7 /** Channel mode (audio coding mode) */ typedef enum { AC3_CHMODE_DUALMONO = 0, AC3_CHMODE_MONO, AC3_CHMODE_STEREO, AC3_CHMODE_3F, AC3_CHMODE_2F1R, AC3_CHMODE_3F1R, AC3_CHMODE_2F2R, AC3_CHMODE_3F2R } AC3ChannelMode; /* possible frequencies */ const uint16_t AC3SampleRateTable[3] = { 48000, 44100, 32000 }; /* possible bitrates */ const uint16_t AC3BitrateTable[19] = { 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 448, 512, 576, 640 }; const uint8_t AC3ChannelsTable[8] = { 2, 1, 2, 3, 3, 4, 4, 5 }; const uint16_t AC3FrameSizeTable[38][3] = { { 64, 69, 96 }, { 64, 70, 96 }, { 80, 87, 120 }, { 80, 88, 120 }, { 96, 104, 144 }, { 96, 105, 144 }, { 112, 121, 168 }, { 112, 122, 168 }, { 128, 139, 192 }, { 128, 140, 192 }, { 160, 174, 240 }, { 160, 175, 240 }, { 192, 208, 288 }, { 192, 209, 288 }, { 224, 243, 336 }, { 224, 244, 336 }, { 256, 278, 384 }, { 256, 279, 384 }, { 320, 348, 480 }, { 320, 349, 480 }, { 384, 417, 576 }, { 384, 418, 576 }, { 448, 487, 672 }, { 448, 488, 672 }, { 512, 557, 768 }, { 512, 558, 768 }, { 640, 696, 960 }, { 640, 697, 960 }, { 768, 835, 1152 }, { 768, 836, 1152 }, { 896, 975, 1344 }, { 896, 976, 1344 }, { 1024, 1114, 1536 }, { 1024, 1115, 1536 }, { 1152, 1253, 1728 }, { 1152, 1254, 1728 }, { 1280, 1393, 1920 }, { 1280, 1394, 1920 }, }; const uint8_t EAC3Blocks[4] = { 1, 2, 3, 6 }; typedef enum { EAC3_FRAME_TYPE_INDEPENDENT = 0, EAC3_FRAME_TYPE_DEPENDENT, EAC3_FRAME_TYPE_AC3_CONVERT, EAC3_FRAME_TYPE_RESERVED } EAC3FrameType; ES_AC3::ES_AC3(uint16_t pid) : ElementaryStream(pid) { m_PTS = 0; m_DTS = 0; m_FrameSize = 0; m_SampleRate = 0; m_Channels = 0; m_BitRate = 0; es_alloc_init = 1920*2; } ES_AC3::~ES_AC3() { } void ES_AC3::Parse(STREAM_PKT* pkt) { int p = es_parsed; int l; while ((l = es_len - p) > 8) { if (FindHeaders(es_buf + p, l) < 0) break; p++; } es_parsed = p; if (es_found_frame && l >= m_FrameSize) { bool streamChange = SetAudioInformation(m_Channels, m_SampleRate, m_BitRate, 0, 0); pkt->pid = pid; pkt->data = &es_buf[p]; pkt->size = m_FrameSize; pkt->duration = 90000 * 1536 / m_SampleRate; pkt->dts = m_DTS; pkt->pts = m_PTS; pkt->streamChange = streamChange; es_consumed = p + m_FrameSize; es_parsed = es_consumed; es_found_frame = false; } } int ES_AC3::FindHeaders(uint8_t *buf, int buf_size) { if (es_found_frame) return -1; if (buf_size < 9) return -1; uint8_t *buf_ptr = buf; if ((buf_ptr[0] == 0x0b && buf_ptr[1] == 0x77)) { CBitstream bs(buf_ptr + 2, AC3_HEADER_SIZE * 8); // read ahead to bsid to distinguish between AC-3 and E-AC-3 int bsid = bs.showBits(29) & 0x1F; if (bsid > 16) return 0; if (bsid <= 10) { // Normal AC-3 bs.skipBits(16); int fscod = bs.readBits(2); int frmsizecod = bs.readBits(6); bs.skipBits(5); // skip bsid, already got it bs.skipBits(3); // skip bitstream mode int acmod = bs.readBits(3); if (fscod == 3 || frmsizecod > 37) return 0; if (acmod == AC3_CHMODE_STEREO) { bs.skipBits(2); // skip dsurmod } else { if ((acmod & 1) && acmod != AC3_CHMODE_MONO) bs.skipBits(2); if (acmod & 4) bs.skipBits(2); } int lfeon = bs.readBits(1); int srShift = std::max(bsid, 8) - 8; m_SampleRate = AC3SampleRateTable[fscod] >> srShift; m_BitRate = (AC3BitrateTable[frmsizecod>>1] * 1000) >> srShift; m_Channels = AC3ChannelsTable[acmod] + lfeon; m_FrameSize = AC3FrameSizeTable[frmsizecod][fscod] * 2; } else { // Enhanced AC-3 int frametype = bs.readBits(2); if (frametype == EAC3_FRAME_TYPE_RESERVED) return 0; bs.readBits(3); // int substreamid m_FrameSize = (bs.readBits(11) + 1) << 1; if (m_FrameSize < AC3_HEADER_SIZE) return 0; int numBlocks = 6; int sr_code = bs.readBits(2); if (sr_code == 3) { int sr_code2 = bs.readBits(2); if (sr_code2 == 3) return 0; m_SampleRate = AC3SampleRateTable[sr_code2] / 2; } else { numBlocks = EAC3Blocks[bs.readBits(2)]; m_SampleRate = AC3SampleRateTable[sr_code]; } int channelMode = bs.readBits(3); int lfeon = bs.readBits(1); m_BitRate = (uint32_t)(8.0 * m_FrameSize * m_SampleRate / (numBlocks * 256.0)); m_Channels = AC3ChannelsTable[channelMode] + lfeon; } es_found_frame = true; m_DTS = c_pts; m_PTS = c_pts; c_pts += 90000 * 1536 / m_SampleRate; return -1; } return 0; } void ES_AC3::Reset() { ElementaryStream::Reset(); } pvr.mythtv-5.10.15-Leia/src/demuxer/ES_AC3.h000066400000000000000000000025011360567320200202440ustar00rootroot00000000000000/* * Copyright (C) 2005-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ #ifndef ES_AC3_H #define ES_AC3_H #include "elementaryStream.h" namespace TSDemux { class ES_AC3 : public ElementaryStream { private: int m_SampleRate; int m_Channels; int m_BitRate; int m_FrameSize; int64_t m_PTS; /* pts of the current frame */ int64_t m_DTS; /* dts of the current frame */ int FindHeaders(uint8_t *buf, int buf_size); public: ES_AC3(uint16_t pid); virtual ~ES_AC3(); virtual void Parse(STREAM_PKT* pkt); virtual void Reset(); }; } #endif /* ES_AC3_H */ pvr.mythtv-5.10.15-Leia/src/demuxer/ES_MPEGAudio.cpp000066400000000000000000000074361360567320200217570ustar00rootroot00000000000000/* * Copyright (C) 2005-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ #include "ES_MPEGAudio.h" #include "bitstream.h" using namespace TSDemux; const uint16_t FrequencyTable[3] = { 44100, 48000, 32000 }; const uint16_t BitrateTable[2][3][15] = { { {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448 }, {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384 }, {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 } }, { {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256}, {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160}, {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160} } }; ES_MPEG2Audio::ES_MPEG2Audio(uint16_t pid) : ElementaryStream(pid) { m_PTS = 0; m_DTS = 0; m_FrameSize = 0; m_SampleRate = 0; m_Channels = 0; m_BitRate = 0; es_alloc_init = 2048; } ES_MPEG2Audio::~ES_MPEG2Audio() { } void ES_MPEG2Audio::Parse(STREAM_PKT* pkt) { int p = es_parsed; int l; while ((l = es_len - p) > 3) { if (FindHeaders(es_buf + p, l) < 0) break; p++; } es_parsed = p; if (es_found_frame && l >= m_FrameSize) { bool streamChange = SetAudioInformation(m_Channels, m_SampleRate, m_BitRate, 0, 0); pkt->pid = pid; pkt->data = &es_buf[p]; pkt->size = m_FrameSize; pkt->duration = 90000 * 1152 / m_SampleRate; pkt->dts = m_DTS; pkt->pts = m_PTS; pkt->streamChange = streamChange; es_consumed = p + m_FrameSize; es_parsed = es_consumed; es_found_frame = false; } } int ES_MPEG2Audio::FindHeaders(uint8_t *buf, int buf_size) { if (es_found_frame) return -1; if (buf_size < 4) return -1; uint8_t *buf_ptr = buf; if ((buf_ptr[0] == 0xFF && (buf_ptr[1] & 0xE0) == 0xE0)) { CBitstream bs(buf_ptr, 4 * 8); bs.skipBits(11); // syncword int audioVersion = bs.readBits(2); if (audioVersion == 1) return 0; int mpeg2 = !(audioVersion & 1); int mpeg25 = !(audioVersion & 3); int layer = bs.readBits(2); if (layer == 0) return 0; layer = 4 - layer; bs.skipBits(1); // protetion bit int bitrate_index = bs.readBits(4); if (bitrate_index == 15 || bitrate_index == 0) return 0; m_BitRate = BitrateTable[mpeg2][layer - 1][bitrate_index] * 1000; int sample_rate_index = bs.readBits(2); if (sample_rate_index == 3) return 0; m_SampleRate = FrequencyTable[sample_rate_index] >> (mpeg2 + mpeg25); int padding = bs.readBits1(); bs.skipBits(1); // private bit int channel_mode = bs.readBits(2); if (channel_mode == 11) m_Channels = 1; else m_Channels = 2; if (layer == 1) m_FrameSize = (12 * m_BitRate / m_SampleRate + padding) * 4; else m_FrameSize = 144 * m_BitRate / m_SampleRate + padding; es_found_frame = true; m_DTS = c_pts; m_PTS = c_pts; c_pts += 90000 * 1152 / m_SampleRate; return -1; } return 0; } pvr.mythtv-5.10.15-Leia/src/demuxer/ES_MPEGAudio.h000066400000000000000000000023621360567320200214150ustar00rootroot00000000000000/* * Copyright (C) 2005-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ #ifndef ES_MPEGAUDIO_H #define ES_MPEGAUDIO_H #include "elementaryStream.h" namespace TSDemux { class ES_MPEG2Audio : public ElementaryStream { private: int m_SampleRate; int m_Channels; int m_BitRate; int m_FrameSize; int64_t m_PTS; int64_t m_DTS; int FindHeaders(uint8_t *buf, int buf_size); public: ES_MPEG2Audio(uint16_t pid); virtual ~ES_MPEG2Audio(); virtual void Parse(STREAM_PKT* pkt); }; } #endif /* ES_MPEGAUDIO_H */ pvr.mythtv-5.10.15-Leia/src/demuxer/ES_MPEGVideo.cpp000066400000000000000000000141451360567320200217570ustar00rootroot00000000000000/* * Copyright (C) 2005-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ #include "ES_MPEGVideo.h" #include "bitstream.h" #include "debug.h" using namespace TSDemux; #define MPEG_PICTURE_START 0x00000100 #define MPEG_SEQUENCE_START 0x000001b3 #define MPEG_SEQUENCE_EXTENSION 0x000001b5 #define MPEG_SLICE_S 0x00000101 #define MPEG_SLICE_E 0x000001af #define PKT_I_FRAME 1 #define PKT_P_FRAME 2 #define PKT_B_FRAME 3 #define PKT_NTYPES 4 /** * MPEG2VIDEO frame duration table (in 90kHz clock domain) */ const unsigned int mpeg2video_framedurations[16] = { 0, 3753, 3750, 3600, 3003, 3000, 1800, 1501, 1500, }; ES_MPEG2Video::ES_MPEG2Video(uint16_t pid) : ElementaryStream(pid) { m_FrameDuration = 0; m_vbvDelay = -1; m_vbvSize = 0; m_Height = 0; m_Width = 0; m_Dar = 0.0f; m_DTS = 0; m_PTS = 0; m_AuDTS = 0; m_AuPTS = 0; m_AuPrevDTS = 0; m_TemporalReference = 0; m_TrLastTime = 0; m_PicNumber = 0; m_FpsScale = 0; es_alloc_init = 80000; Reset(); } ES_MPEG2Video::~ES_MPEG2Video() { } void ES_MPEG2Video::Parse(STREAM_PKT *pkt) { int frame_ptr = es_consumed; int p = es_parsed; uint32_t startcode = m_StartCode; bool frameComplete = false; int l; while ((l = es_len - p) > 3) { if ((startcode & 0xffffff00) == 0x00000100) { if (Parse_MPEG2Video(startcode, p, frameComplete) < 0) { break; } } startcode = startcode << 8 | es_buf[p++]; } es_parsed = p; m_StartCode = startcode; if (frameComplete) { if (!m_NeedSPS && !m_NeedIFrame) { bool streamChange = false; if (es_frame_valid) { if (m_FpsScale == 0) { if (m_FrameDuration > 0) m_FpsScale = static_cast(Rescale(m_FrameDuration, RESCALE_TIME_BASE, PTS_TIME_BASE)); else m_FpsScale = 40000; } streamChange = SetVideoInformation(m_FpsScale, RESCALE_TIME_BASE, m_Height, m_Width, m_Dar, false); } pkt->pid = pid; pkt->size = es_consumed - frame_ptr; pkt->data = &es_buf[frame_ptr]; pkt->dts = m_DTS; pkt->pts = m_PTS; pkt->duration = m_FrameDuration; pkt->streamChange = streamChange; } m_StartCode = 0xffffffff; es_parsed = es_consumed; es_found_frame = false; es_frame_valid = true; } } void ES_MPEG2Video::Reset() { ElementaryStream::Reset(); m_StartCode = 0xffffffff; m_NeedIFrame = true; m_NeedSPS = true; } int ES_MPEG2Video::Parse_MPEG2Video(uint32_t startcode, int buf_ptr, bool &complete) { int len = es_len - buf_ptr; uint8_t *buf = es_buf + buf_ptr; switch (startcode & 0xFF) { case 0: // picture start { if (m_NeedSPS) { es_found_frame = true; return 0; } if (es_found_frame) { complete = true; es_consumed = buf_ptr - 4; return -1; } if (len < 4) return -1; if (!Parse_MPEG2Video_PicStart(buf)) return 0; if (!es_found_frame) { m_AuPrevDTS = m_AuDTS; if (buf_ptr - 4 >= (int)es_pts_pointer) { m_AuDTS = c_dts != PTS_UNSET ? c_dts : c_pts; m_AuPTS = c_pts; } else { m_AuDTS = p_dts != PTS_UNSET ? p_dts : p_pts; m_AuPTS = p_pts; } } if (m_AuPrevDTS == m_AuDTS) { m_DTS = m_AuDTS + m_PicNumber*m_FrameDuration; m_PTS = m_AuPTS + (m_TemporalReference-m_TrLastTime)*m_FrameDuration; } else { m_PTS = m_AuPTS; m_DTS = m_AuDTS; m_PicNumber = 0; m_TrLastTime = m_TemporalReference; } m_PicNumber++; es_found_frame = true; break; } case 0xb3: // Sequence start code { if (es_found_frame) { complete = true; es_consumed = buf_ptr - 4; return -1; } if (len < 8) return -1; if (!Parse_MPEG2Video_SeqStart(buf)) return 0; break; } case 0xb7: // sequence end { if (es_found_frame) { complete = true; es_consumed = buf_ptr; return -1; } break; } default: break; } return 0; } bool ES_MPEG2Video::Parse_MPEG2Video_SeqStart(uint8_t *buf) { CBitstream bs(buf, 8 * 8); m_Width = bs.readBits(12); m_Height = bs.readBits(12); // figure out Display Aspect Ratio uint8_t aspect = bs.readBits(4); switch(aspect) { case 1: m_Dar = 1.0f; break; case 2: m_Dar = 4.0f/3.0f; break; case 3: m_Dar = 16.0f/9.0f; break; case 4: m_Dar = 2.21f; break; default: DBG(DEMUX_DBG_ERROR, "invalid / forbidden DAR in sequence header !\n"); return false; } m_FrameDuration = mpeg2video_framedurations[bs.readBits(4)]; bs.skipBits(18); bs.skipBits(1); m_vbvSize = bs.readBits(10) * 16 * 1024 / 8; m_NeedSPS = false; return true; } bool ES_MPEG2Video::Parse_MPEG2Video_PicStart(uint8_t *buf) { CBitstream bs(buf, 4 * 8); m_TemporalReference = bs.readBits(10); /* temporal reference */ int pct = bs.readBits(3); if (pct < PKT_I_FRAME || pct > PKT_B_FRAME) return true; /* Illegal picture_coding_type */ if (pct == PKT_I_FRAME) m_NeedIFrame = false; int vbvDelay = bs.readBits(16); /* vbv_delay */ if (vbvDelay == 0xffff) m_vbvDelay = -1; else m_vbvDelay = vbvDelay; return true; } pvr.mythtv-5.10.15-Leia/src/demuxer/ES_MPEGVideo.h000066400000000000000000000034721360567320200214250ustar00rootroot00000000000000/* * Copyright (C) 2005-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ #ifndef ES_MPEGVIDEO_H #define ES_MPEGVIDEO_H #include "elementaryStream.h" namespace TSDemux { class ES_MPEG2Video : public ElementaryStream { private: uint32_t m_StartCode; bool m_NeedIFrame; bool m_NeedSPS; int m_FrameDuration; int m_vbvDelay; /* -1 if CBR */ int m_vbvSize; /* Video buffer size (in bytes) */ int m_Width; int m_Height; float m_Dar; int64_t m_DTS; int64_t m_PTS; int64_t m_AuDTS, m_AuPTS, m_AuPrevDTS; int m_TemporalReference; int m_TrLastTime; int m_PicNumber; int m_FpsScale; int Parse_MPEG2Video(uint32_t startcode, int buf_ptr, bool &complete); bool Parse_MPEG2Video_SeqStart(uint8_t *buf); bool Parse_MPEG2Video_PicStart(uint8_t *buf); public: ES_MPEG2Video(uint16_t pid); virtual ~ES_MPEG2Video(); virtual void Parse(STREAM_PKT* pkt); virtual void Reset(); }; } #endif /* ES_MPEGVIDEO_H */ pvr.mythtv-5.10.15-Leia/src/demuxer/ES_Subtitle.cpp000066400000000000000000000027071360567320200220340ustar00rootroot00000000000000/* * Copyright (C) 2005-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ #include "ES_Subtitle.h" using namespace TSDemux; ES_Subtitle::ES_Subtitle(uint16_t pid) : ElementaryStream(pid) { es_alloc_init = 4000; has_stream_info = true; // doesn't provide stream info } ES_Subtitle::~ES_Subtitle() { } void ES_Subtitle::Parse(STREAM_PKT* pkt) { int l = es_len - es_parsed; if (l > 0) { if (l < 2 || es_buf[0] != 0x20 || es_buf[1] != 0x00) { Reset(); return; } if(es_buf[l-1] == 0xff) { pkt->pid = pid; pkt->data = es_buf+2; pkt->size = l-3; pkt->duration = 0; pkt->dts = c_dts; pkt->pts = c_pts; pkt->streamChange = false; } es_parsed = es_consumed = es_len; } } pvr.mythtv-5.10.15-Leia/src/demuxer/ES_Subtitle.h000066400000000000000000000020121360567320200214660ustar00rootroot00000000000000/* * Copyright (C) 2005-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ #ifndef ES_SUBTITLE_H #define ES_SUBTITLE_H #include "elementaryStream.h" namespace TSDemux { class ES_Subtitle : public ElementaryStream { public: ES_Subtitle(uint16_t pid); virtual ~ES_Subtitle(); virtual void Parse(STREAM_PKT* pkt); }; } #endif /* ES_SUBTITLE_H */ pvr.mythtv-5.10.15-Leia/src/demuxer/ES_Teletext.cpp000066400000000000000000000025531360567320200220360ustar00rootroot00000000000000/* * Copyright (C) 2005-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ #include "ES_Teletext.h" using namespace TSDemux; ES_Teletext::ES_Teletext(uint16_t pid) : ElementaryStream(pid) { es_alloc_init = 4000; has_stream_info = true; // doesn't provide stream info } ES_Teletext::~ES_Teletext() { } void ES_Teletext::Parse(STREAM_PKT* pkt) { int l = es_len - es_parsed; if (l < 1) return; if (es_buf[0] < 0x10 || es_buf[0] > 0x1F) { Reset(); return; } pkt->pid = pid; pkt->data = es_buf; pkt->size = l; pkt->duration = 0; pkt->dts = c_dts; pkt->pts = c_pts; pkt->streamChange = false; es_parsed = es_consumed = es_len; } pvr.mythtv-5.10.15-Leia/src/demuxer/ES_Teletext.h000066400000000000000000000020121360567320200214710ustar00rootroot00000000000000/* * Copyright (C) 2005-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ #ifndef ES_TELETEXT_H #define ES_TELETEXT_H #include "elementaryStream.h" namespace TSDemux { class ES_Teletext : public ElementaryStream { public: ES_Teletext(uint16_t pid); virtual ~ES_Teletext(); virtual void Parse(STREAM_PKT* pkt); }; } #endif /* ES_TELETEXT_H */ pvr.mythtv-5.10.15-Leia/src/demuxer/ES_h264.cpp000066400000000000000000000404201360567320200207160ustar00rootroot00000000000000/* * Copyright (C) 2005-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ #include "ES_h264.h" #include "bitstream.h" #include "debug.h" #include // for memset memcpy using namespace TSDemux; static const int h264_lev2cpbsize[][2] = { {10, 175}, {11, 500}, {12, 1000}, {13, 2000}, {20, 2000}, {21, 4000}, {22, 4000}, {30, 10000}, {31, 14000}, {32, 20000}, {40, 25000}, {41, 62500}, {42, 62500}, {50, 135000}, {51, 240000}, {-1, -1}, }; ES_h264::ES_h264(uint16_t pes_pid) : ElementaryStream(pes_pid) { m_Height = 0; m_Width = 0; m_FPS = 25; m_FpsScale = 0; m_FrameDuration = 0; m_vbvDelay = -1; m_vbvSize = 0; m_PixelAspect.den = 1; m_PixelAspect.num = 0; m_DTS = 0; m_PTS = 0; m_Interlaced = false; es_alloc_init = 240000; Reset(); } ES_h264::~ES_h264() { } void ES_h264::Parse(STREAM_PKT* pkt) { size_t frame_ptr = es_consumed; size_t p = es_parsed; uint32_t startcode = m_StartCode; bool frameComplete = false; while ((p + 3) < es_len) { if ((startcode & 0xffffff00) == 0x00000100) { if (Parse_H264(startcode, p, frameComplete) < 0) { break; } } startcode = startcode << 8 | es_buf[p++]; } es_parsed = p; m_StartCode = startcode; if (frameComplete) { if (!m_NeedSPS && !m_NeedIFrame) { double PAR = (double)m_PixelAspect.num/(double)m_PixelAspect.den; double DAR = (PAR * m_Width) / m_Height; DBG(DEMUX_DBG_PARSE, "H.264 SPS: PAR %i:%i\n", m_PixelAspect.num, m_PixelAspect.den); DBG(DEMUX_DBG_PARSE, "H.264 SPS: DAR %.2f\n", DAR); uint64_t duration; if (c_dts != PTS_UNSET && p_dts != PTS_UNSET && c_dts > p_dts) duration = c_dts - p_dts; else duration = static_cast(Rescale(40000, PTS_TIME_BASE, RESCALE_TIME_BASE)); bool streamChange = false; if (es_frame_valid) { if (m_FpsScale == 0) m_FpsScale = static_cast(Rescale(duration, RESCALE_TIME_BASE, PTS_TIME_BASE)); streamChange = SetVideoInformation(m_FpsScale, RESCALE_TIME_BASE, m_Height, m_Width, static_cast(DAR), m_Interlaced); } pkt->pid = pid; pkt->size = es_consumed - frame_ptr; pkt->data = &es_buf[frame_ptr]; pkt->dts = m_DTS; pkt->pts = m_PTS; pkt->duration = duration; pkt->streamChange = streamChange; } m_StartCode = 0xffffffff; es_parsed = es_consumed; es_found_frame = false; es_frame_valid = true; } } void ES_h264::Reset() { ElementaryStream::Reset(); m_StartCode = 0xffffffff; m_NeedIFrame = true; m_NeedSPS = true; m_NeedPPS = true; memset(&m_streamData, 0, sizeof(m_streamData)); } int ES_h264::Parse_H264(uint32_t startcode, int buf_ptr, bool &complete) { int len = es_len - buf_ptr; uint8_t *buf = es_buf + buf_ptr; switch(startcode & 0x9f) { case 1: case 2: case 3: case 4: case 5: { if (m_NeedSPS || m_NeedPPS) { es_found_frame = true; return 0; } // need at least 32 bytes for parsing nal if (len < 32) return -1; h264_private::VCL_NAL vcl; memset(&vcl, 0, sizeof(h264_private::VCL_NAL)); vcl.nal_ref_idc = startcode & 0x60; vcl.nal_unit_type = startcode & 0x1F; if (!Parse_SLH(buf, len, vcl)) return 0; // check for the beginning of a new access unit if (es_found_frame && IsFirstVclNal(vcl)) { complete = true; es_consumed = buf_ptr - 4; return -1; } if (!es_found_frame) { if (buf_ptr - 4 >= (int)es_pts_pointer) { m_DTS = c_dts; m_PTS = c_pts; } else { m_DTS = p_dts; m_PTS = p_pts; } } m_streamData.vcl_nal = vcl; es_found_frame = true; break; } case NAL_SEI: if (es_found_frame) { complete = true; es_consumed = buf_ptr - 4; return -1; } break; case NAL_SPS: { if (es_found_frame) { complete = true; es_consumed = buf_ptr - 4; return -1; } // TODO: how big is SPS? if (len < 256) return -1; if (!Parse_SPS(buf, len)) return 0; m_NeedSPS = false; break; } case NAL_PPS: { if (es_found_frame) { complete = true; es_consumed = buf_ptr - 4; return -1; } // TODO: how big is PPS if (len < 64) return -1; if (!Parse_PPS(buf, len)) return 0; m_NeedPPS = false; break; } case NAL_AUD: if (es_found_frame && (p_pts != PTS_UNSET)) { complete = true; es_consumed = buf_ptr - 4; return -1; } break; case NAL_END_SEQ: if (es_found_frame) { complete = true; es_consumed = buf_ptr; return -1; } break; case 13: case 14: case 15: case 16: case 17: case 18: if (es_found_frame) { complete = true; es_consumed = buf_ptr - 4; return -1; } break; default: break; } return 0; } bool ES_h264::Parse_PPS(uint8_t *buf, int len) { CBitstream bs(buf, len*8); int pps_id = bs.readGolombUE(); int sps_id = bs.readGolombUE(); m_streamData.pps[pps_id].sps = sps_id; bs.readBits1(); m_streamData.pps[pps_id].pic_order_present_flag = bs.readBits1(); return true; } bool ES_h264::Parse_SLH(uint8_t *buf, int len, h264_private::VCL_NAL &vcl) { CBitstream bs(buf, len*8); bs.readGolombUE(); /* first_mb_in_slice */ int slice_type = bs.readGolombUE(); if (slice_type > 4) slice_type -= 5; /* Fixed slice type per frame */ switch (slice_type) { case 0: break; case 1: break; case 2: m_NeedIFrame = false; break; default: return false; } int pps_id = bs.readGolombUE(); int sps_id = m_streamData.pps[pps_id].sps; if (m_streamData.sps[sps_id].cbpsize == 0) return false; m_vbvSize = m_streamData.sps[sps_id].cbpsize; m_vbvDelay = -1; vcl.pic_parameter_set_id = pps_id; vcl.frame_num = bs.readBits(m_streamData.sps[sps_id].log2_max_frame_num); if (!m_streamData.sps[sps_id].frame_mbs_only_flag) { vcl.field_pic_flag = bs.readBits1(); // interlaced if (vcl.field_pic_flag) m_Interlaced = true; } if (vcl.field_pic_flag) vcl.bottom_field_flag = bs.readBits1(); if (vcl.nal_unit_type == 5) vcl.idr_pic_id = bs.readGolombUE(); if (m_streamData.sps[sps_id].pic_order_cnt_type == 0) { vcl.pic_order_cnt_lsb = bs.readBits(m_streamData.sps[sps_id].log2_max_pic_order_cnt_lsb); if(m_streamData.pps[pps_id].pic_order_present_flag && !vcl.field_pic_flag) vcl.delta_pic_order_cnt_bottom = bs.readGolombSE(); } if(m_streamData.sps[sps_id].pic_order_cnt_type == 1 && !m_streamData.sps[sps_id].delta_pic_order_always_zero_flag ) { vcl.delta_pic_order_cnt_0 = bs.readGolombSE(); if(m_streamData.pps[pps_id].pic_order_present_flag && !vcl.field_pic_flag ) vcl.delta_pic_order_cnt_1 = bs.readGolombSE(); } vcl.pic_order_cnt_type = m_streamData.sps[sps_id].pic_order_cnt_type; return true; } bool ES_h264::Parse_SPS(uint8_t *buf, int len) { CBitstream bs(buf, len*8); unsigned int tmp, frame_mbs_only; int cbpsize = -1; int profile_idc = bs.readBits(8); /* constraint_set0_flag = bs.readBits1(); */ /* constraint_set1_flag = bs.readBits1(); */ /* constraint_set2_flag = bs.readBits1(); */ /* constraint_set3_flag = bs.readBits1(); */ /* reserved = bs.readBits(4); */ bs.skipBits(8); int level_idc = bs.readBits(8); unsigned int seq_parameter_set_id = bs.readGolombUE(9); unsigned int i = 0; while (h264_lev2cpbsize[i][0] != -1) { if (h264_lev2cpbsize[i][0] >= level_idc) { cbpsize = h264_lev2cpbsize[i][1]; break; } i++; } if (cbpsize < 0) return false; memset(&m_streamData.sps[seq_parameter_set_id], 0, sizeof(h264_private::SPS)); m_streamData.sps[seq_parameter_set_id].cbpsize = cbpsize * 125; /* Convert from kbit to bytes */ if( profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || profile_idc == 244 || profile_idc == 44 || profile_idc == 83 || profile_idc == 86 || profile_idc == 118 || profile_idc == 128 ) { int chroma_format_idc = bs.readGolombUE(9); /* chroma_format_idc */ if(chroma_format_idc == 3) bs.skipBits(1); /* residual_colour_transform_flag */ bs.readGolombUE(); /* bit_depth_luma - 8 */ bs.readGolombUE(); /* bit_depth_chroma - 8 */ bs.skipBits(1); /* transform_bypass */ if (bs.readBits1()) /* seq_scaling_matrix_present */ { for (int i = 0; i < ((chroma_format_idc != 3) ? 8 : 12); i++) { if (bs.readBits1()) /* seq_scaling_list_present */ { int last = 8, next = 8, size = (i<6) ? 16 : 64; for (int j = 0; j < size; j++) { if (next) next = (last + bs.readGolombSE()) & 0xff; last = !next ? last: next; } } } } } int log2_max_frame_num_minus4 = bs.readGolombUE(); /* log2_max_frame_num - 4 */ m_streamData.sps[seq_parameter_set_id].log2_max_frame_num = log2_max_frame_num_minus4 + 4; int pic_order_cnt_type = bs.readGolombUE(9); m_streamData.sps[seq_parameter_set_id].pic_order_cnt_type = pic_order_cnt_type; if (pic_order_cnt_type == 0) { int log2_max_pic_order_cnt_lsb_minus4 = bs.readGolombUE(); /* log2_max_poc_lsb - 4 */ m_streamData.sps[seq_parameter_set_id].log2_max_pic_order_cnt_lsb = log2_max_pic_order_cnt_lsb_minus4 + 4; } else if (pic_order_cnt_type == 1) { m_streamData.sps[seq_parameter_set_id].delta_pic_order_always_zero_flag = bs.readBits1(); bs.readGolombSE(); /* offset_for_non_ref_pic */ bs.readGolombSE(); /* offset_for_top_to_bottom_field */ tmp = bs.readGolombUE(); /* num_ref_frames_in_pic_order_cnt_cycle */ for (unsigned int i = 0; i < tmp; i++) bs.readGolombSE(); /* offset_for_ref_frame[i] */ } else if(pic_order_cnt_type != 2) { /* Illegal poc */ return false; } bs.readGolombUE(9); /* ref_frames */ bs.skipBits(1); /* gaps_in_frame_num_allowed */ m_Width /* mbs */ = bs.readGolombUE() + 1; m_Height /* mbs */ = bs.readGolombUE() + 1; frame_mbs_only = bs.readBits1(); m_streamData.sps[seq_parameter_set_id].frame_mbs_only_flag = frame_mbs_only; DBG(DEMUX_DBG_PARSE, "H.264 SPS: pic_width: %u mbs\n", (unsigned) m_Width); DBG(DEMUX_DBG_PARSE, "H.264 SPS: pic_height: %u mbs\n", (unsigned) m_Height); DBG(DEMUX_DBG_PARSE, "H.264 SPS: frame only flag: %d\n", frame_mbs_only); m_Width *= 16; m_Height *= 16 * (2-frame_mbs_only); if (!frame_mbs_only) { if (bs.readBits1()) /* mb_adaptive_frame_field_flag */ DBG(DEMUX_DBG_PARSE, "H.264 SPS: MBAFF\n"); } bs.skipBits(1); /* direct_8x8_inference_flag */ if (bs.readBits1()) /* frame_cropping_flag */ { uint32_t crop_left = bs.readGolombUE(); uint32_t crop_right = bs.readGolombUE(); uint32_t crop_top = bs.readGolombUE(); uint32_t crop_bottom = bs.readGolombUE(); DBG(DEMUX_DBG_PARSE, "H.264 SPS: cropping %d %d %d %d\n", crop_left, crop_top, crop_right, crop_bottom); m_Width -= 2*(crop_left + crop_right); if (frame_mbs_only) m_Height -= 2*(crop_top + crop_bottom); else m_Height -= 4*(crop_top + crop_bottom); } /* VUI parameters */ m_PixelAspect.num = 0; if (bs.readBits1()) /* vui_parameters_present flag */ { if (bs.readBits1()) /* aspect_ratio_info_present */ { uint32_t aspect_ratio_idc = bs.readBits(8); DBG(DEMUX_DBG_PARSE, "H.264 SPS: aspect_ratio_idc %d\n", aspect_ratio_idc); if (aspect_ratio_idc == 255 /* Extended_SAR */) { m_PixelAspect.num = bs.readBits(16); /* sar_width */ m_PixelAspect.den = bs.readBits(16); /* sar_height */ DBG(DEMUX_DBG_PARSE, "H.264 SPS: -> sar %dx%d\n", m_PixelAspect.num, m_PixelAspect.den); } else { static const mpeg_rational_t aspect_ratios[] = { /* page 213: */ /* 0: unknown */ {0, 1}, /* 1...16: */ { 1, 1}, {12, 11}, {10, 11}, {16, 11}, { 40, 33}, {24, 11}, {20, 11}, {32, 11}, {80, 33}, {18, 11}, {15, 11}, {64, 33}, {160, 99}, { 4, 3}, { 3, 2}, { 2, 1} }; if (aspect_ratio_idc < sizeof(aspect_ratios)/sizeof(aspect_ratios[0])) { memcpy(&m_PixelAspect, &aspect_ratios[aspect_ratio_idc], sizeof(mpeg_rational_t)); DBG(DEMUX_DBG_PARSE, "H.264 SPS: PAR %d / %d\n", m_PixelAspect.num, m_PixelAspect.den); } else { DBG(DEMUX_DBG_PARSE, "H.264 SPS: aspect_ratio_idc out of range !\n"); } } } if (bs.readBits1()) // overscan { bs.readBits1(); // overscan_appropriate_flag } if (bs.readBits1()) // video_signal_type_present_flag { bs.readBits(3); // video_format bs.readBits1(); // video_full_range_flag if (bs.readBits1()) // colour_description_present_flag { bs.readBits(8); // colour_primaries bs.readBits(8); // transfer_characteristics bs.readBits(8); // matrix_coefficients } } if (bs.readBits1()) // chroma_loc_info_present_flag { bs.readGolombUE(); // chroma_sample_loc_type_top_field bs.readGolombUE(); // chroma_sample_loc_type_bottom_field } if (bs.readBits1()) // timing_info_present_flag { // uint32_t num_units_in_tick = bs.readBits(32); // uint32_t time_scale = bs.readBits(32); // int fixed_frame_rate = bs.readBits1(); // if (num_units_in_tick > 0) // m_FPS = time_scale / (num_units_in_tick * 2); } } DBG(DEMUX_DBG_PARSE, "H.264 SPS: -> video size %dx%d, aspect %d:%d\n", m_Width, m_Height, m_PixelAspect.num, m_PixelAspect.den); return true; } bool ES_h264::IsFirstVclNal(h264_private::VCL_NAL &vcl) { if (m_streamData.vcl_nal.frame_num != vcl.frame_num) return true; if (m_streamData.vcl_nal.pic_parameter_set_id != vcl.pic_parameter_set_id) return true; if (m_streamData.vcl_nal.field_pic_flag != vcl.field_pic_flag) return true; if (m_streamData.vcl_nal.field_pic_flag && vcl.field_pic_flag) { if (m_streamData.vcl_nal.bottom_field_flag != vcl.bottom_field_flag) return true; } if (m_streamData.vcl_nal.nal_ref_idc == 0 || vcl.nal_ref_idc == 0) { if (m_streamData.vcl_nal.nal_ref_idc != vcl.nal_ref_idc) return true; } if (m_streamData.vcl_nal.pic_order_cnt_type == 0 && vcl.pic_order_cnt_type == 0) { if (m_streamData.vcl_nal.pic_order_cnt_lsb != vcl.pic_order_cnt_lsb) return true; if (m_streamData.vcl_nal.delta_pic_order_cnt_bottom != vcl.delta_pic_order_cnt_bottom) return true; } if (m_streamData.vcl_nal.pic_order_cnt_type == 1 && vcl.pic_order_cnt_type == 1) { if (m_streamData.vcl_nal.delta_pic_order_cnt_0 != vcl.delta_pic_order_cnt_0) return true; if (m_streamData.vcl_nal.delta_pic_order_cnt_1 != vcl.delta_pic_order_cnt_1) return true; } if (m_streamData.vcl_nal.nal_unit_type == 5 || vcl.nal_unit_type == 5) { if (m_streamData.vcl_nal.nal_unit_type != vcl.nal_unit_type) return true; } if (m_streamData.vcl_nal.nal_unit_type == 5 && vcl.nal_unit_type == 5) { if (m_streamData.vcl_nal.idr_pic_id != vcl.idr_pic_id) return true; } return false; } pvr.mythtv-5.10.15-Leia/src/demuxer/ES_h264.h000066400000000000000000000063041360567320200203660ustar00rootroot00000000000000/* * Copyright (C) 2005-2013 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ #ifndef ES_H264_H #define ES_H264_H #include "elementaryStream.h" namespace TSDemux { class ES_h264 : public ElementaryStream { private: typedef struct h264_private { struct SPS { int frame_duration; int cbpsize; int pic_order_cnt_type; int frame_mbs_only_flag; int log2_max_frame_num; int log2_max_pic_order_cnt_lsb; int delta_pic_order_always_zero_flag; } sps[256]; struct PPS { int sps; int pic_order_present_flag; } pps[256]; struct VCL_NAL { int frame_num; // slice int pic_parameter_set_id; // slice int field_pic_flag; // slice int bottom_field_flag; // slice int delta_pic_order_cnt_bottom; // slice int delta_pic_order_cnt_0; // slice int delta_pic_order_cnt_1; // slice int pic_order_cnt_lsb; // slice int idr_pic_id; // slice int nal_unit_type; int nal_ref_idc; // start code int pic_order_cnt_type; // sps } vcl_nal; } h264_private_t; typedef struct mpeg_rational_s { int num; int den; } mpeg_rational_t; enum { NAL_SLH = 0x01, // Slice Header NAL_SEI = 0x06, // Supplemental Enhancement Information NAL_SPS = 0x07, // Sequence Parameter Set NAL_PPS = 0x08, // Picture Parameter Set NAL_AUD = 0x09, // Access Unit Delimiter NAL_END_SEQ = 0x0A // End of Sequence }; uint32_t m_StartCode; bool m_NeedIFrame; bool m_NeedSPS; bool m_NeedPPS; int m_Width; int m_Height; int m_FPS; int m_FpsScale; mpeg_rational_t m_PixelAspect; int m_FrameDuration; h264_private m_streamData; int m_vbvDelay; /* -1 if CBR */ int m_vbvSize; /* Video buffer size (in bytes) */ int64_t m_DTS; int64_t m_PTS; bool m_Interlaced; int Parse_H264(uint32_t startcode, int buf_ptr, bool &complete); bool Parse_PPS(uint8_t *buf, int len); bool Parse_SLH(uint8_t *buf, int len, h264_private::VCL_NAL &vcl); bool Parse_SPS(uint8_t *buf, int len); bool IsFirstVclNal(h264_private::VCL_NAL &vcl); public: ES_h264(uint16_t pes_pid); virtual ~ES_h264(); virtual void Parse(STREAM_PKT* pkt); virtual void Reset(); }; } #endif /* ES_H264_H */ pvr.mythtv-5.10.15-Leia/src/demuxer/ES_hevc.cpp000066400000000000000000000174411360567320200211670ustar00rootroot00000000000000/* * Copyright (C) 2005-2012 Team XBMC * Copyright (C) 2015 Team KODI * * http://kodi.tv * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 KODI; see the file COPYING. If not, see * . * */ #include "ES_hevc.h" #include "bitstream.h" #include "debug.h" #include // for memset memcpy using namespace TSDemux; ES_hevc::ES_hevc(uint16_t pes_pid) : ElementaryStream(pes_pid) { m_Height = 0; m_Width = 0; m_FpsScale = 0; m_PixelAspect.den = 1; m_PixelAspect.num = 0; m_DTS = PTS_UNSET; m_PTS = PTS_UNSET; m_Interlaced = false; es_alloc_init = 240000; Reset(); } ES_hevc::~ES_hevc() { } void ES_hevc::Parse(STREAM_PKT* pkt) { if (es_parsed + 10 > es_len) // 2*startcode + header + trail bits return; size_t frame_ptr = es_consumed; size_t p = es_parsed; uint32_t startcode = m_StartCode; bool frameComplete = false; while (p < es_len) { startcode = startcode << 8 | es_buf[p++]; if ((startcode & 0x00ffffff) == 0x00000001) { if (m_LastStartPos != -1) Parse_HEVC(frame_ptr + m_LastStartPos, p - frame_ptr - m_LastStartPos, frameComplete); m_LastStartPos = p - frame_ptr; // save relative position from start if (frameComplete) break; } } es_parsed = p; m_StartCode = startcode; if (frameComplete) { if (!m_NeedSPS) { double PAR = (double)m_PixelAspect.num/(double)m_PixelAspect.den; double DAR = (PAR * m_Width) / m_Height; DBG(DEMUX_DBG_DEBUG, "HEVC SPS: PAR %i:%i\n", m_PixelAspect.num, m_PixelAspect.den); DBG(DEMUX_DBG_DEBUG, "HEVC SPS: DAR %.2f\n", DAR); uint64_t duration; if (c_dts != PTS_UNSET && p_dts != PTS_UNSET && c_dts > p_dts) duration = c_dts - p_dts; else duration = static_cast(Rescale(20000, PTS_TIME_BASE, RESCALE_TIME_BASE)); bool streamChange = false; if (es_frame_valid) { if (m_FpsScale == 0) m_FpsScale = static_cast(Rescale(duration, RESCALE_TIME_BASE, PTS_TIME_BASE)); streamChange = SetVideoInformation(m_FpsScale, RESCALE_TIME_BASE, m_Height, m_Width, static_cast(DAR), m_Interlaced); } pkt->pid = pid; pkt->size = es_consumed - frame_ptr; pkt->data = &es_buf[frame_ptr]; pkt->dts = m_DTS; pkt->pts = m_PTS; pkt->duration = duration; pkt->streamChange = streamChange; } m_StartCode = 0xffffffff; m_LastStartPos = -1; es_parsed = es_consumed; es_found_frame = false; es_frame_valid = true; } } void ES_hevc::Reset() { ElementaryStream::Reset(); m_StartCode = 0xffffffff; m_LastStartPos = -1; m_NeedSPS = true; m_NeedPPS = true; memset(&m_streamData, 0, sizeof(m_streamData)); } void ES_hevc::Parse_HEVC(int buf_ptr, unsigned int NumBytesInNalUnit, bool &complete) { uint8_t *buf = es_buf + buf_ptr; uint16_t header; HDR_NAL hdr; // nal_unit_header header = (buf[0] << 8) | buf[1]; if (header & 0x8000) // ignore forbidden_bit == 1 return; hdr.nal_unit_type = (header & 0x7e00) >> 9; hdr.nuh_layer_id = (header & 0x1f8) >> 3; hdr.nuh_temporal_id = (header & 0x7) - 1; if (hdr.nal_unit_type <= NAL_CRA_NUT) { if (m_NeedSPS || m_NeedPPS) { es_found_frame = true; return; } hevc_private::VCL_NAL vcl; memset(&vcl, 0, sizeof(hevc_private::VCL_NAL)); Parse_SLH(buf, NumBytesInNalUnit, hdr, vcl); // check for the beginning of a new access unit if (es_found_frame && IsFirstVclNal(vcl)) { complete = true; es_consumed = buf_ptr - 3; return; } if (!es_found_frame) { if (buf_ptr - 3 >= (int)es_pts_pointer) { m_DTS = c_dts; m_PTS = c_pts; } else { m_DTS = p_dts; m_PTS = p_pts; } } m_streamData.vcl_nal = vcl; es_found_frame = true; } else { switch (hdr.nal_unit_type) { case NAL_VPS_NUT: break; case NAL_SPS_NUT: { if (es_found_frame) { complete = true; es_consumed = buf_ptr - 3; return; } Parse_SPS(buf, NumBytesInNalUnit, hdr); m_NeedSPS = false; break; } case NAL_PPS_NUT: { if (es_found_frame) { complete = true; es_consumed = buf_ptr - 3; return; } Parse_PPS(buf, NumBytesInNalUnit); m_NeedPPS = false; break; } case NAL_AUD_NUT: if (es_found_frame && (p_pts != PTS_UNSET)) { complete = true; es_consumed = buf_ptr - 3; } break; case NAL_EOS_NUT: if (es_found_frame) { complete = true; es_consumed = buf_ptr + 2; } break; case NAL_FD_NUT: break; case NAL_PFX_SEI_NUT: if (es_found_frame) { complete = true; es_consumed = buf_ptr - 3; } break; case NAL_SFX_SEI_NUT: break; default: DBG(DEMUX_DBG_INFO, "HEVC fixme: nal unknown %i\n", hdr.nal_unit_type); break; } } } void ES_hevc::Parse_PPS(uint8_t *buf, int len) { CBitstream bs(buf, len*8, true); int pps_id = bs.readGolombUE(); int sps_id = bs.readGolombUE(); m_streamData.pps[pps_id].sps = sps_id; m_streamData.pps[pps_id].dependent_slice_segments_enabled_flag = bs.readBits(1); } void ES_hevc::Parse_SLH(uint8_t *buf, int len, HDR_NAL hdr, hevc_private::VCL_NAL &vcl) { CBitstream bs(buf, len*8, true); vcl.nal_unit_type = hdr.nal_unit_type; vcl.first_slice_segment_in_pic_flag = bs.readBits(1); if ((hdr.nal_unit_type >= NAL_BLA_W_LP) && (hdr.nal_unit_type <= NAL_RSV_IRAP_VCL23)) bs.skipBits(1); // no_output_of_prior_pics_flag vcl.pic_parameter_set_id = bs.readGolombUE(); } // 7.3.2.2.1 General sequence parameter set RBSP syntax void ES_hevc::Parse_SPS(uint8_t *buf, int len, HDR_NAL hdr) { CBitstream bs(buf, len*8, true); unsigned int i; int sub_layer_profile_present_flag[8], sub_layer_level_present_flag[8]; bs.skipBits(4); // sps_video_parameter_set_id unsigned int sps_max_sub_layers_minus1 = bs.readBits(3); bs.skipBits(1); // sps_temporal_id_nesting_flag // skip over profile_tier_level bs.skipBits(8 + 32 + 4 + 43 + 1 +8); for (i=0; i 0) { for (i=sps_max_sub_layers_minus1; i<8; i++) bs.skipBits(2); } for (i=0; i. * */ #ifndef ES_HEVC_H #define ES_HEVC_H #include "elementaryStream.h" namespace TSDemux { class ES_hevc : public ElementaryStream { private: typedef struct hevc_private { struct PPS { int sps; int dependent_slice_segments_enabled_flag; } pps[64]; struct VCL_NAL { int pic_parameter_set_id; // slice unsigned int first_slice_segment_in_pic_flag; unsigned int nal_unit_type; } vcl_nal; } hevc_private_t; typedef struct HDR_NAL_t { unsigned nal_unit_type; unsigned nuh_layer_id; unsigned nuh_temporal_id; } HDR_NAL; typedef struct mpeg_rational_s { int num; int den; } mpeg_rational_t; enum { NAL_TRAIL_N = 0x00, // Coded slice segment of trailing picture NAL_TRAIL_R = 0x01, // Coded slice segment of trailing picture NAL_TSA_N = 0x02, // Coded slice segment of TSA picture NAL_TSA_R = 0x03, // Coded slice segment of TSA picture NAL_STSA_N = 0x04, // Coded slice segment of STSA picture NAL_STSA_R = 0x05, // Coded slice segment of STSA picture NAL_RADL_N = 0x06, // Coded slice segment of RADL picture NAL_RADL_R = 0x07, // Coded slice segment of RADL picture NAL_RASL_N = 0x08, // Coded slice segment of RASL picture NAL_RASL_R = 0x09, // Coded slice segment of RASL picture NAL_BLA_W_LP = 0x10, // Coded slice segment of a BLA picture NAL_CRA_NUT = 0x15, // Coded slice segment of a CRA picture NAL_RSV_IRAP_VCL22 = 0x16, // Reserved IRAP VCL NAL unit types NAL_RSV_IRAP_VCL23 = 0x17, // Reserved IRAP VCL NAL unit types NAL_VPS_NUT = 0x20, // Video Parameter SET NAL_SPS_NUT = 0x21, // Sequence Parameter Set NAL_PPS_NUT = 0x22, // Picture Parameter Set NAL_AUD_NUT = 0x23, // Access Unit Delimiter NAL_EOS_NUT = 0x24, // End of Sequence NAL_EOB_NUT = 0x25, // End of Bitstream NAL_FD_NUT = 0x26, // Filler Data NAL_PFX_SEI_NUT = 0x27, // Supplemental Enhancement Information NAL_SFX_SEI_NUT = 0x28, // Supplemental Enhancement Information }; uint32_t m_StartCode; int m_LastStartPos; bool m_NeedSPS; bool m_NeedPPS; int m_Width; int m_Height; int m_FpsScale; mpeg_rational_t m_PixelAspect; hevc_private_t m_streamData; int64_t m_DTS; int64_t m_PTS; bool m_Interlaced; void Parse_HEVC(int buf_ptr, unsigned int NumBytesInNalUnit, bool &complete); void Parse_PPS(uint8_t *buf, int len); void Parse_SLH(uint8_t *buf, int len, HDR_NAL hdr, hevc_private::VCL_NAL &vcl); void Parse_SPS(uint8_t *buf, int len, HDR_NAL hdr); bool IsFirstVclNal(hevc_private::VCL_NAL &vcl); public: ES_hevc(uint16_t pes_pid); virtual ~ES_hevc(); virtual void Parse(STREAM_PKT* pkt); virtual void Reset(); }; } #endif /* ES_HEVC_H */ pvr.mythtv-5.10.15-Leia/src/demuxer/bitstream.cpp000066400000000000000000000052671360567320200216500ustar00rootroot00000000000000/* * Copyright (C) 2005-2012 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ #include "bitstream.h" using namespace TSDemux; void CBitstream::skipBits(unsigned int num) { if (m_doEP3) { while (num) { unsigned int tmp = m_offset >> 3; if (!(m_offset & 7) && (m_data[tmp--] == 3) && (m_data[tmp--] == 0) && (m_data[tmp] == 0)) m_offset += 8; // skip EP3 byte if (!(m_offset & 7) && (num >= 8)) // byte boundary, speed up things a little bit { m_offset += 8; num -= 8; } else if ((tmp = 8-(m_offset & 7)) <= num) // jump to byte boundary { m_offset += tmp; num -= tmp; } else { m_offset += num; num = 0; } if (m_offset >= m_len) { m_error = true; break; } } return; } m_offset += num; } unsigned int CBitstream::readBits(int num) { unsigned int r = 0; while(num > 0) { if (m_doEP3) { size_t tmp = m_offset >> 3; if (!(m_offset & 7) && (m_data[tmp--] == 3) && (m_data[tmp--] == 0) && (m_data[tmp] == 0)) m_offset += 8; // skip EP3 byte } if(m_offset >= m_len) { m_error = true; return 0; } num--; if(m_data[m_offset / 8] & (1 << (7 - (m_offset & 7)))) r |= 1 << num; m_offset++; } return r; } unsigned int CBitstream::showBits(int num) { unsigned int r = 0; size_t offs = m_offset; while(num > 0) { if(offs >= m_len) { m_error = true; return 0; } num--; if(m_data[offs / 8] & (1 << (7 - (offs & 7)))) r |= 1 << num; offs++; } return r; } unsigned int CBitstream::readGolombUE(int maxbits) { int lzb = -1; int bits = 0; for(int b = 0; !b; lzb++, bits++) { if (bits > maxbits) return 0; b = readBits1(); } return (1 << lzb) - 1 + readBits(lzb); } signed int CBitstream::readGolombSE() { int v, pos; v = readGolombUE(); if(v == 0) return 0; pos = (v & 1); v = (v + 1) >> 1; return pos ? v : -v; } pvr.mythtv-5.10.15-Leia/src/demuxer/bitstream.h000066400000000000000000000036161360567320200213110ustar00rootroot00000000000000/* * Copyright (C) 2005-2012 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, see * . * */ #ifndef BITSTREAM_H #define BITSTREAM_H #include #include namespace TSDemux { class CBitstream { private: uint8_t *m_data; size_t m_offset; const size_t m_len; bool m_error; const bool m_doEP3; public: CBitstream(uint8_t *data, size_t bits) : m_data(data) , m_offset(0) , m_len(bits) , m_error(false) , m_doEP3(false) {} // this is a bitstream that has embedded emulation_prevention_three_byte // sequences that need to be removed as used in HECV. // Data must start at byte 2 CBitstream(uint8_t *data, size_t bits, bool doEP3) : m_data(data) , m_offset(16) // skip header and use as sentinel for EP3 detection , m_len(bits) , m_error(false) , m_doEP3(true) {} void skipBits(unsigned int num); unsigned int readBits(int num); unsigned int showBits(int num); unsigned int readBits1() { return readBits(1); } unsigned int readGolombUE(int maxbits = 32); signed int readGolombSE(); size_t length() { return m_len; } bool isError() { return m_error; } }; } #endif /* BITSTREAM_H */ pvr.mythtv-5.10.15-Leia/src/demuxer/debug.cpp000066400000000000000000000051511360567320200207340ustar00rootroot00000000000000/* * Copyright (C) 2015 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "debug.h" #include #include #include #include #include #ifdef _MSC_VER #define snprintf _snprintf #endif typedef struct { const char* name; int cur_level; void (*msg_callback)(int level, char* msg); } debug_ctx_t; static debug_ctx_t debug_ctx = {"TSDemux", DEMUX_DBG_NONE, NULL}; /** * Set the debug level to be used for the subsystem * \param ctx the subsystem debug context to use * \param level the debug level for the subsystem * \return an integer subsystem id used for future interaction */ static inline void __dbg_setlevel(debug_ctx_t* ctx, int level) { if (ctx != NULL) { ctx->cur_level = level; } } /** * Generate a debug message at a given debug level * \param ctx the subsystem debug context to use * \param level the debug level of the debug message * \param fmt a printf style format string for the message * \param ... arguments to the format */ static inline void __dbg(debug_ctx_t* ctx, int level, const char* fmt, va_list ap) { if (ctx != NULL && level <= ctx->cur_level) { char msg[4096]; int len = snprintf(msg, sizeof (msg), "(%s)", ctx->name); vsnprintf(msg + len, sizeof (msg) - len, fmt, ap); if (ctx->msg_callback) { ctx->msg_callback(level, msg); } else { fwrite(msg, strlen(msg), 1, stderr); } } } void TSDemux::DBGLevel(int l) { __dbg_setlevel(&debug_ctx, l); } void TSDemux::DBGAll() { __dbg_setlevel(&debug_ctx, DEMUX_DBG_ALL); } void TSDemux::DBGNone() { __dbg_setlevel(&debug_ctx, DEMUX_DBG_NONE); } void TSDemux::DBG(int level, const char* fmt, ...) { va_list ap; va_start(ap, fmt); __dbg(&debug_ctx, level, fmt, ap); va_end(ap); } void TSDemux::SetDBGMsgCallback(void (*msgcb)(int level, char*)) { debug_ctx.msg_callback = msgcb; } pvr.mythtv-5.10.15-Leia/src/demuxer/debug.h000066400000000000000000000023771360567320200204100ustar00rootroot00000000000000/* * Copyright (C) 2015 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef TS_DEBUG_H #define TS_DEBUG_H #define DEMUX_DBG_NONE -1 #define DEMUX_DBG_ERROR 0 #define DEMUX_DBG_WARN 1 #define DEMUX_DBG_INFO 2 #define DEMUX_DBG_DEBUG 3 #define DEMUX_DBG_PARSE 4 #define DEMUX_DBG_ALL 6 namespace TSDemux { void DBGLevel(int l); void DBGAll(void); void DBGNone(void); void DBG(int level, const char* fmt, ...); void SetDBGMsgCallback(void (*msgcb)(int level, char*)); } #endif /* TS_DEBUG_H */ pvr.mythtv-5.10.15-Leia/src/demuxer/elementaryStream.cpp000066400000000000000000000164441360567320200231760ustar00rootroot00000000000000/* * Copyright (C) 2013 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "elementaryStream.h" #include "debug.h" #include // for malloc free size_t #include // memset memcpy memmove #include // for INT_MAX #include using namespace TSDemux; ElementaryStream::ElementaryStream(uint16_t pes_pid) : pid(pes_pid) , stream_type(STREAM_TYPE_UNKNOWN) , c_dts(PTS_UNSET) , c_pts(PTS_UNSET) , p_dts(PTS_UNSET) , p_pts(PTS_UNSET) , has_stream_info(false) , es_alloc_init(ES_INIT_BUFFER_SIZE) , es_buf(NULL) , es_alloc(0) , es_len(0) , es_consumed(0) , es_pts_pointer(0) , es_parsed(0) , es_found_frame(false) , es_frame_valid(false) { memset(&stream_info, 0, sizeof(STREAM_INFO)); } ElementaryStream::~ElementaryStream(void) { if (es_buf) { DBG(DEMUX_DBG_DEBUG, "free stream buffer %.4x: allocated size was %zu\n", pid, es_alloc); free(es_buf); es_buf = NULL; } } void ElementaryStream::Reset(void) { ClearBuffer(); es_found_frame = false; es_frame_valid = false; } void ElementaryStream::ClearBuffer() { es_len = es_consumed = es_pts_pointer = es_parsed = 0; } int ElementaryStream::Append(const unsigned char* buf, size_t len, bool new_pts) { // Mark position where current pts become applicable if (new_pts) es_pts_pointer = es_len; if (es_buf && es_consumed) { if (es_consumed < es_len) { memmove(es_buf, es_buf + es_consumed, es_len - es_consumed); es_len -= es_consumed; es_parsed -= es_consumed; if (es_pts_pointer > es_consumed) es_pts_pointer -= es_consumed; else es_pts_pointer = 0; es_consumed = 0; } else ClearBuffer(); } if (es_len + len > es_alloc) { if (es_alloc >= ES_MAX_BUFFER_SIZE) return -ENOMEM; size_t n = (es_alloc ? (es_alloc + len) * 2 : es_alloc_init); if (n > ES_MAX_BUFFER_SIZE) n = ES_MAX_BUFFER_SIZE; DBG(DEMUX_DBG_DEBUG, "realloc buffer size to %zu for stream %.4x\n", n, pid); unsigned char* p = es_buf; es_buf = (unsigned char*)realloc(es_buf, n * sizeof(*es_buf)); if (es_buf) { es_alloc = n; } else { free(p); es_alloc = 0; es_len = 0; return -ENOMEM; } } if (!es_buf) return -ENOMEM; memcpy(es_buf + es_len, buf, len); es_len += len; return 0; } const char* ElementaryStream::GetStreamCodecName(STREAM_TYPE stream_type) { switch (stream_type) { case STREAM_TYPE_VIDEO_MPEG1: return "mpeg1video"; case STREAM_TYPE_VIDEO_MPEG2: return "mpeg2video"; case STREAM_TYPE_AUDIO_MPEG1: return "mp1"; case STREAM_TYPE_AUDIO_MPEG2: return "mp2"; case STREAM_TYPE_AUDIO_AAC: return "aac"; case STREAM_TYPE_AUDIO_AAC_ADTS: return "aac"; case STREAM_TYPE_AUDIO_AAC_LATM: return "aac_latm"; case STREAM_TYPE_VIDEO_H264: return "h264"; case STREAM_TYPE_VIDEO_HEVC: return "hevc"; case STREAM_TYPE_AUDIO_AC3: return "ac3"; case STREAM_TYPE_AUDIO_EAC3: return "eac3"; case STREAM_TYPE_DVB_TELETEXT: return "teletext"; case STREAM_TYPE_DVB_SUBTITLE: return "dvbsub"; case STREAM_TYPE_VIDEO_MPEG4: return "mpeg4video"; case STREAM_TYPE_VIDEO_VC1: return "vc1"; case STREAM_TYPE_AUDIO_LPCM: return "lpcm"; case STREAM_TYPE_AUDIO_DTS: return "dts"; case STREAM_TYPE_PRIVATE_DATA: default: return "data"; } } const char* ElementaryStream::GetStreamCodecName() const { return GetStreamCodecName(stream_type); } bool ElementaryStream::GetStreamPacket(STREAM_PKT* pkt) { ResetStreamPacket(pkt); Parse(pkt); if (pkt->data) return true; return false; } void ElementaryStream::Parse(STREAM_PKT* pkt) { // No parser: pass-through if (es_consumed < es_len) { es_consumed = es_parsed = es_len; pkt->pid = pid; pkt->size = es_consumed; pkt->data = es_buf; pkt->dts = c_dts; pkt->pts = c_pts; if (c_dts == PTS_UNSET || p_dts == PTS_UNSET) pkt->duration = 0; else pkt->duration = c_dts - p_dts; pkt->streamChange = false; } } void ElementaryStream::ResetStreamPacket(STREAM_PKT* pkt) { pkt->pid = 0xffff; pkt->size = 0; pkt->data = NULL; pkt->dts = PTS_UNSET; pkt->pts = PTS_UNSET; pkt->duration = 0; pkt->streamChange = false; } uint64_t ElementaryStream::Rescale(uint64_t a, uint64_t b, uint64_t c) { uint64_t r = c / 2; if (b <= INT_MAX && c <= INT_MAX) { if (a <= INT_MAX) return (a * b + r) / c; else return a / c * b + (a % c * b + r) / c; } else { uint64_t a0 = a & 0xFFFFFFFF; uint64_t a1 = a >> 32; uint64_t b0 = b & 0xFFFFFFFF; uint64_t b1 = b >> 32; uint64_t t1 = a0 * b1 + a1 * b0; uint64_t t1a = t1 << 32; a0 = a0 * b0 + t1a; a1 = a1 * b1 + (t1 >> 32) + (a0 < t1a); a0 += r; a1 += a0 < r; for (int i = 63; i >= 0; i--) { a1 += a1 + ((a0 >> i) & 1); t1 += t1; if (c <= a1) { a1 -= c; t1++; } } return t1; } } bool ElementaryStream::SetVideoInformation(int FpsScale, int FpsRate, int Height, int Width, float Aspect, bool Interlaced) { bool ret = false; if ((stream_info.fps_scale != FpsScale) || (stream_info.fps_rate != FpsRate) || (stream_info.height != Height) || (stream_info.width != Width) || (stream_info.aspect != Aspect) || (stream_info.interlaced != Interlaced)) ret = true; stream_info.fps_scale = FpsScale; stream_info.fps_rate = FpsRate; stream_info.height = Height; stream_info.width = Width; stream_info.aspect = Aspect; stream_info.interlaced = Interlaced; has_stream_info = true; return ret; } bool ElementaryStream::SetAudioInformation(int Channels, int SampleRate, int BitRate, int BitsPerSample, int BlockAlign) { bool ret = false; if ((stream_info.channels != Channels) || (stream_info.sample_rate != SampleRate) || (stream_info.block_align != BlockAlign) || (stream_info.bit_rate != BitRate) || (stream_info.bits_per_sample != BitsPerSample)) ret = true; stream_info.channels = Channels; stream_info.sample_rate = SampleRate; stream_info.block_align = BlockAlign; stream_info.bit_rate = BitRate; stream_info.bits_per_sample = BitsPerSample; has_stream_info = true; return ret; } pvr.mythtv-5.10.15-Leia/src/demuxer/elementaryStream.h000066400000000000000000000110121360567320200226250ustar00rootroot00000000000000/* * Copyright (C) 2013 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef ELEMENTARYSTREAM_H #define ELEMENTARYSTREAM_H #include #include // for size_t #define ES_INIT_BUFFER_SIZE 64000 #define ES_MAX_BUFFER_SIZE 1048576 #define PTS_MASK 0x1ffffffffLL #define PTS_UNSET 0x1ffffffffLL #define PTS_TIME_BASE 90000LL #define RESCALE_TIME_BASE 1000000LL namespace TSDemux { enum STREAM_TYPE { STREAM_TYPE_UNKNOWN = 0, STREAM_TYPE_VIDEO_MPEG1, STREAM_TYPE_VIDEO_MPEG2, STREAM_TYPE_AUDIO_MPEG1, STREAM_TYPE_AUDIO_MPEG2, STREAM_TYPE_AUDIO_AAC, STREAM_TYPE_AUDIO_AAC_ADTS, STREAM_TYPE_AUDIO_AAC_LATM, STREAM_TYPE_VIDEO_H264, STREAM_TYPE_VIDEO_HEVC, STREAM_TYPE_AUDIO_AC3, STREAM_TYPE_AUDIO_EAC3, STREAM_TYPE_DVB_TELETEXT, STREAM_TYPE_DVB_SUBTITLE, STREAM_TYPE_VIDEO_MPEG4, STREAM_TYPE_VIDEO_VC1, STREAM_TYPE_AUDIO_LPCM, STREAM_TYPE_AUDIO_DTS, STREAM_TYPE_PRIVATE_DATA }; struct STREAM_INFO { char language[4]; int composition_id; int ancillary_id; int fps_scale; int fps_rate; int height; int width; float aspect; int channels; int sample_rate; int block_align; int bit_rate; int bits_per_sample; bool interlaced; }; struct STREAM_PKT { uint16_t pid; size_t size; const unsigned char* data; uint64_t dts; uint64_t pts; uint64_t duration; bool streamChange; }; class ElementaryStream { public: ElementaryStream(uint16_t pes_pid); virtual ~ElementaryStream(); virtual void Reset(); void ClearBuffer(); int Append(const unsigned char* buf, size_t len, bool new_pts = false); const char* GetStreamCodecName() const; static const char* GetStreamCodecName(STREAM_TYPE stream_type); uint16_t pid; STREAM_TYPE stream_type; uint64_t c_dts; ///< current MPEG stream DTS (decode time for video) uint64_t c_pts; ///< current MPEG stream PTS (presentation time for audio and video) uint64_t p_dts; ///< previous MPEG stream DTS (decode time for video) uint64_t p_pts; ///< previous MPEG stream PTS (presentation time for audio and video) bool has_stream_info; ///< true if stream info is completed else it requires parsing of iframe STREAM_INFO stream_info; bool GetStreamPacket(STREAM_PKT* pkt); virtual void Parse(STREAM_PKT* pkt); protected: void ResetStreamPacket(STREAM_PKT* pkt); uint64_t Rescale(uint64_t a, uint64_t b, uint64_t c); bool SetVideoInformation(int FpsScale, int FpsRate, int Height, int Width, float Aspect, bool Interlaced); bool SetAudioInformation(int Channels, int SampleRate, int BitRate, int BitsPerSample, int BlockAlign); size_t es_alloc_init; ///< Initial allocation of memory for buffer unsigned char* es_buf; ///< The Pointer to buffer size_t es_alloc; ///< Allocated size of memory for buffer size_t es_len; ///< Size of data in buffer size_t es_consumed; ///< Consumed payload. Will be erased on next append size_t es_pts_pointer; ///< Position in buffer where current PTS becomes applicable size_t es_parsed; ///< Parser: Last processed position in buffer bool es_found_frame; ///< Parser: Found frame bool es_frame_valid; }; } #endif /* ELEMENTARYSTREAM_H */ pvr.mythtv-5.10.15-Leia/src/demuxer/tsDemuxer.cpp000066400000000000000000000676611360567320200216440ustar00rootroot00000000000000/* * Copyright (C) 2013 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "tsDemuxer.h" #include "ES_MPEGVideo.h" #include "ES_MPEGAudio.h" #include "ES_h264.h" #include "ES_hevc.h" #include "ES_AAC.h" #include "ES_AC3.h" #include "ES_Subtitle.h" #include "ES_Teletext.h" #include "debug.h" #include #define MAX_RESYNC_SIZE 65536 using namespace TSDemux; AVContext::AVContext(TSDemuxer* const demux, uint64_t pos, uint16_t channel) : av_pos(pos) , av_data_len(FLUTS_NORMAL_TS_PACKETSIZE) , av_pkt_size(0) , is_configured(false) , channel(channel) , pid(0xffff) , transport_error(false) , has_payload(false) , payload_unit_start(false) , discontinuity(false) , payload(NULL) , payload_len(0) , packet(NULL) { m_demux = demux; memset(av_buf, 0, sizeof(av_buf)); }; void AVContext::Reset(void) { Myth::OS::CLockGuard lock(mutex); pid = 0xffff; transport_error = false; has_payload = false; payload_unit_start = false; discontinuity = false; payload = NULL; payload_len = 0; packet = NULL; } uint16_t AVContext::GetPID() const { return pid; } PACKET_TYPE AVContext::GetPIDType() const { Myth::OS::CLockGuard lock(mutex); if (packet) return packet->packet_type; return PACKET_TYPE_UNKNOWN; } uint16_t AVContext::GetPIDChannel() const { Myth::OS::CLockGuard lock(mutex); if (packet) return packet->channel; return 0xffff; } bool AVContext::HasPIDStreamData() const { Myth::OS::CLockGuard lock(mutex); // PES packets append frame buffer of elementary stream until next start of unit // On new unit start, flag is held if (packet && packet->has_stream_data) return true; return false; } bool AVContext::HasPIDPayload() const { return has_payload; } ElementaryStream* AVContext::GetPIDStream() { Myth::OS::CLockGuard lock(mutex); if (packet && packet->packet_type == PACKET_TYPE_PES) return packet->stream; return NULL; } std::vector AVContext::GetStreams() { Myth::OS::CLockGuard lock(mutex); std::vector v; for (std::map::iterator it = packets.begin(); it != packets.end(); ++it) if (it->second.packet_type == PACKET_TYPE_PES && it->second.stream) v.push_back(it->second.stream); return v; } void AVContext::StartStreaming(uint16_t pid) { Myth::OS::CLockGuard lock(mutex); std::map::iterator it = packets.find(pid); if (it != packets.end()) it->second.streaming = true; } void AVContext::StopStreaming(uint16_t pid) { Myth::OS::CLockGuard lock(mutex); std::map::iterator it = packets.find(pid); if (it != packets.end()) it->second.streaming = false; } ElementaryStream* AVContext::GetStream(uint16_t pid) const { Myth::OS::CLockGuard lock(mutex); std::map::const_iterator it = packets.find(pid); if (it != packets.end()) return it->second.stream; return NULL; } uint16_t AVContext::GetChannel(uint16_t pid) const { Myth::OS::CLockGuard lock(mutex); std::map::const_iterator it = packets.find(pid); if (it != packets.end()) return it->second.channel; return 0xffff; } void AVContext::ResetPackets() { Myth::OS::CLockGuard lock(mutex); for (std::map::iterator it = packets.begin(); it != packets.end(); ++it) { it->second.Reset(); } } //////////////////////////////////////////////////////////////////////////////// ///// ///// MPEG-TS parser for the context ///// uint8_t AVContext::av_rb8(const unsigned char* p) { uint8_t val = *(uint8_t*)p; return val; } uint16_t AVContext::av_rb16(const unsigned char* p) { uint16_t val = av_rb8(p) << 8; val |= av_rb8(p + 1); return val; } uint32_t AVContext::av_rb32(const unsigned char* p) { uint32_t val = av_rb16(p) << 16; val |= av_rb16(p + 2); return val; } uint64_t AVContext::decode_pts(const unsigned char* p) { uint64_t pts = (uint64_t)(av_rb8(p) & 0x0e) << 29 | (av_rb16(p + 1) >> 1) << 15 | av_rb16(p + 3) >> 1; return pts; } STREAM_TYPE AVContext::get_stream_type(uint8_t pes_type) { switch (pes_type) { case 0x01: return STREAM_TYPE_VIDEO_MPEG1; case 0x02: return STREAM_TYPE_VIDEO_MPEG2; case 0x03: return STREAM_TYPE_AUDIO_MPEG1; case 0x04: return STREAM_TYPE_AUDIO_MPEG2; case 0x06: return STREAM_TYPE_PRIVATE_DATA; case 0x0f: case 0x11: return STREAM_TYPE_AUDIO_AAC; case 0x10: return STREAM_TYPE_VIDEO_MPEG4; case 0x1b: return STREAM_TYPE_VIDEO_H264; case 0x24: return STREAM_TYPE_VIDEO_HEVC; case 0xea: return STREAM_TYPE_VIDEO_VC1; case 0x80: return STREAM_TYPE_AUDIO_LPCM; case 0x81: case 0x83: case 0x84: case 0x87: return STREAM_TYPE_AUDIO_AC3; case 0x82: case 0x85: case 0x8a: return STREAM_TYPE_AUDIO_DTS; } return STREAM_TYPE_UNKNOWN; } int AVContext::configure_ts() { size_t data_size = AV_CONTEXT_PACKETSIZE; uint64_t pos = av_pos; int fluts[][2] = { {FLUTS_NORMAL_TS_PACKETSIZE, 0}, {FLUTS_M2TS_TS_PACKETSIZE, 0}, {FLUTS_DVB_ASI_TS_PACKETSIZE, 0}, {FLUTS_ATSC_TS_PACKETSIZE, 0} }; int nb = sizeof (fluts) / (2 * sizeof (int)); int score = TS_CHECK_MIN_SCORE; for (int i = 0; i < MAX_RESYNC_SIZE; i++) { const unsigned char* data = m_demux->ReadAV(pos, data_size); if (!data) return AVCONTEXT_IO_ERROR; if (data[0] == 0x47) { int count, found; for (int t = 0; t < nb; t++) // for all fluts { const unsigned char* ndata; uint64_t npos = pos; int do_retry = score; // Reach for score do { --do_retry; npos += fluts[t][0]; if (!(ndata = m_demux->ReadAV(npos, data_size))) return AVCONTEXT_IO_ERROR; } while (ndata[0] == 0x47 && (++fluts[t][1]) && do_retry); } // Is score reached ? count = found = 0; for (int t = 0; t < nb; t++) { if (fluts[t][1] == score) { found = t; ++count; } // Reset score for next retry fluts[t][1] = 0; } // One and only one is eligible if (count == 1) { DBG(DEMUX_DBG_DEBUG, "%s: packet size is %d\n", __FUNCTION__, fluts[found][0]); av_pkt_size = fluts[found][0]; av_pos = pos; return AVCONTEXT_CONTINUE; } // More one: Retry for highest score else if (count > 1 && ++score > TS_CHECK_MAX_SCORE) // Packet size remains undetermined break; // None: Bad sync. Shift and retry else pos++; } else pos++; } DBG(DEMUX_DBG_ERROR, "%s: invalid stream\n", __FUNCTION__); return AVCONTEXT_TS_NOSYNC; } int AVContext::TSResync() { if (!is_configured) { int ret = configure_ts(); if (ret != AVCONTEXT_CONTINUE) return ret; is_configured = true; } for (int i = 0; i < MAX_RESYNC_SIZE; i++) { const unsigned char* data = m_demux->ReadAV(av_pos, av_pkt_size); if (!data) return AVCONTEXT_IO_ERROR; if (data[0] == 0x47) { memcpy(av_buf, data, av_pkt_size); Reset(); return AVCONTEXT_CONTINUE; } av_pos++; } return AVCONTEXT_TS_NOSYNC; } uint64_t AVContext::GoNext() { av_pos += av_pkt_size; Reset(); return av_pos; } uint64_t AVContext::Shift() { av_pos++; Reset(); return av_pos; } void AVContext::GoPosition(uint64_t pos) { av_pos = pos; Reset(); } uint64_t AVContext::GetPosition() const { return av_pos; } /* * Process TS packet * * returns: * * AVCONTEXT_CONTINUE * Parse completed. If has payload, process it else Continue to next packet. * * AVCONTEXT_STREAM_PID_DATA * Parse completed. A new PES unit starts and data of elementary stream for * the PID must be picked before processing this payload. * * AVCONTEXT_DISCONTINUITY * Discontinuity. PID will wait until next unit start. So continue to next * packet. * * AVCONTEXT_TS_NOSYNC * Bad sync byte. Should run TSResync(). * * AVCONTEXT_TS_ERROR * Parsing error ! */ int AVContext::ProcessTSPacket() { Myth::OS::CLockGuard lock(mutex); int ret = AVCONTEXT_CONTINUE; std::map::iterator it; if (av_rb8(this->av_buf) != 0x47) // ts sync byte return AVCONTEXT_TS_NOSYNC; uint16_t header = av_rb16(this->av_buf + 1); this->pid = header & 0x1fff; this->transport_error = (header & 0x8000) != 0; this->payload_unit_start = (header & 0x4000) != 0; // Cleaning context this->discontinuity = false; this->has_payload = false; this->payload = NULL; this->payload_len = 0; if (this->transport_error) return AVCONTEXT_CONTINUE; // Null packet if (this->pid == 0x1fff) return AVCONTEXT_CONTINUE; uint8_t flags = av_rb8(this->av_buf + 3); bool has_payload = (flags & 0x10) != 0; bool is_discontinuity = false; uint8_t continuity_counter = flags & 0x0f; bool has_adaptation = (flags & 0x20) != 0; size_t n = 0; if (has_adaptation) { size_t len = (size_t)av_rb8(this->av_buf + 4); if (len > (this->av_data_len - 5)) { #if defined(TSDEMUX_DEBUG) assert(false); #else return AVCONTEXT_TS_ERROR; #endif } n = len + 1; if (len > 0) { is_discontinuity = (av_rb8(this->av_buf + 5) & 0x80) != 0; } } if (has_payload) { // Payload start after adaptation fields this->payload = this->av_buf + n + 4; this->payload_len = this->av_data_len - n - 4; } it = this->packets.find(this->pid); if (it == this->packets.end()) { // Not registred PID // We are waiting for unit start of PID 0 else next packet is required if (this->pid == 0 && this->payload_unit_start) { // Registering PID 0 Packet pid0; pid0.pid = this->pid; pid0.packet_type = PACKET_TYPE_PSI; pid0.continuity = continuity_counter; it = this->packets.insert(it, std::make_pair(this->pid, pid0)); } else return AVCONTEXT_CONTINUE; } else { // PID is registred // Checking unit start is required if (it->second.wait_unit_start && !this->payload_unit_start) { // Not unit start. Save packet flow continuity... it->second.continuity = continuity_counter; this->discontinuity = true; return AVCONTEXT_DISCONTINUITY; } // Checking continuity where possible if (it->second.continuity != 0xff) { uint8_t expected_cc = has_payload ? (it->second.continuity + 1) & 0x0f : it->second.continuity; if (!is_discontinuity && expected_cc != continuity_counter) { this->discontinuity = true; // If unit is not start then reset PID and wait the next unit start if (!this->payload_unit_start) { it->second.Reset(); DBG(DEMUX_DBG_WARN, "PID %.4x discontinuity detected: found %u, expected %u\n", this->pid, continuity_counter, expected_cc); return AVCONTEXT_DISCONTINUITY; } } } it->second.continuity = continuity_counter; } this->discontinuity |= is_discontinuity; this->has_payload = has_payload; this->packet = &(it->second); // It is time to stream data for PES if (this->payload_unit_start && this->packet->streaming && this->packet->packet_type == PACKET_TYPE_PES && !this->packet->wait_unit_start) { this->packet->has_stream_data = true; ret = AVCONTEXT_STREAM_PID_DATA; } return ret; } /* * Process payload of packet depending of its type * * PACKET_TYPE_PSI -> parse_ts_psi() * PACKET_TYPE_PES -> parse_ts_pes() */ int AVContext::ProcessTSPayload() { Myth::OS::CLockGuard lock(mutex); if (!this->packet) return AVCONTEXT_CONTINUE; int ret = 0; switch (this->packet->packet_type) { case PACKET_TYPE_PSI: ret = parse_ts_psi(); break; case PACKET_TYPE_PES: ret = parse_ts_pes(); break; case PACKET_TYPE_UNKNOWN: break; } return ret; } void AVContext::clear_pmt() { DBG(DEMUX_DBG_DEBUG, "%s\n", __FUNCTION__); std::vector pid_list; for (std::map::iterator it = this->packets.begin(); it != this->packets.end(); ++it) { if (it->second.packet_type == PACKET_TYPE_PSI && it->second.packet_table.table_id == 0x02) { pid_list.push_back(it->first); clear_pes(it->second.channel); } } for (std::vector::iterator it = pid_list.begin(); it != pid_list.end(); ++it) this->packets.erase(*it); } void AVContext::clear_pes(uint16_t channel) { DBG(DEMUX_DBG_DEBUG, "%s(%u)\n", __FUNCTION__, channel); std::vector pid_list; for (std::map::iterator it = this->packets.begin(); it != this->packets.end(); ++it) { if (it->second.packet_type == PACKET_TYPE_PES && it->second.channel == channel) pid_list.push_back(it->first); } for (std::vector::iterator it = pid_list.begin(); it != pid_list.end(); ++it) this->packets.erase(*it); } /* * Parse PSI payload * * returns: * * AVCONTEXT_CONTINUE * Parse completed. Continue to next packet * * AVCONTEXT_PROGRAM_CHANGE * Parse completed. The program has changed. All streams are resetted and * streaming flag is set to false. Client must inspect streams MAP and enable * streaming for those recognized. * * AVCONTEXT_TS_ERROR * Parsing error ! */ int AVContext::parse_ts_psi() { size_t len; if (!this->has_payload || !this->payload || !this->payload_len || !this->packet) return AVCONTEXT_CONTINUE; if (this->payload_unit_start) { // Reset wait for unit start this->packet->wait_unit_start = false; // pointer field present len = (size_t)av_rb8(this->payload); if (len > this->payload_len) { #if defined(TSDEMUX_DEBUG) assert(false); #else return AVCONTEXT_TS_ERROR; #endif } // table ID uint8_t table_id = av_rb8(this->payload + 1); // table length len = (size_t)av_rb16(this->payload + 2); if ((len & 0x3000) != 0x3000) { #if defined(TSDEMUX_DEBUG) assert(false); #else return AVCONTEXT_TS_ERROR; #endif } len &= 0x0fff; this->packet->packet_table.Reset(); size_t n = this->payload_len - 4; memcpy(this->packet->packet_table.buf, this->payload + 4, n); this->packet->packet_table.table_id = table_id; this->packet->packet_table.offset = n; this->packet->packet_table.len = len; // check for incomplete section if (this->packet->packet_table.offset < this->packet->packet_table.len) return AVCONTEXT_CONTINUE; } else { // next part of PSI if (this->packet->packet_table.offset == 0) { #if defined(TSDEMUX_DEBUG) assert(false); #else return AVCONTEXT_TS_ERROR; #endif } if ((this->payload_len + this->packet->packet_table.offset) > TABLE_BUFFER_SIZE) { #if defined(TSDEMUX_DEBUG) assert(false); #else return AVCONTEXT_TS_ERROR; #endif } memcpy(this->packet->packet_table.buf + this->packet->packet_table.offset, this->payload, this->payload_len); this->packet->packet_table.offset += this->payload_len; // check for incomplete section if (this->packet->packet_table.offset < this->packet->packet_table.len) return AVCONTEXT_CONTINUE; } // now entire table is filled const unsigned char* psi = this->packet->packet_table.buf; const unsigned char* end_psi = psi + this->packet->packet_table.len; switch (this->packet->packet_table.table_id) { case 0x00: // parse PAT table { // check if version number changed uint16_t id = av_rb16(psi); // check if applicable if ((av_rb8(psi + 2) & 0x01) == 0) return AVCONTEXT_CONTINUE; // check if version number changed uint8_t version = (av_rb8(psi + 2) & 0x3e) >> 1; if (id == this->packet->packet_table.id && version == this->packet->packet_table.version) return AVCONTEXT_CONTINUE; DBG(DEMUX_DBG_DEBUG, "%s: new PAT version %u\n", __FUNCTION__, version); // clear old associated pmt clear_pmt(); // parse new version of PAT psi += 5; end_psi -= 4; // CRC32 if (psi >= end_psi) { #if defined(TSDEMUX_DEBUG) assert(false); #else return AVCONTEXT_TS_ERROR; #endif } len = end_psi - psi; if (len % 4) { #if defined(TSDEMUX_DEBUG) assert(false); #else return AVCONTEXT_TS_ERROR; #endif } size_t n = len / 4; for (size_t i = 0; i < n; i++, psi += 4) { uint16_t channel = av_rb16(psi); uint16_t pmt_pid = av_rb16(psi + 2); // Reserved fields in table sections must be "set" to '1' bits. //if ((pmt_pid & 0xe000) != 0xe000) // return AVCONTEXT_TS_ERROR; pmt_pid &= 0x1fff; DBG(DEMUX_DBG_DEBUG, "%s: PAT version %u: new PMT %.4x channel %u\n", __FUNCTION__, version, pmt_pid, channel); if (this->channel == 0 || this->channel == channel) { Packet& pmt = this->packets[pmt_pid]; pmt.pid = pmt_pid; pmt.packet_type = PACKET_TYPE_PSI; pmt.channel = channel; DBG(DEMUX_DBG_DEBUG, "%s: PAT version %u: register PMT %.4x channel %u\n", __FUNCTION__, version, pmt_pid, channel); } } // PAT is processed. New version is available this->packet->packet_table.id = id; this->packet->packet_table.version = version; break; } case 0x02: // parse PMT table { uint16_t id = av_rb16(psi); // check if applicable if ((av_rb8(psi + 2) & 0x01) == 0) return AVCONTEXT_CONTINUE; // check if version number changed uint8_t version = (av_rb8(psi + 2) & 0x3e) >> 1; if (id == this->packet->packet_table.id && version == this->packet->packet_table.version) return AVCONTEXT_CONTINUE; DBG(DEMUX_DBG_DEBUG, "%s: PMT(%.4x) version %u\n", __FUNCTION__, this->packet->pid, version); // clear old pes clear_pes(this->packet->channel); // parse new version of PMT psi += 7; end_psi -= 4; // CRC32 if (psi >= end_psi) { #if defined(TSDEMUX_DEBUG) assert(false); #else return AVCONTEXT_TS_ERROR; #endif } len = (size_t)(av_rb16(psi) & 0x0fff); psi += 2 + len; while (psi < end_psi) { if (end_psi - psi < 5) { #if defined(TSDEMUX_DEBUG) assert(false); #else return AVCONTEXT_TS_ERROR; #endif } uint8_t pes_type = av_rb8(psi); uint16_t pes_pid = av_rb16(psi + 1); // Reserved fields in table sections must be "set" to '1' bits. //if ((pes_pid & 0xe000) != 0xe000) // return AVCONTEXT_TS_ERROR; pes_pid &= 0x1fff; // len of descriptor section len = (size_t)(av_rb16(psi + 3) & 0x0fff); psi += 5; // ignore unknown streams STREAM_TYPE stream_type = get_stream_type(pes_type); DBG(DEMUX_DBG_DEBUG, "%s: PMT(%.4x) version %u: new PES %.4x %s\n", __FUNCTION__, this->packet->pid, version, pes_pid, ElementaryStream::GetStreamCodecName(stream_type)); if (stream_type != STREAM_TYPE_UNKNOWN) { Packet& pes = this->packets[pes_pid]; pes.pid = pes_pid; pes.packet_type = PACKET_TYPE_PES; pes.channel = this->packet->channel; // Disable streaming by default pes.streaming = false; // Get basic stream infos from PMT table STREAM_INFO stream_info; stream_info = parse_pes_descriptor(psi, len, &stream_type); ElementaryStream* es; switch (stream_type) { case STREAM_TYPE_VIDEO_MPEG1: case STREAM_TYPE_VIDEO_MPEG2: es = new ES_MPEG2Video(pes_pid); break; case STREAM_TYPE_AUDIO_MPEG1: case STREAM_TYPE_AUDIO_MPEG2: es = new ES_MPEG2Audio(pes_pid); break; case STREAM_TYPE_AUDIO_AAC: case STREAM_TYPE_AUDIO_AAC_ADTS: case STREAM_TYPE_AUDIO_AAC_LATM: es = new ES_AAC(pes_pid); break; case STREAM_TYPE_VIDEO_H264: es = new ES_h264(pes_pid); break; case STREAM_TYPE_VIDEO_HEVC: es = new ES_hevc(pes_pid); break; case STREAM_TYPE_AUDIO_AC3: case STREAM_TYPE_AUDIO_EAC3: es = new ES_AC3(pes_pid); break; case STREAM_TYPE_DVB_SUBTITLE: es = new ES_Subtitle(pes_pid); break; case STREAM_TYPE_DVB_TELETEXT: es = new ES_Teletext(pes_pid); break; default: // No parser: pass-through es = new ElementaryStream(pes_pid); es->has_stream_info = true; break; } es->stream_type = stream_type; es->stream_info = stream_info; pes.stream = es; DBG(DEMUX_DBG_DEBUG, "%s: PMT(%.4x) version %u: register PES %.4x %s\n", __FUNCTION__, this->packet->pid, version, pes_pid, es->GetStreamCodecName()); } psi += len; } if (psi != end_psi) { #if defined(TSDEMUX_DEBUG) assert(false); #else return AVCONTEXT_TS_ERROR; #endif } // PMT is processed. New version is available this->packet->packet_table.id = id; this->packet->packet_table.version = version; return AVCONTEXT_PROGRAM_CHANGE; } default: // CAT, NIT table break; } return AVCONTEXT_CONTINUE; } STREAM_INFO AVContext::parse_pes_descriptor(const unsigned char* p, size_t len, STREAM_TYPE* st) { const unsigned char* desc_end = p + len; STREAM_INFO si; memset(&si, 0, sizeof(STREAM_INFO)); while (p < desc_end) { uint8_t desc_tag = av_rb8(p); uint8_t desc_len = av_rb8(p + 1); p += 2; DBG(DEMUX_DBG_DEBUG, "%s: tag %.2x len %d\n", __FUNCTION__, desc_tag, desc_len); switch (desc_tag) { case 0x02: case 0x03: break; case 0x0a: /* ISO 639 language descriptor */ if (desc_len >= 4) { si.language[0] = av_rb8(p); si.language[1] = av_rb8(p + 1); si.language[2] = av_rb8(p + 2); si.language[3] = 0; } break; case 0x56: /* DVB teletext descriptor */ *st = STREAM_TYPE_DVB_TELETEXT; break; case 0x6a: /* DVB AC3 */ case 0x81: /* AC3 audio stream */ *st = STREAM_TYPE_AUDIO_AC3; break; case 0x7a: /* DVB enhanced AC3 */ *st = STREAM_TYPE_AUDIO_EAC3; break; case 0x7b: /* DVB DTS */ *st = STREAM_TYPE_AUDIO_DTS; break; case 0x7c: /* DVB AAC */ *st = STREAM_TYPE_AUDIO_AAC; break; case 0x59: /* subtitling descriptor */ if (desc_len >= 8) { /* * Byte 4 is the subtitling_type field * av_rb8(p + 3) & 0x10 : normal * av_rb8(p + 3) & 0x20 : for the hard of hearing */ *st = STREAM_TYPE_DVB_SUBTITLE; si.language[0] = av_rb8(p); si.language[1] = av_rb8(p + 1); si.language[2] = av_rb8(p + 2); si.language[3] = 0; si.composition_id = (int)av_rb16(p + 4); si.ancillary_id = (int)av_rb16(p + 6); } break; case 0x05: /* registration descriptor */ case 0x1E: /* SL descriptor */ case 0x1F: /* FMC descriptor */ case 0x52: /* stream identifier descriptor */ default: break; } p += desc_len; } return si; } /* * Parse PES payload * * returns: * * AVCONTEXT_CONTINUE * Parse completed. When streaming is enabled for PID, data is appended to * the frame buffer of corresponding elementary stream. * * AVCONTEXT_TS_ERROR * Parsing error ! */ int AVContext::parse_ts_pes() { if (!this->has_payload || !this->payload || !this->payload_len || !this->packet) return AVCONTEXT_CONTINUE; if (!this->packet->stream) return AVCONTEXT_CONTINUE; if (this->payload_unit_start) { // Wait for unit start: Reset frame buffer to clear old data if (this->packet->wait_unit_start) { packet->stream->Reset(); packet->stream->p_dts = PTS_UNSET; packet->stream->p_pts = PTS_UNSET; } this->packet->wait_unit_start = false; this->packet->has_stream_data = false; // Reset header table this->packet->packet_table.Reset(); // Header len is at least 6 bytes. So getting 6 bytes first this->packet->packet_table.len = 6; } // Position in the payload buffer. Start at 0 size_t pos = 0; while (this->packet->packet_table.offset < this->packet->packet_table.len) { if (pos >= this->payload_len) return AVCONTEXT_CONTINUE; size_t n = this->packet->packet_table.len - this->packet->packet_table.offset; if (n > (this->payload_len - pos)) n = this->payload_len - pos; memcpy(this->packet->packet_table.buf + this->packet->packet_table.offset, this->payload + pos, n); this->packet->packet_table.offset += n; pos += n; if (this->packet->packet_table.offset == 6) { if (memcmp(this->packet->packet_table.buf, "\x00\x00\x01", 3) == 0) { uint8_t stream_id = av_rb8(this->packet->packet_table.buf + 3); if (stream_id == 0xbd || (stream_id >= 0xc0 && stream_id <= 0xef)) this->packet->packet_table.len = 9; } } else if (this->packet->packet_table.offset == 9) { this->packet->packet_table.len += av_rb8(this->packet->packet_table.buf + 8); } } // parse header table bool has_pts = false; if (this->packet->packet_table.len >= 9) { uint8_t flags = av_rb8(this->packet->packet_table.buf + 7); //this->packet->stream->frame_num++; switch (flags & 0xc0) { case 0x80: // PTS only { has_pts = true; if (this->packet->packet_table.len >= 14) { uint64_t pts = decode_pts(this->packet->packet_table.buf + 9); this->packet->stream->p_dts = this->packet->stream->c_dts; this->packet->stream->p_pts = this->packet->stream->c_pts; this->packet->stream->c_dts = this->packet->stream->c_pts = pts; } else { this->packet->stream->c_dts = this->packet->stream->c_pts = PTS_UNSET; } } break; case 0xc0: // PTS,DTS { has_pts = true; if (this->packet->packet_table.len >= 19 ) { uint64_t pts = decode_pts(this->packet->packet_table.buf + 9); uint64_t dts = decode_pts(this->packet->packet_table.buf + 14); int64_t d = (pts - dts) & PTS_MASK; // more than two seconds of PTS/DTS delta, probably corrupt if(d > 180000) { this->packet->stream->c_dts = this->packet->stream->c_pts = PTS_UNSET; } else { this->packet->stream->p_dts = this->packet->stream->c_dts; this->packet->stream->p_pts = this->packet->stream->c_pts; this->packet->stream->c_dts = dts; this->packet->stream->c_pts = pts; } } else { this->packet->stream->c_dts = this->packet->stream->c_pts = PTS_UNSET; } } break; } this->packet->packet_table.Reset(); } if (this->packet->streaming) { const unsigned char* data = this->payload + pos; size_t len = this->payload_len - pos; this->packet->stream->Append(data, len, has_pts); } return AVCONTEXT_CONTINUE; } pvr.mythtv-5.10.15-Leia/src/demuxer/tsDemuxer.h000066400000000000000000000071571360567320200213030ustar00rootroot00000000000000/* * Copyright (C) 2013 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef TSDEMUXER_H #define TSDEMUXER_H #include "tsPacket.h" #include "elementaryStream.h" #include "private/os/threads/mutex.h" #include #include #define FLUTS_NORMAL_TS_PACKETSIZE 188 #define FLUTS_M2TS_TS_PACKETSIZE 192 #define FLUTS_DVB_ASI_TS_PACKETSIZE 204 #define FLUTS_ATSC_TS_PACKETSIZE 208 #define AV_CONTEXT_PACKETSIZE 208 #define TS_CHECK_MIN_SCORE 2 #define TS_CHECK_MAX_SCORE 10 namespace TSDemux { class TSDemuxer { public: virtual const unsigned char* ReadAV(uint64_t pos, size_t len) = 0; }; enum { AVCONTEXT_TS_ERROR = -3, AVCONTEXT_IO_ERROR = -2, AVCONTEXT_TS_NOSYNC = -1, AVCONTEXT_CONTINUE = 0, AVCONTEXT_PROGRAM_CHANGE = 1, AVCONTEXT_STREAM_PID_DATA = 2, AVCONTEXT_DISCONTINUITY = 3 }; class AVContext { public: AVContext(TSDemuxer* const demux, uint64_t pos, uint16_t channel); void Reset(void); uint16_t GetPID() const; PACKET_TYPE GetPIDType() const; uint16_t GetPIDChannel() const; bool HasPIDStreamData() const; bool HasPIDPayload() const; ElementaryStream* GetPIDStream(); std::vector GetStreams(); void StartStreaming(uint16_t pid); void StopStreaming(uint16_t pid); ElementaryStream* GetStream(uint16_t pid) const; uint16_t GetChannel(uint16_t pid) const; void ResetPackets(); // TS parser int TSResync(); uint64_t GoNext(); uint64_t Shift(); void GoPosition(uint64_t pos); uint64_t GetPosition() const; int ProcessTSPacket(); int ProcessTSPayload(); private: AVContext(const AVContext&); AVContext& operator=(const AVContext&); int configure_ts(); static STREAM_TYPE get_stream_type(uint8_t pes_type); static uint8_t av_rb8(const unsigned char* p); static uint16_t av_rb16(const unsigned char* p); static uint32_t av_rb32(const unsigned char* p); static uint64_t decode_pts(const unsigned char* p); void clear_pmt(); void clear_pes(uint16_t channel); int parse_ts_psi(); static STREAM_INFO parse_pes_descriptor(const unsigned char* p, size_t len, STREAM_TYPE* st); int parse_ts_pes(); // Critical section mutable Myth::OS::CMutex mutex; // AV stream owner TSDemuxer* m_demux; // Raw packet buffer uint64_t av_pos; size_t av_data_len; size_t av_pkt_size; unsigned char av_buf[AV_CONTEXT_PACKETSIZE]; // TS Streams context bool is_configured; uint16_t channel; std::map packets; // Packet context uint16_t pid; bool transport_error; bool has_payload; bool payload_unit_start; bool discontinuity; const unsigned char* payload; size_t payload_len; Packet* packet; }; } #endif /* TSDEMUXER_H */ pvr.mythtv-5.10.15-Leia/src/demuxer/tsPacket.h000066400000000000000000000034131360567320200210700ustar00rootroot00000000000000/* * Copyright (C) 2013 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef TSPACKET_H #define TSPACKET_H #include "tsTable.h" #include "elementaryStream.h" namespace TSDemux { enum PACKET_TYPE { PACKET_TYPE_UNKNOWN = 0, PACKET_TYPE_PSI, PACKET_TYPE_PES }; class Packet { public: Packet(void) : pid(0xffff) , continuity(0xff) , packet_type(PACKET_TYPE_UNKNOWN) , channel(0) , wait_unit_start(true) , has_stream_data(false) , streaming(false) , stream(NULL) , packet_table() { } ~Packet(void) { if (stream) delete stream; } void Reset(void) { continuity = 0xff; wait_unit_start = true; packet_table.Reset(); if (stream) stream->Reset(); } uint16_t pid; uint8_t continuity; PACKET_TYPE packet_type; uint16_t channel; bool wait_unit_start; bool has_stream_data; bool streaming; ElementaryStream* stream; TSTable packet_table; }; } #endif /* TSPACKET_H */ pvr.mythtv-5.10.15-Leia/src/demuxer/tsTable.h000066400000000000000000000026541360567320200207160ustar00rootroot00000000000000/* * Copyright (C) 2013 Jean-Luc Barriere * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #ifndef TSTABLE_H #define TSTABLE_H #include #include // for memset // PSI section size (EN 300 468) #define TABLE_BUFFER_SIZE 4096 namespace TSDemux { class TSTable { public: uint8_t table_id; uint8_t version; uint16_t id; uint16_t len; uint16_t offset; unsigned char buf[TABLE_BUFFER_SIZE]; TSTable(void) : table_id(0xff) , version(0xff) , id(0xffff) , len(0) , offset(0) { memset(buf, 0, TABLE_BUFFER_SIZE); } void Reset(void) { len = 0; offset = 0; } }; } #endif /* TSTABLE_H */ pvr.mythtv-5.10.15-Leia/src/filestreaming.cpp000066400000000000000000000050521360567320200210260ustar00rootroot00000000000000/* * Copyright (C) 2005-2015 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "filestreaming.h" #include "client.h" #define MAX_READ_SIZE 131072 using namespace ADDON; FileStreaming::FileStreaming(const std::string& filePath) : m_valid(false) , m_file(0) , m_flen(0) , m_pos(0) { m_valid = _init(filePath.c_str()); } FileStreaming::~FileStreaming() { if (m_file) XBMC->CloseFile(m_file); } int FileStreaming::Read(void* buffer, unsigned n) { if (!m_valid) return -1; char* b = (char*)buffer; bool eof = false; n = (n > MAX_READ_SIZE ? MAX_READ_SIZE : n); unsigned r = n; do { size_t s = XBMC->ReadFile(m_file, b, r); if (s > 0) { r -= s; b += s; m_pos += s; eof = false; } else { if (eof) break; eof = true; XBMC->SeekFile(m_file, 0, 0); } } while (r > 0 || eof); if (eof) XBMC->Log(LOG_DEBUG, "%s: EOF", __FUNCTION__); return (int)(n -r); } int64_t FileStreaming::Seek(int64_t offset, Myth::WHENCE_t whence) { switch (whence) { case Myth::WHENCE_SET: if (offset <= GetSize() && offset >= 0) return (m_pos = XBMC->SeekFile(m_file, offset, 0)); break; case Myth::WHENCE_CUR: if ((m_pos + offset) <= GetSize() && m_pos + offset >= 0) return (m_pos = XBMC->SeekFile(m_file, m_pos + offset, 0)); break; case Myth::WHENCE_END: if (offset >= 0 && (GetSize() - offset) >= 0) return (m_pos = XBMC->SeekFile(m_file, GetSize() - offset, 0)); break; default: break; } return -1; } bool FileStreaming::_init(const char* filePath) { m_file = XBMC->OpenFile(filePath, 0); if (m_file) { m_flen = XBMC->GetFileLength(m_file); return true; } XBMC->Log(LOG_DEBUG, "%s: cannot open file '%s'", __FUNCTION__, filePath); return false; } pvr.mythtv-5.10.15-Leia/src/filestreaming.h000066400000000000000000000025531360567320200204760ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2015 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include class FileStreaming : public Myth::Stream { public: FileStreaming(const std::string& filePath); virtual ~FileStreaming(); bool IsValid() { return m_valid; } virtual int Read(void* buffer, unsigned n); virtual int64_t Seek(int64_t offset, Myth::WHENCE_t whence); virtual int64_t GetPosition() const { return m_pos; } virtual int64_t GetSize() const { return m_flen; } private: bool m_valid; void* m_file; int64_t m_flen; int64_t m_pos; bool _init(const char* filePath); }; pvr.mythtv-5.10.15-Leia/src/pvrclient-launcher.cpp000066400000000000000000000104511360567320200220010ustar00rootroot00000000000000/* * Copyright (C) 2017 Team Kodi * http://www.kodi.tv * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "pvrclient-launcher.h" #include "client.h" #include "private/os/threads/event.h" #include "private/os/threads/thread.h" using namespace ADDON; class PVRClientLauncherPrivate : private Myth::OS::CThread { public: PVRClientLauncherPrivate(PVRClientMythTV* client); virtual ~PVRClientLauncherPrivate(); bool Start(); bool WaitForCompletion(unsigned timeout); protected: void *Process(); private: PVRClientMythTV* m_client; Myth::OS::CEvent m_alarm; }; PVRClientLauncher::PVRClientLauncher(PVRClientMythTV* client) : m_p(new PVRClientLauncherPrivate(client)) { } PVRClientLauncher::~PVRClientLauncher() { delete m_p; } bool PVRClientLauncher::Start() { return m_p->Start(); } bool PVRClientLauncher::WaitForCompletion(unsigned timeout) { return m_p->WaitForCompletion(timeout); } PVRClientLauncherPrivate::PVRClientLauncherPrivate(PVRClientMythTV* client) : Myth::OS::CThread() , m_client(client) { PVR->ConnectionStateChange(m_client->GetBackendName(), PVR_CONNECTION_STATE_CONNECTING, m_client->GetBackendVersion()); } PVRClientLauncherPrivate::~PVRClientLauncherPrivate() { StopThread(false); // Set stopping. don't wait as we need to signal the thread first m_alarm.Signal(); StopThread(true); // Wait for thread to stop } bool PVRClientLauncherPrivate::Start() { return StartThread(true); } bool PVRClientLauncherPrivate::WaitForCompletion(unsigned timeout) { return m_alarm.Wait(timeout); } void* PVRClientLauncherPrivate::Process() { bool notifyAddonFailure = true; // By default this launcher will retry for ever until the user cancel it by a dialog. bool retry = true; while (!IsStopped() && retry) { if (m_client->Connect()) { PVR->ConnectionStateChange(m_client->GetBackendName(), PVR_CONNECTION_STATE_CONNECTED, m_client->GetBackendVersion()); /* Read setting "LiveTV Priority" from backend database */ bool savedLiveTVPriority; if (!XBMC->GetSetting("livetv_priority", &savedLiveTVPriority)) savedLiveTVPriority = DEFAULT_LIVETV_PRIORITY; g_bLiveTVPriority = m_client->GetLiveTVPriority(); if (g_bLiveTVPriority != savedLiveTVPriority) m_client->SetLiveTVPriority(savedLiveTVPriority); /* End of process */ // Connected. std::string msg = XBMC->GetLocalizedString(30114); XBMC->QueueNotification(QUEUE_INFO, msg.c_str()); break; } if (notifyAddonFailure) { PVRClientMythTV::CONN_ERROR error = m_client->GetConnectionError(); if (error == PVRClientMythTV::CONN_ERROR_UNKNOWN_VERSION) { // Failed to connect the MythTV backend with the known protocol versions. std::string msg = XBMC->GetLocalizedString(30300); XBMC->QueueNotification(QUEUE_ERROR, msg.c_str()); } else if (error == PVRClientMythTV::CONN_ERROR_API_UNAVAILABLE) { // Failed to connect the API services of MythTV backend. Please check your PIN code or backend setup. std::string msg = XBMC->GetLocalizedString(30301); XBMC->QueueNotification(QUEUE_ERROR, msg.c_str()); } else { // No response from MythTV backend. std::string msg = XBMC->GetLocalizedString(30304); XBMC->QueueNotification(QUEUE_WARNING, msg.c_str()); } // No longer notify the failure notifyAddonFailure = false; } else { m_alarm.Wait(PVRCLIENT_LAUNCHER_RETRY * 1000); } } XBMC->Log(LOG_NOTICE, "Launcher stopped"); // Signal the launcher has finished m_alarm.Broadcast(); return 0; } pvr.mythtv-5.10.15-Leia/src/pvrclient-launcher.h000066400000000000000000000022471360567320200214520ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2017 Team Kodi * http://www.kodi.tv * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "pvrclient-mythtv.h" #define PVRCLIENT_LAUNCHER_RETRY 30 /* Wait for 30 seconds before retry */ class PVRClientLauncherPrivate; class PVRClientLauncher { public: PVRClientLauncher(PVRClientMythTV* client); ~PVRClientLauncher(); bool Start(); bool WaitForCompletion(unsigned timeout); private: PVRClientLauncherPrivate *m_p; }; pvr.mythtv-5.10.15-Leia/src/pvrclient-mythtv.cpp000066400000000000000000002715731360567320200215510ustar00rootroot00000000000000/* * Copyright (C) 2005-2014 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, 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 XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * http://www.gnu.org/copyleft/gpl.html * */ #include "pvrclient-mythtv.h" #include "client.h" #include "tools.h" #include "avinfo.h" #include "filestreaming.h" #include "taskhandler.h" #include "private/os/threads/mutex.h" #include #include #include using namespace ADDON; PVRClientMythTV::PVRClientMythTV() : m_connectionError(CONN_ERROR_NOT_CONNECTED) , m_eventHandler(NULL) , m_control(NULL) , m_liveStream(NULL) , m_recordingStream(NULL) , m_dummyStream(NULL) , m_hang(false) , m_powerSaving(false) , m_stopTV(false) , m_artworksManager(NULL) , m_scheduleManager(NULL) , m_lock(new Myth::OS::CMutex) , m_todo(NULL) , m_channelsLock(new Myth::OS::CMutex) , m_recordingsLock(new Myth::OS::CMutex) , m_recordingChangePinCount(0) , m_recordingsAmountChange(false) , m_recordingsAmount(0) , m_deletedRecAmountChange(false) , m_deletedRecAmount(0) { } PVRClientMythTV::~PVRClientMythTV() { SAFE_DELETE(m_todo); SAFE_DELETE(m_dummyStream); SAFE_DELETE(m_liveStream); SAFE_DELETE(m_recordingStream); SAFE_DELETE(m_artworksManager); SAFE_DELETE(m_scheduleManager); SAFE_DELETE(m_eventHandler); SAFE_DELETE(m_control); delete m_recordingsLock; delete m_channelsLock; delete m_lock; } static void Log(int level, char *msg) { if (msg && level != MYTH_DBG_NONE) { bool doLog = true; //g_bExtraDebug; addon_log_t loglevel = LOG_DEBUG; switch (level) { case MYTH_DBG_ERROR: loglevel = LOG_ERROR; doLog = true; break; case MYTH_DBG_WARN: loglevel = LOG_NOTICE; doLog = true; break; case MYTH_DBG_INFO: loglevel = LOG_INFO; doLog = true; break; case MYTH_DBG_DEBUG: case MYTH_DBG_PROTO: case MYTH_DBG_ALL: loglevel = LOG_DEBUG; break; } if (XBMC && doLog) XBMC->Log(loglevel, "%s", msg); } } void PVRClientMythTV::SetDebug(bool silent /*= false*/) { // Setup libcppmyth logging if (g_bExtraDebug) Myth::DBGAll(); else if (silent) Myth::DBGLevel(MYTH_DBG_NONE); else Myth::DBGLevel(MYTH_DBG_ERROR); Myth::SetDBGMsgCallback(Log); } bool PVRClientMythTV::Connect() { assert(m_control == NULL); SetDebug(true); Myth::Control *control = new Myth::Control(g_szMythHostname, g_iProtoPort, g_iWSApiPort, g_szWSSecurityPin, true); if (!control->IsOpen()) { switch(control->GetProtoError()) { case Myth::ProtoBase::ERROR_UNKNOWN_VERSION: m_connectionError = CONN_ERROR_UNKNOWN_VERSION; break; default: m_connectionError = CONN_ERROR_SERVER_UNREACHABLE; } delete control; XBMC->Log(LOG_NOTICE, "Failed to connect to MythTV backend on %s:%d", g_szMythHostname.c_str(), g_iProtoPort); // Try wake up for the next attempt if (!g_szMythHostEther.empty()) XBMC->WakeOnLan(g_szMythHostEther.c_str()); return false; } if (!control->CheckService()) { m_connectionError = CONN_ERROR_API_UNAVAILABLE; delete control; XBMC->Log(LOG_NOTICE,"Failed to connect to MythTV backend on %s:%d with pin %s", g_szMythHostname.c_str(), g_iWSApiPort, g_szWSSecurityPin.c_str()); return false; } m_connectionError = CONN_ERROR_NO_ERROR; m_control = control; SetDebug(false); // Create event handler and subscription as needed unsigned subid = 0; m_eventHandler = new Myth::EventHandler(g_szMythHostname, g_iProtoPort); subid = m_eventHandler->CreateSubscription(this); m_eventHandler->SubscribeForEvent(subid, Myth::EVENT_HANDLER_STATUS); m_eventHandler->SubscribeForEvent(subid, Myth::EVENT_HANDLER_TIMER); m_eventHandler->SubscribeForEvent(subid, Myth::EVENT_ASK_RECORDING); m_eventHandler->SubscribeForEvent(subid, Myth::EVENT_RECORDING_LIST_CHANGE); // Create schedule manager and new subscription handled by dedicated thread m_scheduleManager = new MythScheduleManager(g_szMythHostname, g_iProtoPort, g_iWSApiPort, g_szWSSecurityPin); subid = m_eventHandler->CreateSubscription(this); m_eventHandler->SubscribeForEvent(subid, Myth::EVENT_SCHEDULE_CHANGE); // Create artwork manager m_artworksManager = new ArtworkManager(g_szMythHostname, g_iWSApiPort, g_szWSSecurityPin); // Create the task handler to process various task m_todo = new TaskHandler(); // Now all is ready: Start event handler m_eventHandler->Start(); return true; } PVRClientMythTV::CONN_ERROR PVRClientMythTV::GetConnectionError() const { return m_connectionError; } unsigned PVRClientMythTV::GetBackendAPIVersion() { if (m_control) return m_control->CheckService(); return 0; } const char *PVRClientMythTV::GetBackendName() { static std::string myName; myName.clear(); if (m_control) myName.append("MythTV (").append(m_control->GetServerHostName()).append(")"); XBMC->Log(LOG_DEBUG, "%s: %s", __FUNCTION__, myName.c_str()); return myName.c_str(); } const char *PVRClientMythTV::GetBackendVersion() { static std::string myVersion; myVersion.clear(); if (m_control) { Myth::VersionPtr version = m_control->GetVersion(); myVersion = version->version; } XBMC->Log(LOG_DEBUG, "%s: %s", __FUNCTION__, myVersion.c_str()); return myVersion.c_str(); } const char *PVRClientMythTV::GetConnectionString() { static std::string myConnectionString; myConnectionString.clear(); myConnectionString.append("http://").append(g_szMythHostname).append(":").append(Myth::IntToString(g_iWSApiPort)); XBMC->Log(LOG_DEBUG, "%s: %s", __FUNCTION__, myConnectionString.c_str()); return myConnectionString.c_str(); } PVR_ERROR PVRClientMythTV::GetDriveSpace(long long *iTotal, long long *iUsed) { if (!m_control) return PVR_ERROR_SERVER_ERROR; if (g_bExtraDebug) XBMC->Log(LOG_DEBUG, "%s", __FUNCTION__); int64_t total = 0, used = 0; if (m_control->QueryFreeSpaceSummary(&total, &used)) { *iTotal = (long long)total; *iUsed = (long long)used; return PVR_ERROR_NO_ERROR; } return PVR_ERROR_UNKNOWN; } void PVRClientMythTV::OnSleep() { if (m_eventHandler) m_eventHandler->Stop(); if (m_scheduleManager) m_scheduleManager->CloseControl(); if (m_control) m_control->Close(); } void PVRClientMythTV::OnWake() { if (m_control) m_control->Open(); if (m_scheduleManager) m_scheduleManager->OpenControl(); if (m_eventHandler) m_eventHandler->Start(); } void PVRClientMythTV::OnDeactivatedGUI() { if (g_bAllowMythShutdown && m_control && m_control->IsOpen()) AllowBackendShutdown(); m_powerSaving = true; } void PVRClientMythTV::OnActivatedGUI() { // block shutdown if backend is connected if (g_bAllowMythShutdown && m_control && m_control->IsOpen()) BlockBackendShutdown(); m_powerSaving = false; } void PVRClientMythTV::HandleBackendMessage(Myth::EventMessagePtr msg) { switch (msg->event) { case Myth::EVENT_SCHEDULE_CHANGE: HandleScheduleChange(); break; case Myth::EVENT_ASK_RECORDING: HandleAskRecording(*msg); break; case Myth::EVENT_RECORDING_LIST_CHANGE: HandleRecordingListChange(*msg); break; case Myth::EVENT_HANDLER_TIMER: RunHouseKeeping(); break; case Myth::EVENT_HANDLER_STATUS: if (msg->subject[0] == EVENTHANDLER_DISCONNECTED) { m_hang = true; if (m_control) m_control->Close(); if (m_scheduleManager) m_scheduleManager->CloseControl(); XBMC->QueueNotification(QUEUE_ERROR, XBMC->GetLocalizedString(30302)); // Connection to MythTV backend lost } else if (msg->subject[0] == EVENTHANDLER_CONNECTED) { if (m_hang) { if (m_control) m_control->Open(); if (m_scheduleManager) m_scheduleManager->OpenControl(); m_hang = false; XBMC->QueueNotification(QUEUE_INFO, XBMC->GetLocalizedString(30303)); // Connection to MythTV restored // still in mode power saving I have to allow shutdown again if (m_powerSaving && g_bAllowMythShutdown) AllowBackendShutdown(); } // Refreshing all HandleChannelChange(); HandleScheduleChange(); HandleRecordingListChange(Myth::EventMessage()); } else if (msg->subject[0] == EVENTHANDLER_NOTCONNECTED) { // Try wake up if GUI is activated if (!m_powerSaving && !g_szMythHostEther.empty()) XBMC->WakeOnLan(g_szMythHostEther.c_str()); } break; default: break; } } void PVRClientMythTV::HandleChannelChange() { FillChannelsAndChannelGroups(); PVR->TriggerChannelUpdate(); PVR->TriggerChannelGroupsUpdate(); } void PVRClientMythTV::HandleScheduleChange() { if (!m_scheduleManager) return; m_scheduleManager->Update(); PVR->TriggerTimerUpdate(); } void PVRClientMythTV::HandleAskRecording(const Myth::EventMessage& msg) { if (!m_control) return; // ASK_RECORDING