From bb0882c5dad030f676e424265ebcd869bb3ff899 Mon Sep 17 00:00:00 2001 From: Jan-Simon Möller Date: Mon, 16 Apr 2018 22:14:52 +0200 Subject: Introduce meta-agl-profile-core and meta-agl-profile-graphics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rework towards agl profiles. This change is part of a series of changes to create the AGL profiles. This set will mainly introduce the 'core' profile. It is setup to be a drop-in change, thus some files were kept in (dummy) locations for now. However, they'll be taken care of in the next changes in this series. The main target of the meta-agl-profile-core layer is to host: - a minimal, bootable image with network and package management enabled -- agl-image-boot - a minimal image with network and packagemanagement and the AGL APIs -- agl-image-minimal The layer meta-agl-profile-graphical is used as superset of these and includes support for egl+wayland+weston. All recipes concerning graphics were moved there. This is not a full profile as we still have to migrate some parts of meta-agl-demo in a follow-up changeset. The roadmap as discussed during the F2F session in Karlsruhe is: - week 16 : core profile and profiles w/o graphics - week 17 : graphical profiles - week 18 : final conversion of the demo image v2: moved agl-login-manager from -graphics to -core (see Jose's comment) v3: moved back after discussion - follow-up in separate changeset Change-Id: Idacb0d1274baac1f63f8d1b850d4b1104ac33918 Signed-off-by: Jan-Simon Möller --- meta-agl-profile-core/classes/cloc.bbclass | 29 + meta-agl-profile-core/conf/include/agl-devel.inc | 15 + meta-agl-profile-core/conf/include/agl-gplv2.inc | 8 + meta-agl-profile-core/conf/include/base-agl.inc | 19 + meta-agl-profile-core/conf/layer.conf | 10 + meta-agl-profile-core/files/group | 90 + meta-agl-profile-core/files/passwd | 60 + .../recipes-core/dbus/.appends.core | 0 .../recipes-core/dbus/dbus-cynara_%.bbappend | 1 + .../recipes-core/dbus/dbus/dbus.service | 10 + .../recipes-core/dbus/dbus/dbus.socket | 9 + .../recipes-core/dbus/dbus/dbus_env.conf | 5 + .../recipes-core/dbus/dbus_%.bbappend | 28 + .../recipes-core/glibc/.appends.core | 0 .../glibc/glibc/arm/local-arm-futex.diff | 22 + .../recipes-core/glibc/glibc_2.2%.bbappend | 3 + .../recipes-core/images/agl-image-boot.bb | 9 + .../recipes-core/images/agl-image-boot.inc | 10 + .../recipes-core/images/agl-image-minimal-qa.bb | 12 + .../recipes-core/images/agl-image-minimal.bb | 9 + .../recipes-core/images/agl-image-minimal.inc | 10 + .../packagegroup-agl-core-automotive.bb | 13 + .../packagegroup-agl-core-connectivity.bb | 15 + .../packagegroup-agl-core-graphics.bb | 10 + .../packagegroups/packagegroup-agl-core-kernel.bb | 13 + .../packagegroup-agl-core-multimedia.bb | 13 + .../packagegroup-agl-core-navi-lbs.bb | 13 + .../packagegroup-agl-core-os-commonlibs.bb | 13 + .../packagegroup-agl-core-security.bb | 13 + .../packagegroup-agl-core-speech-services.bb | 13 + .../packagegroups/packagegroup-agl-image-boot.bb | 18 + .../packagegroup-agl-image-minimal.bb | 27 + .../packagegroups/packagegroup-core-boot-agl.bb | 50 + .../recipes-core/psplash/.appends.core | 0 .../recipes-core/psplash/files/psplash-anim | 11 + .../recipes-core/psplash/files/psplash-colors.h | 34 + .../recipes-core/psplash/files/psplash-poky-img.h | 5411 +++++++++++++++++ .../psplash/files/psplash-quit.service | 11 + .../psplash/files/psplash-start.service | 12 + .../recipes-core/psplash/psplash_git.bbappend | 27 + .../recipes-core/systemd/.appends.core | 0 .../systemd/0001-Switch-Smack-label-earlier.patch | 52 + .../recipes-core/systemd/systemd/e2fsck.conf | 3 + .../recipes-core/systemd/systemd/wired.network | 5 + .../recipes-core/systemd/systemd_%.bbappend | 26 + .../recipes-core/systemd/systemd_234.bbappend | 6 + .../recipes-devtools/gdb/gdb_%.bbappend | 1 + .../low-level-can-generator_git.bb | 16 + .../nativesdk-packagegroup-sdk-host.bbappend | 1 + .../packagegroups/packagegroup-agl-devel.bb | 24 + .../run-agl-postinsts/run-agl-postinsts | 48 + .../run-agl-postinsts/run-agl-postinsts.service | 17 + .../run-agl-postinsts/run-agl-postinsts_1.0.bb | 46 + .../run-postinsts/run-postinsts_%.bbappend | 5 + .../recipes-ivi/images/agl-image-ivi-crosssdk.bb | 19 + .../recipes-ivi/images/agl-image-ivi-qa.bb | 14 + .../recipes-ivi/images/agl-image-ivi.bb | 17 + .../recipes-ivi/images/agl-image-ivi.inc | 3 + .../packagegroups/packagegroup-agl-image-ivi.bb | 31 + .../packagegroup-agl-ivi-automotive.bb | 14 + .../packagegroup-agl-ivi-connectivity.bb | 19 + .../packagegroups/packagegroup-agl-ivi-graphics.bb | 14 + .../packagegroups/packagegroup-agl-ivi-kernel.bb | 14 + .../packagegroup-agl-ivi-multimedia.bb | 17 + .../packagegroups/packagegroup-agl-ivi-navi-lbs.bb | 14 + .../packagegroup-agl-ivi-os-commonlibs.bb | 14 + .../packagegroups/packagegroup-agl-ivi-security.bb | 14 + .../packagegroup-agl-ivi-speech-services.bb | 14 + .../gstreamer1.0-plugins-good_%.bbappend | 2 + .../lightmediascanner/.appends.meta-efl | 0 ...ine-comparison_fn_t-for-non-glibc-systems.patch | 33 + .../files/dbus-lightmediascanner.conf | 7 + .../id3-plugin-support-out-of-tree-build.patch | 11 + .../files/lightmediascanner.service | 11 + .../files/plugin-ogg-fix-chucksize-issue.patch | 53 + .../lightmediascanner/lightmediascanner_%.bbappend | 33 + .../lightmediascanner/lightmediascanner_0.5.1.bb | 63 + .../pulseaudio/agl-audio-plugin_0.1.bb | 28 + ...01-install-files-for-a-module-development.patch | 78 + ...ume-ramp-additions-to-the-low-level-infra.patch | 566 ++ ...-ramp-adding-volume-ramping-to-sink-input.patch | 189 + ...put-Code-cleanup-regarding-volume-ramping.patch | 62 + ...volume-Add-support-for-volume-ramp-factor.patch | 299 + ...nput-Remove-pa_sink_input_set_volume_ramp.patch | 63 + .../pulseaudio-10.0/enable-ofono-hfp-backend.patch | 11 + ...08-install-files-for-a-module-development.patch | 53 + ...ume-ramp-additions-to-the-low-level-infra.patch | 503 ++ ...-ramp-adding-volume-ramping-to-sink-input.patch | 159 + ...12-volume-ramp-add-volume-ramping-to-sink.patch | 159 + ...add-internal-corking-state-for-sink-input.patch | 72 + .../pulseaudio/0020-core-util-Add-pa_join.patch | 37 + ...21-dynarray-Add-pa_dynarray_get_raw_array.patch | 21 + ...022-device-port-Add-pa_device_port.active.patch | 198 + .../0030-volume-api-Add-libvolume-api.patch | 6118 ++++++++++++++++++++ .../0031-Add-module-main-volume-policy.patch | 1418 +++++ .../0039-main-volume-policy-adapt-to-pa6rev.patch | 11 + .../pulseaudio/pulseaudio_%.bbappend | 28 + .../pulseaudio/pulseaudio_10.0.bbappend | 15 + .../files/org.freedesktop.GeoClue2.Client.conf | 8 + .../recipes-navigation/geoclue/geoclue_%.bbappend | 9 + .../recipes-navigation/gpsd/gpsd_%.bbappend | 14 + .../recipes-support/libsoup/libsoup-2.4_%.bbappend | 1 + .../recipes-test/aiostress/aiostress_0.22.bb | 24 + .../blobsallad/blobsallad/0001-Makefile.patch | 53 + .../blobsallad/blobsallad/0002-auto.patch | 95 + .../blobsallad/blobsallad/0003-printcleanup.patch | 11 + .../blobsallad/blobsallad/0004-bs_main.c.patch | 15 + .../blobsallad/blobsallad_2006-11-14-23-57.bb | 36 + .../recipes-test/dung/dung_3.4.25-m2.bb | 18 + .../recipes-test/ebizzy/ebizzy_0.3.bb | 20 + .../recipes-test/ffsb/ffsb_6.0-rc2.bb | 14 + .../recipes-test/fontconfig/fontconfig_%.bbappend | 17 + .../files/0001-Makefile-dont-build-gfx-demos.patch | 32 + ...mos-Makefile-Do-not-hardcode-libtool-path.patch | 30 + .../recipes-test/freetype/freetype_2.8.bbappend | 32 + .../files/0001-fix_missing_header_sys_stat.patch | 11 + .../recipes-test/fsfuzzer/fsfuzzer_0.7.bb | 18 + .../recipes-test/glmark2/glmark2_%.bbappend | 2 + .../recipes-test/himeno/himeno_2.0.bb | 27 + .../interbench/files/interbench.c.patch | 68 + .../recipes-test/interbench/interbench_0.31.bb | 31 + .../iperf-2.0.9/0001-fix-out-of-tree-config.patch | 52 + .../iperf/iperf-2.0.9/0002-fix-bool-size-m4.patch | 16 + .../iperf/iperf-2.0.9/iperf-2.0.5_ManPage.patch | 8 + .../recipes-test/iperf/iperf_2.0.9.bb | 20 + .../recipes-test/ipv6connect/ipv6connect.bb | 24 + .../recipes-test/linpack/linpack.bb | 23 + .../recipes-test/linus-stress/linus-stress.bb | 23 + .../packagegroups/packagegroup-agl-test.bb | 57 + .../recipes-test/trinity/trinity_git.bb | 42 + meta-agl-profile-demo/conf/layer.conf | 10 + .../bluez-alsa/bluez-alsa_git.bb | 38 + .../bluez-alsa/files/bluez-alsa.service | 11 + .../bluez5/bluez5/bluetooth.conf | 39 + .../recipes-connectivity/bluez5/bluez5_%.bbappend | 6 + .../busybox/busybox_%.bbappend | 2 + .../busybox/files/enable-wget-https.cfg | 3 + .../connman-ncurses/connman-ncurses_git.bb | 26 + .../recipes-connectivity/connman/.appends.core | 0 .../connman/connman_%.bbappend | 3 + .../files/0001-disable-when-booting-over-nfs.patch | 11 + .../0001-remove-I-usr-include-in-pkg-config.patch | 40 + .../recipes-connectivity/rtl-sdr/rtl-sdr_0.5.3.bb | 26 + .../rygel/.appends.meta-multimedia | 0 ...-missing-link-to-unistring-for-lms-plugin.patch | 28 + .../recipes-connectivity/rygel/files/rygel.service | 13 + .../recipes-connectivity/rygel/rygel_%.bbappend | 25 + .../packagegroup-ivi-common-core-multimedia.bb | 13 + .../0001-Fix-build-with-systemd-209.patch | 30 + ...on-t-execute-processes-as-a-specific-user.patch | 81 + ...t-type-should-be-in-lowercase-so-use-Type.patch | 98 + .../0004-Modify-systemd-config-directory.patch | 24 + .../dlt-daemon/dlt-daemon_2.11.1.bb | 54 + .../dlt-daemon/dlt-daemon_2.15.0.bb | 52 + .../0001-Fix-duplicated-command-line-arg-t.patch | 25 + .../audiomanager/audiomanager/audiomanager.service | 17 + .../audiomanager/audiomanager_7.4.bb | 56 + .../classes/agl-graphical.bbclass | 7 + meta-agl-profile-graphical/conf/layer.conf | 10 + .../agl-login-manager/agl-login-manager_0.1.bb | 21 + .../agl-desktop-config/agl-desktop-config_0.1.bb | 21 + .../agl-desktop-config/files/user-weston-term.path | 8 + .../files/user-weston-term.service | 12 + .../recipes-graphics/images/agl-image-weston.bb | 12 + .../recipes-graphics/images/agl-image-weston.inc | 7 + .../packagegroups/packagegroup-agl-image-weston.bb | 17 + .../wayland/Readme.weston-ini-conf | 34 + ...ton-crush-when-repeat-touching-very-quick.patch | 31 + .../0001-simple-id-agent-initial-commit.patch | 264 + .../0002-ivi-controller-load-id-agent-module.patch | 69 + ...ler-add-resize-setting-suit-to-surface-si.patch | 62 + .../disable-sanitizer-tests.patch | 13 + .../wandboard_fix_build.patch | 13 + .../wayland/wayland-ivi-extension_1.13.0.bb | 33 + .../wayland/wayland-ivi-extension_2.0.2.bb | 31 + .../0001-Change-socket-mode-add-rw-for-group.patch | 29 + .../recipes-graphics/wayland/wayland_%.bbappend | 6 + .../recipes-graphics/wayland/weston-ini-conf.bb | 30 + .../wayland/weston-ini-conf/core.cfg | 4 + .../wayland/weston-ini-conf/hdmi-a-1-270.cfg | 6 + .../wayland/weston-ini-conf/hdmi-a-1-90.cfg | 6 + .../wayland/weston-ini-conf/id-agent.cfg | 2 + .../wayland/weston-ini-conf/ivishell.cfg | 4 + .../wayland/weston-ini-conf/shell.cfg | 3 + .../recipes-graphics/wayland/weston-init.bbappend | 79 + .../wayland/weston-init/weston.service.add | 7 + .../wayland/weston-init/weston_tmpfiles.conf | 6 + ...llow-regular-users-to-launch-Weston_2.0.0.patch | 46 + ...-rework-goto-labels-to-avoid-memory-leaks.patch | 66 + .../weston/0002-ivi-shell-removed-assert.patch | 11 + ...-ivi-shell-introduction-of-IVI_INVALID_ID.patch | 18 + ...face-added-interface-to-change-surface-id.patch | 73 + ...yout-introcuded-configure_desktop_changed.patch | 74 + ...t-introcuded-surface_create_and_configure.patch | 117 + ...inked-libweston-desktop-and-added-structs.patch | 74 + ...ayout-use-libweston-desktop-api-for-views.patch | 30 + ...dded-libweston-desktop-api_implementation.patch | 166 + ...ivi-shell-remove-surface_destroy_listener.patch | 24 + ...l-create-weston-desktop-in_wet_shell_init.patch | 34 + ...r-register-for-desktop_surface_configured.patch | 133 + ...simple-egl-remove-ivi-application-support.patch | 164 + ...simple-shm-remove-ivi-application-support.patch | 107 + ...dow-client-remove-ivi-application-support.patch | 130 + ...016-ivi-shell_add_screen_remove_layer_api.patch | 82 + .../recipes-graphics/wayland/weston_2.0.0.bbappend | 23 + meta-agl/classes/.gitkeep | 0 meta-agl/classes/agl-graphical.bbclass | 7 - meta-agl/classes/cloc.bbclass | 29 - meta-agl/conf/include/agl-devel.inc | 15 - meta-agl/conf/include/agl-gplv2.inc | 8 - meta-agl/conf/include/base-agl.inc | 19 - meta-agl/files/group | 90 - meta-agl/files/passwd | 60 - meta-agl/recipes-automotive/.gitkeep | 0 meta-agl/recipes-bsp/.gitkeep | 0 .../agl-login-manager/agl-login-manager_0.1.bb | 21 - .../bluez-alsa/bluez-alsa_git.bb | 38 - .../bluez-alsa/files/bluez-alsa.service | 11 - .../bluez5/bluez5/bluetooth.conf | 39 - .../recipes-connectivity/bluez5/bluez5_%.bbappend | 6 - .../busybox/busybox_%.bbappend | 2 - .../busybox/files/enable-wget-https.cfg | 3 - .../connman-ncurses/connman-ncurses_git.bb | 26 - .../recipes-connectivity/connman/.appends.core | 0 .../connman/connman_%.bbappend | 3 - .../files/0001-disable-when-booting-over-nfs.patch | 11 - .../0001-remove-I-usr-include-in-pkg-config.patch | 40 - .../recipes-connectivity/rtl-sdr/rtl-sdr_0.5.3.bb | 26 - .../rygel/.appends.meta-multimedia | 0 ...-missing-link-to-unistring-for-lms-plugin.patch | 28 - .../recipes-connectivity/rygel/files/rygel.service | 13 - .../recipes-connectivity/rygel/rygel_%.bbappend | 25 - meta-agl/recipes-core/dbus/.appends.core | 0 meta-agl/recipes-core/dbus/dbus-cynara_%.bbappend | 1 - meta-agl/recipes-core/dbus/dbus/dbus.service | 10 - meta-agl/recipes-core/dbus/dbus/dbus.socket | 9 - meta-agl/recipes-core/dbus/dbus/dbus_env.conf | 5 - meta-agl/recipes-core/dbus/dbus_%.bbappend | 28 - meta-agl/recipes-core/glibc/.appends.core | 0 .../glibc/glibc/arm/local-arm-futex.diff | 22 - meta-agl/recipes-core/glibc/glibc_2.2%.bbappend | 3 - .../recipes-core/images/agl-image-minimal-qa.bb | 12 - meta-agl/recipes-core/images/agl-image-minimal.bb | 9 - meta-agl/recipes-core/images/agl-image-minimal.inc | 10 - .../packagegroup-agl-core-automotive.bb | 13 - .../packagegroup-agl-core-connectivity.bb | 15 - .../packagegroup-agl-core-graphics.bb | 10 - .../packagegroups/packagegroup-agl-core-kernel.bb | 13 - .../packagegroup-agl-core-multimedia.bb | 13 - .../packagegroup-agl-core-navi-lbs.bb | 13 - .../packagegroup-agl-core-os-commonlibs.bb | 13 - .../packagegroup-agl-core-security.bb | 13 - .../packagegroup-agl-core-speech-services.bb | 13 - .../packagegroup-agl-image-minimal.bb | 27 - .../packagegroups/packagegroup-core-boot-agl.bb | 50 - meta-agl/recipes-core/psplash/.appends.core | 0 meta-agl/recipes-core/psplash/files/psplash-anim | 11 - .../recipes-core/psplash/files/psplash-colors.h | 34 - .../recipes-core/psplash/files/psplash-poky-img.h | 5411 ----------------- .../psplash/files/psplash-quit.service | 11 - .../psplash/files/psplash-start.service | 12 - meta-agl/recipes-core/psplash/psplash_git.bbappend | 27 - meta-agl/recipes-core/systemd/.appends.core | 0 .../systemd/0001-Switch-Smack-label-earlier.patch | 52 - meta-agl/recipes-core/systemd/systemd/e2fsck.conf | 3 - .../recipes-core/systemd/systemd/wired.network | 5 - meta-agl/recipes-core/systemd/systemd_%.bbappend | 26 - meta-agl/recipes-core/systemd/systemd_234.bbappend | 6 - meta-agl/recipes-devtools/gdb/gdb_%.bbappend | 1 - .../low-level-can-generator_git.bb | 16 - .../nativesdk-packagegroup-sdk-host.bbappend | 1 - .../packagegroups/packagegroup-agl-devel.bb | 24 - .../run-agl-postinsts/run-agl-postinsts | 48 - .../run-agl-postinsts/run-agl-postinsts.service | 17 - .../run-agl-postinsts/run-agl-postinsts_1.0.bb | 46 - .../run-postinsts/run-postinsts_%.bbappend | 5 - .../agl-desktop-config/agl-desktop-config_0.1.bb | 21 - .../agl-desktop-config/files/user-weston-term.path | 8 - .../files/user-weston-term.service | 12 - .../recipes-graphics/images/agl-image-weston.bb | 12 - .../recipes-graphics/images/agl-image-weston.inc | 7 - .../packagegroups/packagegroup-agl-image-weston.bb | 17 - .../wayland/Readme.weston-ini-conf | 34 - .../0001-Change-socket-mode-add-rw-for-group.patch | 29 - .../recipes-graphics/wayland/wayland_%.bbappend | 5 - .../recipes-graphics/wayland/weston-ini-conf.bb | 30 - .../wayland/weston-ini-conf/core.cfg | 4 - .../wayland/weston-ini-conf/hdmi-a-1-270.cfg | 6 - .../wayland/weston-ini-conf/hdmi-a-1-90.cfg | 6 - .../wayland/weston-ini-conf/id-agent.cfg | 2 - .../wayland/weston-ini-conf/ivishell.cfg | 4 - .../wayland/weston-ini-conf/shell.cfg | 3 - .../recipes-graphics/wayland/weston-init.bbappend | 79 - .../wayland/weston-init/weston.service.add | 7 - .../wayland/weston-init/weston_tmpfiles.conf | 6 - ...llow-regular-users-to-launch-Weston_2.0.0.patch | 46 - ...-rework-goto-labels-to-avoid-memory-leaks.patch | 66 - .../weston/0002-ivi-shell-removed-assert.patch | 11 - ...-ivi-shell-introduction-of-IVI_INVALID_ID.patch | 18 - ...face-added-interface-to-change-surface-id.patch | 73 - ...yout-introcuded-configure_desktop_changed.patch | 74 - ...t-introcuded-surface_create_and_configure.patch | 117 - ...inked-libweston-desktop-and-added-structs.patch | 74 - ...ayout-use-libweston-desktop-api-for-views.patch | 30 - ...dded-libweston-desktop-api_implementation.patch | 166 - ...ivi-shell-remove-surface_destroy_listener.patch | 24 - ...l-create-weston-desktop-in_wet_shell_init.patch | 34 - ...r-register-for-desktop_surface_configured.patch | 133 - ...simple-egl-remove-ivi-application-support.patch | 164 - ...simple-shm-remove-ivi-application-support.patch | 107 - ...dow-client-remove-ivi-application-support.patch | 130 - ...016-ivi-shell_add_screen_remove_layer_api.patch | 82 - .../recipes-graphics/wayland/weston_2.0.0.bbappend | 23 - .../recipes-ivi/images/agl-image-ivi-crosssdk.bb | 19 - meta-agl/recipes-ivi/images/agl-image-ivi-qa.bb | 14 - meta-agl/recipes-ivi/images/agl-image-ivi.bb | 17 - meta-agl/recipes-ivi/images/agl-image-ivi.inc | 3 - .../packagegroups/packagegroup-agl-image-ivi.bb | 32 - .../packagegroup-agl-ivi-automotive.bb | 14 - .../packagegroup-agl-ivi-connectivity.bb | 19 - .../packagegroups/packagegroup-agl-ivi-graphics.bb | 14 - .../packagegroups/packagegroup-agl-ivi-kernel.bb | 14 - .../packagegroup-agl-ivi-multimedia.bb | 17 - .../packagegroups/packagegroup-agl-ivi-navi-lbs.bb | 14 - .../packagegroup-agl-ivi-os-commonlibs.bb | 14 - .../packagegroups/packagegroup-agl-ivi-security.bb | 14 - .../packagegroup-agl-ivi-speech-services.bb | 14 - .../gstreamer1.0-plugins-good_%.bbappend | 2 - .../lightmediascanner/.appends.meta-efl | 0 ...ine-comparison_fn_t-for-non-glibc-systems.patch | 33 - .../files/dbus-lightmediascanner.conf | 7 - .../id3-plugin-support-out-of-tree-build.patch | 11 - .../files/lightmediascanner.service | 11 - .../files/plugin-ogg-fix-chucksize-issue.patch | 53 - .../lightmediascanner/lightmediascanner_%.bbappend | 33 - .../lightmediascanner/lightmediascanner_0.5.1.bb | 63 - .../pulseaudio/agl-audio-plugin_0.1.bb | 28 - meta-agl/recipes-navi-lbs/.gitkeep | 0 .../files/org.freedesktop.GeoClue2.Client.conf | 8 - .../recipes-navigation/geoclue/geoclue_%.bbappend | 9 - meta-agl/recipes-navigation/gpsd/gpsd_%.bbappend | 14 - meta-agl/recipes-support/.gitkeep | 0 .../recipes-support/libsoup/libsoup-2.4_%.bbappend | 1 - .../packagegroups/packagegroup-agl-test.bb | 15 - meta-ivi-common/classes/.gitkeep | 0 meta-ivi-common/conf/layer.conf | 10 - meta-ivi-common/recipes-connectivity/.gitkeep | 0 .../packagegroup-ivi-common-core-automotive.bb | 14 - .../packagegroup-ivi-common-core-connectivity.bb | 15 - .../packagegroup-ivi-common-core-graphics.bb | 17 - .../packagegroup-ivi-common-core-kernel.bb | 15 - .../packagegroup-ivi-common-core-multimedia.bb | 28 - .../packagegroup-ivi-common-core-navi-lbs.bb | 15 - .../packagegroup-ivi-common-core-os-commonlibs.bb | 16 - .../packagegroup-ivi-common-core-security.bb | 15 - ...packagegroup-ivi-common-core-speech-services.bb | 15 - .../packagegroups/packagegroup-ivi-common-core.bb | 23 - meta-ivi-common/recipes-devtools/.gitkeep | 0 meta-ivi-common/recipes-extended/.gitkeep | 0 .../0001-Fix-build-with-systemd-209.patch | 30 - ...on-t-execute-processes-as-a-specific-user.patch | 81 - ...t-type-should-be-in-lowercase-so-use-Type.patch | 98 - .../0004-Modify-systemd-config-directory.patch | 24 - .../dlt-daemon/dlt-daemon_2.11.1.bb | 54 - .../dlt-daemon/dlt-daemon_2.15.0.bb | 52 - meta-ivi-common/recipes-graphics/.gitkeep | 0 ...ton-crush-when-repeat-touching-very-quick.patch | 31 - .../0001-simple-id-agent-initial-commit.patch | 264 - .../0002-ivi-controller-load-id-agent-module.patch | 69 - ...ler-add-resize-setting-suit-to-surface-si.patch | 62 - .../disable-sanitizer-tests.patch | 13 - .../wandboard_fix_build.patch | 13 - .../wayland/wayland-ivi-extension_1.13.0.bb | 33 - .../wayland/wayland-ivi-extension_2.0.2.bb | 31 - .../recipes-graphics/wayland/weston_%.bbappend | 1 - .../0001-Fix-duplicated-command-line-arg-t.patch | 25 - .../audiomanager/audiomanager/audiomanager.service | 17 - .../audiomanager/audiomanager_7.4.bb | 56 - ...01-install-files-for-a-module-development.patch | 78 - ...ume-ramp-additions-to-the-low-level-infra.patch | 566 -- ...-ramp-adding-volume-ramping-to-sink-input.patch | 189 - ...put-Code-cleanup-regarding-volume-ramping.patch | 62 - ...volume-Add-support-for-volume-ramp-factor.patch | 299 - ...nput-Remove-pa_sink_input_set_volume_ramp.patch | 63 - .../pulseaudio-10.0/enable-ofono-hfp-backend.patch | 11 - ...08-install-files-for-a-module-development.patch | 53 - ...ume-ramp-additions-to-the-low-level-infra.patch | 503 -- ...-ramp-adding-volume-ramping-to-sink-input.patch | 159 - ...12-volume-ramp-add-volume-ramping-to-sink.patch | 159 - ...add-internal-corking-state-for-sink-input.patch | 72 - .../pulseaudio/0020-core-util-Add-pa_join.patch | 37 - ...21-dynarray-Add-pa_dynarray_get_raw_array.patch | 21 - ...022-device-port-Add-pa_device_port.active.patch | 198 - .../0030-volume-api-Add-libvolume-api.patch | 6118 -------------------- .../0031-Add-module-main-volume-policy.patch | 1418 ----- .../0039-main-volume-policy-adapt-to-pa6rev.patch | 11 - .../pulseaudio/pulseaudio_%.bbappend | 28 - .../pulseaudio/pulseaudio_10.0.bbappend | 15 - meta-ivi-common/recipes-support/.gitkeep | 0 .../recipes-test/aiostress/aiostress_0.22.bb | 24 - .../blobsallad/blobsallad/0001-Makefile.patch | 53 - .../blobsallad/blobsallad/0002-auto.patch | 95 - .../blobsallad/blobsallad/0003-printcleanup.patch | 11 - .../blobsallad/blobsallad/0004-bs_main.c.patch | 15 - .../blobsallad/blobsallad_2006-11-14-23-57.bb | 36 - .../recipes-test/dung/dung_3.4.25-m2.bb | 18 - meta-ivi-common/recipes-test/ebizzy/ebizzy_0.3.bb | 20 - meta-ivi-common/recipes-test/ffsb/ffsb_6.0-rc2.bb | 14 - .../recipes-test/fontconfig/fontconfig_%.bbappend | 17 - .../files/0001-Makefile-dont-build-gfx-demos.patch | 32 - ...mos-Makefile-Do-not-hardcode-libtool-path.patch | 30 - .../recipes-test/freetype/freetype_2.8.bbappend | 32 - .../files/0001-fix_missing_header_sys_stat.patch | 11 - .../recipes-test/fsfuzzer/fsfuzzer_0.7.bb | 18 - .../recipes-test/glmark2/glmark2_%.bbappend | 2 - meta-ivi-common/recipes-test/himeno/himeno_2.0.bb | 27 - .../interbench/files/interbench.c.patch | 68 - .../recipes-test/interbench/interbench_0.31.bb | 31 - .../iperf-2.0.9/0001-fix-out-of-tree-config.patch | 52 - .../iperf/iperf-2.0.9/0002-fix-bool-size-m4.patch | 16 - .../iperf/iperf-2.0.9/iperf-2.0.5_ManPage.patch | 8 - meta-ivi-common/recipes-test/iperf/iperf_2.0.9.bb | 20 - .../recipes-test/ipv6connect/ipv6connect.bb | 24 - meta-ivi-common/recipes-test/linpack/linpack.bb | 23 - .../recipes-test/linus-stress/linus-stress.bb | 23 - .../packagegroups/packagegroup-ivi-common-test.bb | 51 - .../recipes-test/trinity/trinity_git.bb | 42 - templates/base/00_local.conf.agl.inc | 3 + templates/base/bblayers.conf.sample | 24 +- .../feature/agl-appfw-smack/50_bblayers.conf.inc | 7 - .../feature/agl-appfw-smack/50_local.conf.inc | 2 - .../agl-ci-change-features-nogfx/included.dep | 2 +- .../feature/agl-ci-change-features/included.dep | 2 +- .../agl-ci-snapshot-features-nogfx/included.dep | 2 +- .../feature/agl-ci-snapshot-features/included.dep | 2 +- 435 files changed, 20674 insertions(+), 20775 deletions(-) create mode 100644 meta-agl-profile-core/classes/cloc.bbclass create mode 100644 meta-agl-profile-core/conf/include/agl-devel.inc create mode 100644 meta-agl-profile-core/conf/include/agl-gplv2.inc create mode 100644 meta-agl-profile-core/conf/include/base-agl.inc create mode 100644 meta-agl-profile-core/conf/layer.conf create mode 100644 meta-agl-profile-core/files/group create mode 100644 meta-agl-profile-core/files/passwd create mode 100644 meta-agl-profile-core/recipes-core/dbus/.appends.core create mode 120000 meta-agl-profile-core/recipes-core/dbus/dbus-cynara_%.bbappend create mode 100644 meta-agl-profile-core/recipes-core/dbus/dbus/dbus.service create mode 100644 meta-agl-profile-core/recipes-core/dbus/dbus/dbus.socket create mode 100644 meta-agl-profile-core/recipes-core/dbus/dbus/dbus_env.conf create mode 100644 meta-agl-profile-core/recipes-core/dbus/dbus_%.bbappend create mode 100644 meta-agl-profile-core/recipes-core/glibc/.appends.core create mode 100644 meta-agl-profile-core/recipes-core/glibc/glibc/arm/local-arm-futex.diff create mode 100644 meta-agl-profile-core/recipes-core/glibc/glibc_2.2%.bbappend create mode 100644 meta-agl-profile-core/recipes-core/images/agl-image-boot.bb create mode 100644 meta-agl-profile-core/recipes-core/images/agl-image-boot.inc create mode 100644 meta-agl-profile-core/recipes-core/images/agl-image-minimal-qa.bb create mode 100644 meta-agl-profile-core/recipes-core/images/agl-image-minimal.bb create mode 100644 meta-agl-profile-core/recipes-core/images/agl-image-minimal.inc create mode 100644 meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-automotive.bb create mode 100644 meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-connectivity.bb create mode 100644 meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-graphics.bb create mode 100644 meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-kernel.bb create mode 100644 meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-multimedia.bb create mode 100644 meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-navi-lbs.bb create mode 100644 meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-os-commonlibs.bb create mode 100644 meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-security.bb create mode 100644 meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-speech-services.bb create mode 100644 meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-image-boot.bb create mode 100644 meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-image-minimal.bb create mode 100644 meta-agl-profile-core/recipes-core/packagegroups/packagegroup-core-boot-agl.bb create mode 100644 meta-agl-profile-core/recipes-core/psplash/.appends.core create mode 100755 meta-agl-profile-core/recipes-core/psplash/files/psplash-anim create mode 100644 meta-agl-profile-core/recipes-core/psplash/files/psplash-colors.h create mode 100644 meta-agl-profile-core/recipes-core/psplash/files/psplash-poky-img.h create mode 100644 meta-agl-profile-core/recipes-core/psplash/files/psplash-quit.service create mode 100644 meta-agl-profile-core/recipes-core/psplash/files/psplash-start.service create mode 100644 meta-agl-profile-core/recipes-core/psplash/psplash_git.bbappend create mode 100644 meta-agl-profile-core/recipes-core/systemd/.appends.core create mode 100644 meta-agl-profile-core/recipes-core/systemd/systemd/0001-Switch-Smack-label-earlier.patch create mode 100644 meta-agl-profile-core/recipes-core/systemd/systemd/e2fsck.conf create mode 100644 meta-agl-profile-core/recipes-core/systemd/systemd/wired.network create mode 100644 meta-agl-profile-core/recipes-core/systemd/systemd_%.bbappend create mode 100644 meta-agl-profile-core/recipes-core/systemd/systemd_234.bbappend create mode 100644 meta-agl-profile-core/recipes-devtools/gdb/gdb_%.bbappend create mode 100644 meta-agl-profile-core/recipes-devtools/low-level-can-generator/low-level-can-generator_git.bb create mode 100644 meta-agl-profile-core/recipes-devtools/packagegroups/nativesdk-packagegroup-sdk-host.bbappend create mode 100644 meta-agl-profile-core/recipes-devtools/packagegroups/packagegroup-agl-devel.bb create mode 100755 meta-agl-profile-core/recipes-devtools/run-agl-postinsts/run-agl-postinsts/run-agl-postinsts create mode 100644 meta-agl-profile-core/recipes-devtools/run-agl-postinsts/run-agl-postinsts/run-agl-postinsts.service create mode 100644 meta-agl-profile-core/recipes-devtools/run-agl-postinsts/run-agl-postinsts_1.0.bb create mode 100644 meta-agl-profile-core/recipes-devtools/run-postinsts/run-postinsts_%.bbappend create mode 100644 meta-agl-profile-core/recipes-ivi/images/agl-image-ivi-crosssdk.bb create mode 100644 meta-agl-profile-core/recipes-ivi/images/agl-image-ivi-qa.bb create mode 100644 meta-agl-profile-core/recipes-ivi/images/agl-image-ivi.bb create mode 100644 meta-agl-profile-core/recipes-ivi/images/agl-image-ivi.inc create mode 100644 meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-image-ivi.bb create mode 100644 meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-automotive.bb create mode 100644 meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-connectivity.bb create mode 100644 meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-graphics.bb create mode 100644 meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-kernel.bb create mode 100644 meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-multimedia.bb create mode 100644 meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-navi-lbs.bb create mode 100644 meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-os-commonlibs.bb create mode 100644 meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-security.bb create mode 100644 meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-speech-services.bb create mode 100644 meta-agl-profile-core/recipes-multimedia/gstreamer1.0-plugins-good/gstreamer1.0-plugins-good_%.bbappend create mode 100644 meta-agl-profile-core/recipes-multimedia/lightmediascanner/.appends.meta-efl create mode 100644 meta-agl-profile-core/recipes-multimedia/lightmediascanner/files/0001-Define-comparison_fn_t-for-non-glibc-systems.patch create mode 100644 meta-agl-profile-core/recipes-multimedia/lightmediascanner/files/dbus-lightmediascanner.conf create mode 100644 meta-agl-profile-core/recipes-multimedia/lightmediascanner/files/id3-plugin-support-out-of-tree-build.patch create mode 100644 meta-agl-profile-core/recipes-multimedia/lightmediascanner/files/lightmediascanner.service create mode 100644 meta-agl-profile-core/recipes-multimedia/lightmediascanner/files/plugin-ogg-fix-chucksize-issue.patch create mode 100644 meta-agl-profile-core/recipes-multimedia/lightmediascanner/lightmediascanner_%.bbappend create mode 100644 meta-agl-profile-core/recipes-multimedia/lightmediascanner/lightmediascanner_0.5.1.bb create mode 100644 meta-agl-profile-core/recipes-multimedia/pulseaudio/agl-audio-plugin_0.1.bb create mode 100644 meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio-10.0/0001-install-files-for-a-module-development.patch create mode 100644 meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio-10.0/0002-volume-ramp-additions-to-the-low-level-infra.patch create mode 100644 meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio-10.0/0003-volume-ramp-adding-volume-ramping-to-sink-input.patch create mode 100644 meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio-10.0/0004-sink-input-Code-cleanup-regarding-volume-ramping.patch create mode 100644 meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio-10.0/0005-sink-input-volume-Add-support-for-volume-ramp-factor.patch create mode 100644 meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio-10.0/0006-sink-input-Remove-pa_sink_input_set_volume_ramp.patch create mode 100644 meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio-10.0/enable-ofono-hfp-backend.patch create mode 100644 meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0008-install-files-for-a-module-development.patch create mode 100644 meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0010-volume-ramp-additions-to-the-low-level-infra.patch create mode 100644 meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0011-volume-ramp-adding-volume-ramping-to-sink-input.patch create mode 100644 meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0012-volume-ramp-add-volume-ramping-to-sink.patch create mode 100644 meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0013-add-internal-corking-state-for-sink-input.patch create mode 100644 meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0020-core-util-Add-pa_join.patch create mode 100644 meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0021-dynarray-Add-pa_dynarray_get_raw_array.patch create mode 100644 meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0022-device-port-Add-pa_device_port.active.patch create mode 100644 meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0030-volume-api-Add-libvolume-api.patch create mode 100644 meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0031-Add-module-main-volume-policy.patch create mode 100644 meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0039-main-volume-policy-adapt-to-pa6rev.patch create mode 100644 meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio_%.bbappend create mode 100644 meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio_10.0.bbappend create mode 100644 meta-agl-profile-core/recipes-navigation/geoclue/files/org.freedesktop.GeoClue2.Client.conf create mode 100644 meta-agl-profile-core/recipes-navigation/geoclue/geoclue_%.bbappend create mode 100644 meta-agl-profile-core/recipes-navigation/gpsd/gpsd_%.bbappend create mode 100644 meta-agl-profile-core/recipes-support/libsoup/libsoup-2.4_%.bbappend create mode 100644 meta-agl-profile-core/recipes-test/aiostress/aiostress_0.22.bb create mode 100644 meta-agl-profile-core/recipes-test/blobsallad/blobsallad/0001-Makefile.patch create mode 100644 meta-agl-profile-core/recipes-test/blobsallad/blobsallad/0002-auto.patch create mode 100644 meta-agl-profile-core/recipes-test/blobsallad/blobsallad/0003-printcleanup.patch create mode 100644 meta-agl-profile-core/recipes-test/blobsallad/blobsallad/0004-bs_main.c.patch create mode 100644 meta-agl-profile-core/recipes-test/blobsallad/blobsallad_2006-11-14-23-57.bb create mode 100644 meta-agl-profile-core/recipes-test/dung/dung_3.4.25-m2.bb create mode 100644 meta-agl-profile-core/recipes-test/ebizzy/ebizzy_0.3.bb create mode 100644 meta-agl-profile-core/recipes-test/ffsb/ffsb_6.0-rc2.bb create mode 100644 meta-agl-profile-core/recipes-test/fontconfig/fontconfig_%.bbappend create mode 100644 meta-agl-profile-core/recipes-test/freetype/files/0001-Makefile-dont-build-gfx-demos.patch create mode 100644 meta-agl-profile-core/recipes-test/freetype/files/0001-ft2demos-Makefile-Do-not-hardcode-libtool-path.patch create mode 100644 meta-agl-profile-core/recipes-test/freetype/freetype_2.8.bbappend create mode 100644 meta-agl-profile-core/recipes-test/fsfuzzer/files/0001-fix_missing_header_sys_stat.patch create mode 100644 meta-agl-profile-core/recipes-test/fsfuzzer/fsfuzzer_0.7.bb create mode 100644 meta-agl-profile-core/recipes-test/glmark2/glmark2_%.bbappend create mode 100644 meta-agl-profile-core/recipes-test/himeno/himeno_2.0.bb create mode 100644 meta-agl-profile-core/recipes-test/interbench/files/interbench.c.patch create mode 100644 meta-agl-profile-core/recipes-test/interbench/interbench_0.31.bb create mode 100644 meta-agl-profile-core/recipes-test/iperf/iperf-2.0.9/0001-fix-out-of-tree-config.patch create mode 100644 meta-agl-profile-core/recipes-test/iperf/iperf-2.0.9/0002-fix-bool-size-m4.patch create mode 100644 meta-agl-profile-core/recipes-test/iperf/iperf-2.0.9/iperf-2.0.5_ManPage.patch create mode 100644 meta-agl-profile-core/recipes-test/iperf/iperf_2.0.9.bb create mode 100644 meta-agl-profile-core/recipes-test/ipv6connect/ipv6connect.bb create mode 100644 meta-agl-profile-core/recipes-test/linpack/linpack.bb create mode 100644 meta-agl-profile-core/recipes-test/linus-stress/linus-stress.bb create mode 100644 meta-agl-profile-core/recipes-test/packagegroups/packagegroup-agl-test.bb create mode 100644 meta-agl-profile-core/recipes-test/trinity/trinity_git.bb create mode 100644 meta-agl-profile-demo/conf/layer.conf create mode 100644 meta-agl-profile-demo/recipes-connectivity/bluez-alsa/bluez-alsa_git.bb create mode 100644 meta-agl-profile-demo/recipes-connectivity/bluez-alsa/files/bluez-alsa.service create mode 100644 meta-agl-profile-demo/recipes-connectivity/bluez5/bluez5/bluetooth.conf create mode 100644 meta-agl-profile-demo/recipes-connectivity/bluez5/bluez5_%.bbappend create mode 100644 meta-agl-profile-demo/recipes-connectivity/busybox/busybox_%.bbappend create mode 100644 meta-agl-profile-demo/recipes-connectivity/busybox/files/enable-wget-https.cfg create mode 100644 meta-agl-profile-demo/recipes-connectivity/connman-ncurses/connman-ncurses_git.bb create mode 100644 meta-agl-profile-demo/recipes-connectivity/connman/.appends.core create mode 100644 meta-agl-profile-demo/recipes-connectivity/connman/connman_%.bbappend create mode 100644 meta-agl-profile-demo/recipes-connectivity/connman/files/0001-disable-when-booting-over-nfs.patch create mode 100644 meta-agl-profile-demo/recipes-connectivity/rtl-sdr/rtl-sdr/0001-remove-I-usr-include-in-pkg-config.patch create mode 100644 meta-agl-profile-demo/recipes-connectivity/rtl-sdr/rtl-sdr_0.5.3.bb create mode 100644 meta-agl-profile-demo/recipes-connectivity/rygel/.appends.meta-multimedia create mode 100644 meta-agl-profile-demo/recipes-connectivity/rygel/files/0001-Fix-missing-link-to-unistring-for-lms-plugin.patch create mode 100644 meta-agl-profile-demo/recipes-connectivity/rygel/files/rygel.service create mode 100644 meta-agl-profile-demo/recipes-connectivity/rygel/rygel_%.bbappend create mode 100644 meta-agl-profile-demo/recipes-core/packagegroups/packagegroup-ivi-common-core-multimedia.bb create mode 100644 meta-agl-profile-demo/recipes-extended/dlt-daemon/dlt-daemon/0001-Fix-build-with-systemd-209.patch create mode 100644 meta-agl-profile-demo/recipes-extended/dlt-daemon/dlt-daemon/0002-Don-t-execute-processes-as-a-specific-user.patch create mode 100644 meta-agl-profile-demo/recipes-extended/dlt-daemon/dlt-daemon/0003-systemd-unit-type-should-be-in-lowercase-so-use-Type.patch create mode 100644 meta-agl-profile-demo/recipes-extended/dlt-daemon/dlt-daemon/0004-Modify-systemd-config-directory.patch create mode 100644 meta-agl-profile-demo/recipes-extended/dlt-daemon/dlt-daemon_2.11.1.bb create mode 100644 meta-agl-profile-demo/recipes-extended/dlt-daemon/dlt-daemon_2.15.0.bb create mode 100644 meta-agl-profile-demo/recipes-multimedia/audiomanager/audiomanager/0001-Fix-duplicated-command-line-arg-t.patch create mode 100644 meta-agl-profile-demo/recipes-multimedia/audiomanager/audiomanager/audiomanager.service create mode 100644 meta-agl-profile-demo/recipes-multimedia/audiomanager/audiomanager_7.4.bb create mode 100644 meta-agl-profile-graphical/classes/agl-graphical.bbclass create mode 100644 meta-agl-profile-graphical/conf/layer.conf create mode 100644 meta-agl-profile-graphical/recipes-config/agl-login-manager/agl-login-manager_0.1.bb create mode 100644 meta-agl-profile-graphical/recipes-graphics/agl-desktop-config/agl-desktop-config_0.1.bb create mode 100644 meta-agl-profile-graphical/recipes-graphics/agl-desktop-config/files/user-weston-term.path create mode 100644 meta-agl-profile-graphical/recipes-graphics/agl-desktop-config/files/user-weston-term.service create mode 100644 meta-agl-profile-graphical/recipes-graphics/images/agl-image-weston.bb create mode 100644 meta-agl-profile-graphical/recipes-graphics/images/agl-image-weston.inc create mode 100644 meta-agl-profile-graphical/recipes-graphics/packagegroups/packagegroup-agl-image-weston.bb create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/Readme.weston-ini-conf create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/wayland-ivi-extension/0001-Resolve-weston-crush-when-repeat-touching-very-quick.patch create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/wayland-ivi-extension/0001-simple-id-agent-initial-commit.patch create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/wayland-ivi-extension/0002-ivi-controller-load-id-agent-module.patch create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/wayland-ivi-extension/0003-ivi-controller-add-resize-setting-suit-to-surface-si.patch create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/wayland-ivi-extension/disable-sanitizer-tests.patch create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/wayland-ivi-extension/wandboard_fix_build.patch create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/wayland-ivi-extension_1.13.0.bb create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/wayland-ivi-extension_2.0.2.bb create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/wayland/0001-Change-socket-mode-add-rw-for-group.patch create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/wayland_%.bbappend create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/weston-ini-conf.bb create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/weston-ini-conf/core.cfg create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/weston-ini-conf/hdmi-a-1-270.cfg create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/weston-ini-conf/hdmi-a-1-90.cfg create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/weston-ini-conf/id-agent.cfg create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/weston-ini-conf/ivishell.cfg create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/weston-ini-conf/shell.cfg create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/weston-init.bbappend create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/weston-init/weston.service.add create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/weston-init/weston_tmpfiles.conf create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/weston/0001-Allow-regular-users-to-launch-Weston_2.0.0.patch create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/weston/0001-ivi-shell-rework-goto-labels-to-avoid-memory-leaks.patch create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/weston/0002-ivi-shell-removed-assert.patch create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/weston/0003-ivi-shell-introduction-of-IVI_INVALID_ID.patch create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/weston/0004-layout-interface-added-interface-to-change-surface-id.patch create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/weston/0005-ivi-layout-introcuded-configure_desktop_changed.patch create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/weston/0006-ivi-layout-introcuded-surface_create_and_configure.patch create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/weston/0007-ivi-shell-linked-libweston-desktop-and-added-structs.patch create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/weston/0008-ivi-layout-use-libweston-desktop-api-for-views.patch create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/weston/0009-ivi-shell-added-libweston-desktop-api_implementation.patch create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/weston/0010-ivi-shell-remove-surface_destroy_listener.patch create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/weston/0011-ivi-shell-create-weston-desktop-in_wet_shell_init.patch create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/weston/0012-hmi-controller-register-for-desktop_surface_configured.patch create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/weston/0013-simple-egl-remove-ivi-application-support.patch create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/weston/0014-simple-shm-remove-ivi-application-support.patch create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/weston/0015-window-client-remove-ivi-application-support.patch create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/weston/0016-ivi-shell_add_screen_remove_layer_api.patch create mode 100644 meta-agl-profile-graphical/recipes-graphics/wayland/weston_2.0.0.bbappend delete mode 100644 meta-agl/classes/.gitkeep delete mode 100644 meta-agl/classes/agl-graphical.bbclass delete mode 100644 meta-agl/classes/cloc.bbclass delete mode 100644 meta-agl/conf/include/agl-devel.inc delete mode 100644 meta-agl/conf/include/agl-gplv2.inc delete mode 100644 meta-agl/conf/include/base-agl.inc delete mode 100644 meta-agl/files/group delete mode 100644 meta-agl/files/passwd delete mode 100644 meta-agl/recipes-automotive/.gitkeep delete mode 100644 meta-agl/recipes-bsp/.gitkeep delete mode 100644 meta-agl/recipes-config/agl-login-manager/agl-login-manager_0.1.bb delete mode 100644 meta-agl/recipes-connectivity/bluez-alsa/bluez-alsa_git.bb delete mode 100644 meta-agl/recipes-connectivity/bluez-alsa/files/bluez-alsa.service delete mode 100644 meta-agl/recipes-connectivity/bluez5/bluez5/bluetooth.conf delete mode 100644 meta-agl/recipes-connectivity/bluez5/bluez5_%.bbappend delete mode 100644 meta-agl/recipes-connectivity/busybox/busybox_%.bbappend delete mode 100644 meta-agl/recipes-connectivity/busybox/files/enable-wget-https.cfg delete mode 100644 meta-agl/recipes-connectivity/connman-ncurses/connman-ncurses_git.bb delete mode 100644 meta-agl/recipes-connectivity/connman/.appends.core delete mode 100644 meta-agl/recipes-connectivity/connman/connman_%.bbappend delete mode 100644 meta-agl/recipes-connectivity/connman/files/0001-disable-when-booting-over-nfs.patch delete mode 100644 meta-agl/recipes-connectivity/rtl-sdr/rtl-sdr/0001-remove-I-usr-include-in-pkg-config.patch delete mode 100644 meta-agl/recipes-connectivity/rtl-sdr/rtl-sdr_0.5.3.bb delete mode 100644 meta-agl/recipes-connectivity/rygel/.appends.meta-multimedia delete mode 100644 meta-agl/recipes-connectivity/rygel/files/0001-Fix-missing-link-to-unistring-for-lms-plugin.patch delete mode 100644 meta-agl/recipes-connectivity/rygel/files/rygel.service delete mode 100644 meta-agl/recipes-connectivity/rygel/rygel_%.bbappend delete mode 100644 meta-agl/recipes-core/dbus/.appends.core delete mode 120000 meta-agl/recipes-core/dbus/dbus-cynara_%.bbappend delete mode 100644 meta-agl/recipes-core/dbus/dbus/dbus.service delete mode 100644 meta-agl/recipes-core/dbus/dbus/dbus.socket delete mode 100644 meta-agl/recipes-core/dbus/dbus/dbus_env.conf delete mode 100644 meta-agl/recipes-core/dbus/dbus_%.bbappend delete mode 100644 meta-agl/recipes-core/glibc/.appends.core delete mode 100644 meta-agl/recipes-core/glibc/glibc/arm/local-arm-futex.diff delete mode 100644 meta-agl/recipes-core/glibc/glibc_2.2%.bbappend delete mode 100644 meta-agl/recipes-core/images/agl-image-minimal-qa.bb delete mode 100644 meta-agl/recipes-core/images/agl-image-minimal.bb delete mode 100644 meta-agl/recipes-core/images/agl-image-minimal.inc delete mode 100644 meta-agl/recipes-core/packagegroups/packagegroup-agl-core-automotive.bb delete mode 100644 meta-agl/recipes-core/packagegroups/packagegroup-agl-core-connectivity.bb delete mode 100644 meta-agl/recipes-core/packagegroups/packagegroup-agl-core-graphics.bb delete mode 100644 meta-agl/recipes-core/packagegroups/packagegroup-agl-core-kernel.bb delete mode 100644 meta-agl/recipes-core/packagegroups/packagegroup-agl-core-multimedia.bb delete mode 100644 meta-agl/recipes-core/packagegroups/packagegroup-agl-core-navi-lbs.bb delete mode 100644 meta-agl/recipes-core/packagegroups/packagegroup-agl-core-os-commonlibs.bb delete mode 100644 meta-agl/recipes-core/packagegroups/packagegroup-agl-core-security.bb delete mode 100644 meta-agl/recipes-core/packagegroups/packagegroup-agl-core-speech-services.bb delete mode 100644 meta-agl/recipes-core/packagegroups/packagegroup-agl-image-minimal.bb delete mode 100644 meta-agl/recipes-core/packagegroups/packagegroup-core-boot-agl.bb delete mode 100644 meta-agl/recipes-core/psplash/.appends.core delete mode 100755 meta-agl/recipes-core/psplash/files/psplash-anim delete mode 100644 meta-agl/recipes-core/psplash/files/psplash-colors.h delete mode 100644 meta-agl/recipes-core/psplash/files/psplash-poky-img.h delete mode 100644 meta-agl/recipes-core/psplash/files/psplash-quit.service delete mode 100644 meta-agl/recipes-core/psplash/files/psplash-start.service delete mode 100644 meta-agl/recipes-core/psplash/psplash_git.bbappend delete mode 100644 meta-agl/recipes-core/systemd/.appends.core delete mode 100644 meta-agl/recipes-core/systemd/systemd/0001-Switch-Smack-label-earlier.patch delete mode 100644 meta-agl/recipes-core/systemd/systemd/e2fsck.conf delete mode 100644 meta-agl/recipes-core/systemd/systemd/wired.network delete mode 100644 meta-agl/recipes-core/systemd/systemd_%.bbappend delete mode 100644 meta-agl/recipes-core/systemd/systemd_234.bbappend delete mode 100644 meta-agl/recipes-devtools/gdb/gdb_%.bbappend delete mode 100644 meta-agl/recipes-devtools/low-level-can-generator/low-level-can-generator_git.bb delete mode 100644 meta-agl/recipes-devtools/packagegroups/nativesdk-packagegroup-sdk-host.bbappend delete mode 100644 meta-agl/recipes-devtools/packagegroups/packagegroup-agl-devel.bb delete mode 100755 meta-agl/recipes-devtools/run-agl-postinsts/run-agl-postinsts/run-agl-postinsts delete mode 100644 meta-agl/recipes-devtools/run-agl-postinsts/run-agl-postinsts/run-agl-postinsts.service delete mode 100644 meta-agl/recipes-devtools/run-agl-postinsts/run-agl-postinsts_1.0.bb delete mode 100644 meta-agl/recipes-devtools/run-postinsts/run-postinsts_%.bbappend delete mode 100644 meta-agl/recipes-graphics/agl-desktop-config/agl-desktop-config_0.1.bb delete mode 100644 meta-agl/recipes-graphics/agl-desktop-config/files/user-weston-term.path delete mode 100644 meta-agl/recipes-graphics/agl-desktop-config/files/user-weston-term.service delete mode 100644 meta-agl/recipes-graphics/images/agl-image-weston.bb delete mode 100644 meta-agl/recipes-graphics/images/agl-image-weston.inc delete mode 100644 meta-agl/recipes-graphics/packagegroups/packagegroup-agl-image-weston.bb delete mode 100644 meta-agl/recipes-graphics/wayland/Readme.weston-ini-conf delete mode 100644 meta-agl/recipes-graphics/wayland/wayland/0001-Change-socket-mode-add-rw-for-group.patch delete mode 100644 meta-agl/recipes-graphics/wayland/wayland_%.bbappend delete mode 100644 meta-agl/recipes-graphics/wayland/weston-ini-conf.bb delete mode 100644 meta-agl/recipes-graphics/wayland/weston-ini-conf/core.cfg delete mode 100644 meta-agl/recipes-graphics/wayland/weston-ini-conf/hdmi-a-1-270.cfg delete mode 100644 meta-agl/recipes-graphics/wayland/weston-ini-conf/hdmi-a-1-90.cfg delete mode 100644 meta-agl/recipes-graphics/wayland/weston-ini-conf/id-agent.cfg delete mode 100644 meta-agl/recipes-graphics/wayland/weston-ini-conf/ivishell.cfg delete mode 100644 meta-agl/recipes-graphics/wayland/weston-ini-conf/shell.cfg delete mode 100644 meta-agl/recipes-graphics/wayland/weston-init.bbappend delete mode 100644 meta-agl/recipes-graphics/wayland/weston-init/weston.service.add delete mode 100644 meta-agl/recipes-graphics/wayland/weston-init/weston_tmpfiles.conf delete mode 100644 meta-agl/recipes-graphics/wayland/weston/0001-Allow-regular-users-to-launch-Weston_2.0.0.patch delete mode 100644 meta-agl/recipes-graphics/wayland/weston/0001-ivi-shell-rework-goto-labels-to-avoid-memory-leaks.patch delete mode 100644 meta-agl/recipes-graphics/wayland/weston/0002-ivi-shell-removed-assert.patch delete mode 100644 meta-agl/recipes-graphics/wayland/weston/0003-ivi-shell-introduction-of-IVI_INVALID_ID.patch delete mode 100644 meta-agl/recipes-graphics/wayland/weston/0004-layout-interface-added-interface-to-change-surface-id.patch delete mode 100644 meta-agl/recipes-graphics/wayland/weston/0005-ivi-layout-introcuded-configure_desktop_changed.patch delete mode 100644 meta-agl/recipes-graphics/wayland/weston/0006-ivi-layout-introcuded-surface_create_and_configure.patch delete mode 100644 meta-agl/recipes-graphics/wayland/weston/0007-ivi-shell-linked-libweston-desktop-and-added-structs.patch delete mode 100644 meta-agl/recipes-graphics/wayland/weston/0008-ivi-layout-use-libweston-desktop-api-for-views.patch delete mode 100644 meta-agl/recipes-graphics/wayland/weston/0009-ivi-shell-added-libweston-desktop-api_implementation.patch delete mode 100644 meta-agl/recipes-graphics/wayland/weston/0010-ivi-shell-remove-surface_destroy_listener.patch delete mode 100644 meta-agl/recipes-graphics/wayland/weston/0011-ivi-shell-create-weston-desktop-in_wet_shell_init.patch delete mode 100644 meta-agl/recipes-graphics/wayland/weston/0012-hmi-controller-register-for-desktop_surface_configured.patch delete mode 100644 meta-agl/recipes-graphics/wayland/weston/0013-simple-egl-remove-ivi-application-support.patch delete mode 100644 meta-agl/recipes-graphics/wayland/weston/0014-simple-shm-remove-ivi-application-support.patch delete mode 100644 meta-agl/recipes-graphics/wayland/weston/0015-window-client-remove-ivi-application-support.patch delete mode 100644 meta-agl/recipes-graphics/wayland/weston/0016-ivi-shell_add_screen_remove_layer_api.patch delete mode 100644 meta-agl/recipes-graphics/wayland/weston_2.0.0.bbappend delete mode 100644 meta-agl/recipes-ivi/images/agl-image-ivi-crosssdk.bb delete mode 100644 meta-agl/recipes-ivi/images/agl-image-ivi-qa.bb delete mode 100644 meta-agl/recipes-ivi/images/agl-image-ivi.bb delete mode 100644 meta-agl/recipes-ivi/images/agl-image-ivi.inc delete mode 100644 meta-agl/recipes-ivi/packagegroups/packagegroup-agl-image-ivi.bb delete mode 100644 meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-automotive.bb delete mode 100644 meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-connectivity.bb delete mode 100644 meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-graphics.bb delete mode 100644 meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-kernel.bb delete mode 100644 meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-multimedia.bb delete mode 100644 meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-navi-lbs.bb delete mode 100644 meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-os-commonlibs.bb delete mode 100644 meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-security.bb delete mode 100644 meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-speech-services.bb delete mode 100644 meta-agl/recipes-multimedia/gstreamer1.0-plugins-good/gstreamer1.0-plugins-good_%.bbappend delete mode 100644 meta-agl/recipes-multimedia/lightmediascanner/.appends.meta-efl delete mode 100644 meta-agl/recipes-multimedia/lightmediascanner/files/0001-Define-comparison_fn_t-for-non-glibc-systems.patch delete mode 100644 meta-agl/recipes-multimedia/lightmediascanner/files/dbus-lightmediascanner.conf delete mode 100644 meta-agl/recipes-multimedia/lightmediascanner/files/id3-plugin-support-out-of-tree-build.patch delete mode 100644 meta-agl/recipes-multimedia/lightmediascanner/files/lightmediascanner.service delete mode 100644 meta-agl/recipes-multimedia/lightmediascanner/files/plugin-ogg-fix-chucksize-issue.patch delete mode 100644 meta-agl/recipes-multimedia/lightmediascanner/lightmediascanner_%.bbappend delete mode 100644 meta-agl/recipes-multimedia/lightmediascanner/lightmediascanner_0.5.1.bb delete mode 100644 meta-agl/recipes-multimedia/pulseaudio/agl-audio-plugin_0.1.bb delete mode 100644 meta-agl/recipes-navi-lbs/.gitkeep delete mode 100644 meta-agl/recipes-navigation/geoclue/files/org.freedesktop.GeoClue2.Client.conf delete mode 100644 meta-agl/recipes-navigation/geoclue/geoclue_%.bbappend delete mode 100644 meta-agl/recipes-navigation/gpsd/gpsd_%.bbappend delete mode 100644 meta-agl/recipes-support/.gitkeep delete mode 100644 meta-agl/recipes-support/libsoup/libsoup-2.4_%.bbappend delete mode 100644 meta-agl/recipes-test/packagegroups/packagegroup-agl-test.bb delete mode 100644 meta-ivi-common/classes/.gitkeep delete mode 100644 meta-ivi-common/conf/layer.conf delete mode 100644 meta-ivi-common/recipes-connectivity/.gitkeep delete mode 100644 meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-automotive.bb delete mode 100644 meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-connectivity.bb delete mode 100644 meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-graphics.bb delete mode 100644 meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-kernel.bb delete mode 100644 meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-multimedia.bb delete mode 100644 meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-navi-lbs.bb delete mode 100644 meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-os-commonlibs.bb delete mode 100644 meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-security.bb delete mode 100644 meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-speech-services.bb delete mode 100644 meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core.bb delete mode 100644 meta-ivi-common/recipes-devtools/.gitkeep delete mode 100644 meta-ivi-common/recipes-extended/.gitkeep delete mode 100644 meta-ivi-common/recipes-extended/dlt-daemon/dlt-daemon/0001-Fix-build-with-systemd-209.patch delete mode 100644 meta-ivi-common/recipes-extended/dlt-daemon/dlt-daemon/0002-Don-t-execute-processes-as-a-specific-user.patch delete mode 100644 meta-ivi-common/recipes-extended/dlt-daemon/dlt-daemon/0003-systemd-unit-type-should-be-in-lowercase-so-use-Type.patch delete mode 100644 meta-ivi-common/recipes-extended/dlt-daemon/dlt-daemon/0004-Modify-systemd-config-directory.patch delete mode 100644 meta-ivi-common/recipes-extended/dlt-daemon/dlt-daemon_2.11.1.bb delete mode 100644 meta-ivi-common/recipes-extended/dlt-daemon/dlt-daemon_2.15.0.bb delete mode 100644 meta-ivi-common/recipes-graphics/.gitkeep delete mode 100644 meta-ivi-common/recipes-graphics/wayland/wayland-ivi-extension/0001-Resolve-weston-crush-when-repeat-touching-very-quick.patch delete mode 100644 meta-ivi-common/recipes-graphics/wayland/wayland-ivi-extension/0001-simple-id-agent-initial-commit.patch delete mode 100644 meta-ivi-common/recipes-graphics/wayland/wayland-ivi-extension/0002-ivi-controller-load-id-agent-module.patch delete mode 100644 meta-ivi-common/recipes-graphics/wayland/wayland-ivi-extension/0003-ivi-controller-add-resize-setting-suit-to-surface-si.patch delete mode 100644 meta-ivi-common/recipes-graphics/wayland/wayland-ivi-extension/disable-sanitizer-tests.patch delete mode 100644 meta-ivi-common/recipes-graphics/wayland/wayland-ivi-extension/wandboard_fix_build.patch delete mode 100644 meta-ivi-common/recipes-graphics/wayland/wayland-ivi-extension_1.13.0.bb delete mode 100644 meta-ivi-common/recipes-graphics/wayland/wayland-ivi-extension_2.0.2.bb delete mode 100644 meta-ivi-common/recipes-graphics/wayland/weston_%.bbappend delete mode 100644 meta-ivi-common/recipes-multimedia/audiomanager/audiomanager/0001-Fix-duplicated-command-line-arg-t.patch delete mode 100644 meta-ivi-common/recipes-multimedia/audiomanager/audiomanager/audiomanager.service delete mode 100644 meta-ivi-common/recipes-multimedia/audiomanager/audiomanager_7.4.bb delete mode 100644 meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio-10.0/0001-install-files-for-a-module-development.patch delete mode 100644 meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio-10.0/0002-volume-ramp-additions-to-the-low-level-infra.patch delete mode 100644 meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio-10.0/0003-volume-ramp-adding-volume-ramping-to-sink-input.patch delete mode 100644 meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio-10.0/0004-sink-input-Code-cleanup-regarding-volume-ramping.patch delete mode 100644 meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio-10.0/0005-sink-input-volume-Add-support-for-volume-ramp-factor.patch delete mode 100644 meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio-10.0/0006-sink-input-Remove-pa_sink_input_set_volume_ramp.patch delete mode 100644 meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio-10.0/enable-ofono-hfp-backend.patch delete mode 100644 meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0008-install-files-for-a-module-development.patch delete mode 100644 meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0010-volume-ramp-additions-to-the-low-level-infra.patch delete mode 100644 meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0011-volume-ramp-adding-volume-ramping-to-sink-input.patch delete mode 100644 meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0012-volume-ramp-add-volume-ramping-to-sink.patch delete mode 100644 meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0013-add-internal-corking-state-for-sink-input.patch delete mode 100644 meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0020-core-util-Add-pa_join.patch delete mode 100644 meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0021-dynarray-Add-pa_dynarray_get_raw_array.patch delete mode 100644 meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0022-device-port-Add-pa_device_port.active.patch delete mode 100644 meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0030-volume-api-Add-libvolume-api.patch delete mode 100644 meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0031-Add-module-main-volume-policy.patch delete mode 100644 meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0039-main-volume-policy-adapt-to-pa6rev.patch delete mode 100644 meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio_%.bbappend delete mode 100644 meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio_10.0.bbappend delete mode 100644 meta-ivi-common/recipes-support/.gitkeep delete mode 100644 meta-ivi-common/recipes-test/aiostress/aiostress_0.22.bb delete mode 100755 meta-ivi-common/recipes-test/blobsallad/blobsallad/0001-Makefile.patch delete mode 100755 meta-ivi-common/recipes-test/blobsallad/blobsallad/0002-auto.patch delete mode 100755 meta-ivi-common/recipes-test/blobsallad/blobsallad/0003-printcleanup.patch delete mode 100755 meta-ivi-common/recipes-test/blobsallad/blobsallad/0004-bs_main.c.patch delete mode 100644 meta-ivi-common/recipes-test/blobsallad/blobsallad_2006-11-14-23-57.bb delete mode 100644 meta-ivi-common/recipes-test/dung/dung_3.4.25-m2.bb delete mode 100644 meta-ivi-common/recipes-test/ebizzy/ebizzy_0.3.bb delete mode 100644 meta-ivi-common/recipes-test/ffsb/ffsb_6.0-rc2.bb delete mode 100644 meta-ivi-common/recipes-test/fontconfig/fontconfig_%.bbappend delete mode 100644 meta-ivi-common/recipes-test/freetype/files/0001-Makefile-dont-build-gfx-demos.patch delete mode 100644 meta-ivi-common/recipes-test/freetype/files/0001-ft2demos-Makefile-Do-not-hardcode-libtool-path.patch delete mode 100644 meta-ivi-common/recipes-test/freetype/freetype_2.8.bbappend delete mode 100644 meta-ivi-common/recipes-test/fsfuzzer/files/0001-fix_missing_header_sys_stat.patch delete mode 100644 meta-ivi-common/recipes-test/fsfuzzer/fsfuzzer_0.7.bb delete mode 100644 meta-ivi-common/recipes-test/glmark2/glmark2_%.bbappend delete mode 100644 meta-ivi-common/recipes-test/himeno/himeno_2.0.bb delete mode 100755 meta-ivi-common/recipes-test/interbench/files/interbench.c.patch delete mode 100644 meta-ivi-common/recipes-test/interbench/interbench_0.31.bb delete mode 100644 meta-ivi-common/recipes-test/iperf/iperf-2.0.9/0001-fix-out-of-tree-config.patch delete mode 100644 meta-ivi-common/recipes-test/iperf/iperf-2.0.9/0002-fix-bool-size-m4.patch delete mode 100755 meta-ivi-common/recipes-test/iperf/iperf-2.0.9/iperf-2.0.5_ManPage.patch delete mode 100644 meta-ivi-common/recipes-test/iperf/iperf_2.0.9.bb delete mode 100644 meta-ivi-common/recipes-test/ipv6connect/ipv6connect.bb delete mode 100644 meta-ivi-common/recipes-test/linpack/linpack.bb delete mode 100644 meta-ivi-common/recipes-test/linus-stress/linus-stress.bb delete mode 100644 meta-ivi-common/recipes-test/packagegroups/packagegroup-ivi-common-test.bb delete mode 100644 meta-ivi-common/recipes-test/trinity/trinity_git.bb delete mode 100644 templates/feature/agl-appfw-smack/50_bblayers.conf.inc diff --git a/meta-agl-profile-core/classes/cloc.bbclass b/meta-agl-profile-core/classes/cloc.bbclass new file mode 100644 index 000000000..53713bfc3 --- /dev/null +++ b/meta-agl-profile-core/classes/cloc.bbclass @@ -0,0 +1,29 @@ +# (C) 2017 Jan-Simon Möller +# +# License: GPLv2 +# +# summary with +# cloc --sum-reports `find . -name "*clocreport" | grep -v "\-native" ` --out summary.report + +CLOC_DIRECTORY ??= "${DEPLOY_DIR}/cloc/" +CLOCSTATEDIR = "${WORKDIR}/cloc-destdir/" + +python do_cloc() { + + import subprocess + + source_dir = d.getVar('S', True) + pn = d.getVar('PN', True) + + destdir = d.expand('${CLOCSTATEDIR}') + bb.utils.mkdirhier(destdir) + + cloc_cmd = 'cloc %s -q --out=%s/%s.clocreport' % (source_dir, destdir, pn ) + subprocess.call(cloc_cmd, shell=True) + +} + + +addtask cloc before do_configure after do_unpack + +EXPORT_FUNCTIONS do_cloc diff --git a/meta-agl-profile-core/conf/include/agl-devel.inc b/meta-agl-profile-core/conf/include/agl-devel.inc new file mode 100644 index 000000000..705b1739a --- /dev/null +++ b/meta-agl-profile-core/conf/include/agl-devel.inc @@ -0,0 +1,15 @@ +IMAGE_FEATURES =+ "debug-tweaks eclipse-debug tools-debug tools-profile" + +#IMAGE_INSTALL_append = " \ +# packagegroup-agl-core-devel \ +#" + +IMAGE_INSTALL_append = "${@bb.utils.contains('IMAGE_FSTYPES', 'wic.vmdk', ' open-vm-tools vboxguestdrivers', '', d)}" + +# disable install of debug files in SDK +# initial value: SDKIMAGE_FEATURES="dev-pkgs dbg-pkgs staticdev-pkgs" +SDKIMAGE_FEATURES="dev-pkgs" + +# allows insertion of code or items specific to developement +OVERRIDES .= ":agl-devel" +DISTRO_FEATURES_append = " agl-devel" diff --git a/meta-agl-profile-core/conf/include/agl-gplv2.inc b/meta-agl-profile-core/conf/include/agl-gplv2.inc new file mode 100644 index 000000000..fc9a4072b --- /dev/null +++ b/meta-agl-profile-core/conf/include/agl-gplv2.inc @@ -0,0 +1,8 @@ +# GPLv3 Compliance +PREFERRED_VERSION_bash = "3.2.%" +PREFERRED_VERSION_gawk = "3.1.%" +PREFERRED_VERSION_gdbm = "1.8.%" +PREFERRED_VERSION_gnupg = "1.4.7" +PREFERRED_VERSION_gnutls = "3.3.%" +PREFERRED_VERSION_mc = "4.7.5.%" +PREFERRED_VERSION_readline = "5.2" diff --git a/meta-agl-profile-core/conf/include/base-agl.inc b/meta-agl-profile-core/conf/include/base-agl.inc new file mode 100644 index 000000000..a332c08a4 --- /dev/null +++ b/meta-agl-profile-core/conf/include/base-agl.inc @@ -0,0 +1,19 @@ +# AGL includes all kernel modules here for ease-of-use during development. +# Comment this out to be able to select the kernel modules yourself. +IMAGE_INSTALL_append = " kernel-modules" + +# Likewise as we included all kernel modules by default in the filesystem, +# we do not need a separate tarball stored. +# Comment this out to receive the separate modules tarball again. +MODULE_TARBALL_DEPLOY ?= "0" + +# Comment out below if want to use QtWebkit +PACKAGECONFIG_remove_pn-qtquick1 = "webkit" + + +ASSUME_PROVIDED_remove = "tar-native" + +# Use static IDs to enable full-filesystem updates +USERADDEXTENSION = "useradd-staticids" +USERADD_ERROR_DYNAMIC = "error" + diff --git a/meta-agl-profile-core/conf/layer.conf b/meta-agl-profile-core/conf/layer.conf new file mode 100644 index 000000000..83c5555bc --- /dev/null +++ b/meta-agl-profile-core/conf/layer.conf @@ -0,0 +1,10 @@ +# We have a conf and classes directory, add to BBPATH +BBPATH =. "${LAYERDIR}:" + +# We have recipes-* directories, add to BBFILES +BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \ + ${LAYERDIR}/recipes-*/*/*.bbappend" + +BBFILE_COLLECTIONS += "aglprofilecore" +BBFILE_PATTERN_aglprofilecore = "^${LAYERDIR}/" +BBFILE_PRIORITY_aglprofilecore = "80" diff --git a/meta-agl-profile-core/files/group b/meta-agl-profile-core/files/group new file mode 100644 index 000000000..f8a3843bd --- /dev/null +++ b/meta-agl-profile-core/files/group @@ -0,0 +1,90 @@ +root::0: +daemon::1: +bin::2: +sys::3: +adm::4: +tty::5: +disk::6: +lp::7: +mail::8: +news::9: +uucp::10: +man::12: +proxy::13: +kmem::15: +input::19: +dialout::20: +fax::21: +voice::22: +cdrom::24: +floppy::25: +tape::26: +sudo::27: +audio::29: +dip::30: +www-data::33: +backup::34: +operator::37: +list::38: +irc::39: +src::40: +gnats::41: +shadow::42: +utmp::43: +video::44: +sasl::45: +plugdev::46: +staff::50: +games::60: +shutdown::70: +users::100: +nogroup::65534: +cynara::999: +dhcp::998: +avahi::997: +tracing::1000: +sshd::996: +systemd-bus-proxy::995: +netdev::993: +messagebus::994: +afm::992: +weston-launch::986: +lock::990: +systemd-journal::989: +systemd-timesync::988: +pulse::991: +bind::987: +trinity::985: +mpd::984: +mysql::983: +polkitd::982: +datetime::981: +network::980: +zabbix::979: +nm-openvpn::978: +xuser::1002: +builder::977: +rpc::976: +crontab::975: +lpadmin::974: +_apt::972: +rpcuser::970: +avahi-autoipd::969: +ntp::968: +dovecot::967: +dovenull::966: +quagga::965: +quaggavty::964: +rwhod::963: +ftp::962: +squid::960: +postfix::959: +vmail::958: +opensaf::957: +lldpd::956: +postdrop::954: +display::200: +agl-driver::1001: +agl-passenger::1002: +systemd-network::1005: +systemd-resolve::1006: diff --git a/meta-agl-profile-core/files/passwd b/meta-agl-profile-core/files/passwd new file mode 100644 index 000000000..754cb819a --- /dev/null +++ b/meta-agl-profile-core/files/passwd @@ -0,0 +1,60 @@ +root::0:0::: +daemon::1:1::: +bin::2:2::: +sys::3:3::: +sync::4:65534::: +games::5:60::: +man::6:12::: +lp::7:7::: +mail::8:8::: +news::9:9::: +uucp::10:10::: +proxy::13:13::: +www-data::33:33::: +backup::34:34::: +list::38:38::: +irc::39:39::: +gnats::41:41::: +nobody::65534:65534::: +cynara::999:999::: +dhcp::998:998::: +avahi::997:997::: +sshd::996:996::: +systemd-bus-proxy::995:995::: +agl-driver::1001:1001::: +agl-passenger::1002:1002::: +messagebus::994:994::: +afm::992:992::: +systemd-timesync::988:988::: +pulse::991:991::: +bind::987:987::: +trinity::985:985::: +mpd::984:984::: +mysql::983:983::: +polkitd::982:982::: +zabbix::979:979::: +nm-openvpn::978:978::: +xuser::1002:1002::: +builder::977:977::: +rpc::976:976::: +distcc::973:65534::: +_apt::972:972::: +ppp::971:65534::: +rpcuser::970:970::: +avahi-autoipd::969:969::: +ntp::968:968::: +dovecot::967:967::: +dovenull::966:966::: +quagga::965:965::: +rwhod::963:963::: +ftp::962:962::: +radvd::961:65534::: +squid::960:960::: +postfix::959:959::: +vmail::958:958::: +opensaf::957:957::: +lldpd::956:956::: +cyrus::955:8::: +display::200:200::: +systemd-network::1005:1005::: +systemd-resolve::1006:1006::: diff --git a/meta-agl-profile-core/recipes-core/dbus/.appends.core b/meta-agl-profile-core/recipes-core/dbus/.appends.core new file mode 100644 index 000000000..e69de29bb diff --git a/meta-agl-profile-core/recipes-core/dbus/dbus-cynara_%.bbappend b/meta-agl-profile-core/recipes-core/dbus/dbus-cynara_%.bbappend new file mode 120000 index 000000000..fcdfb1783 --- /dev/null +++ b/meta-agl-profile-core/recipes-core/dbus/dbus-cynara_%.bbappend @@ -0,0 +1 @@ +dbus_%.bbappend \ No newline at end of file diff --git a/meta-agl-profile-core/recipes-core/dbus/dbus/dbus.service b/meta-agl-profile-core/recipes-core/dbus/dbus/dbus.service new file mode 100644 index 000000000..dee6ad741 --- /dev/null +++ b/meta-agl-profile-core/recipes-core/dbus/dbus/dbus.service @@ -0,0 +1,10 @@ +[Unit] +Description=D-Bus User Message Bus +Documentation=man:dbus-daemon(1) +Requires=dbus.socket + +[Service] +ExecStart=/usr/bin/dbus-daemon --session --address=systemd: --nofork --nopidfile --systemd-activation +ExecReload=/usr/bin/dbus-send --print-reply --session --type=method_call --dest=org.freedesktop.DBus / org.freedesktop.DBus.ReloadConfig +Restart=always +RestartSec=1 diff --git a/meta-agl-profile-core/recipes-core/dbus/dbus/dbus.socket b/meta-agl-profile-core/recipes-core/dbus/dbus/dbus.socket new file mode 100644 index 000000000..af76b2f12 --- /dev/null +++ b/meta-agl-profile-core/recipes-core/dbus/dbus/dbus.socket @@ -0,0 +1,9 @@ +[Unit] +Description=D-Bus User Message Bus Socket +Before=sockets.target + +[Socket] +ListenStream=%t/bus + +[Install] +WantedBy=default.target diff --git a/meta-agl-profile-core/recipes-core/dbus/dbus/dbus_env.conf b/meta-agl-profile-core/recipes-core/dbus/dbus/dbus_env.conf new file mode 100644 index 000000000..f8f02669b --- /dev/null +++ b/meta-agl-profile-core/recipes-core/dbus/dbus/dbus_env.conf @@ -0,0 +1,5 @@ +[Unit] +Wants=dbus.service + +[Service] +Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/%I/bus diff --git a/meta-agl-profile-core/recipes-core/dbus/dbus_%.bbappend b/meta-agl-profile-core/recipes-core/dbus/dbus_%.bbappend new file mode 100644 index 000000000..e63ea0f28 --- /dev/null +++ b/meta-agl-profile-core/recipes-core/dbus/dbus_%.bbappend @@ -0,0 +1,28 @@ +FILESEXTRAPATHS_append := ":${THISDIR}/dbus" + +SRC_URI_append = "file://dbus.service \ + file://dbus.socket \ + file://dbus_env.conf \ + " + +inherit systemd + +do_install_append() { + if [ "${PN}" != "nativesdk-dbus" ]; then + if ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'true', 'false', d)}; then + install -m 644 -p -D ${WORKDIR}/dbus.service ${D}${systemd_user_unitdir}/dbus.service + install -m 644 -p -D ${WORKDIR}/dbus.socket ${D}${systemd_user_unitdir}/dbus.socket + install -m 644 -p -D ${WORKDIR}/dbus_env.conf ${D}${systemd_system_unitdir}/user@.service.d/dbus_env.conf + + # Execute these manually on behalf of systemctl script (from systemd-systemctl-native.bb) + # because it does not support systemd's user mode. + mkdir -p ${D}/etc/systemd/user/default.target.wants/ + ln -sf ${systemd_user_unitdir}/dbus.socket ${D}/etc/systemd/user/default.target.wants/dbus.socket + fi + fi +} + +FILES_${PN} += " \ + ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', '${systemd_user_unitdir}/dbus.*', '', d)} \ + ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', '${systemd_system_unitdir}/user@.service.d/dbus_env.conf', '', d)} \ + " diff --git a/meta-agl-profile-core/recipes-core/glibc/.appends.core b/meta-agl-profile-core/recipes-core/glibc/.appends.core new file mode 100644 index 000000000..e69de29bb diff --git a/meta-agl-profile-core/recipes-core/glibc/glibc/arm/local-arm-futex.diff b/meta-agl-profile-core/recipes-core/glibc/glibc/arm/local-arm-futex.diff new file mode 100644 index 000000000..27d1144d0 --- /dev/null +++ b/meta-agl-profile-core/recipes-core/glibc/glibc/arm/local-arm-futex.diff @@ -0,0 +1,22 @@ +Description: Lie about futex_atomic_cmpxchg_inatomic kernel support. + In past versions of glibc, we incorrectly assumed all ARM kernels + in all configurations supported futex_atomic_cmpxchg_inatomic. This + was clearly a lie, however it was a lie that we relied on, because + the fallback implementation appears to not play nicely with certain + applications like pulseaudio. Restore the lie for kernels > 2.6.32 + and plug our ears and scream "LA LA LA" about how wrong this is. +Author: Adam Conrad +Bug-Ubuntu: https://launchpad.net/bugs/1436162 +Bug-Debian: https://bugs.debian.org/788799 +Last-Update: 2015-03-25 + +--- a/sysdeps/unix/sysv/linux/arm/kernel-features.h ++++ b/sysdeps/unix/sysv/linux/arm/kernel-features.h +@@ -22,7 +22,7 @@ + /* The ARM kernel before 3.14.3 may or may not support + futex_atomic_cmpxchg_inatomic, depending on kernel + configuration. */ +-#if __LINUX_KERNEL_VERSION < 0x030E03 ++#if __LINUX_KERNEL_VERSION < 0x020620 + # undef __ASSUME_SET_ROBUST_LIST + #endif diff --git a/meta-agl-profile-core/recipes-core/glibc/glibc_2.2%.bbappend b/meta-agl-profile-core/recipes-core/glibc/glibc_2.2%.bbappend new file mode 100644 index 000000000..0868a2c7d --- /dev/null +++ b/meta-agl-profile-core/recipes-core/glibc/glibc_2.2%.bbappend @@ -0,0 +1,3 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" + +SRC_URI_append_arm = " file://arm/local-arm-futex.diff " diff --git a/meta-agl-profile-core/recipes-core/images/agl-image-boot.bb b/meta-agl-profile-core/recipes-core/images/agl-image-boot.bb new file mode 100644 index 000000000..84cdbcf31 --- /dev/null +++ b/meta-agl-profile-core/recipes-core/images/agl-image-boot.bb @@ -0,0 +1,9 @@ +SUMMARY = "An AGL small image just capable of allowing a device to boot." + +require agl-image-boot.inc + +LICENSE = "MIT" + +IMAGE_INSTALL_append = "\ + packagegroup-agl-image-boot \ + " diff --git a/meta-agl-profile-core/recipes-core/images/agl-image-boot.inc b/meta-agl-profile-core/recipes-core/images/agl-image-boot.inc new file mode 100644 index 000000000..825393978 --- /dev/null +++ b/meta-agl-profile-core/recipes-core/images/agl-image-boot.inc @@ -0,0 +1,10 @@ +IMAGE_LINGUAS = " " + +inherit core-image + +IMAGE_INSTALL = "${CORE_IMAGE_EXTRA_INSTALL}" + +IMAGE_ROOTFS_SIZE ?= "8192" + +# Allow extra IMAGE_FSTYPES to be added by boards configs +IMAGE_FSTYPES += "${AGL_EXTRA_IMAGE_FSTYPES}" diff --git a/meta-agl-profile-core/recipes-core/images/agl-image-minimal-qa.bb b/meta-agl-profile-core/recipes-core/images/agl-image-minimal-qa.bb new file mode 100644 index 000000000..b162f2904 --- /dev/null +++ b/meta-agl-profile-core/recipes-core/images/agl-image-minimal-qa.bb @@ -0,0 +1,12 @@ +SUMMARY = "An AGL small image just capable of allowing a device to boot and run tests." + +DESCRIPTION = "A minimal set of AGL Distribution. This image also has additional \ +packages (e.g. commandline tools) for Quality Assurance(QA)." + +require agl-image-minimal.bb + +LICENSE = "MIT" + +IMAGE_INSTALL_append = " \ + packagegroup-ivi-common-test \ + " diff --git a/meta-agl-profile-core/recipes-core/images/agl-image-minimal.bb b/meta-agl-profile-core/recipes-core/images/agl-image-minimal.bb new file mode 100644 index 000000000..1fd213d0f --- /dev/null +++ b/meta-agl-profile-core/recipes-core/images/agl-image-minimal.bb @@ -0,0 +1,9 @@ +SUMMARY = "An AGL small image just capable of allowing a device to boot." + +require agl-image-minimal.inc + +LICENSE = "MIT" + +IMAGE_INSTALL_append = "\ + packagegroup-agl-image-minimal \ + " diff --git a/meta-agl-profile-core/recipes-core/images/agl-image-minimal.inc b/meta-agl-profile-core/recipes-core/images/agl-image-minimal.inc new file mode 100644 index 000000000..825393978 --- /dev/null +++ b/meta-agl-profile-core/recipes-core/images/agl-image-minimal.inc @@ -0,0 +1,10 @@ +IMAGE_LINGUAS = " " + +inherit core-image + +IMAGE_INSTALL = "${CORE_IMAGE_EXTRA_INSTALL}" + +IMAGE_ROOTFS_SIZE ?= "8192" + +# Allow extra IMAGE_FSTYPES to be added by boards configs +IMAGE_FSTYPES += "${AGL_EXTRA_IMAGE_FSTYPES}" diff --git a/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-automotive.bb b/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-automotive.bb new file mode 100644 index 000000000..d9f2279e1 --- /dev/null +++ b/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-automotive.bb @@ -0,0 +1,13 @@ +DESCRIPTION = "The minimal set of packages for Automotive Subsystem" +LICENSE = "MIT" + +inherit packagegroup + +PACKAGES = "\ + packagegroup-agl-core-automotive \ + " + +ALLOW_EMPTY_${PN} = "1" + +RDEPENDS_${PN} += "\ + " diff --git a/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-connectivity.bb b/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-connectivity.bb new file mode 100644 index 000000000..e909d5e5f --- /dev/null +++ b/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-connectivity.bb @@ -0,0 +1,15 @@ +DESCRIPTION = "The minimal set of packages for Connectivity Subsystem" +LICENSE = "MIT" + +inherit packagegroup + +PACKAGES = "\ + packagegroup-agl-core-connectivity \ + " + +ALLOW_EMPTY_${PN} = "1" + +RDEPENDS_${PN} += "\ + dhcp-server \ + ${@bb.utils.contains('VIRTUAL-RUNTIME_net_manager','connman','connman connman-client connman-tests connman-tools connman-ncurses','',d)} \ + " diff --git a/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-graphics.bb b/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-graphics.bb new file mode 100644 index 000000000..1cc6f457b --- /dev/null +++ b/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-graphics.bb @@ -0,0 +1,10 @@ +DESCRIPTION = "The minimal set of packages for Graphics Subsystem" +LICENSE = "MIT" + +inherit packagegroup + +PACKAGES = "\ + packagegroup-agl-core-graphics \ + " + +ALLOW_EMPTY_${PN} = "1" diff --git a/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-kernel.bb b/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-kernel.bb new file mode 100644 index 000000000..3d5556fd5 --- /dev/null +++ b/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-kernel.bb @@ -0,0 +1,13 @@ +DESCRIPTION = "The minimal set of packages for Kernel Subsystem" +LICENSE = "MIT" + +inherit packagegroup + +PACKAGES = "\ + packagegroup-agl-core-kernel \ + " + +ALLOW_EMPTY_${PN} = "1" + +RDEPENDS_${PN} += "\ + " diff --git a/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-multimedia.bb b/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-multimedia.bb new file mode 100644 index 000000000..01ca4cb85 --- /dev/null +++ b/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-multimedia.bb @@ -0,0 +1,13 @@ +DESCRIPTION = "The minimal set of packages for Multimedia Subsystem" +LICENSE = "MIT" + +inherit packagegroup + +PACKAGES = "\ + packagegroup-agl-core-multimedia \ + " + +ALLOW_EMPTY_${PN} = "1" + +RDEPENDS_${PN} += "\ + " diff --git a/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-navi-lbs.bb b/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-navi-lbs.bb new file mode 100644 index 000000000..2b04d5387 --- /dev/null +++ b/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-navi-lbs.bb @@ -0,0 +1,13 @@ +DESCRIPTION = "The minimal set of packages for Navigation and Location Based Services Subsystem" +LICENSE = "MIT" + +inherit packagegroup + +PACKAGES = "\ + packagegroup-agl-core-navi-lbs \ + " + +ALLOW_EMPTY_${PN} = "1" + +RDEPENDS_${PN} += "\ + " diff --git a/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-os-commonlibs.bb b/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-os-commonlibs.bb new file mode 100644 index 000000000..c44166e12 --- /dev/null +++ b/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-os-commonlibs.bb @@ -0,0 +1,13 @@ +DESCRIPTION = "The minimal set of packages for Operating System and Common libraries Subsystem" +LICENSE = "MIT" + +inherit packagegroup + +PACKAGES = "\ + packagegroup-agl-core-os-commonlibs \ + " + +ALLOW_EMPTY_${PN} = "1" + +RDEPENDS_${PN} += "\ + " diff --git a/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-security.bb b/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-security.bb new file mode 100644 index 000000000..eb5a68f0a --- /dev/null +++ b/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-security.bb @@ -0,0 +1,13 @@ +DESCRIPTION = "The minimal set of packages for Security Subsystem" +LICENSE = "MIT" + +inherit packagegroup + +PACKAGES = "\ + packagegroup-agl-core-security \ + " + +ALLOW_EMPTY_${PN} = "1" + +RDEPENDS_${PN} += "\ + " diff --git a/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-speech-services.bb b/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-speech-services.bb new file mode 100644 index 000000000..a494e5889 --- /dev/null +++ b/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-core-speech-services.bb @@ -0,0 +1,13 @@ +DESCRIPTION = "The minimal set of packages for Speech Services Subsystem" +LICENSE = "MIT" + +inherit packagegroup + +PACKAGES = "\ + packagegroup-agl-core-speech-services \ + " + +ALLOW_EMPTY_${PN} = "1" + +RDEPENDS_${PN} += "\ + " diff --git a/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-image-boot.bb b/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-image-boot.bb new file mode 100644 index 000000000..29f859c49 --- /dev/null +++ b/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-image-boot.bb @@ -0,0 +1,18 @@ +DESCRIPTION = "The minimal set of packages required by AGL" +LICENSE = "MIT" + +inherit packagegroup + +PACKAGES = "\ + packagegroup-agl-image-boot \ + " + +ALLOW_EMPTY_${PN} = "1" + +RDEPENDS_${PN} += "\ + packagegroup-core-boot-agl \ + " + + +RDEPENDS_${PN} += "\ + " diff --git a/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-image-minimal.bb b/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-image-minimal.bb new file mode 100644 index 000000000..630c11d43 --- /dev/null +++ b/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-agl-image-minimal.bb @@ -0,0 +1,27 @@ +DESCRIPTION = "The minimal set of packages required by AGL" +LICENSE = "MIT" + +inherit packagegroup + +PACKAGES = "\ + packagegroup-agl-image-minimal \ + " + +ALLOW_EMPTY_${PN} = "1" + +RDEPENDS_${PN} += "\ + packagegroup-core-boot-agl \ + " + + +RDEPENDS_${PN} += "\ + packagegroup-agl-core-automotive \ + packagegroup-agl-core-connectivity \ + packagegroup-agl-core-graphics \ + packagegroup-agl-core-multimedia \ + packagegroup-agl-core-navi-lbs \ + packagegroup-agl-core-os-commonlibs \ + packagegroup-agl-core-speech-services \ + packagegroup-agl-core-security \ + packagegroup-agl-core-kernel \ + " diff --git a/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-core-boot-agl.bb b/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-core-boot-agl.bb new file mode 100644 index 000000000..c9d679879 --- /dev/null +++ b/meta-agl-profile-core/recipes-core/packagegroups/packagegroup-core-boot-agl.bb @@ -0,0 +1,50 @@ +# +# Copyright (C) 2007 OpenedHand Ltd. +# +# derived from oe-core: meta/recipes-core/packagegroups/packagegroup-core-boot.bb + +SUMMARY = "Minimal boot requirements" +DESCRIPTION = "The minimal set of packages required to boot the system" +LICENSE = "MIT" + +PACKAGE_ARCH = "${MACHINE_ARCH}" + +inherit packagegroup + +# +# Set by the machine configuration with packages essential for device bootup +# +MACHINE_ESSENTIAL_EXTRA_RDEPENDS ?= "" +MACHINE_ESSENTIAL_EXTRA_RRECOMMENDS ?= "" + +# Distro can override the following VIRTUAL-RUNTIME providers: +VIRTUAL-RUNTIME_dev_manager ?= "udev" +VIRTUAL-RUNTIME_login_manager ?= "busybox" +VIRTUAL-RUNTIME_init_manager ?= "sysvinit" +VIRTUAL-RUNTIME_initscripts ?= "initscripts" +VIRTUAL-RUNTIME_keymaps ?= "keymaps" + +SYSVINIT_SCRIPTS = "${@bb.utils.contains('MACHINE_FEATURES', 'rtc', 'busybox-hwclock', '', d)} \ + modutils-initscripts \ + init-ifupdown \ + ${VIRTUAL-RUNTIME_initscripts} \ + " + +RDEPENDS_${PN} = "\ + base-files \ + base-passwd \ + busybox \ + run-agl-postinsts \ + ${@bb.utils.contains("DISTRO_FEATURES", "sysvinit", "${SYSVINIT_SCRIPTS}", "", d)} \ + ${@bb.utils.contains("MACHINE_FEATURES", "keyboard", "${VIRTUAL-RUNTIME_keymaps}", "", d)} \ + netbase \ + ${VIRTUAL-RUNTIME_login_manager} \ + ${VIRTUAL-RUNTIME_init_manager} \ + ${VIRTUAL-RUNTIME_dev_manager} \ + ${VIRTUAL-RUNTIME_update-alternatives} \ + ${MACHINE_ESSENTIAL_EXTRA_RDEPENDS}" + +RRECOMMENDS_${PN} = "\ + tzdata \ + ${MACHINE_ESSENTIAL_EXTRA_RRECOMMENDS}" + diff --git a/meta-agl-profile-core/recipes-core/psplash/.appends.core b/meta-agl-profile-core/recipes-core/psplash/.appends.core new file mode 100644 index 000000000..e69de29bb diff --git a/meta-agl-profile-core/recipes-core/psplash/files/psplash-anim b/meta-agl-profile-core/recipes-core/psplash/files/psplash-anim new file mode 100755 index 000000000..ac9bf674a --- /dev/null +++ b/meta-agl-profile-core/recipes-core/psplash/files/psplash-anim @@ -0,0 +1,11 @@ +#/bin/bash + +psplash-default "$@" & +sleep .2 +while :; do + for x in 0 1 2 3 4 5 6 7 8 9 10 -9 -8 -7 -6 -5 -4 -3 -2 -1 0 -1 -2 -3 -4 -5 -6 -7 -8 -9 10 9 8 7 6 5 4 3 2 1; do + psplash-write "PROGRESS ${x}0" || exit 0 + psplash-write "MSG $(journalctl -n1 -ocat)" || exit 0 + sleep .1 + done +done diff --git a/meta-agl-profile-core/recipes-core/psplash/files/psplash-colors.h b/meta-agl-profile-core/recipes-core/psplash/files/psplash-colors.h new file mode 100644 index 000000000..447490397 --- /dev/null +++ b/meta-agl-profile-core/recipes-core/psplash/files/psplash-colors.h @@ -0,0 +1,34 @@ +/* + * pslash - a lightweight framebuffer splashscreen for embedded devices. + * + * Copyright (c) 2012 sleep(5) ltd + * Author: Tomas Frydrych + * + * This program is free software; you can redistribute 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. + * + */ + +#ifndef _HAVE_PSPLASH_COLORS_H +#define _HAVE_PSPLASH_COLORS_H + +/* This is the overall background color */ +#define PSPLASH_BACKGROUND_COLOR 0xff,0xff,0xff + +/* This is the color of any text output */ +#define PSPLASH_TEXT_COLOR 0x00,0x00,0x00 + +/* This is the color of the progress bar indicator */ +#define PSPLASH_BAR_COLOR 0x00,0x00,0x00 + +/* This is the color of the progress bar background */ +#define PSPLASH_BAR_BACKGROUND_COLOR 0xff,0xff,0xff + +#endif diff --git a/meta-agl-profile-core/recipes-core/psplash/files/psplash-poky-img.h b/meta-agl-profile-core/recipes-core/psplash/files/psplash-poky-img.h new file mode 100644 index 000000000..c0e8b0818 --- /dev/null +++ b/meta-agl-profile-core/recipes-core/psplash/files/psplash-poky-img.h @@ -0,0 +1,5411 @@ +/* GdkPixbuf RGB C-Source image dump 1-byte-run-length-encoded */ + +#define POKY_IMG_ROWSTRIDE (1800) +#define POKY_IMG_WIDTH (600) +#define POKY_IMG_HEIGHT (400) +#define POKY_IMG_BYTES_PER_PIXEL (3) /* 3:RGB, 4:RGBA */ +#define POKY_IMG_RLE_PIXEL_DATA ((uint8*) \ + "\377\377\377\377\377\377\377\377\203\377\377\377\1\376\376\376\221\377" \ + "\377\377\1\376\376\376\215\377\377\377\1\376\376\376\203\377\377\377" \ + "\1\376\376\376\233\377\377\377\1\376\376\376\203\377\377\377\1\376\376" \ + "\376\202\377\377\377\5\376\376\376\377\377\377\376\376\376\377\377\377" \ + "\376\376\376\206\377\377\377\1\376\376\376\203\377\377\377\1\376\376" \ + "\376\204\377\377\377\1\376\376\376\203\377\377\377\5\376\376\376\377" \ + "\377\377\376\376\376\377\377\377\376\376\376\377\377\377\377\377\377" \ + "\377\377\377\377\377\377\377\377\377\377\202\376\376\376\207\377\377" \ + "\377\1\376\376\376\205\377\377\377\1\376\376\376\211\377\377\377\3\376" \ + "\376\376\377\377\377\376\376\376\235\377\377\377\1\376\376\376\203\377" \ + "\377\377\1\376\376\376\213\377\377\377\3\376\376\376\377\377\377\376" \ + "\376\376\216\377\377\377\1\376\376\376\202\377\377\377\1\376\376\376" \ + "\377\377\377\377\377\377\377\377\377\377\377\377\365\377\377\377\1\376" \ + "\376\376\203\377\377\377\1\376\376\376\207\377\377\377\1\376\376\376" \ + "\203\377\377\377\1\376\376\376\202\377\377\377\1\376\376\376\205\377" \ + "\377\377\1\376\376\376\203\377\377\377\12\376\376\376\377\377\377\346" \ + "\346\346\315\315\315\316\316\316\265\265\265\235\235\235\234\234\234" \ + "\233\233\233\204\204\204\203kkm\202lln\2EEG;;=\215::<\204kkm\3kkkxxx" \ + "\235\235\235\202\234\234\234\1\265\265\265\202\316\316\316\1\332\332" \ + "\332\207\377\377\377\202\376\376\376\2\377\377\377\376\376\376\211\377" \ + "\377\377\3\376\376\376\377\377\377\376\376\376\203\377\377\377\5\376" \ + "\376\376\377\377\377\376\376\376\377\377\377\376\376\376\377\377\377" \ + "\377\377\377\377\377\377\377\377\377\366\377\377\377\1\376\376\376\205" \ + "\377\377\377\1\376\376\376\214\377\377\377\11\376\376\376\332\332\332" \ + "\316\316\320\247\247\251\236\236\240\204\204\206kkm__a<<>\202::<\11;" \ + ";=99;;;=99;::<;;=::<;;=99;\203::<\1<<>\213::<\13;;=::<;;=::<;;=::<;;" \ + "=::<;;=::<;;=\207::<\3SSUllnxxz\202\234\234\236\202\316\316\316\2\377" \ + "\377\377\376\376\376\214\377\377\377\1\376\376\376\203\377\377\377\1" \ + "\376\376\376\377\377\377\377\377\377\377\377\377\377\377\377\376\377" \ + "\377\377\1\376\376\376\203\377\377\377\1\376\376\376\203\377\377\377" \ + "\7\332\332\334\302\302\304\234\234\236\203\203\205llnEEG;;=\202::<\6" \ + ";;=::<;;=::<;;=99;\204::<\1""99;\202;;=\1""99;\205::<\1;;=\213::<\11" \ + ";;=::<;;=::<;;=::<;;=::<;;=\202::<\1""99;\206::<\1;;=\203::<\13;;=99" \ + ";;;=::<;;=::\202::<\7llnkkm\233" \ + "\233\235\235\235\237\302\302\304\316\316\320\347\347\351\241\377\377" \ + "\377\202\376\376\376\203\377\377\377\17\376\376\376\377\377\377\376\376" \ + "\376\377\377\377\376\376\376\363\363\363\316\316\316\315\315\315\234" \ + "\234\234\235\235\235xxxllnFFH::<;;=\205::<\5;;=99;;;=::<;;=\212::<\202" \ + ";;=\212::<\5;;=99;;;=::<99;\202::<\5__a\250\250\252\346\346\346\377\377" \ + "\377\376\376\376\202\377\377\377\1\376\376\376\377\377\377\377\377\377" \ + "\377\377\377\377\377\377\271\377\377\377\202\376\376\376\2\377\377\377" \ + "\376\376\376\203\377\377\377\3\363\363\363\266\266\266wwy\202;;=\210" \ + "::<\1<<>\203::<\2<<>99;\215::<\1;;=\205::<\11;;=::<;;;___xxx\235\235" \ + "\235\266\266\266\315\315\315\364\364\364\207\377\377\377\1\376\376\376" \ + "\213\377\377\377\1\376\376\376\231\377\377\377\5\376\376\376\377\377" \ + "\377\376\376\376\377\377\377\376\376\376\202\377\377\377\1\376\376\376" \ + "\204\377\377\377\1\376\376\376\202\377\377\377\5\316\316\316\302\302" \ + "\302\233\233\233yyykkk\202::<\6;;=::<;;=::<99;;;=\211::<\1;;=\202::<" \ + "\1;;=\206::<\1""99;\202;;=\202::<\203;;=\1""99;\202::<\3__a\251\251\253" \ + "\346\346\346\204\377\377\377\3\376\376\376\377\377\377\376\376\376\377" \ + "\377\377\377\377\377\377\377\377\377\377\377\266\377\377\377\1\376\376" \ + "\376\202\377\377\377\2\302\302\302xxx\203::<\3;;=::<;;=\232::<\1;;=\202" \ + "::<\6RRTkkm\235\235\237\301\301\303\332\332\334\376\376\376\222\377\377" \ + "\377\1\376\376\376\260\377\377\377\3\376\376\376\377\377\377\376\376" \ + "\376\202\377\377\377\5\345\345\347\316\316\320\235\235\237xxzSSU\215" \ + "::<\202;;=\202::<\203;;=\2::<;;=\203::<\1;;=\204::<\10;;=::<;;=::<;;" \ + "=kkm\266\266\266\363\363\363\202\377\377\377\1\376\376\376\377\377\377" \ + "\377\377\377\377\377\377\377\377\377\245\377\377\377\1\376\376\376\214" \ + "\377\377\377\1\376\376\376\202\377\377\377\5\376\376\376\377\377\377" \ + "\332\332\332\205\205\207GGI\202::<\1;;=\211::<\202;;=\205::<\2;;=::<" \ + "\202;;=\203::<\14;;=99;::<;;=99;;;=FFFxxx\234\234\234\315\315\315\364" \ + "\364\364\376\376\376\323\377\377\377\4\317\317\317\250\250\250xxxSSS" \ + "\202::<\1;;=\206::<\2;;=::<\203;;=\202::<\2;;=99;\204::<\7;;=::<;;=:" \ + ":<;;=::<;;=\204::<\3\204\204\206\301\301\301\376\376\376\220\377\377" \ + "\377\1\376\376\376\377\377\377\377\377\377\377\377\377\377\377\377\225" \ + "\377\377\377\1\376\376\376\203\377\377\377\1\376\376\376\206\377\377" \ + "\377\1\376\376\376\202\377\377\377\4\363\363\363\251\251\251___;;=\202" \ + "::<\1;;=\202::<\202;;=\204::<\1;;=\202::<\7;;=::<;;=::<;;=::<;;=\203" \ + "::<\3""99;::<;;=\202::<\5;;=__a\221\221\223\265\265\267\346\346\346\323" \ + "\377\377\377\1\376\376\376\211\377\377\377\5\363\363\363\301\301\303" \ + "\235\235\237lln::<\202;;=\203::<\1;;=\204::<\1;;=\202::<\2""99;;;=\205" \ + "::<\2;;=99;\203::<\1""99;\204::<\3TTT\233\233\233\346\346\346\207\377" \ + "\377\377\1\376\376\376\377\377\377\377\377\377\377\377\377\377\377\377" \ + "\250\377\377\377\3\316\316\316\204\204\204;;=\203::<\1;;=\203::<\1;;" \ + "=\202::<\1;;=\205::<\3;;=::<;;=\202::<\4""99;;;=::<;;=\202::<\202;;=" \ + "\4___\221\221\221\301\301\303\363\363\365\203\377\377\377\1\376\376\376" \ + "\203\377\377\377\202\376\376\376\321\377\377\377\1\376\376\376\210\377" \ + "\377\377\1\376\376\376\202\377\377\377\4\316\316\316\235\235\235kkk;" \ + ";=\202::<\202;;=\203::<\5;;=::<;;=99;;;=\204::<\202;;=\7::<;;=99;::<" \ + ";;=::<;;=\202::<\202;;=\2xxz\302\302\304\213\377\377\377\1\376\376\376" \ + "\377\377\377\377\377\377\377\377\377\377\377\377\224\377\377\377\1\376" \ + "\376\376\212\377\377\377\3\363\363\363\266\266\266TTV\203::<\3;;=::<" \ + ";;=\202::<\203;;=\202::<\202;;=\205::<\1;;=\202::<\1;;=\204::<\4SSU\221" \ + "\221\223\301\301\301\363\363\363\206\377\377\377\1\376\376\376\203\377" \ + "\377\377\1\376\376\376\202\377\377\377\1\376\376\376\315\377\377\377" \ + "\202\376\376\376\202\377\377\377\1\376\376\376\210\377\377\377\1\376" \ + "\376\376\202\377\377\377\1\376\376\376\202\377\377\377\3\316\316\316" \ + "\221\221\223__a\203::<\1;;=\203::<\3;;=::<;;=\203::<\5;;=99;;;=::<;;" \ + "=\204::<\1""99;\205::<\3SSU\234\234\236\346\346\346\207\377\377\377\3" \ + "\376\376\376\377\377\377\376\376\376\377\377\377\377\377\377\377\377" \ + "\377\377\377\377\233\377\377\377\4\376\376\376\347\347\347\221\221\221" \ + "FFH\207::<\4""99;;;=::<;;=\20299;\202;;=\202::<\1;;=\203::<\2;;=::<\202" \ + ";;=\202::<\3xxz\250\250\252\346\346\350\215\377\377\377\203\376\376\376" \ + "\316\377\377\377\1\376\376\376\202\377\377\377\1\376\376\376\211\377" \ + "\377\377\1\376\376\376\211\377\377\377\4\363\363\363\265\265\267\205" \ + "\205\207FFH\210::<\3;;=::<;;=\204::<\1;;=\207::<\2;;=::<\202;;=\2\203" \ + "\203\205\317\317\321\206\377\377\377\1\376\376\376\377\377\377\377\377" \ + "\377\377\377\377\377\377\377\233\377\377\377\3\316\316\316yy{99;\206" \ + "::<\2;;=99;\202;;=\205::<\5""99;::<;;=::<;;=\202::<\6;;=::<;;=SSU\204" \ + "\204\204\301\301\301\226\377\377\377\1\376\376\376\317\377\377\377\1" \ + "\376\376\376\203\377\377\377\1\376\376\376\204\377\377\377\1\376\376" \ + "\376\204\377\377\377\1\376\376\376\205\377\377\377\1\376\376\376\202" \ + "\377\377\377\3\316\316\316\221\221\221SSU\203::<\3;;=::<99;\204::<\1" \ + ";;=\203::<\2""99;;;=\202::<\1;;=\204::<\5""99;<<>::99;\202::<\4""99;;;=F" \ + "FF\234\234\234\377\377\377\377\377\377\377\377\375\377\377\377\11\316" \ + "\316\320kkm::<;;=::<;;=99;::<;;=\203::<\202;;=\2::<99;\205::<\13;;=F" \ + "FH\221\221\221\346\346\346\376\376\376\377\377\377\376\376\376\377\377" \ + "\377\376\376\376\377\377\377\376\376\376\204\377\377\377\1\376\376\376" \ + "\273\377\377\377\2\376\376\376\317\317\317\212::<\6;;=;;;\316\316\316" \ + "\376\376\376\377\377\377\376\376\376\304\377\377\377\1\376\376\376\206" \ + "\377\377\377\5\376\376\376\377\377\377\376\376\376\377\377\377\376\376" \ + "\376\204\377\377\377\4\363\363\363\235\235\235RRT;;=\202::<\202;;=\7" \ + "::<;;=99;::<;;=::<;;=\203::<\1;;=\202::<\6;;=::\202::<\2FFH\331\331\333\377\377\377\377\205\377" \ + "\377\377\1\316\316\316\214::<\1\316\316\316\377\377\377\377\216\377\377" \ + "\377\1\376\376\376\203\377\377\377\4\376\376\376\377\377\377\363\363" \ + "\363__a\204::<\2;;=99;\206::<\2;;=\204\204\204\203\377\377\377\1\376" \ + "\376\376\377\377\377\377\377\377\377\377\220\377\377\377\1\204\204\204" \ + "\205::<\1;;=\203::<\1;;=\203::<\4__a\363\363\363\377\377\377\376\376" \ + "\376\377\377\377\377\204\377\377\377\1\316\316\316\214::<\1\316\316\316" \ + "\377\377\377\377\224\377\377\377\4\376\376\376\363\363\363xxx::<\202" \ + ";;=\202::<\1;;=\203::<\1;;=\203::<\1\205\205\207\204\377\377\377\1\376" \ + "\376\376\377\377\377\377\377\377\377\377\215\377\377\377\1\250\250\250" \ + "\205::<\1;;=\203::<\12;;=99;;;=::<__a\363\363\365\377\377\377\376\376" \ + "\376\377\377\377\376\376\376\377\377\377\377\203\377\377\377\1\316\316" \ + "\316\214::<\1\316\316\316\377\377\377\377\227\377\377\377\5\204\204\204" \ + "::<;;=::<;;=\204::<\1""99;\204::<\1\204\204\204\377\377\377\377\377\377" \ + "\377\377\213\377\377\377\1\376\376\376\202\377\377\377\4\376\376\376" \ + "\377\377\377\265\265\267;;=\212::<\4;;=::<__a\363\363\363\217\377\377" \ + "\377\1\376\376\376\367\377\377\377\1\316\316\316\214::<\1\316\316\316" \ + "\376\377\377\377\202\377\377\375\3\377\376\377\377\377\377\376\377\375" \ + "\224\377\377\377\3\204\204\206::<;;=\211::<\7""99;::<\203\203\205\377" \ + "\377\377\376\376\376\377\377\377\376\376\376\205\377\377\377\1\376\376" \ + "\376\202\377\377\377\202\376\376\376\377\377\377\377\377\377\377\377" \ + "\2\264\264\266;;=\202::<\202;;=\1""99;\207::<\2__a\363\363\365\217\377" \ + "\377\377\3\376\376\376\377\377\377\376\376\376\366\377\377\377\1\316" \ + "\316\316\214::<\1\316\316\316\375\377\377\377\5\377\377\375\377\376\377" \ + "\377\375\377\377\377\375\377\377\377\202\377\376\377\221\377\377\377" \ + "\1\376\376\376\202\377\377\377\1\204\204\206\203::<\1;;=\202::<\2;;=" \ + "::<\202;;=\202::<\3;;=\204\204\204\376\376\376\211\377\377\377\3\376" \ + "\376\376\377\377\377\376\376\376\377\377\377\377\375\377\377\377\7\376" \ + "\376\376\264\264\266;;=99;::<;;=99;\204::<\1;;=\203::<\2aac\363\363\363" \ + "\221\377\377\377\1\376\376\376\367\377\377\377\1\316\316\316\214::<\1" \ + "\316\316\316\375\377\377\377\202\376\376\376\203\377\377\377\202\376" \ + "\377\377\222\377\377\377\10\376\376\376\377\377\377\376\376\376\204\204" \ + "\206::<;;=::<;;=\203::<\202;;=\202::<\6""99;;;=\205\205\207\376\376\376" \ + "\377\377\377\376\376\376\203\377\377\377\202\376\376\376\202\377\377" \ + "\377\1\376\376\376\377\377\377\377\375\377\377\377\3\376\376\376\302" \ + "\302\304;;=\203::<\1;;=\204::<\6;;=99;;;=::\202::<\2__a\363\363\365\202\377\377\377\1" \ + "\376\376\376\213\377\377\377\1\376\376\376\375\377\377\377\1\316\316" \ + "\316\214::<\1\316\316\316\374\377\377\377\7\377\376\377\376\377\377\376" \ + "\376\374\377\376\377\377\377\375\376\377\377\377\377\375\226\377\377" \ + "\377\1\376\376\376\202\377\377\377\1\203\203\203\214::<\2;;=\265\265" \ + "\265\206\377\377\377\1\376\376\376\377\377\377\377\374\377\377\377\4" \ + "\364\364\364GGI99;;;=\206::<\1;;=\203::<\2__a\363\363\363\205\377\377" \ + "\377\1\376\376\376\212\377\377\377\1\363\363\363\203\377\377\377\1\376" \ + "\376\376\370\377\377\377\1\316\316\316\214::<\1\316\316\316\374\377\377" \ + "\377\10\377\377\375\377\376\377\377\377\377\377\377\375\377\376\377\370" \ + "\373\362\370\373\364\377\376\377\220\377\377\377\1\376\376\376\202\377" \ + "\377\377\1\376\376\376\202\377\377\377\1\376\376\376\202\377\377\377" \ + "\1\204\204\204\203::<\1;;=\210::<\2FFH\332\332\334\204\377\377\377\1" \ + "\376\376\376\377\377\377\377\374\377\377\377\3\363\363\363___;;=\202" \ + "::<\1;;=\204::<\6;;=99;;;=::<__a\363\363\365\220\377\377\377\3\265\265" \ + "\265FFF\333\333\333\373\377\377\377\1\316\316\316\214::<\1\316\316\316" \ + "\376\377\377\377\6\374\377\377\377\377\375\371\374\365\242\320c\240\322" \ + "c\371\372\362\221\377\377\377\1\376\376\376\210\377\377\377\2\203\203" \ + "\203;;=\202::<\1;;=\203::<\1;;=\203::<\3;;=FFH\333\333\333\202\377\377" \ + "\377\1\376\376\376\377\377\377\377\371\377\377\377\1\376\376\376\203" \ + "\377\377\377\2kkm::<\202;;=\1""99;\205::<\202;;=\3::<__a\363\363\363" \ + "\220\377\377\377\5\265\265\267::<;;=FFH\332\332\332\206\377\377\377\3" \ + "\376\376\376\377\377\377\376\376\376\361\377\377\377\1\316\316\316\213" \ + "::<\2;;=\316\316\316\365\377\377\377\22\376\376\377\377\377\375\377\377" \ + "\377\377\377\375\377\377\377\377\376\377\377\377\375\377\377\377\376" \ + "\376\377\377\377\377\371\374\365\242\320c\215\307\77\215\305@\242\322" \ + "e\372\373\365\376\377\375\377\376\377\230\377\377\377\3\205\205\207:" \ + ":<;;=\206::<\1;;=\202::<\4;;=SSU\363\363\365\376\376\376\377\377\377" \ + "\377\374\377\377\377\13\376\376\376\204\204\204::<;;=99;::<;;=::<;;=" \ + "::<;;=\203::<\3__a\364\364\366\376\376\376\217\377\377\377\1\265\265" \ + "\267\203::<\3;;=FFF\332\332\332\206\377\377\377\1\376\376\376\361\377" \ + "\377\377\2\376\376\376\317\317\317\212::<\6;;=;;;\316\316\316\376\376" \ + "\376\377\377\377\376\376\376\361\377\377\377\6\376\376\377\377\376\377" \ + "\375\376\377\376\377\377\377\377\375\375\377\376\202\377\377\377\17\376" \ + "\376\376\377\377\377\371\372\364\240\322a\215\305@\212\307>\215\307\77" \ + "\215\305>\242\320c\370\372\365\377\377\377\377\376\377\376\377\375\377" \ + "\377\375\377\376\377\225\377\377\377\5kkm::<;;=99;;;=\210::<\4__a\364" \ + "\364\364\376\376\376\377\377\377\202\376\376\376\377\377\377\377\363" \ + "\377\377\377\3\376\376\376\377\377\377\376\376\376\202\377\377\377\4" \ + "\250\250\252::<;;=99;\202;;=\205::<\202;;=\3FFH\345\345\345\376\376\376" \ + "\217\377\377\377\4\264\264\266;;=::<;;=\203::<\2GGI\332\332\332\203\377" \ + "\377\377\1\376\376\376\356\377\377\377\1\376\376\376\205\377\377\377" \ + "\2\315\315\315;;;\211::<\3;;;:::\315\315\315\202\377\377\377\1\376\376" \ + "\376\361\377\377\377\23\377\377\375\375\376\377\376\377\377\376\377\375" \ + "\377\374\377\377\377\375\375\377\376\377\377\377\377\377\375\371\372" \ + "\364\242\321g\215\306A\212\307>\215\306A\212\306@\214\305@\212\306B\241" \ + "\322_\367\372\361\204\377\377\377\1\377\377\375\220\377\377\377\1\376" \ + "\376\376\203\377\377\377\3\363\363\363__a99;\202::<\6;;=::<99;;;=99;" \ + ";;=\203::<\1\205\205\207\204\377\377\377\1\376\376\376\377\377\377\377" \ + "\362\377\377\377\1\376\376\376\202\377\377\377\22\376\376\376\265\265" \ + "\267::<99;;;=::<;;=99;;;=::<;;=::<;;=::\214\305@\214" \ + "\306>\202\214\305@\4\241\321a\371\374\365\376\376\377\377\377\375\202" \ + "\376\377\377\221\377\377\377\1\376\376\376\203\377\377\377\3\362\362" \ + "\362``b99;\205::<\1;;=\203::<\6;;=99;\235\235\237\376\376\376\377\377" \ + "\377\376\376\376\377\377\377\377\366\377\377\377\2\332\332\332FFH\202" \ + ";;=\4""99;;;=::<;;=\205::<\2FFH\332\332\334\202\377\377\377\3\376\376" \ + "\376\377\377\377\376\376\376\213\377\377\377\4\266\266\26699;::<;;=\202" \ + "::<\1;;=\202::<\4;;=::\215\305" \ + "@\212\306@\213\310=\214\306<\216\306\77\214\304=\214\306>\241\321c\372" \ + "\375\362\376\376\376\377\376\377\376\376\374\220\377\377\377\2\376\376" \ + "\376\377\377\377\203\376\376\376\4\377\377\377\364\364\364FFH;;=\202" \ + "::<\1;;=\202::<\1;;=\203::<\3;;=::<\265\265\265\377\377\377\377\367\377" \ + "\377\377\4\362\362\362SSU::<;;=\205::<\1""99;\202;;=\3::<;;=\265\265" \ + "\267\216\377\377\377\3\376\376\376\377\377\377\265\265\265\202::<\5;" \ + ";=99;;;=::<;;=\204::<\4;;=FFH\332\332\332\376\376\376\205\377\377\377" \ + "\1\376\376\376\355\377\377\377\1\376\376\376\214\377\377\377\1\376\376" \ + "\376\366\377\377\377\1\375\377\376\202\377\377\375\24\377\377\377\376" \ + "\376\376\373\373\363\243\322b\213\307A\214\306>\215\305@\214\305@\212" \ + "\307>\214\306>\215\305>\213\307A\214\305@\216\310@\214\306>\215\305>" \ + "\242\320c\366\373\364\375\377\376\377\376\377\221\377\377\377\1\376\376" \ + "\376\204\377\377\377\3\376\376\376\333\333\333EEG\202;;=\2::<;;=\207" \ + "::<\3GGI\332\332\332\376\376\376\377\377\377\377\365\377\377\377\1__" \ + "a\205::<\10;;=::<;;=::<;;=::<;;=\265\265\265\202\377\377\377\3\376\376" \ + "\376\377\377\377\376\376\376\213\377\377\377\1\266\266\266\203::<\5""9" \ + "9;<<>::<;;=::<\202;;=\203::<\4;;=FFH\333\333\333\376\376\376\202\377" \ + "\377\377\1\376\376\376\355\377\377\377\1\376\376\376\202\377\377\377" \ + "\1\376\376\376\215\377\377\377\1\376\376\376\363\377\377\377\3\377\376" \ + "\377\377\377\377\375\377\376\202\377\377\377\2\373\373\363\241\321d\202" \ + "\214\306>\17\216\306=\215\305@\215\307\77\214\306>\217\304>\214\306>" \ + "\214\305B\215\307\77\211\305A\215\306A\216\306\77\214\305@\242\322e\370" \ + "\373\364\377\377\375\230\377\377\377\1\333\333\335\203::<\202;;=\206" \ + "::<\3;;=FFH\363\363\363\377\377\377\377\364\377\377\377\1\204\204\206" \ + "\203::<\1;;=\207::<\2;;=\204\204\206\220\377\377\377\1\346\346\346\204" \ + "::<\1;;=\203::<\1;;=\202::<\202;;=\203::<\2FFH\332\332\332\357\377\377" \ + "\377\3\376\376\376\377\377\377\376\376\376\377\377\377\377\204\377\377" \ + "\377\1\377\377\375\202\377\377\377\17\377\376\377\370\373\364\243\322" \ + "b\214\306>\213\310\77\212\307>\214\306>\215\306C\212\307>\214\306<\213" \ + "\310\77\214\305@\214\306<\214\306>\216\306\77\203\214\306>\3\214\306" \ + "<\265\334\211\376\376\376\222\377\377\377\1\376\376\376\205\377\377\377" \ + "\4\376\376\377\265\265\267::<;;=\212::<\1___\377\377\377\377\363\377" \ + "\377\377\1\265\265\267\204::<\1;;=\206::<\2;;=\203\203\203\222\377\377" \ + "\377\2\265\265\265;;=\203::<\1;;=\205::<\1;;=\204::<\3;;=FFH\332\332" \ + "\332\206\377\377\377\3\376\376\376\377\377\377\376\376\376\377\377\377" \ + "\377\345\377\377\377\10\376\376\377\377\377\375\377\377\377\377\377\375" \ + "\377\377\377\377\376\377\377\377\375\376\377\377\202\377\377\377\6\370" \ + "\373\362\243\322b\211\307B\213\310=\214\305@\214\306<\202\215\305@\4" \ + "\214\306<\214\305@\214\306<\215\307\77\202\214\306>\6\212\307>\214\306" \ + ">\215\307\77\214\305@\244\317c\367\375\361\233\377\377\377\3\234\234" \ + "\236::<99;\211::<\2;;=\204\204\206\377\377\377\377\360\377\377\377\13" \ + "\376\376\376\332\332\33299;::<99;;;=::<99;;;=::<;;=\202::<\3;;=^^`\364" \ + "\364\364\223\377\377\377\12\265\265\267;;=::<;;=99;;;=::<;;=::<;;=\202" \ + "::<\1;;=\203::<\3;;=FFF\332\332\332\206\377\377\377\1\376\376\376\377" \ + "\377\377\377\345\377\377\377\6\376\376\377\377\376\377\375\376\377\376" \ + "\377\377\377\377\375\375\377\376\203\377\377\377\27\377\377\375\372\373" \ + "\366\241\321a\217\304@\212\307<\214\306>\215\305>\215\305@\213\310=\212" \ + "\306@\214\306>\214\305B\215\307\77\215\305>\215\306A\212\307>\214\306" \ + ">\215\307\77\214\306>\242\322b\370\373\362\376\376\377\377\375\376\233" \ + "\377\377\377\1\204\204\206\203::<\13;;=::<;;=::<;;=::<;;=::<;;=\266\266" \ + "\266\376\376\376\203\377\377\377\1\376\376\376\377\377\377\377\352\377" \ + "\377\377\2\363\363\363TTV\202::<\3;;=99;;;=\204::<\4;;=99;FFH\363\363" \ + "\363\224\377\377\377\7\376\376\376\265\265\265;;=::<;;=::<;;=\203::<" \ + "\1;;=\203::<\1;;=\203::<\2GGI\332\332\332\203\377\377\377\1\376\376\376" \ + "\377\377\377\377\347\377\377\377\7\377\377\375\375\376\377\376\377\377" \ + "\376\377\375\377\374\377\377\377\375\375\377\376\202\377\377\377\5\372" \ + "\373\366\240\320b\215\307\77\212\306@\215\305>\202\214\305@\20\215\305" \ + "@\212\306@\214\305D\216\306\77\214\306>\215\307\77\214\306>\212\306@" \ + "\214\306>\215\307\77\215\305@\242\320c\370\373\362\377\377\373\377\376" \ + "\377\377\377\375\232\377\377\377\3\376\376\376\377\377\377^^`\202;;=" \ + "\205::<\1""99;\202;;=\5::<;;=\332\332\332\377\377\377\376\376\376\377" \ + "\377\377\377\347\377\377\377\1\376\376\376\204\377\377\377\1lln\204:" \ + ":<\202;;=\203::<\6;;=99;GGI\332\332\332\377\377\377\376\376\376\225\377" \ + "\377\377\2\264\264\264;;=\202::<\2""99;;;=\202::<\3""99;;;=::<\202;;" \ + "=\202::<\4;;=::\212\307<\214\306>\214\306<\214\306>\216" \ + "\306\77\215\305<\212\307>\213\307A\215\305>\212\307>\215\307\77\214\306" \ + ">\242\321a\373\374\364\377\377\377\376\377\377\376\376\376\376\377\377" \ + "\234\377\377\377\2\364\364\364RRT\202::<\4""99;;;=::<;;=\205::<\3SSU" \ + "\362\362\362\377\377\377\202\376\376\376\377\377\377\377\351\377\377" \ + "\377\1\234\234\236\204::<\1;;=\203::<\1;;=\203::<\1\265\265\267\231\377" \ + "\377\377\2\265\265\267;;=\203::<\2""99;;;=\202::<\1;;=\202::<\1;;=\202" \ + "::<\4;;=::\212\307>\212\306@\214\305B" \ + "\214\305@\214\305B\214\306>\212\307>\212\310\77\214\306>\217\304@\214" \ + "\306>\214\305@\242\322b\370\373\362\377\377\377\202\377\376\377\1\377" \ + "\377\375\235\377\377\377\3\376\376\376\332\332\334GGI\202;;=\6::<;;=" \ + "99;;;=::<;;=\203::<\1yyy\202\376\376\376\202\377\377\377\1\376\376\376" \ + "\377\377\377\377\345\377\377\377\4\376\376\376\317\317\317::<;;=\202" \ + "::<\3;;=99;;;=\204::<\6;;=\221\221\223\377\377\377\376\376\376\377\377" \ + "\377\376\376\376\226\377\377\377\3\376\376\376\265\265\267;;=\202::<" \ + "\2;;=99;\205::<\1;;=\204::<\4;;=FFH\332\332\332\376\376\376\205\377\377" \ + "\377\1\376\376\376\377\377\377\377\342\377\377\377\1\375\377\376\202" \ + "\377\377\375\34\377\377\377\376\376\376\373\373\363\243\322b\211\307" \ + "B\212\307<\215\305>\214\306>\212\307>\214\305@\217\304>\212\307<\214" \ + "\306<\214\306>\215\307\77\213\307A\214\306>\215\305@\215\307\77\212\307" \ + ">\244\317c\370\373\362\377\377\373\376\377\377\377\376\377\375\376\377" \ + "\377\377\375\377\376\377\236\377\377\377\4\265\265\267::<;;=99;\202;" \ + ";=\205::<\202;;=\1\250\250\250\202\377\377\377\1\376\376\376\377\377" \ + "\377\377\343\377\377\377\1\376\376\376\202\377\377\377\3\363\363\363" \ + "FFH;;=\202::<\5;;=::<;;=::<99;\202;;=\2::\213\310=\214\306>\214" \ + "\305@\213\310=\212\306@\217\304>\202\215\307=\14\214\306>\215\305>\214" \ + "\306>\215\305>\217\304@\215\307\77\215\307=\242\320c\367\375\361\376" \ + "\376\377\377\376\377\376\376\376\202\377\377\375\2\374\377\377\377\376" \ + "\377\234\377\377\377\1\376\376\376\202\377\377\377\10\221\221\221::<" \ + ";;=99;::<;;=::<;;=\205::<\2\333\333\333\376\376\376\377\377\377\377\347" \ + "\377\377\377\1kkk\202::<\1;;=\205::<\1;;=\202::<\2RRT\363\363\365\236" \ + "\377\377\377\1\265\265\267\203::<\2""99;;;=\203::<\1;;=\202::<\202;;" \ + "=\203::<\2FFH\332\332\332\377\377\377\377\346\377\377\377\1\377\377\375" \ + "\202\377\377\377\32\377\376\377\370\373\364\243\322b\214\306>\213\310" \ + "\77\214\305@\215\305>\215\305@\214\306>\214\305B\212\307<\215\307=\214" \ + "\305B\214\306>\215\306A\212\306@\212\307>\214\306>\212\307<\244\317c" \ + "\370\373\364\377\377\377\377\375\376\377\377\375\376\377\377\377\377" \ + "\377\202\377\376\377\241\377\377\377\2kkm::<\202;;=\1""99;\204::<\203" \ + ";;=\2SSU\364\364\364\377\377\377\377\336\377\377\377\3\376\376\376\377" \ + "\377\377\376\376\376\204\377\377\377\2\376\376\376\250\250\252\202::" \ + "<\1;;=\210::<\2FFH\333\333\333\202\377\377\377\1\376\376\376\235\377" \ + "\377\377\2\265\265\265;;=\203::<\1;;=\205::<\1;;=\204::<\3;;=FFH\332" \ + "\332\332\206\377\377\377\3\376\376\376\377\377\377\376\376\376\243\377" \ + "\377\377\4\376\377\377\377\377\375\377\376\377\376\376\377\202\377\377" \ + "\377\2\376\377\375\376\377\377\230\377\377\377\10\376\377\377\377\376" \ + "\377\376\377\377\376\377\375\376\376\376\376\377\377\377\377\377\377" \ + "\376\377\231\377\377\377\7\377\376\377\376\376\374\376\377\377\377\377" \ + "\375\374\377\377\376\377\377\377\376\377\231\377\377\377\17\375\377\374" \ + "\377\377\375\377\377\377\377\376\377\376\377\377\377\376\377\377\377" \ + "\377\376\377\377\376\376\374\377\377\377\377\377\373\377\377\377\376" \ + "\377\377\377\377\377\377\377\375\220\377\377\377\4\377\377\373\377\377" \ + "\377\377\377\375\377\377\377\202\376\377\377\2\377\377\375\377\377\373" \ + "\251\377\377\377\10\376\376\377\377\377\375\377\377\377\377\377\375\377" \ + "\377\377\377\376\377\377\377\375\376\377\377\202\377\377\377\6\370\373" \ + "\362\243\322b\211\307B\213\310=\214\305@\214\306<\202\215\305@\4\214" \ + "\306<\214\305@\214\306<\215\307\77\202\214\306>\6\212\307>\214\306>\215" \ + "\307\77\214\305@\244\317c\367\375\361\251\377\377\377\6\363\363\363T" \ + "TT::<;;=::<;;=\206::<\2;;=www\204\377\377\377\1\376\376\376\377\377\377" \ + "\377\340\377\377\377\2\332\332\332;;=\203::<\3;;=99;;;=\203::<\3;;=:" \ + ":<\265\265\267\204\377\377\377\1\376\376\376\235\377\377\377\12\265\265" \ + "\267;;=::<;;=99;;;=::<;;=::<;;=\202::<\1;;=\203::<\3;;=FFF\332\332\332" \ + "\206\377\377\377\1\376\376\376\244\377\377\377\202\377\377\375\1\377" \ + "\377\377\202\376\377\375\3\376\376\377\377\377\377\377\376\377\230\377" \ + "\377\377\3\376\377\375\377\377\377\377\377\373\202\377\376\377\2\377" \ + "\377\377\376\376\376\231\377\377\377\10\376\377\373\376\375\377\377\377" \ + "\375\377\376\377\377\375\377\377\377\373\377\376\377\377\377\375\230" \ + "\377\377\377\12\377\376\377\377\377\377\377\375\376\376\377\377\376\377" \ + "\372\376\377\377\377\377\377\376\377\375\377\376\377\377\377\375\203" \ + "\377\377\377\202\376\377\375\1\375\376\377\227\377\377\377\1\377\374" \ + "\377\250\377\377\377\6\376\376\377\377\376\377\375\376\377\376\377\377" \ + "\377\377\375\375\377\376\203\377\377\377\27\377\377\375\372\373\366\241" \ + "\321a\217\304@\212\307<\214\306>\215\305>\215\305@\213\310=\212\306@" \ + "\214\306>\214\305B\215\307\77\215\305>\215\306A\212\307>\214\306>\215" \ + "\307\77\214\306>\242\322b\370\373\362\376\376\377\377\375\376\251\377" \ + "\377\377\2\331\331\331;;=\206::<\1;;=\203::<\2;;=\265\265\265\204\377" \ + "\377\377\1\376\376\376\202\377\377\377\1\376\376\376\377\377\377\377" \ + "\322\377\377\377\1\376\376\376\203\377\377\377\3\376\376\376\377\377" \ + "\377\376\376\376\202\377\377\377\2\363\363\363SSU\203::<\2;;=::<\202" \ + ";;=\2""99;;;=\202::<\1\204\204\204\206\377\377\377\1\376\376\376\234" \ + "\377\377\377\7\376\376\376\265\265\265;;=::<;;=::<;;=\203::<\1;;=\203" \ + "::<\1;;=\203::<\2GGI\332\332\332\203\377\377\377\1\376\376\376\247\377" \ + "\377\377\1\377\377\375\202\377\376\377\1\377\375\377\202\377\377\377" \ + "\1\377\376\377\232\377\377\377\6\377\377\375\377\377\377\375\377\376" \ + "\376\377\375\377\377\375\377\375\377\230\377\377\377\202\377\377\375" \ + "\2\377\377\377\376\376\376\202\377\377\377\2\376\377\377\374\377\377" \ + "\230\377\377\377\1\377\377\375\202\377\376\377\1\375\376\377\203\377" \ + "\377\377\1\377\377\375\202\377\377\377\6\376\376\377\377\377\375\377" \ + "\377\377\377\375\377\377\376\377\377\377\375\220\377\377\377\1\376\377" \ + "\377\202\377\377\377\3\376\377\375\376\376\376\377\376\377\252\377\377" \ + "\377\7\377\377\375\375\376\377\376\377\377\376\377\375\377\374\377\377" \ + "\377\375\375\377\376\202\377\377\377\5\372\373\366\240\320b\215\307\77" \ + "\212\306@\215\305>\202\214\305@\20\215\305@\212\306@\214\305D\216\306" \ + "\77\214\306>\215\307\77\214\306>\212\306@\214\306>\215\307\77\215\305" \ + "@\242\320c\370\373\362\377\377\373\377\376\377\377\377\375\252\377\377" \ + "\377\2\250\250\25099;\204::<\12;;=99;::<;;=99;::\212\307<\214\306" \ + ">\214\306<\214\306>\216\306\77\215\305<\212\307>\213\307A\215\305>\212" \ + "\307>\215\307\77\214\306>\242\321a\373\374\364\377\377\377\376\377\377" \ + "\376\376\376\376\377\377\253\377\377\377\1yyy\205::<\3;;=::<99;\202;" \ + ";=\3::<__a\376\376\376\377\377\377\377\335\377\377\377\1\376\376\376" \ + "\202\377\377\377\5\301\301\301::<;;=99;;;=\207::<\2GGI\332\332\332\203" \ + "\377\377\377\1\376\376\376\243\377\377\377\2\265\265\267;;=\203::<\2" \ + "99;;;=\202::<\1;;=\202::<\1;;=\202::<\4;;=::\212\307>\212\306@\214\305B\214\305@\214\305B\214\306>" \ + "\212\307>\212\310\77\214\306>\217\304@\214\306>\214\305@\242\322b\370" \ + "\373\362\377\377\377\202\377\376\377\1\377\377\375\254\377\377\377\4" \ + "\363\363\363SSU;;=99;\202;;=\1""99;\204::<\3;;=::<\235\235\237\377\377" \ + "\377\377\334\377\377\377\1\376\376\376\202\377\377\377\2\363\363\363" \ + "GGI\202::<\7;;=::<99;::<;;=::<;;=\202::<\2\266\266\266\376\376\376\204" \ + "\377\377\377\202\376\376\376\202\377\377\377\1\376\376\376\236\377\377" \ + "\377\3\376\376\376\265\265\267;;=\202::<\2;;=99;\205::<\1;;=\204::<\4" \ + ";;=FFH\332\332\332\376\376\376\205\377\377\377\1\376\376\376\240\377" \ + "\377\377\10\376\377\375\377\375\377\377\377\375\376\377\375\377\377\377" \ + "\377\376\377\377\377\377\376\376\374\230\377\377\377\10\374\377\377\377" \ + "\376\374\377\377\377\376\376\374\377\376\377\376\377\377\377\377\377" \ + "\377\376\377\230\377\377\377\3\377\377\375\377\377\377\376\377\375\203" \ + "\377\377\377\1\377\376\377\231\377\377\377\6\377\375\377\376\376\374" \ + "\377\377\377\377\376\377\376\377\375\377\376\377\202\377\377\377\2\377" \ + "\376\377\377\377\377\202\376\377\377\2\376\376\377\376\377\377\222\377" \ + "\377\377\2\377\377\375\377\375\377\202\376\377\377\4\376\376\376\376" \ + "\377\377\375\377\374\377\375\377\251\377\377\377\1\375\377\376\202\377" \ + "\377\375\34\377\377\377\376\376\376\373\373\363\243\322b\211\307B\212" \ + "\307<\215\305>\214\306>\212\307>\214\305@\217\304>\212\307<\214\306<" \ + "\214\306>\215\307\77\213\307A\214\306>\215\305@\215\307\77\212\307>\244" \ + "\317c\370\373\362\377\377\373\376\377\377\377\376\377\375\376\377\377" \ + "\377\375\377\376\377\252\377\377\377\5\376\376\376\377\377\377\333\333" \ + "\33399;;;=\202::<\5;;=99;;;=99;;;=\203::<\1\332\332\334\377\377\377\377" \ + "\330\377\377\377\1\376\376\376\205\377\377\377\1xxx\202::<\1;;=\202:" \ + ":<\1;;=\204::<\4:::xxx\376\376\376\377\377\377\202\376\376\376\205\377" \ + "\377\377\3\376\376\376\377\377\377\376\376\376\237\377\377\377\1\265" \ + "\265\265\204::<\6;;=::<;;=::<;;=::<\202;;=\203::<\4;;=FFH\333\333\333" \ + "\376\376\376\202\377\377\377\1\376\376\376\242\377\377\377\7\376\376" \ + "\376\377\376\377\326\352\267\247\324o\247\324m\252\324r\247\324o\231" \ + "\252\324p\10\323\353\271\377\376\377\377\377\377\376\377\377\350\365" \ + "\333\253\323p\250\324r\251\324k\230\252\324p\10\250\325n\252\324p\277" \ + "\337\223\376\377\377\377\377\377\375\377\376\376\377\377\276\336\222" \ + "\230\252\324p\7\250\325p\250\324r\247\324o\253\324n\251\323m\346\364" \ + "\332\377\376\377\202\377\377\377\7\323\352\266\253\323p\251\323m\253" \ + "\323r\251\323o\247\324m\252\324r\220\252\324p\10\252\324n\253\324n\247" \ + "\324k\252\324p\254\325o\247\324m\252\324p\324\353\267\250\377\377\377" \ + "\3\377\376\377\377\377\377\375\377\376\202\377\377\377\11\373\373\363" \ + "\241\321d\214\306>\213\310=\214\306>\214\305@\213\310=\212\306@\217\304" \ + ">\202\215\307=\14\214\306>\215\305>\214\306>\215\305>\217\304@\215\307" \ + "\77\215\307=\242\320c\367\375\361\376\376\377\377\376\377\376\376\376" \ + "\202\377\377\375\2\374\377\377\377\376\377\254\377\377\377\2\376\376" \ + "\376\251\251\251\202::<\5;;=::<;;=99;;;=\204::<\1``b\377\377\377\377" \ + "\334\377\377\377\3\376\376\376\301\301\301:::\205::<\1""99;\202::<\4" \ + ";;=::\10\304\341\237\377\374\377\377\376\377\377\377\377" \ + "\341\362\322\215\305>\212\307>\215\305>\230\214\306>\4\215\305<\214\305" \ + "@\252\324r\376\377\377\202\377\377\377\2\377\377\375\250\324r\230\214" \ + "\306>\20\215\307\77\214\306>\214\306<\214\305B\212\307>\337\363\320\377" \ + "\376\377\376\377\377\376\376\374\305\342\240\214\305@\213\310=\215\305" \ + "@\214\306>\212\307<\214\305@\220\214\306>\10\214\305@\215\306C\212\307" \ + "<\214\306>\215\305>\212\306@\215\305>\304\343\237\250\377\377\377\1\377" \ + "\377\375\202\377\377\377\32\377\376\377\370\373\364\243\322b\214\306" \ + ">\213\310\77\214\305@\215\305>\215\305@\214\306>\214\305B\212\307<\215" \ + "\307=\214\305B\214\306>\215\306A\212\306@\212\307>\214\306>\212\307<" \ + "\244\317c\370\373\364\377\377\377\377\375\376\377\377\375\376\377\377" \ + "\377\377\377\202\377\376\377\257\377\377\377\1kkm\202::<\2;;=::<\202" \ + ";;=\3::<;;=::<\202;;=\1\233\233\233\377\377\377\377\330\377\377\377\1" \ + "\376\376\376\202\377\377\377\3\364\364\366FFH;;=\205::<\3;;=::<;;=\202" \ + "::<\1\316\316\316\256\377\377\377\2\265\265\265;;=\203::<\1;;=\205::" \ + "<\1;;=\204::<\3;;=FFH\332\332\332\206\377\377\377\3\376\376\376\377\377" \ + "\377\376\376\376\235\377\377\377\1\304\343\240\235\214\306>\1\305\342" \ + "\237\203\377\377\377\1\342\362\316\235\214\306>\1\250\325p\204\377\377" \ + "\377\1\252\324p\234\214\306>\2\215\307\77\342\362\316\203\377\377\377" \ + "\3\305\342\237\214\305@\215\305>\202\214\306>\1\214\305@\222\214\306" \ + ">\1\214\305@\205\214\306>\1\305\342\237\241\377\377\377\10\376\376\377" \ + "\377\377\375\377\377\377\377\377\375\377\377\377\377\376\377\377\377" \ + "\375\376\377\377\202\377\377\377\6\370\373\362\243\322b\211\307B\213" \ + "\310=\214\305@\214\306<\202\215\305@\4\214\306<\214\305@\214\306<\215" \ + "\307\77\202\214\306>\6\212\307>\214\306>\215\307\77\214\305@\244\317" \ + "c\367\375\361\267\377\377\377\2\363\363\363FFF\204::<\1;;=\203::<\4:" \ + "9>::<;;=\332\332\332\377\377\377\377\332\377\377\377\1yy{\202::<\2""9" \ + "9;;;=\202::<\6;;=99;::<;;=::<\234\234\236\260\377\377\377\12\265\265" \ + "\267;;=::<;;=99;;;=::<;;=::<;;=\202::<\1;;=\203::<\3;;=FFF\332\332\332" \ + "\206\377\377\377\1\376\376\376\236\377\377\377\1\304\343\240\235\214" \ + "\306>\1\305\342\237\203\377\377\377\1\342\362\316\235\214\306>\1\250" \ + "\325p\204\377\377\377\1\252\324p\234\214\306>\2\215\307\77\342\362\316" \ + "\203\377\377\377\3\305\342\237\214\305@\215\305>\202\214\306>\1\214\305" \ + "@\222\214\306>\1\214\305@\205\214\306>\1\305\342\237\240\377\377\377" \ + "\6\376\376\377\377\376\377\375\376\377\376\377\377\377\377\375\375\377" \ + "\376\203\377\377\377\27\377\377\375\372\373\366\241\321a\217\304@\212" \ + "\307<\214\306>\215\305>\215\305@\213\310=\212\306@\214\306>\214\305B" \ + "\215\307\77\215\305>\215\306A\212\307>\214\306>\215\307\77\214\306>\242" \ + "\322b\370\373\362\376\376\377\377\375\376\267\377\377\377\1\301\301\301" \ + "\205::<\3;;=::<;;=\202::<\2""99;```\377\377\377\377\331\377\377\377\1" \ + "\301\301\301\202::<\1;;=\203::<\1;;=\202::<\3<<>::<__a\261\377\377\377" \ + "\7\376\376\376\265\265\265;;=::<;;=::<;;=\203::<\1;;=\203::<\1;;=\203" \ + "::<\2GGI\332\332\332\203\377\377\377\1\376\376\376\240\377\377\377\1" \ + "\304\343\240\235\214\306>\1\305\342\237\203\377\377\377\1\342\362\316" \ + "\235\214\306>\1\250\325p\204\377\377\377\1\252\324p\234\214\306>\2\215" \ + "\307\77\342\362\316\203\377\377\377\3\305\342\237\214\305@\215\305>\202" \ + "\214\306>\1\214\305@\222\214\306>\1\214\305@\205\214\306>\1\305\342\237" \ + "\240\377\377\377\7\377\377\375\375\376\377\376\377\377\376\377\375\377" \ + "\374\377\377\377\375\375\377\376\202\377\377\377\5\372\373\366\240\320" \ + "b\215\307\77\212\306@\215\305>\202\214\305@\20\215\305@\212\306@\214" \ + "\305D\216\306\77\214\306>\215\307\77\214\306>\212\306@\214\306>\215\307" \ + "\77\215\305@\242\320c\370\373\362\377\377\373\377\376\377\377\377\375" \ + "\270\377\377\377\3\204\204\204::<;;=\206::<\4;;=::<;;=\234\234\236\377" \ + "\377\377\377\325\377\377\377\4\376\376\376\377\377\377\363\363\363SS" \ + "U\211::<\4""99;::<\332\332\334\376\376\376\202\377\377\377\1\376\376" \ + "\376\257\377\377\377\2\264\264\264;;=\202::<\2""99;;;=\202::<\3""99;" \ + ";;=::<\202;;=\202::<\4;;=::\1\305\342\237\203\377" \ + "\377\377\1\342\362\316\235\214\306>\1\250\325p\204\377\377\377\1\252" \ + "\324p\234\214\306>\2\215\307\77\342\362\316\203\377\377\377\3\305\342" \ + "\237\214\305@\215\305>\202\214\306>\1\214\305@\222\214\306>\1\214\305" \ + "@\205\214\306>\1\305\342\237\241\377\377\377\37\376\377\377\376\377\375" \ + "\377\375\376\375\377\376\377\377\375\377\377\377\377\376\377\370\373" \ + "\362\241\321a\215\307\77\215\307=\214\305@\214\306>\212\307<\214\306" \ + ">\214\306<\214\306>\216\306\77\215\305<\212\307>\213\307A\215\305>\212" \ + "\307>\215\307\77\214\306>\242\321a\373\374\364\377\377\377\376\377\377" \ + "\376\376\376\376\377\377\270\377\377\377\3\363\363\363TTT;;=\202::<\1" \ + ";;=\203::<\5""99;;;=::<;;=\332\332\332\377\377\377\377\323\377\377\377" \ + "\1\376\376\376\202\377\377\377\4\221\221\221;;=99;;;=\202::<\1;;=\202" \ + "::<\1;;=\202::<\1\233\233\233\202\377\377\377\1\376\376\376\262\377\377" \ + "\377\2\265\265\267;;=\203::<\2""99;;;=\202::<\1;;=\202::<\1;;=\202::" \ + "<\4;;=::\1\305\342\237" \ + "\203\377\377\377\1\342\362\316\235\214\306>\1\250\325p\204\377\377\377" \ + "\1\252\324p\234\214\306>\2\215\307\77\342\362\316\203\377\377\377\3\305" \ + "\342\237\214\305@\215\305>\202\214\306>\1\214\305@\222\214\306>\1\214" \ + "\305@\205\214\306>\1\305\342\237\240\377\377\377\202\377\377\375\3\377" \ + "\374\377\375\377\376\376\377\377\202\377\377\377\25\370\373\364\243\322" \ + "b\217\304@\212\306@\214\305@\215\305>\212\307>\212\306@\214\305B\214" \ + "\305@\214\305B\214\306>\212\307>\212\310\77\214\306>\217\304@\214\306" \ + ">\214\305@\242\322b\370\373\362\377\377\377\202\377\376\377\1\377\377" \ + "\375\272\377\377\377\7\316\316\316::<;;=::<99;::<;;=\205::<\1kkm\377" \ + "\377\377\377\325\377\377\377\1\315\315\315\206::<\6""99;::<99;;;=::<" \ + "```\206\377\377\377\1\376\376\376\257\377\377\377\3\376\376\376\265\265" \ + "\267;;=\202::<\2;;=99;\205::<\1;;=\204::<\4;;=FFH\332\332\332\376\376" \ + "\376\205\377\377\377\1\376\376\376\232\377\377\377\1\304\343\240\235" \ + "\214\306>\1\305\342\237\203\377\377\377\1\342\362\316\235\214\306>\1" \ + "\250\325p\204\377\377\377\1\252\324p\234\214\306>\2\215\307\77\342\362" \ + "\316\203\377\377\377\3\305\342\237\214\305@\215\305>\202\214\306>\1\214" \ + "\305@\222\214\306>\1\214\305@\205\214\306>\1\305\342\237\241\377\377" \ + "\377\1\375\377\376\202\377\377\375\34\377\377\377\376\376\376\373\373" \ + "\363\243\322b\211\307B\212\307<\215\305>\214\306>\212\307>\214\305@\217" \ + "\304>\212\307<\214\306<\214\306>\215\307\77\213\307A\214\306>\215\305" \ + "@\215\307\77\212\307>\244\317c\370\373\362\377\377\373\376\377\377\377" \ + "\376\377\375\376\377\377\377\375\377\376\377\272\377\377\377\2\222\222" \ + "\22299;\205::<\1;;=\203::<\2;;=\250\250\250\377\377\377\377\324\377\377" \ + "\377\4```;;=99;;;=\204::<\5;;=::<;;=::<\331\331\331\207\377\377\377\1" \ + "\376\376\376\260\377\377\377\1\265\265\265\204::<\6;;=::<;;=::<;;=::" \ + "<\202;;=\203::<\4;;=FFH\333\333\333\376\376\376\202\377\377\377\1\376" \ + "\376\376\234\377\377\377\1\304\343\240\235\214\306>\1\305\342\237\203" \ + "\377\377\377\1\342\362\316\235\214\306>\1\250\325p\204\377\377\377\1" \ + "\252\324p\234\214\306>\2\215\307\77\342\362\316\203\377\377\377\3\305" \ + "\342\237\214\305@\215\305>\202\214\306>\1\214\305@\222\214\306>\1\214" \ + "\305@\205\214\306>\1\305\342\237\240\377\377\377\3\377\376\377\377\377" \ + "\377\375\377\376\202\377\377\377\11\373\373\363\241\321d\214\306>\213" \ + "\310=\214\306>\214\305@\213\310=\212\306@\217\304>\202\215\307=\14\214" \ + "\306>\215\305>\214\306>\215\305>\217\304@\215\307\77\215\307=\242\320" \ + "c\367\375\361\376\376\377\377\376\377\376\376\376\202\377\377\375\2\374" \ + "\377\377\377\376\377\262\377\377\377\2\376\376\376\377\377\377\202\376" \ + "\376\376\204\377\377\377\5\363\363\363SSU99;::<;;=\207::<\2GGG\363\363" \ + "\363\377\377\377\377\322\377\377\377\4\234\234\234:::::<;;=\202::<\1" \ + ";;=\203::<\202;;=\1\234\234\236\207\377\377\377\1\376\376\376\262\377" \ + "\377\377\1\265\265\267\203::<\2""99;;;=\203::<\1;;=\202::<\202;;=\203" \ + "::<\2FFH\332\332\332\237\377\377\377\1\304\343\240\235\214\306>\1\305" \ + "\342\237\203\377\377\377\1\342\362\316\235\214\306>\1\250\325p\204\377" \ + "\377\377\1\252\324p\234\214\306>\2\215\307\77\342\362\316\203\377\377" \ + "\377\3\305\342\237\214\305@\215\305>\202\214\306>\1\214\305@\222\214" \ + "\306>\1\214\305@\205\214\306>\1\305\342\237\240\377\377\377\1\377\377" \ + "\375\202\377\377\377\32\377\376\377\370\373\364\243\322b\214\306>\213" \ + "\310\77\214\305@\215\305>\215\305@\214\306>\214\305B\212\307<\215\307" \ + "=\214\305B\214\306>\215\306A\212\306@\212\307>\214\306>\212\307<\244" \ + "\317c\370\373\364\377\377\377\377\375\376\377\377\375\376\377\377\377" \ + "\377\377\202\377\376\377\273\377\377\377\2\376\376\376\316\316\316\206" \ + "::<\202;;=\4::<;;=::\1\305\342\237\203\377" \ + "\377\377\1\342\362\316\235\214\306>\1\250\325p\204\377\377\377\1\252" \ + "\324p\234\214\306>\2\215\307\77\342\362\316\203\377\377\377\3\305\342" \ + "\237\214\305@\215\305>\202\214\306>\1\214\305@\222\214\306>\1\214\305" \ + "@\205\214\306>\1\305\342\237\231\377\377\377\10\376\376\377\377\377\375" \ + "\377\377\377\377\377\375\377\377\377\377\376\377\377\377\375\376\377" \ + "\377\202\377\377\377\6\370\373\362\243\322b\211\307B\213\310=\214\305" \ + "@\214\306<\202\215\305@\4\214\306<\214\305@\214\306<\215\307\77\202\214" \ + "\306>\6\212\307>\214\306>\215\307\77\214\305@\244\317c\367\375\361\305" \ + "\377\377\377\2xxz;;=\203::<\3;;=::<;;=\203::<\2;;=\315\315\315\377\377" \ + "\377\377\313\377\377\377\203\376\376\376\202\377\377\377\3xxz;;=::<\202" \ + ";;=\1""99;\202;;=\202::<\4;;=::<\333\333\335\376\376\376\274\377\377" \ + "\377\12\265\265\267;;=::<;;=99;;;=::<;;=::<;;=\202::<\1;;=\202::<\4;" \ + ";=99;GGI\332\332\332\235\377\377\377\1\304\343\240\235\214\306>\1\305" \ + "\342\237\203\377\377\377\1\342\362\316\235\214\306>\1\250\325p\204\377" \ + "\377\377\1\252\324p\234\214\306>\2\215\307\77\342\362\316\203\377\377" \ + "\377\3\305\342\237\214\305@\215\305>\202\214\306>\1\214\305@\222\214" \ + "\306>\1\214\305@\205\214\306>\1\305\342\237\230\377\377\377\6\376\376" \ + "\377\377\376\377\375\376\377\376\377\377\377\377\375\375\377\376\203" \ + "\377\377\377\27\377\377\375\372\373\366\241\321a\217\304@\212\307<\214" \ + "\306>\215\305>\215\305@\213\310=\212\306@\214\306>\214\305B\215\307\77" \ + "\215\305>\215\306A\212\307>\214\306>\215\307\77\214\306>\242\322b\370" \ + "\373\362\376\376\377\377\375\376\304\377\377\377\2\364\364\364FFH\203" \ + "::<\2""99;;;=\203::<\4<<>99;TTT\376\376\376\377\377\377\377\310\377\377" \ + "\377\1\376\376\376\205\377\377\377\3\316\316\316::<99;\206::<\1;;=\202" \ + "::<\1\221\221\221\203\377\377\377\1\376\376\376\272\377\377\377\7\376" \ + "\376\376\265\265\265;;=::<;;=::<;;=\203::<\1;;=\203::<\6;;=::<;;=::<" \ + "FFH\332\332\332\234\377\377\377\1\304\343\240\235\214\306>\1\305\342" \ + "\237\203\377\377\377\1\342\362\316\235\214\306>\1\250\325p\204\377\377" \ + "\377\1\252\324p\234\214\306>\2\215\307\77\342\362\316\203\377\377\377" \ + "\3\305\342\237\214\305@\215\305>\202\214\306>\1\214\305@\222\214\306" \ + ">\1\214\305@\205\214\306>\1\305\342\237\230\377\377\377\7\377\377\375" \ + "\375\376\377\376\377\377\376\377\375\377\374\377\377\377\375\375\377" \ + "\376\202\377\377\377\5\372\373\366\240\320b\215\307\77\212\306@\215\305" \ + ">\202\214\305@\20\215\305@\212\306@\214\305D\216\306\77\214\306>\215" \ + "\307\77\214\306>\212\306@\214\306>\215\307\77\215\305@\242\320c\370\373" \ + "\362\377\377\373\377\376\377\377\377\375\304\377\377\377\3\376\376\376" \ + "\265\265\267;;=\204::<\1""99;\203::<\3;;=::<\234\234\234\203\377\377" \ + "\377\1\376\376\376\377\377\377\377\306\377\377\377\7\376\376\376\377" \ + "\377\377\376\376\376\377\377\377__a::<;;=\203::<\7;;=::<;;=::<;;=SSU" \ + "\363\363\363\300\377\377\377\2\264\264\264;;=\202::<\2""99;;;=\202::" \ + "<\3""99;;;=::<\202;;=\204::<\2FFH\332\332\332\233\377\377\377\1\304\343" \ + "\240\235\214\306>\1\305\342\237\203\377\377\377\1\342\362\316\235\214" \ + "\306>\1\250\325p\204\377\377\377\1\252\324p\234\214\306>\2\215\307\77" \ + "\342\362\316\203\377\377\377\3\305\342\237\214\305@\215\305>\202\214" \ + "\306>\1\214\305@\222\214\306>\1\214\305@\205\214\306>\1\305\342\237\231" \ + "\377\377\377\37\376\377\377\376\377\375\377\375\376\375\377\376\377\377" \ + "\375\377\377\377\377\376\377\370\373\362\241\321a\215\307\77\215\307" \ + "=\214\305@\214\306>\212\307<\214\306>\214\306<\214\306>\216\306\77\215" \ + "\305<\212\307>\213\307A\215\305>\212\307>\215\307\77\214\306>\242\321" \ + "a\373\374\364\377\377\377\376\377\377\376\376\376\376\377\377\301\377" \ + "\377\377\1\376\376\376\204\377\377\377\2kkm99;\203::<\202;;=\1""99;\203" \ + "::<\2FFH\363\363\363\377\377\377\377\310\377\377\377\1\376\376\376\203" \ + "\377\377\377\3\250\250\252::<;;=\203::<\1;;=\202::<\5;;=::<;;=\301\301" \ + "\301\376\376\376\301\377\377\377\2\265\265\267;;=\203::<\2""99;;;=\202" \ + "::<\1;;=\202::<\2;;=::<\202;;=\3::\1\305\342\237\203\377\377\377\1\342\362\316" \ + "\235\214\306>\1\250\325p\204\377\377\377\1\252\324p\234\214\306>\2\215" \ + "\307\77\342\362\316\203\377\377\377\3\305\342\237\214\305@\215\305>\202" \ + "\214\306>\1\214\305@\222\214\306>\1\214\305@\205\214\306>\1\305\342\237" \ + "\230\377\377\377\202\377\377\375\3\377\374\377\375\377\376\376\377\377" \ + "\202\377\377\377\25\370\373\364\243\322b\217\304@\212\306@\214\305@\215" \ + "\305>\212\307>\212\306@\214\305B\214\305@\214\305B\214\306>\212\307>" \ + "\212\310\77\214\306>\217\304@\214\306>\214\305@\242\322b\370\373\362" \ + "\377\377\377\202\377\376\377\1\377\377\375\301\377\377\377\1\376\376" \ + "\376\204\377\377\377\2\376\376\376\346\346\350\203::<\4;;=99;::<;;=\204" \ + "::<\3\203\203\203\377\377\377\376\376\376\377\377\377\377\311\377\377" \ + "\377\2\364\364\364FFH\202::<\5;;=::<;;=::<;;=\202::<\2;;=kkm\202\377" \ + "\377\377\1\376\376\376\300\377\377\377\3\376\376\376\265\265\267;;=\202" \ + "::<\2;;=99;\204::<\3;;=99;;;=\202::<\3;;=::<\265\265\265\232\377\377" \ + "\377\1\304\343\240\235\214\306>\1\305\342\237\203\377\377\377\1\342\362" \ + "\316\235\214\306>\1\250\325p\204\377\377\377\1\252\324p\234\214\306>" \ + "\2\215\307\77\342\362\316\203\377\377\377\3\305\342\237\214\305@\215" \ + "\305>\202\214\306>\1\214\305@\222\214\306>\1\214\305@\205\214\306>\1" \ + "\305\342\237\231\377\377\377\1\375\377\376\202\377\377\375\34\377\377" \ + "\377\376\376\376\373\373\363\243\322b\211\307B\212\307<\215\305>\214" \ + "\306>\212\307>\214\305@\217\304>\212\307<\214\306<\214\306>\215\307\77" \ + "\213\307A\214\306>\215\305@\215\307\77\212\307>\244\317c\370\373\362" \ + "\377\377\373\376\377\377\377\376\377\375\376\377\377\377\375\377\376" \ + "\377\301\377\377\377\202\376\376\376\2\377\377\377\376\376\376\202\377" \ + "\377\377\1\234\234\236\203::<\1;;=\206::<\2;;=\331\331\331\377\377\377" \ + "\377\306\377\377\377\1\376\376\376\203\377\377\377\4\233\233\233;;=:" \ + ":<;;=\202::<\3;;=99;;;=\203::<\1\346\346\350\305\377\377\377\1\265\265" \ + "\265\204::<\3;;=::<;;=\203::<\5;;=99;;;=::<\265\265\267\233\377\377\377" \ + "\1\304\343\240\235\214\306>\1\305\342\237\203\377\377\377\1\342\362\316" \ + "\235\214\306>\1\250\325p\204\377\377\377\1\252\324p\234\214\306>\2\215" \ + "\307\77\342\362\316\203\377\377\377\3\305\342\237\214\305@\215\305>\202" \ + "\214\306>\1\214\305@\222\214\306>\1\214\305@\205\214\306>\1\305\342\237" \ + "\230\377\377\377\3\377\376\377\377\377\377\375\377\376\202\377\377\377" \ + "\11\373\373\363\241\321d\214\306>\213\310=\214\306>\214\305@\213\310" \ + "=\212\306@\217\304>\202\215\307=\14\214\306>\215\305>\214\306>\215\305" \ + ">\217\304@\215\307\77\215\307=\242\320c\367\375\361\376\376\377\377\376" \ + "\377\376\376\376\202\377\377\375\2\374\377\377\377\376\377\301\377\377" \ + "\377\1\376\376\376\202\377\377\377\1\376\376\376\202\377\377\377\6\364" \ + "\364\364SSU::<;;=::<;;=\205::<\4""99;kkk\377\377\377\376\376\376\377" \ + "\377\377\377\307\377\377\377\2\346\346\346;;;\204::<\3;;=99;;;=\203:" \ + ":<\1\234\234\236\205\377\377\377\1\376\376\376\301\377\377\377\1\265" \ + "\265\267\203::<\2""99;;;=\202::<\1;;;\204::<\1\265\265\267\234\377\377" \ + "\377\1\304\343\240\235\214\306>\1\305\342\237\203\377\377\377\1\342\362" \ + "\316\235\214\306>\1\250\325p\204\377\377\377\1\252\324p\234\214\306>" \ + "\2\215\307\77\342\362\316\203\377\377\377\3\305\342\237\214\305@\215" \ + "\305>\202\214\306>\1\214\305@\222\214\306>\1\214\305@\205\214\306>\1" \ + "\305\342\237\230\377\377\377\1\377\377\375\202\377\377\377\32\377\376" \ + "\377\370\373\364\243\322b\214\306>\213\310\77\214\305@\215\305>\215\305" \ + "@\214\306>\214\305B\212\307<\215\307=\214\305B\214\306>\215\306A\212" \ + "\306@\212\307>\214\306>\212\307<\244\317c\370\373\364\377\377\377\377" \ + "\375\376\377\377\375\376\377\377\377\377\377\202\377\376\377\306\377" \ + "\377\377\1\376\376\376\202\377\377\377\2\301\301\303::<\202;;=\11::<" \ + ";;=::<;;=::<99;;;=::<\301\301\301\377\377\377\377\306\377\377\377\12" \ + "\376\376\376\377\377\377\204\204\204;;=::<:9>;;=::<99;;;=\203::<\5SS" \ + "U\363\363\363\376\376\376\377\377\377\376\376\376\305\377\377\377\5\265" \ + "\265\26599;;;=::<;;=\206::<\1\266\266\270\235\377\377\377\1\304\343\240" \ + "\235\214\306>\1\305\342\237\203\377\377\377\1\342\362\316\235\214\306" \ + ">\1\250\325p\204\377\377\377\1\252\324p\234\214\306>\2\215\307\77\342" \ + "\362\316\203\377\377\377\3\305\342\237\214\305@\215\305>\202\214\306" \ + ">\1\214\305@\222\214\306>\1\214\305@\205\214\306>\1\305\342\237\221\377" \ + "\377\377\10\376\376\377\377\377\375\377\377\377\377\377\375\377\377\377" \ + "\377\376\377\377\377\375\376\377\377\202\377\377\377\6\370\373\362\243" \ + "\322b\211\307B\213\310=\214\305@\214\306<\202\215\305@\4\214\306<\214" \ + "\305@\214\306<\215\307\77\202\214\306>\6\212\307>\214\306>\215\307\77" \ + "\214\305@\244\317c\367\375\361\322\377\377\377\1kkk\203::<\4;;=99;::" \ + "<;;=\203::<\1SSU\210\377\377\377\1\376\376\376\377\377\377\377\276\377" \ + "\377\377\1\316\316\316\202::<\1;;=\202::<\202;;=\202::<\4;;=::<\265\265" \ + "\267\376\376\376\307\377\377\377\3\376\376\376\377\377\377\265\265\267" \ + "\207::<\3""99;\266\266\270\376\376\377\202\377\377\377\1\376\376\376" \ + "\232\377\377\377\1\304\343\240\235\214\306>\1\305\342\237\203\377\377" \ + "\377\1\342\362\316\235\214\306>\1\250\325p\204\377\377\377\1\252\324" \ + "p\234\214\306>\2\215\307\77\342\362\316\203\377\377\377\3\305\342\237" \ + "\214\305@\215\305>\202\214\306>\1\214\305@\222\214\306>\1\214\305@\205" \ + "\214\306>\1\305\342\237\220\377\377\377\6\376\376\377\377\376\377\375" \ + "\376\377\376\377\377\377\377\375\375\377\376\203\377\377\377\27\377\377" \ + "\375\372\373\366\241\321a\217\304@\212\307<\214\306>\215\305>\215\305" \ + "@\213\310=\212\306@\214\306>\214\305B\215\307\77\215\305>\215\306A\212" \ + "\307>\214\306>\215\307\77\214\306>\242\322b\370\373\362\376\376\377\377" \ + "\375\376\321\377\377\377\1\346\346\346\204::<\1;;=\202::<\5;;=99;;;=" \ + "::<\266\266\266\205\377\377\377\202\376\376\376\2\377\377\377\376\376" \ + "\376\377\377\377\377\273\377\377\377\5\376\376\376\377\377\377kkm::<" \ + ";;=\202::<\1;;=\203::<\3;;=::\1\305\342\237" \ + "\203\377\377\377\1\342\362\316\235\214\306>\1\250\325p\204\377\377\377" \ + "\1\252\324p\234\214\306>\2\215\307\77\342\362\316\203\377\377\377\3\305" \ + "\342\237\214\305@\215\305>\202\214\306>\1\214\305@\222\214\306>\1\214" \ + "\305@\205\214\306>\1\305\342\237\220\377\377\377\7\377\377\375\375\376" \ + "\377\376\377\377\376\377\375\377\374\377\377\377\375\375\377\376\202" \ + "\377\377\377\5\372\373\366\240\320b\215\307\77\212\306@\215\305>\202" \ + "\214\305@\20\215\305@\212\306@\214\305D\216\306\77\214\306>\215\307\77" \ + "\214\306>\212\306@\214\306>\215\307\77\215\305@\242\320c\370\373\362" \ + "\377\377\373\377\376\377\377\377\375\322\377\377\377\1\221\221\223\202" \ + "::<\12;;=99;::<;;=::<;;=99;;;=EEG\364\364\364\203\377\377\377\1\376\376" \ + "\376\202\377\377\377\1\376\376\376\377\377\377\377\275\377\377\377\2" \ + "\316\316\320;;=\205::<\2""99;;;=\203::<\3\316\316\316\377\377\377\376" \ + "\376\376\313\377\377\377\3\265\265\265;;=99;\202::<\1\266\266\270\203" \ + "\377\377\377\3\376\376\376\377\377\377\376\376\376\232\377\377\377\1" \ + "\304\343\240\235\214\306>\1\305\342\237\203\377\377\377\1\342\362\316" \ + "\235\214\306>\1\250\325p\204\377\377\377\1\252\324p\234\214\306>\2\215" \ + "\307\77\342\362\316\203\377\377\377\3\305\342\237\214\305@\215\305>\202" \ + "\214\306>\1\214\305@\222\214\306>\1\214\305@\205\214\306>\1\305\342\237" \ + "\221\377\377\377\37\376\377\377\376\377\375\377\375\376\375\377\376\377" \ + "\377\375\377\377\377\377\376\377\370\373\362\241\321a\215\307\77\215" \ + "\307=\214\305@\214\306>\212\307<\214\306>\214\306<\214\306>\216\306\77" \ + "\215\305<\212\307>\213\307A\215\305>\212\307>\215\307\77\214\306>\242" \ + "\321a\373\374\364\377\377\377\376\377\377\376\376\376\376\377\377\322" \ + "\377\377\377\2\363\363\363FFH\203::<\202;;=\203::<\3;;=::<\235\235\235" \ + "\204\377\377\377\1\376\376\376\377\377\377\377\277\377\377\377\1__a\202" \ + "::<\1;;=\203::<\5;;=::<;;=::<\204\204\206\312\377\377\377\1\376\376\376" \ + "\202\377\377\377\7\376\376\376\377\377\377\265\265\267;;=99;\266\266" \ + "\270\376\376\377\203\377\377\377\202\376\376\376\233\377\377\377\1\304" \ + "\343\240\235\214\306>\1\305\342\237\203\377\377\377\1\342\362\316\235" \ + "\214\306>\1\250\325p\204\377\377\377\1\252\324p\234\214\306>\2\215\307" \ + "\77\342\362\316\203\377\377\377\3\305\342\237\214\305@\215\305>\202\214" \ + "\306>\1\214\305@\222\214\306>\1\214\305@\205\214\306>\1\305\342\237\220" \ + "\377\377\377\202\377\377\375\3\377\374\377\375\377\376\376\377\377\202" \ + "\377\377\377\25\370\373\364\243\322b\217\304@\212\306@\214\305@\215\305" \ + ">\212\307>\212\306@\214\305B\214\305@\214\305B\214\306>\212\307>\212" \ + "\310\77\214\306>\217\304@\214\306>\214\305@\242\322b\370\373\362\377" \ + "\377\377\202\377\376\377\1\377\377\375\324\377\377\377\4\234\234\234" \ + ";;=::<<<>\204::<\1;;=\202::<\2FFH\363\363\363\204\377\377\377\1\376\376" \ + "\376\202\377\377\377\1\376\376\376\377\377\377\377\272\377\377\377\1" \ + "\265\265\265\202::<\5;;=99;::<;;=::<\202;;=\3""99;;;=\346\346\346\320" \ + "\377\377\377\2\264\264\266\265\265\267\203\377\377\377\202\376\376\376" \ + "\235\377\377\377\1\304\343\240\235\214\306>\1\305\342\237\203\377\377" \ + "\377\1\342\362\316\235\214\306>\1\250\325p\204\377\377\377\1\252\324" \ + "p\234\214\306>\2\215\307\77\342\362\316\203\377\377\377\3\305\342\237" \ + "\214\305@\215\305>\202\214\306>\1\214\305@\222\214\306>\1\214\305@\205" \ + "\214\306>\1\305\342\237\221\377\377\377\1\375\377\376\202\377\377\375" \ + "\34\377\377\377\376\376\376\373\373\363\243\322b\211\307B\212\307<\215" \ + "\305>\214\306>\212\307>\214\305@\217\304>\212\307<\214\306<\214\306>" \ + "\215\307\77\213\307A\214\306>\215\305@\215\307\77\212\307>\244\317c\370" \ + "\373\362\377\377\373\376\377\377\377\376\377\375\376\377\377\377\375" \ + "\377\376\377\320\377\377\377\1\376\376\376\203\377\377\377\2SSU;;=\203" \ + "::<\1;;=\203::<\3""99;::<\234\234\236\203\377\377\377\1\376\376\376\377" \ + "\377\377\377\276\377\377\377\5RRT99;;;=99;;;=\203::<\4""99;;;=::<\234" \ + "\234\236\314\377\377\377\1\376\376\376\212\377\377\377\1\376\376\376" \ + "\235\377\377\377\1\304\343\240\235\214\306>\1\305\342\237\203\377\377" \ + "\377\1\342\362\316\235\214\306>\1\250\325p\204\377\377\377\1\252\324" \ + "p\234\214\306>\2\215\307\77\342\362\316\203\377\377\377\3\305\342\237" \ + "\214\305@\215\305>\202\214\306>\1\214\305@\222\214\306>\1\214\305@\205" \ + "\214\306>\1\305\342\237\220\377\377\377\3\377\376\377\377\377\377\375" \ + "\377\376\202\377\377\377\11\373\373\363\241\321d\214\306>\213\310=\214" \ + "\306>\214\305@\213\310=\212\306@\217\304>\202\215\307=\14\214\306>\215" \ + "\305>\214\306>\215\305>\217\304@\215\307\77\215\307=\242\320c\367\375" \ + "\361\376\376\377\377\376\377\376\376\376\202\377\377\375\2\374\377\377" \ + "\377\376\377\324\377\377\377\3\265\265\265;;=99;\202;;=\1""99;\202;;" \ + "=\5::<;;=::\1\305\342\237\203\377\377" \ + "\377\1\342\362\316\235\214\306>\1\250\325p\204\377\377\377\1\252\324" \ + "p\234\214\306>\2\215\307\77\342\362\316\203\377\377\377\3\305\342\237" \ + "\214\305@\215\305>\202\214\306>\1\214\305@\222\214\306>\1\214\305@\205" \ + "\214\306>\1\305\342\237\220\377\377\377\1\377\377\375\202\377\377\377" \ + "\32\377\376\377\370\373\364\243\322b\214\306>\213\310\77\214\305@\215" \ + "\305>\215\305@\214\306>\214\305B\212\307<\215\307=\214\305B\214\306>" \ + "\215\306A\212\306@\212\307>\214\306>\212\307<\244\317c\370\373\364\377" \ + "\377\377\377\375\376\377\377\375\376\377\377\377\377\377\202\377\376" \ + "\377\326\377\377\377\1__a\203::<\1;;=\203::<\1;;=\202::<\1\234\234\234" \ + "\377\377\377\377\274\377\377\377\1\376\376\376\203\377\377\377\3SSU;" \ + ";=99;\210::<\1\234\234\234\365\377\377\377\7\376\377\375\304\341\236" \ + "\215\306A\214\305B\215\307=\212\307>\212\306@\230\214\305@\1\304\341" \ + "\236\203\377\377\377\4\341\362\320\214\306>\213\310\77\215\305@\231\214" \ + "\305@\2\215\307\77\252\322q\202\377\376\377\202\377\377\377\1\250\325" \ + "n\230\214\305@\3\215\305>\215\306A\215\307\77\202\214\306<\10\342\360" \ + "\317\376\377\377\377\377\375\376\377\377\305\342\240\215\305@\212\306" \ + "@\215\305>\202\214\305@\1\215\307=\220\214\305@\10\214\306>\212\306@" \ + "\216\306A\212\307>\215\305>\215\305@\214\305@\304\343\237\211\377\377" \ + "\377\10\376\376\377\377\377\375\377\377\377\377\377\375\377\377\377\377" \ + "\376\377\377\377\375\376\377\377\202\377\377\377\6\370\373\362\243\322" \ + "b\211\307B\213\310=\214\305@\214\306<\202\215\305@\4\214\306<\214\305" \ + "@\214\306<\215\307\77\202\214\306>\6\212\307>\214\306>\215\307\77\214" \ + "\305@\244\317c\367\375\361\335\377\377\377\2\376\376\376\316\316\316" \ + "\211::<\3;;=GGI\363\363\365\203\377\377\377\1\376\376\376\377\377\377" \ + "\377\266\377\377\377\10\376\376\376\377\377\377\376\376\376\377\377\377" \ + "\265\265\265;;=::<;;=\207::<\2GGI\363\363\363\364\377\377\377\7\377\376" \ + "\377\377\377\375\304\341\236\215\305>\215\307\77\214\306>\214\305@\231" \ + "\214\306>\7\304\343\237\377\377\377\375\376\377\377\377\375\341\360\321" \ + "\215\306A\214\305@\233\214\306>\6\252\324n\376\376\376\377\377\377\376" \ + "\377\377\377\376\377\252\324p\230\214\306>\7\215\306A\212\307>\214\306" \ + ">\212\307>\214\306>\343\361\320\376\377\377\202\377\377\377\7\305\342" \ + "\237\215\305>\213\310\77\214\306>\214\305@\212\306@\215\307\77\222\214" \ + "\306>\6\215\305>\212\307>\214\306>\215\307=\215\305@\305\342\237\210" \ + "\377\377\377\6\376\376\377\377\376\377\375\376\377\376\377\377\377\377" \ + "\375\375\377\376\203\377\377\377\27\377\377\375\372\373\366\241\321a" \ + "\217\304@\212\307<\214\306>\215\305>\215\305@\213\310=\212\306@\214\306" \ + ">\214\305B\215\307\77\215\305>\215\306A\212\307>\214\306>\215\307\77" \ + "\214\306>\242\322b\370\373\362\376\376\377\377\375\376\336\377\377\377" \ + "\1kkm\202::<\1;;=\205::<\202;;=\3\233\233\235\377\377\377\376\376\376" \ + "\377\377\377\377\274\377\377\377\3SSU99;;;=\20299;\1;;=\203::<\3;;=:" \ + ":<\234\234\236\366\377\377\377\7\376\377\375\305\342\240\213\304\77\213" \ + "\310\77\214\305@\215\306A\216\306=\230\214\306>\10\305\342\240\377\377" \ + "\375\376\377\377\377\376\377\341\360\317\214\306<\214\305@\212\306@\231" \ + "\214\306>\7\215\305@\252\324p\377\377\377\377\377\375\376\377\377\377" \ + "\376\374\252\324p\230\214\306>\7\212\307>\215\307\77\216\306A\212\307" \ + ">\213\304\77\343\361\320\377\377\375\202\377\377\377\3\307\342\237\214" \ + "\304\77\213\310\77\203\214\306>\1\215\307\77\220\214\306>\4\214\305@" \ + "\214\306<\215\304B\213\310\77\202\212\307>\2\215\305@\305\342\240\210" \ + "\377\377\377\7\377\377\375\375\376\377\376\377\377\376\377\375\377\374" \ + "\377\377\377\375\375\377\376\202\377\377\377\5\372\373\366\240\320b\215" \ + "\307\77\212\306@\215\305>\202\214\305@\20\215\305@\212\306@\214\305D" \ + "\216\306\77\214\306>\215\307\77\214\306>\212\306@\214\306>\215\307\77" \ + "\215\305@\242\320c\370\373\362\377\377\373\377\376\377\377\377\375\331" \ + "\377\377\377\1\376\376\376\203\377\377\377\4\376\376\376\317\317\321" \ + "::<;;=\203::<\3;;=::<;;=\202::<\4FFH\363\363\363\377\377\377\376\376" \ + "\376\377\377\377\377\264\377\377\377\1\376\376\376\205\377\377\377\1" \ + "\265\265\267\202;;=\3::<99;;;=\202::<\202;;=\2::\231\214\306>\2\305\342\240\377\377\377\202\377\376\377\3\341" \ + "\362\316\216\306\77\214\306<\231\214\306>\3\215\305@\212\307>\252\324" \ + "p\203\377\377\377\2\377\376\377\247\324o\230\214\306>\20\215\306A\214" \ + "\305B\215\307\77\211\305\77\214\304;\342\362\315\377\377\377\377\376" \ + "\377\376\376\376\305\342\237\215\306A\210\307;\215\306A\216\306A\214" \ + "\306>\212\306@\220\214\306>\202\214\305@\6\216\305C\213\305=\214\305" \ + "B\215\307\77\216\306\77\303\344\237\211\377\377\377\37\376\377\377\376" \ + "\377\375\377\375\376\375\377\376\377\377\375\377\377\377\377\376\377" \ + "\370\373\362\241\321a\215\307\77\215\307=\214\305@\214\306>\212\307<" \ + "\214\306>\214\306<\214\306>\216\306\77\215\305<\212\307>\213\307A\215" \ + "\305>\212\307>\215\307\77\214\306>\242\321a\373\374\364\377\377\377\376" \ + "\377\377\376\376\376\376\377\377\331\377\377\377\3\376\376\376\377\377" \ + "\377\376\376\376\203\377\377\377\1kkm\202::<\6;;=::<;;=::<;;=::<\202" \ + ";;=\1\233\233\235\377\377\377\377\267\377\377\377\1\376\376\376\204\377" \ + "\377\377\2kkm;;=\202::<\2;;=::<\202;;=\203::<\5\265\265\267\377\377\377" \ + "\376\376\376\377\377\377\376\376\376\362\377\377\377\2\376\377\377\377" \ + "\376\377\202\377\377\377\202\377\376\377\2\377\377\377\377\377\375\231" \ + "\377\377\377\4\377\376\377\376\377\377\375\377\376\377\377\377\202\376" \ + "\377\377\231\377\377\377\10\374\377\375\377\376\377\377\377\375\376\376" \ + "\376\377\377\377\376\377\377\376\376\374\377\376\377\230\377\377\377" \ + "\1\377\376\377\203\377\377\375\4\376\377\377\377\375\377\377\377\377" \ + "\376\377\377\202\377\377\377\3\376\376\376\377\376\377\377\377\375\202" \ + "\376\377\377\1\377\377\375\220\377\377\377\10\377\377\375\377\377\377" \ + "\376\376\376\377\377\377\377\377\375\377\377\377\376\377\377\377\375" \ + "\377\210\377\377\377\202\377\377\375\3\377\374\377\375\377\376\376\377" \ + "\377\202\377\377\377\25\370\373\364\243\322b\217\304@\212\306@\214\305" \ + "@\215\305>\212\307>\212\306@\214\305B\214\305@\214\305B\214\306>\212" \ + "\307>\212\310\77\214\306>\217\304@\214\306>\214\305@\242\322b\370\373" \ + "\362\377\377\377\202\377\376\377\1\377\377\375\340\377\377\377\1\316" \ + "\316\316\203::<\3;;=99;;;=\204::<\2FFH\363\363\363\202\377\377\377\1" \ + "\376\376\376\377\377\377\377\264\377\377\377\1\376\376\376\202\377\377" \ + "\377\1\316\316\320\206::<\1;;=\203::<\2SSU\376\376\376\366\377\377\377" \ + "\1\377\377\375\202\377\376\377\202\377\377\377\3\377\377\375\377\377" \ + "\377\376\377\377\230\377\377\377\202\376\377\377\6\377\377\375\377\377" \ + "\377\376\377\375\377\377\377\376\377\375\377\377\375\231\377\377\377" \ + "\2\376\377\377\377\377\375\202\377\377\377\1\376\376\376\232\377\377" \ + "\377\5\377\376\377\377\377\377\376\377\375\377\377\377\377\377\375\204" \ + "\377\377\377\202\376\377\377\1\376\376\376\202\377\377\377\202\376\377" \ + "\377\220\377\377\377\1\377\377\375\202\377\377\377\4\376\376\374\377" \ + "\376\377\377\377\377\376\377\375\212\377\377\377\1\375\377\376\202\377" \ + "\377\375\34\377\377\377\376\376\376\373\373\363\243\322b\211\307B\212" \ + "\307<\215\305>\214\306>\212\307>\214\305@\217\304>\212\307<\214\306<" \ + "\214\306>\215\307\77\213\307A\214\306>\215\305@\215\307\77\212\307>\244" \ + "\317c\370\373\362\377\377\373\376\377\377\377\376\377\375\376\377\377" \ + "\377\375\377\376\377\334\377\377\377\1\376\376\376\202\377\377\377\10" \ + "\376\376\376kkm::<;;=99;;;=::<;;=\202::<\202;;=\1\234\234\236\203\377" \ + "\377\377\1\376\376\376\377\377\377\377\262\377\377\377\5\376\376\376" \ + "\377\377\377\376\376\376\377\377\377lln\210::<\3""99;;;=\265\265\265" \ + "\202\377\377\377\1\376\376\376\202\377\377\377\1\376\376\376\370\377" \ + "\377\377\1\376\377\377\230\377\377\377\7\377\376\377\377\377\375\377" \ + "\376\377\376\376\377\377\377\375\377\377\377\377\377\375\233\377\377" \ + "\377\1\377\376\377\203\377\377\377\1\376\377\375\231\377\377\377\5\377" \ + "\377\375\377\377\377\377\377\375\377\377\377\377\377\375\202\377\377" \ + "\377\1\377\377\375\203\377\377\377\2\376\376\376\377\376\377\226\377" \ + "\377\377\5\377\377\375\377\377\377\376\377\377\377\377\375\376\377\377" \ + "\210\377\377\377\3\377\376\377\377\377\377\375\377\376\202\377\377\377" \ + "\11\373\373\363\241\321d\214\306>\213\310=\214\306>\214\305@\213\310" \ + "=\212\306@\217\304>\202\215\307=\14\214\306>\215\305>\214\306>\215\305" \ + ">\217\304@\215\307\77\215\307=\242\320c\367\375\361\376\376\377\377\376" \ + "\377\376\376\376\202\377\377\375\2\374\377\377\377\376\377\333\377\377" \ + "\377\1\376\376\376\202\377\377\377\3\376\376\376\377\377\377\316\316" \ + "\320\203::<\1;;=\202::<\1;;=\203::<\2FFH\377\377\377\202\376\376\376" \ + "\377\377\377\377\262\377\377\377\5\376\376\376\377\377\377\376\376\376" \ + "\377\377\377\332\332\332\206::<\1;;=\202::<\5;;=FFH\363\363\363\377\377" \ + "\377\376\376\376\203\377\377\377\1\376\376\376\365\377\377\377\1\377" \ + "\377\375\202\377\377\377\1\377\377\375\230\377\377\377\2\376\377\377" \ + "\377\377\375\204\377\377\377\2\377\376\377\376\377\375\230\377\377\377" \ + "\4\377\377\375\377\377\377\377\377\373\376\377\377\203\377\377\377\1" \ + "\377\376\377\230\377\377\377\13\376\377\377\377\377\375\377\377\377\376" \ + "\377\377\377\375\376\377\377\377\377\377\375\376\377\377\377\376\377" \ + "\377\377\377\376\376\376\202\377\377\377\1\377\377\375\226\377\377\377" \ + "\202\376\377\377\2\377\377\375\377\376\377\210\377\377\377\1\377\377" \ + "\375\202\377\377\377\32\377\376\377\370\373\364\243\322b\214\306>\213" \ + "\310\77\214\305@\215\305>\215\305@\214\306>\214\305B\212\307<\215\307" \ + "=\214\305B\214\306>\215\306A\212\306@\212\307>\214\306>\212\307<\244" \ + "\317c\370\373\364\377\377\377\377\375\376\377\377\375\376\377\377\377" \ + "\377\377\202\377\376\377\333\377\377\377\1\376\376\376\204\377\377\377" \ + "\11\376\376\376\377\377\377kkm::<;;=99;;;=::<;;=\202::<\3;;=::<\264\264" \ + "\264\377\377\377\377\265\377\377\377\1\376\376\376\202\377\377\377\1" \ + "\204\204\204\203::<\1;;=\206::<\1\235\235\237\377\377\377\377\377\377" \ + "\377\377\203\377\377\377\10\376\376\377\377\377\375\377\377\377\377\377" \ + "\375\377\377\377\377\376\377\377\377\375\376\377\377\202\377\377\377" \ + "\6\370\373\362\243\322b\211\307B\213\310=\214\305@\214\306<\202\215\305" \ + "@\4\214\306<\214\305@\214\306<\215\307\77\202\214\306>\6\212\307>\214" \ + "\306>\215\307\77\214\305@\244\317c\367\375\361\352\377\377\377\1\316" \ + "\316\316\203::<\1;;=\203::<\202;;=\2::\215\305>\215" \ + "\305@\213\310=\212\306@\214\306>\214\305B\215\307\77\215\305>\215\306" \ + "A\212\307>\214\306>\215\307\77\214\306>\242\322b\370\373\362\376\376" \ + "\377\377\375\376\352\377\377\377\2kkm;;=\207::<\3;;=::<\301\301\301\377" \ + "\377\377\377\266\377\377\377\2\221\221\221;;=\202::<\202;;=\202::<\1" \ + ";;=\202::<\1\235\235\237\377\377\377\377\377\377\377\377\203\377\377" \ + "\377\7\377\377\375\375\376\377\376\377\377\376\377\375\377\374\377\377" \ + "\377\375\375\377\376\202\377\377\377\5\372\373\366\240\320b\215\307\77" \ + "\212\306@\215\305>\202\214\305@\20\215\305@\212\306@\214\305D\216\306" \ + "\77\214\306>\215\307\77\214\306>\212\306@\214\306>\215\307\77\215\305" \ + "@\242\320c\370\373\362\377\377\373\377\376\377\377\377\375\350\377\377" \ + "\377\4\376\376\376\377\377\377\265\265\26799;\203::<\3;;=::<;;=\203:" \ + ":<\2kkk\376\376\376\377\377\377\377\264\377\377\377\2\362\362\362FFH" \ + "\202::<\1;;=\203::<\5;;=::<;;=::<\363\363\363\377\377\377\377\377\377" \ + "\377\377\204\377\377\377\37\376\377\377\376\377\375\377\375\376\375\377" \ + "\376\377\377\375\377\377\377\377\376\377\370\373\362\241\321a\215\307" \ + "\77\215\307=\214\305@\214\306>\212\307<\214\306>\214\306<\214\306>\216" \ + "\306\77\215\305<\212\307>\213\307A\215\305>\212\307>\215\307\77\214\306" \ + ">\242\321a\373\374\364\377\377\377\376\377\377\376\376\376\376\377\377" \ + "\352\377\377\377\2\376\376\376TTV\204::<\7;;=99;::<;;=99;::<\332\332" \ + "\332\377\377\377\377\263\377\377\377\3\376\376\376\266\266\266;;=\203" \ + "::<\202;;=\204::<\1\205\205\207\377\377\377\377\377\377\377\377\204\377" \ + "\377\377\202\377\377\375\3\377\374\377\375\377\376\376\377\377\202\377" \ + "\377\377\25\370\373\364\243\322b\217\304@\212\306@\214\305@\215\305>" \ + "\212\307>\212\306@\214\305B\214\305@\214\305B\214\306>\212\307>\212\310" \ + "\77\214\306>\217\304@\214\306>\214\305@\242\322b\370\373\362\377\377" \ + "\377\202\377\376\377\1\377\377\375\354\377\377\377\2\265\265\267::<\202" \ + ";;=\205::<\4;;=::<\204\204\204\376\376\376\377\377\377\377\263\377\377" \ + "\377\1SSU\202::<\1;;=\206::<\2;;=\346\346\346\377\377\377\377\377\377" \ + "\377\377\205\377\377\377\1\375\377\376\202\377\377\375\34\377\377\377" \ + "\376\376\376\373\373\363\243\322b\211\307B\212\307<\215\305>\214\306" \ + ">\212\307>\214\305@\217\304>\212\307<\214\306<\214\306>\215\307\77\213" \ + "\307A\214\306>\215\305@\215\307\77\212\307>\244\317c\370\373\362\377" \ + "\377\373\376\377\377\377\376\377\375\376\377\377\377\375\377\376\377" \ + "\354\377\377\377\4FFH;;=99;;;=\203::<\5;;=99;;;=99;\364\364\364\377\377" \ + "\377\377\262\377\377\377\1\316\316\316\202;;=\1""99;\203::<\1;;=\203" \ + "::<\1xxz\377\377\377\377\377\377\377\377\205\377\377\377\3\377\376\377" \ + "\377\377\377\375\377\376\202\377\377\377\11\373\373\363\241\321d\214" \ + "\306>\213\310=\214\306>\214\305@\213\310=\212\306@\217\304>\202\215\307" \ + "=\14\214\306>\215\305>\214\306>\215\305>\217\304@\215\307\77\215\307" \ + "=\242\320c\367\375\361\376\376\377\377\376\377\376\376\376\202\377\377" \ + "\375\2\374\377\377\377\376\377\354\377\377\377\1\235\235\237\204::<\1" \ + "<<>\202::<\4;;=::<;;=\247\247\251\377\377\377\377\262\377\377\377\4\204" \ + "\204\204;;=::<;;=\206::<\2;;=\316\316\316\377\377\377\377\377\377\377" \ + "\377\205\377\377\377\1\377\377\375\202\377\377\377\32\377\376\377\370" \ + "\373\364\243\322b\214\306>\213\310\77\214\305@\215\305>\215\305@\214" \ + "\306>\214\305B\212\307<\215\307=\214\305B\214\306>\215\306A\212\306@" \ + "\212\307>\214\306>\212\307<\244\317c\370\373\364\377\377\377\377\375" \ + "\376\377\377\375\376\377\377\377\377\377\202\377\376\377\355\377\377" \ + "\377\1\363\363\363\212::<\1TTV\377\377\377\377\261\377\377\377\5\347" \ + "\347\351::<;;=::<;;=\204::<\3;;=::\6\212\307>\214\306>\215\307\77\214\305" \ + "@\244\317c\367\375\361\361\377\377\377\1\376\376\376\204\377\377\377" \ + "\1\204\204\204\202;;=\203::<\1;;=\202::<\202;;=\1\302\302\302\203\377" \ + "\377\377\1\376\376\376\377\377\377\377\244\377\377\377\1\376\376\376" \ + "\203\377\377\377\1\376\376\376\203\377\377\377\1\234\234\236\202::<\1" \ + ";;=\204::<\6;;=::<;;=\264\264\264\377\377\377\376\376\376\377\377\377" \ + "\377\373\377\377\377\6\376\376\377\377\376\377\375\376\377\376\377\377" \ + "\377\377\375\375\377\376\203\377\377\377\27\377\377\375\372\373\366\241" \ + "\321a\217\304@\212\307<\214\306>\215\305>\215\305@\213\310=\212\306@" \ + "\214\306>\214\305B\215\307\77\215\305>\215\306A\212\307>\214\306>\215" \ + "\307\77\214\306>\242\322b\370\373\362\376\376\377\377\375\376\365\377" \ + "\377\377\1\332\332\332\202::<\1;;=\202::<\6""99;::<;;=99;;;=xxx\205\377" \ + "\377\377\1\376\376\376\377\377\377\377\243\377\377\377\1\376\376\376" \ + "\206\377\377\377\4SSU;;=::<;;=\202::<\1;;=\203::<\3GGI\362\362\362\376" \ + "\376\376\377\377\377\377\374\377\377\377\7\377\377\375\375\376\377\376" \ + "\377\377\376\377\375\377\374\377\377\377\375\375\377\376\202\377\377" \ + "\377\5\372\373\366\240\320b\215\307\77\212\306@\215\305>\202\214\305" \ + "@\20\215\305@\212\306@\214\305D\216\306\77\214\306>\215\307\77\214\306" \ + ">\212\306@\214\306>\215\307\77\215\305@\242\320c\370\373\362\377\377" \ + "\373\377\376\377\377\377\375\364\377\377\377\3\376\376\376\377\377\377" \ + "__a\203::<\202;;=\6::<99;;;=::<;;=\345\345\345\203\377\377\377\1\376" \ + "\376\376\377\377\377\377\245\377\377\377\3\376\376\376\377\377\377\376" \ + "\376\376\202\377\377\377\2\316\316\316::<\202;;=\205::<\202;;=\1\203" \ + "\203\205\204\377\377\377\1\376\376\376\377\377\377\377\372\377\377\377" \ + "\37\376\377\377\376\377\375\377\375\376\375\377\376\377\377\375\377\377" \ + "\377\377\376\377\370\373\362\241\321a\215\307\77\215\307=\214\305@\214" \ + "\306>\212\307<\214\306>\214\306<\214\306>\216\306\77\215\305<\212\307" \ + ">\213\307A\215\305>\212\307>\215\307\77\214\306>\242\321a\373\374\364" \ + "\377\377\377\376\377\377\376\376\376\376\377\377\362\377\377\377\202" \ + "\376\376\376\3\377\377\377\376\376\376\265\265\267\202::<\1;;=\207::" \ + "<\3\251\251\253\377\377\377\376\376\376\203\377\377\377\1\376\376\376" \ + "\377\377\377\377\247\377\377\377\2\376\376\376\204\204\206\207::<\1;" \ + ";=\202::<\3\346\346\346\377\377\377\376\376\376\377\377\377\377\374\377" \ + "\377\377\202\377\377\375\3\377\374\377\375\377\376\376\377\377\202\377" \ + "\377\377\25\370\373\364\243\322b\217\304@\212\306@\214\305@\215\305>" \ + "\212\307>\212\306@\214\305B\214\305@\214\305B\214\306>\212\307>\212\310" \ + "\77\214\306>\217\304@\214\306>\214\305@\242\322b\370\373\362\377\377" \ + "\377\202\377\376\377\1\377\377\375\364\377\377\377\17\376\376\376\377" \ + "\377\377\376\376\376\377\377\377FFH;;=99;::<;;=::<;;=99;;;=::\214" \ + "\306>\212\307>\214\305@\217\304>\212\307<\214\306<\214\306>\215\307\77" \ + "\213\307A\214\306>\215\305@\215\307\77\212\307>\244\317c\370\373\362" \ + "\377\377\373\376\377\377\377\376\377\375\376\377\377\377\375\377\376" \ + "\377\361\377\377\377\202\376\376\376\2\377\377\377\376\376\376\202\377" \ + "\377\377\1\221\221\221\205::<\202;;=\5::<;;=99;\316\316\320\376\376\376" \ + "\377\377\377\377\250\377\377\377\1\376\376\376\202\377\377\377\4\266" \ + "\266\270::<99;;;=\203::<\1;;=\203::<\1\265\265\265\377\377\377\377\377" \ + "\377\377\377\3\377\376\377\377\377\377\375\377\376\202\377\377\377\11" \ + "\373\373\363\241\321d\214\306>\213\310=\214\306>\214\305@\213\310=\212" \ + "\306@\217\304>\202\215\307=\14\214\306>\215\305>\214\306>\215\305>\217" \ + "\304@\215\307\77\215\307=\242\320c\367\375\361\376\376\377\377\376\377" \ + "\376\376\376\202\377\377\375\2\374\377\377\377\376\377\360\377\377\377" \ + "\1\376\376\376\202\377\377\377\202\376\376\376\202\377\377\377\6\346" \ + "\346\346;;=99;::<99;;;=\204::<\2;;=\204\204\206\202\377\377\377\1\376" \ + "\376\376\377\377\377\377\251\377\377\377\1__a\203::<\3;;=::<;;=\203:" \ + ":<\4FFF\363\363\363\377\377\377\376\376\376\377\377\377\377\375\377\377" \ + "\377\1\377\377\375\202\377\377\377\32\377\376\377\370\373\364\243\322" \ + "b\214\306>\213\310\77\214\305@\215\305>\215\305@\214\306>\214\305B\212" \ + "\307<\215\307=\214\305B\214\306>\215\306A\212\306@\212\307>\214\306>" \ + "\212\307<\244\317c\370\373\364\377\377\377\377\375\376\377\377\375\376" \ + "\377\377\377\377\377\202\377\376\377\371\377\377\377\4^^`;;=::<;;=\202" \ + "::<\5;;=::<;;=::\6\212\307>\214\306" \ + ">\215\307\77\214\305@\244\317c\367\375\361\377\377\377\377\202\377\377" \ + "\377\3\265\265\267::<;;=\204::<\1;;=\202::<\2;;=\265\265\265\202\377" \ + "\377\377\1\376\376\376\377\377\377\377\246\377\377\377\2\376\376\376" \ + "\234\234\234\202;;=\203::<\1;;=\202::<\3""99;::<\332\332\332\377\377" \ + "\377\377\370\377\377\377\6\376\376\377\377\376\377\375\376\377\376\377" \ + "\377\377\377\375\375\377\376\203\377\377\377\27\377\377\375\372\373\366" \ + "\241\321a\217\304@\212\307<\214\306>\215\305>\215\305@\213\310=\212\306" \ + "@\214\306>\214\305B\215\307\77\215\305>\215\306A\212\307>\214\306>\215" \ + "\307\77\214\306>\242\322b\370\373\362\376\376\377\377\375\376\377\377" \ + "\377\377\5\377\377\377\363\363\365;;=::<;;=\202::<\3;;=::<;;=\202::<" \ + "\3xxz\377\377\377\376\376\376\377\377\377\377\246\377\377\377\3\376\376" \ + "\376\377\377\377SSS\202::<\1;;=\202::<\1;;=\202::<\6;;=SSU\377\377\377" \ + "\376\376\376\377\377\377\376\376\376\202\377\377\377\1\376\376\376\377" \ + "\377\377\377\362\377\377\377\7\377\377\375\375\376\377\376\377\377\376" \ + "\377\375\377\374\377\377\377\375\375\377\376\202\377\377\377\5\372\373" \ + "\366\240\320b\215\307\77\212\306@\215\305>\202\214\305@\20\215\305@\212" \ + "\306@\214\305D\216\306\77\214\306>\215\307\77\214\306>\212\306@\214\306" \ + ">\215\307\77\215\305@\242\320c\370\373\362\377\377\373\377\376\377\377" \ + "\377\375\377\377\377\377\11\377\377\377\376\376\376\204\204\206;;=::" \ + "<99;;;=::<;;=\204::<\3\362\362\362\377\377\377\376\376\376\377\377\377" \ + "\377\246\377\377\377\1\333\333\333\203::<\202;;=\202::<\5<<>99;::<\250" \ + "\250\252\376\376\376\203\377\377\377\1\376\376\376\377\377\377\377\365" \ + "\377\377\377\37\376\377\377\376\377\375\377\375\376\375\377\376\377\377" \ + "\375\377\377\377\377\376\377\370\373\362\241\321a\215\307\77\215\307" \ + "=\214\305@\214\306>\212\307<\214\306>\214\306<\214\306>\216\306\77\215" \ + "\305<\212\307>\213\307A\215\305>\212\307>\215\307\77\214\306>\242\321" \ + "a\373\374\364\377\377\377\376\377\377\376\376\376\376\377\377\377\377" \ + "\377\377\202\377\377\377\1\301\301\301\202::<\1;;=\203::<\1;;=\203::" \ + "<\1\266\266\270\377\377\377\377\250\377\377\377\2\220\220\220;;=\204" \ + "::<\6;;=::<99;;;=::<\346\346\346\205\377\377\377\1\376\376\376\377\377" \ + "\377\377\363\377\377\377\202\377\377\375\3\377\374\377\375\377\376\376" \ + "\377\377\202\377\377\377\25\370\373\364\243\322b\217\304@\212\306@\214" \ + "\305@\215\305>\212\307>\212\306@\214\305B\214\305@\214\305B\214\306>" \ + "\212\307>\212\310\77\214\306>\217\304@\214\306>\214\305@\242\322b\370" \ + "\373\362\377\377\377\202\377\376\377\1\377\377\375\377\377\377\377\204" \ + "\377\377\377\2TTV99;\202::<\1;;=\202::<\6;;=::<;;=__a\377\377\377\376" \ + "\376\376\377\377\377\377\244\377\377\377\3\376\376\376\377\377\377TT" \ + "V\207::<\3;;=99;```\377\377\377\377\373\377\377\377\1\375\377\376\202" \ + "\377\377\375\34\377\377\377\376\376\376\373\373\363\243\322b\211\307" \ + "B\212\307<\215\305>\214\306>\212\307>\214\305@\217\304>\212\307<\214" \ + "\306<\214\306>\215\307\77\213\307A\214\306>\215\305@\215\307\77\212\307" \ + ">\244\317c\370\373\362\377\377\373\376\377\377\377\376\377\375\376\377" \ + "\377\377\375\377\376\377\377\377\377\377\203\377\377\377\3\221\221\221" \ + "::<;;=\202::<\202;;=\203::<\2;;=\345\345\347\377\377\377\377\246\377" \ + "\377\377\4\332\332\332;;=::<;;=\203::<\1;;=\203::<\1\265\265\265\203" \ + "\377\377\377\3\376\376\376\377\377\377\376\376\376\377\377\377\377\364" \ + "\377\377\377\3\377\376\377\377\377\377\375\377\376\202\377\377\377\11" \ + "\373\373\363\241\321d\214\306>\213\310=\214\306>\214\305@\213\310=\212" \ + "\306@\217\304>\202\215\307=\14\214\306>\215\305>\214\306>\215\305>\217" \ + "\304@\215\307\77\215\307=\242\320c\367\375\361\376\376\377\377\376\377" \ + "\376\376\376\202\377\377\375\2\374\377\377\377\376\377\377\377\377\377" \ + "\202\377\377\377\5\376\376\376\332\332\332;;=::<;;=\202::<\6;;=::<;;" \ + "=99;::<\250\250\252\377\377\377\377\244\377\377\377\6\376\376\376\377" \ + "\377\377\221\221\223::<;;=99;\202::<\3;;=::<;;=\202::<\1\363\363\363" \ + "\377\377\377\377\372\377\377\377\1\377\377\375\202\377\377\377\32\377" \ + "\376\377\370\373\364\243\322b\214\306>\213\310\77\214\305@\215\305>\215" \ + "\305@\214\306>\214\305B\212\307<\215\307=\214\305B\214\306>\215\306A" \ + "\212\306@\212\307>\214\306>\212\307<\244\317c\370\373\364\377\377\377" \ + "\377\375\376\377\377\375\376\377\377\377\377\377\202\377\376\377\377" \ + "\377\377\377\204\377\377\377\2\376\376\376SSU\204::<\204;;=\2::<__a\377" \ + "\377\377\377\243\377\377\377\6\376\376\376\377\377\377\376\376\376TT" \ + "V99;;;=\204::<\4;;=99;<<>xxz\377\377\377\377\364\377\377\377\10\376\376" \ + "\377\377\377\375\377\377\377\377\377\375\377\377\377\377\376\377\377" \ + "\377\375\376\377\377\202\377\377\377\6\370\373\362\243\322b\211\307B" \ + "\213\310=\214\305@\214\306<\202\215\305@\4\214\306<\214\305@\214\306" \ + "<\215\307\77\202\214\306>\6\212\307>\214\306>\215\307\77\214\305@\244" \ + "\317c\367\375\361\377\377\377\377\213\377\377\377\5\376\376\376\377\377" \ + "\377\221\221\223::<;;=\204::<\5;;=::<;;=::<\363\363\363\204\377\377\377" \ + "\1\376\376\376\202\377\377\377\202\376\376\376\377\377\377\377\233\377" \ + "\377\377\5\332\332\332::<;;=99;<<>\202::<\1;;=\203::<\1\265\265\267\377" \ + "\377\377\377\363\377\377\377\6\376\376\377\377\376\377\375\376\377\376" \ + "\377\377\377\377\375\375\377\376\203\377\377\377\27\377\377\375\372\373" \ + "\366\241\321a\217\304@\212\307<\214\306>\215\305>\215\305@\213\310=\212" \ + "\306@\214\306>\214\305B\215\307\77\215\305>\215\306A\212\307>\214\306" \ + ">\215\307\77\214\306>\242\322b\370\373\362\376\376\377\377\375\376\377" \ + "\377\377\377\213\377\377\377\2\375\375\375\333\333\333\202::<\1;;=\202" \ + "::<\1;;=\202::<\3""99;::<\265\265\265\206\377\377\377\3\376\376\376\377" \ + "\377\377\376\376\376\377\377\377\377\233\377\377\377\2\235\235\23599" \ + ";\202;;=\1""99;\202;;=\202::<\3;;=::<\363\363\365\377\377\377\377\363" \ + "\377\377\377\7\377\377\375\375\376\377\376\377\377\376\377\375\377\374" \ + "\377\377\377\375\375\377\376\202\377\377\377\5\372\373\366\240\320b\215" \ + "\307\77\212\306@\215\305>\202\214\305@\20\215\305@\212\306@\214\305D" \ + "\216\306\77\214\306>\215\307\77\214\306>\212\306@\214\306>\215\307\77" \ + "\215\305@\242\320c\370\373\362\377\377\373\377\376\377\377\377\375\377" \ + "\377\377\377\214\377\377\377\2\376\376\376SSU\207::<\3;;=::\212\307<\214\306>\214\306<\214\306>\216\306" \ + "\77\215\305<\212\307>\213\307A\215\305>\212\307>\215\307\77\214\306>" \ + "\242\321a\373\374\364\377\377\377\376\377\377\376\376\376\376\377\377" \ + "\377\377\377\377\212\377\377\377\4\376\376\376\377\377\377\376\376\376" \ + "\222\222\222\205::<\1;;=\20299;\202::<\3\363\363\363\377\377\377\376" \ + "\376\376\377\377\377\377\240\377\377\377\1\346\346\346\202::<\1;;=\204" \ + "::<\1;;=\202::<\1\250\250\252\202\377\377\377\1\376\376\376\377\377\377" \ + "\377\361\377\377\377\202\377\377\375\3\377\374\377\375\377\376\376\377" \ + "\377\202\377\377\377\25\370\373\364\243\322b\217\304@\212\306@\214\305" \ + "@\215\305>\212\307>\212\306@\214\305B\214\305@\214\305B\214\306>\212" \ + "\307>\212\310\77\214\306>\217\304@\214\306>\214\305@\242\322b\370\373" \ + "\362\377\377\377\202\377\376\377\1\377\377\375\377\377\377\377\212\377" \ + "\377\377\1\376\376\376\203\377\377\377\2\332\332\332<<>\203::<\3;;=:" \ + ":<<<>\203::<\2\301\301\303\376\376\376\202\377\377\377\5\376\376\376" \ + "\377\377\377\376\376\376\377\377\377\376\376\376\377\377\377\377\231" \ + "\377\377\377\4\376\376\376\251\251\253::<;;=\204::<\5;;=::<99;::<\346" \ + "\346\346\377\377\377\377\365\377\377\377\1\375\377\376\202\377\377\375" \ + "\34\377\377\377\376\376\376\373\373\363\243\322b\211\307B\212\307<\215" \ + "\305>\214\306>\212\307>\214\305@\217\304>\212\307<\214\306<\214\306>" \ + "\215\307\77\213\307A\214\306>\215\305@\215\307\77\212\307>\244\317c\370" \ + "\373\362\377\377\373\376\377\377\377\376\377\375\376\377\377\377\375" \ + "\377\376\377\377\377\377\377\212\377\377\377\1\376\376\376\203\377\377" \ + "\377\1SSS\207::<\3;;=::<\205\205\207\205\377\377\377\1\376\376\376\377" \ + "\377\377\377\234\377\377\377\3wwy::<;;=\206::<\2;;=__a\377\377\377\377" \ + "\365\377\377\377\3\377\376\377\377\377\377\375\377\376\202\377\377\377" \ + "\11\373\373\363\241\321d\214\306>\213\310=\214\306>\214\305@\213\310" \ + "=\212\306@\217\304>\202\215\307=\14\214\306>\215\305>\214\306>\215\305" \ + ">\217\304@\215\307\77\215\307=\242\320c\367\375\361\376\376\377\377\376" \ + "\377\376\376\376\202\377\377\375\2\374\377\377\377\376\377\377\377\377" \ + "\377\211\377\377\377\1\376\376\376\203\377\377\377\3\376\376\376\204" \ + "\204\204::<\202;;=\1::<\202;;=\203::<\1SSU\204\377\377\377\1\376\376" \ + "\376\377\377\377\377\235\377\377\377\1;;=\203::<\1;;=\202::<\1;;=\202" \ + "::<\1\234\234\234\202\377\377\377\1\376\376\376\377\377\377\377\362\377" \ + "\377\377\1\377\377\375\202\377\377\377\32\377\376\377\370\373\364\243" \ + "\322b\214\306>\213\310\77\214\305@\215\305>\215\305@\214\306>\214\305" \ + "B\212\307<\215\307=\214\305B\214\306>\215\306A\212\306@\212\307>\214" \ + "\306>\212\307<\244\317c\370\373\364\377\377\377\377\375\376\377\377\375" \ + "\376\377\377\377\377\377\202\377\376\377\377\377\377\377\212\377\377" \ + "\377\1\376\376\376\204\377\377\377\6\301\301\301;;=::<;;=::<;;=\205:" \ + ":<\1\333\333\333\202\377\377\377\1\376\376\376\377\377\377\377\231\377" \ + "\377\377\1\376\376\376\203\377\377\377\1\301\301\303\204::<\1;;=\202" \ + "::<\1:9>\202::<\1\332\332\332\377\377\377\377\356\377\377\377\10\376" \ + "\376\377\377\377\375\377\377\377\377\377\375\377\377\377\377\376\377" \ + "\377\377\375\376\377\377\202\377\377\377\6\370\373\362\243\322b\211\307" \ + "B\213\310=\214\305@\214\306<\202\215\305@\4\214\306<\214\305@\214\306" \ + "<\215\307\77\202\214\306>\6\212\307>\214\306>\215\307\77\214\305@\244" \ + "\317c\367\375\361\377\377\377\377\230\377\377\377\2""99;;;=\210::<\1" \ + "\250\250\250\377\377\377\377\240\377\377\377\3\221\221\223::<;;=\207" \ + "::<\2SSU\376\376\376\377\377\377\377\355\377\377\377\6\376\376\377\377" \ + "\376\377\375\376\377\376\377\377\377\377\375\375\377\376\203\377\377" \ + "\377\27\377\377\375\372\373\366\241\321a\217\304@\212\307<\214\306>\215" \ + "\305>\215\305@\213\310=\212\306@\214\306>\214\305B\215\307\77\215\305" \ + ">\215\306A\212\307>\214\306>\215\307\77\214\306>\242\322b\370\373\362" \ + "\376\376\377\377\375\376\377\377\377\377\227\377\377\377\1yy{\211::<" \ + "\6lll\376\376\376\377\377\377\376\376\376\377\377\377\376\376\376\377" \ + "\377\377\377\224\377\377\377\202\376\376\376\7\377\377\377\376\376\376" \ + "\377\377\377\376\376\376\377\377\377__a;;=\202::<\4<<>;;=::<;;=\202:" \ + ":<\1\204\204\206\203\377\377\377\1\376\376\376\377\377\377\377\352\377" \ + "\377\377\7\377\377\375\375\376\377\376\377\377\376\377\375\377\374\377" \ + "\377\377\375\375\377\376\202\377\377\377\5\372\373\366\240\320b\215\307" \ + "\77\212\306@\215\305>\202\214\305@\20\215\305@\212\306@\214\305D\216" \ + "\306\77\214\306>\215\307\77\214\306>\212\306@\214\306>\215\307\77\215" \ + "\305@\242\320c\370\373\362\377\377\373\377\376\377\377\377\375\377\377" \ + "\377\377\221\377\377\377\3\376\376\376\377\377\377\376\376\376\203\377" \ + "\377\377\1\265\265\267\212::<\1\363\363\363\377\377\377\377\227\377\377" \ + "\377\1\376\376\376\202\377\377\377\1\376\376\376\203\377\377\377\1\345" \ + "\345\345\202::<\202;;=\1""99;\203::<\4;;=::<\301\301\301\376\376\376" \ + "\203\377\377\377\1\376\376\376\377\377\377\377\352\377\377\377\37\376" \ + "\377\377\376\377\375\377\375\376\375\377\376\377\377\375\377\377\377" \ + "\377\376\377\370\373\362\241\321a\215\307\77\215\307=\214\305@\214\306" \ + ">\212\307<\214\306>\214\306<\214\306>\216\306\77\215\305<\212\307>\213" \ + "\307A\215\305>\212\307>\215\307\77\214\306>\242\321a\373\374\364\377" \ + "\377\377\376\377\377\376\376\376\376\377\377\377\377\377\377\222\377" \ + "\377\377\3\376\376\376\377\377\377\376\376\376\202\377\377\377\1\347" \ + "\347\347\212::<\1\302\302\304\205\377\377\377\1\376\376\376\377\377\377" \ + "\377\222\377\377\377\1\376\376\376\202\377\377\377\1\376\376\376\202" \ + "\377\377\377\5\265\265\265::<;;=99;;;=\203::<\1;;=\202::<\1\363\363\363" \ + "\377\377\377\377\356\377\377\377\202\377\377\375\3\377\374\377\375\377" \ + "\376\376\377\377\202\377\377\377\25\370\373\364\243\322b\217\304@\212" \ + "\306@\214\305@\215\305>\212\307>\212\306@\214\305B\214\305@\214\305B" \ + "\214\306>\212\307>\212\310\77\214\306>\217\304@\214\306>\214\305@\242" \ + "\322b\370\373\362\377\377\377\202\377\376\377\1\377\377\375\377\377\377" \ + "\377\230\377\377\377\2\376\376\376TTT\211::<\3\221\221\223\377\377\377" \ + "\376\376\376\202\377\377\377\1\376\376\376\377\377\377\377\231\377\377" \ + "\377\2\204\204\204::<\202;;=\202::<\1;;=\203::<\2``b\376\376\376\377" \ + "\377\377\377\357\377\377\377\1\375\377\376\202\377\377\375\34\377\377" \ + "\377\376\376\376\373\373\363\243\322b\211\307B\212\307<\215\305>\214" \ + "\306>\212\307>\214\305@\217\304>\212\307<\214\306<\214\306>\215\307\77" \ + "\213\307A\214\306>\215\305@\215\307\77\212\307>\244\317c\370\373\362" \ + "\377\377\373\376\377\377\377\376\377\375\376\377\377\377\375\377\376" \ + "\377\377\377\377\377\225\377\377\377\1\376\376\376\202\377\377\377\1" \ + "\221\221\221\210::<\2;;=__a\202\377\377\377\1\376\376\376\377\377\377" \ + "\377\227\377\377\377\1\376\376\376\203\377\377\377\1SSU\202::<\1;;=\204" \ + "::<\202;;=\1\234\234\234\204\377\377\377\1\376\376\376\377\377\377\377" \ + "\352\377\377\377\3\377\376\377\377\377\377\375\377\376\202\377\377\377" \ + "\11\373\373\363\241\321d\214\306>\213\310=\214\306>\214\305@\213\310" \ + "=\212\306@\217\304>\202\215\307=\14\214\306>\215\305>\214\306>\215\305" \ + ">\217\304@\215\307\77\215\307=\242\320c\367\375\361\376\376\377\377\376" \ + "\377\376\376\376\202\377\377\375\2\374\377\377\377\376\377\377\377\377" \ + "\377\222\377\377\377\1\376\376\376\205\377\377\377\1\301\301\301\210" \ + "::<\4""99;;;=\364\364\366\376\376\376\377\377\377\377\233\377\377\377" \ + "\1\346\346\346\207::<\4;;=99;::<\316\316\316\203\377\377\377\1\376\376" \ + "\376\377\377\377\377\353\377\377\377\1\377\377\375\202\377\377\377\32" \ + "\377\376\377\370\373\364\243\322b\214\306>\213\310\77\214\305@\215\305" \ + ">\215\305@\214\306>\214\305B\212\307<\215\307=\214\305B\214\306>\215" \ + "\306A\212\306@\212\307>\214\306>\212\307<\244\317c\370\373\364\377\377" \ + "\377\377\375\376\377\377\375\376\377\377\377\377\377\202\377\376\377" \ + "\377\377\377\377\224\377\377\377\1\376\376\376\204\377\377\377\1\363" \ + "\363\363\210::<\3;;=::<\302\302\304\377\377\377\377\231\377\377\377\1" \ + "\376\376\376\202\377\377\377\1\266\266\270\203::<\203;;=\203::<\1:::" \ + "\377\377\377\377\351\377\377\377\10\376\376\377\377\377\375\377\377\377" \ + "\377\377\375\377\377\377\377\376\377\377\377\375\376\377\377\202\377" \ + "\377\377\6\370\373\362\243\322b\211\307B\213\310=\214\305@\214\306<\202" \ + "\215\305@\4\214\306<\214\305@\214\306<\215\307\77\202\214\306>\6\212" \ + "\307>\214\306>\215\307\77\214\305@\244\317c\367\375\361\377\377\377\377" \ + "\242\377\377\377\3__a::<;;=\207::<\1\221\221\221\377\377\377\377\234" \ + "\377\377\377\1\204\204\206\204::<\202;;=\203::<\1lll\203\377\377\377" \ + "\1\375\375\375\377\377\377\377\344\377\377\377\6\376\376\377\377\376" \ + "\377\375\376\377\376\377\377\377\377\375\375\377\376\203\377\377\377" \ + "\27\377\377\375\372\373\366\241\321a\217\304@\212\307<\214\306>\215\305" \ + ">\215\305@\213\310=\212\306@\214\306>\214\305B\215\307\77\215\305>\215" \ + "\306A\212\307>\214\306>\215\307\77\214\306>\242\322b\370\373\362\376" \ + "\376\377\377\375\376\377\377\377\377\241\377\377\377\2\221\221\223;;" \ + "=\202::<\202;;=\203::<\2;;=^^^\204\377\377\377\1\376\376\376\377\377" \ + "\377\377\224\377\377\377\1\376\376\376\202\377\377\377\1``b\202::<\1" \ + ";;=\206::<\1\234\234\234\205\377\377\377\1\376\376\376\377\377\377\377" \ + "\342\377\377\377\7\377\377\375\375\376\377\376\377\377\376\377\375\377" \ + "\374\377\377\377\375\375\377\376\202\377\377\377\5\372\373\366\240\320" \ + "b\215\307\77\212\306@\215\305>\202\214\305@\20\215\305@\212\306@\214" \ + "\305D\216\306\77\214\306>\215\307\77\214\306>\212\306@\214\306>\215\307" \ + "\77\215\305@\242\320c\370\373\362\377\377\373\377\376\377\377\377\375" \ + "\377\377\377\377\241\377\377\377\6\301\301\303::<;;=::<99;;;=\203::<" \ + "\6;;=:::\377\377\377\376\376\376\377\377\377\376\376\376\377\377\377" \ + "\377\224\377\377\377\1\376\376\376\202\377\377\377\2\363\363\363;;=\211" \ + "::<\1\316\316\316\203\377\377\377\1\376\376\376\202\377\377\377\1\376" \ + "\376\376\377\377\377\377\342\377\377\377\37\376\377\377\376\377\375\377" \ + "\375\376\375\377\376\377\377\375\377\377\377\377\376\377\370\373\362" \ + "\241\321a\215\307\77\215\307=\214\305@\214\306>\212\307<\214\306>\214" \ + "\306<\214\306>\216\306\77\215\305<\212\307>\213\307A\215\305>\212\307" \ + ">\215\307\77\214\306>\242\321a\373\374\364\377\377\377\376\377\377\376" \ + "\376\376\376\377\377\377\377\377\377\241\377\377\377\1\363\363\365\202" \ + "::<\1;;=\202::<\2""99;;;=\202::<\2;;=\316\316\316\377\377\377\377\231" \ + "\377\377\377\10\376\376\376\316\316\316::<;;=::<;;=99;;;=\204::<\202" \ + "\377\377\377\3\376\376\376\377\377\377\376\376\376\377\377\377\377\344" \ + "\377\377\377\202\377\377\375\3\377\374\377\375\377\376\376\377\377\202" \ + "\377\377\377\25\370\373\364\243\322b\217\304@\212\306@\214\305@\215\305" \ + ">\212\307>\212\306@\214\305B\214\305@\214\305B\214\306>\212\307>\212" \ + "\310\77\214\306>\217\304@\214\306>\214\305@\242\322b\370\373\362\377" \ + "\377\377\202\377\376\377\1\377\377\375\377\377\377\377\243\377\377\377" \ + "\1``b\203::<\203;;=\6::<<<>::<\234\234\234\377\377\377\376\376\376\377" \ + "\377\377\377\230\377\377\377\1\234\234\236\204::<\12;;=99;::<;;=::\214\306>\212\307>\214" \ + "\305@\217\304>\212\307<\214\306<\214\306>\215\307\77\213\307A\214\306" \ + ">\215\305@\215\307\77\212\307>\244\317c\370\373\362\377\377\373\376\377" \ + "\377\377\376\377\375\376\377\377\377\375\377\376\377\377\377\377\377" \ + "\242\377\377\377\2\222\222\222::<\202;;=\7""99;::<;;=::<99;;;=lln\202" \ + "\377\377\377\1\376\376\376\377\377\377\377\225\377\377\377\3\376\376" \ + "\376\377\377\377jjl\204;;=\2""99;;;=\202::<\2;;=\221\221\223\202\377" \ + "\377\377\1\376\376\376\202\377\377\377\1\376\376\376\377\377\377\377" \ + "\343\377\377\377\3\377\376\377\377\377\377\375\377\376\202\377\377\377" \ + "\11\373\373\363\241\321d\214\306>\213\310=\214\306>\214\305@\213\310" \ + "=\212\306@\217\304>\202\215\307=\14\214\306>\215\305>\214\306>\215\305" \ + ">\217\304@\215\307\77\215\307=\242\320c\367\375\361\376\376\377\377\376" \ + "\377\376\376\376\202\377\377\375\2\374\377\377\377\376\377\377\377\377" \ + "\377\242\377\377\377\2\264\264\264;;=\206::<\6;;=::\213\310\77\214\305@\215\305>\215\305@\214\306" \ + ">\214\305B\212\307<\215\307=\214\305B\214\306>\215\306A\212\306@\212" \ + "\307>\214\306>\212\307<\244\317c\370\373\364\377\377\377\377\375\376" \ + "\377\377\375\376\377\377\377\377\377\202\377\376\377\377\377\377\377" \ + "\243\377\377\377\2\346\346\346;;=\211::<\1\346\346\350\377\377\377\377" \ + "\230\377\377\377\3\346\346\350::<;;=\202::<\1;;=\205::<\1\346\346\346" \ + "\302\377\377\377\5\376\376\376\377\377\377\376\376\376\377\377\377\376" \ + "\376\376\377\377\377\377\233\377\377\377\10\376\376\377\377\377\375\377" \ + "\377\377\377\377\375\377\377\377\377\376\377\377\377\375\376\377\377" \ + "\202\377\377\377\6\370\373\362\243\322b\211\307B\213\310=\214\305@\214" \ + "\306<\202\215\305@\4\214\306<\214\305@\214\306<\215\307\77\202\214\306" \ + ">\6\212\307>\214\306>\215\307\77\214\305@\244\317c\367\375\361\345\377" \ + "\377\377\1\376\376\376\305\377\377\377\3FFF::<;;=\202::<\3;;=::<;;=\202" \ + "::<\1\301\301\303\377\377\377\377\230\377\377\377\4\301\301\30399;::" \ + "<;;=\204::<\3;;=::\215\305>\215\305@\213\310=\212\306@\214\306>" \ + "\214\305B\215\307\77\215\305>\215\306A\212\307>\214\306>\215\307\77\214" \ + "\306>\242\322b\370\373\362\376\376\377\377\375\376\341\377\377\377\5" \ + "\376\376\376\377\377\377\376\376\376\377\377\377\376\376\376\265\377" \ + "\377\377\3\376\376\376\377\377\377\376\376\376\212\377\377\377\3\376" \ + "\376\376\377\377\377lll\206::<\202;;=\2::<\234\234\236\377\377\377\377" \ + "\224\377\377\377\1\376\376\376\203\377\377\377\2\233\233\235;;=\203:" \ + ":<\2""99;;;=\202::<\2;;=xxz\213\377\377\377\1\376\376\376\265\377\377" \ + "\377\1\376\376\376\377\377\377\377\240\377\377\377\7\377\377\375\375" \ + "\376\377\376\377\377\376\377\375\377\374\377\377\377\375\375\377\376" \ + "\202\377\377\377\5\372\373\366\240\320b\215\307\77\212\306@\215\305>" \ + "\202\214\305@\20\215\305@\212\306@\214\305D\216\306\77\214\306>\215\307" \ + "\77\214\306>\212\306@\214\306>\215\307\77\215\305@\242\320c\370\373\362" \ + "\377\377\373\377\376\377\377\377\375\377\377\377\377\233\377\377\377" \ + "\3\376\376\376\377\377\377\376\376\376\213\377\377\377\6\376\376\376" \ + "\377\377\377\233\233\233;;=::<;;=\206::<\1lln\377\377\377\377\226\377" \ + "\377\377\3\376\376\376\377\377\377kkm\210::<\2;;=\234\234\236\214\377" \ + "\377\377\1\315\315\315\202\234\234\234\262\234\234\236\2\234\234\234" \ + "\265\265\265\377\377\377\377\240\377\377\377\37\376\377\377\376\377\375" \ + "\377\375\376\375\377\376\377\377\375\377\377\377\377\376\377\370\373" \ + "\362\241\321a\215\307\77\215\307=\214\305@\214\306>\212\307<\214\306" \ + ">\214\306<\214\306>\216\306\77\215\305<\212\307>\213\307A\215\305>\212" \ + "\307>\215\307\77\214\306>\242\321a\373\374\364\377\377\377\376\377\377" \ + "\376\376\376\376\377\377\344\377\377\377\4\376\376\376\347\347\347\234" \ + "\234\234\235\235\235\260\234\234\236\204\234\234\234\216\377\377\377" \ + "\1\301\301\301\202::<\1;;=\203::<\202;;=\2::\212\307>\212\306@\214\305B" \ + "\214\305@\214\305B\214\306>\212\307>\212\310\77\214\306>\217\304@\214" \ + "\306>\214\305@\242\322b\370\373\362\377\377\377\202\377\376\377\1\377" \ + "\377\375\346\377\377\377\2\316\316\316:::\263::<\4;;=:::\377\377\377" \ + "\376\376\376\214\377\377\377\3\346\346\346::<;;=\205::<\4;;=::<;;=\346" \ + "\346\346\377\377\377\377\226\377\377\377\2\362\362\362;;=\204::<\3""9" \ + "9;::<;;=\202::<\1\346\346\350\214\377\377\377\2\234\234\234;;=\264::" \ + "<\1kkm\377\377\377\377\240\377\377\377\1\375\377\376\202\377\377\375" \ + "\34\377\377\377\376\376\376\373\373\363\243\322b\211\307B\212\307<\215" \ + "\305>\214\306>\212\307>\214\305@\217\304>\212\307<\214\306<\214\306>" \ + "\215\307\77\213\307A\214\306>\215\305@\215\307\77\212\307>\244\317c\370" \ + "\373\362\377\377\373\376\377\377\377\376\377\375\376\377\377\377\375" \ + "\377\376\377\345\377\377\377\2\316\316\31699;\265::<\216\377\377\377" \ + "\2\376\376\376FFH\203::<\1;;=\203::<\3;;=99;\316\316\316\377\377\377" \ + "\377\226\377\377\377\1\317\317\317\206::<\202;;=\4""99;FFH\377\377\377" \ + "\376\376\376\213\377\377\377\1\234\234\236\202::<\1;;=\261::<\2;;=kk" \ + "m\205\377\377\377\1\376\376\376\377\377\377\377\231\377\377\377\3\377" \ + "\376\377\377\377\377\375\377\376\202\377\377\377\11\373\373\363\241\321" \ + "d\214\306>\213\310=\214\306>\214\305@\213\310=\212\306@\217\304>\202" \ + "\215\307=\14\214\306>\215\305>\214\306>\215\305>\217\304@\215\307\77" \ + "\215\307=\242\320c\367\375\361\376\376\377\377\376\377\376\376\376\202" \ + "\377\377\375\2\374\377\377\377\376\377\345\377\377\377\1\316\316\316" \ + "\264::<\202;;=\215\377\377\377\4\376\376\376\377\377\377lln99;\210::" \ + "<\2\234\234\234\376\376\376\377\377\377\377\225\377\377\377\5\234\234" \ + "\234::<;;=99;::<\202;;=\5::<;;=::\261::<\1kkm\377\377\377\377\237\377\377\377\1\377" \ + "\377\375\202\377\377\377\32\377\376\377\370\373\364\243\322b\214\306" \ + ">\213\310\77\214\305@\215\305>\215\305@\214\306>\214\305B\212\307<\215" \ + "\307=\214\305B\214\306>\215\306A\212\306@\212\307>\214\306>\212\307<" \ + "\244\317c\370\373\364\377\377\377\377\375\376\377\377\375\376\377\377" \ + "\377\377\377\202\377\376\377\346\377\377\377\1\316\316\316\266::<\217" \ + "\377\377\377\2\234\234\236;;=\206::<\3""99;;;=www\377\377\377\377\226" \ + "\377\377\377\3\204\204\206::<;;=\207::<\3\222\222\222\377\377\377\376" \ + "\376\376\213\377\377\377\1\234\234\236\265::<\1kkm\377\377\377\377\210" \ + "\377\377\377\7\376\376\376\377\377\377\377\377\375\376\377\375\376\377" \ + "\377\377\377\377\377\376\377\203\377\377\377\1\376\376\376\203\377\377" \ + "\377\1\376\377\377\203\377\377\377\16\377\377\375\377\377\377\377\376" \ + "\377\377\377\377\377\377\373\376\377\377\377\377\377\377\377\373\371" \ + "\372\364\242\322d\214\306<\215\307\77\214\305@\214\306<\202\215\305@" \ + "\4\214\306<\214\305@\214\306<\215\307\77\202\214\306>\6\212\307>\214" \ + "\306>\215\307\77\214\305@\244\317c\367\375\361\356\377\377\377\1\316" \ + "\316\316\266::<\214\377\377\377\1\376\376\376\202\377\377\377\1\266\266" \ + "\266\202::<\1;;=\203::<\1;;=\202::<\3__a\377\377\377\376\376\376\377" \ + "\377\377\377\224\377\377\377\2kkm;;=\202::<\202;;=\202::<\3;;=::<\265" \ + "\265\265\215\377\377\377\1\234\234\236\265::<\1kkm\377\377\377\377\214" \ + "\377\377\377\2\376\377\377\376\377\375\202\377\377\375\203\377\377\377" \ + "\204\377\377\375\205\377\377\377\1\376\376\377\202\377\377\377\6\377" \ + "\377\375\377\377\377\371\372\362\242\320c\214\305@\215\305@\202\214\306" \ + ">\20\215\305@\213\310=\212\306@\214\306>\214\305B\215\307\77\215\305" \ + ">\215\306A\212\307>\214\306>\215\307\77\214\306>\242\322b\370\373\362" \ + "\376\376\377\377\375\376\355\377\377\377\1\316\316\316\266::<\215\377" \ + "\377\377\4\376\376\376\377\377\377\315\315\315;;=\203::<\1;;=\203::<" \ + "\2;;=99;\377\377\377\377\226\377\377\377\203::<\1;;=\202::<\1;;=\203" \ + "::<\2\317\317\317\376\376\376\214\377\377\377\1\234\234\236\265::<\1" \ + "kkm\377\377\377\377\211\377\377\377\3\376\376\376\377\376\377\377\377" \ + "\377\203\377\376\377\204\377\377\377\1\376\376\376\202\377\377\377\1" \ + "\377\376\377\203\377\377\377\1\376\376\376\203\377\377\377\31\376\376" \ + "\377\377\376\377\371\372\365\241\322e\212\307<\216\306\77\212\311<\216" \ + "\303\77\212\307>\215\305@\212\306@\214\305D\216\306\77\214\306>\215\307" \ + "\77\214\306>\212\306@\214\306>\215\307\77\215\305@\242\320c\370\373\362" \ + "\377\377\373\377\376\377\377\377\375\355\377\377\377\1\316\316\316\266" \ + "::<\220\377\377\377\202::<\4;;=::<;;=::<\202;;=\3""99;;;=\346\346\346" \ + "\377\377\377\377\224\377\377\377\2\362\362\362;;=\202::<\7""99;::<;;" \ + "=88:;;=::<;;=\216\377\377\377\1\234\234\236\265::<\1kkm\377\377\377\377" \ + "\212\377\377\377\202\376\377\377\202\377\377\377\1\377\376\377\206\377" \ + "\377\377\1\376\376\376\202\377\377\377\1\376\376\376\203\377\377\377" \ + "\1\376\376\376\202\377\377\377\6\370\373\364\242\322b\214\306>\214\305" \ + "@\215\305>\214\305@\202\215\306A\20\214\306<\214\306>\216\306\77\215" \ + "\305<\212\307>\213\307A\215\305>\212\307>\215\307\77\214\306>\242\321" \ + "a\373\374\364\377\377\377\376\377\377\376\376\376\376\377\377\355\377" \ + "\377\377\1\316\316\316\266::<\216\377\377\377\6\376\376\376\377\377\377" \ + "SSU;;=99;;;=\206::<\1\316\316\316\377\377\377\377\224\377\377\377\2\316" \ + "\316\31699;\205::<\1;;=\202::<\1FFH\216\377\377\377\1\234\234\236\265" \ + "::<\1kkm\377\377\377\377\207\377\377\377\202\377\376\377\2\377\377\377" \ + "\377\377\375\203\377\377\377\1\376\377\375\202\377\377\375\203\377\377" \ + "\377\202\377\377\375\2\377\377\377\377\377\375\205\377\377\377\26\377" \ + "\377\375\371\372\362\243\322b\211\305A\215\305>\215\307\77\214\305@\214" \ + "\306>\215\305@\212\307>\214\305@\214\305B\214\306>\212\307>\212\310\77" \ + "\214\306>\217\304@\214\306>\214\305@\242\322b\370\373\362\377\377\377" \ + "\202\377\376\377\1\377\377\375\356\377\377\377\1\316\316\316\266::<\220" \ + "\377\377\377\3kkm::<;;=\202::<\6;;=::<;;=::<;;=\233\233\233\377\377\377" \ + "\377\223\377\377\377\2\376\376\376\265\265\265\205::<\1;;=\202::<\2""9" \ + "9;lln\216\377\377\377\1\234\234\236\265::<\1kkm\377\377\377\377\207\377" \ + "\377\377\3\376\377\375\375\377\376\377\377\377\202\377\376\377\3\377" \ + "\376\374\377\377\377\376\377\377\202\377\377\377\1\377\377\375\204\377" \ + "\377\377\2\375\377\376\377\377\375\202\377\377\377\1\377\377\375\202" \ + "\377\377\377\32\376\376\374\365\367\354\223\312K\215\305>\214\306<\211" \ + "\305\77\214\306>\212\307>\215\307\77\214\306>\214\306<\214\306>\215\307" \ + "\77\213\307A\214\306>\215\305@\215\307\77\212\307>\244\317c\370\373\362" \ + "\377\377\373\376\377\377\377\376\377\375\376\377\377\377\375\377\376" \ + "\377\355\377\377\377\1\316\316\316\266::<\217\377\377\377\5\376\376\376" \ + "\234\234\236;;=::<;;=\202::<\2""99;::<\202;;=\1\221\221\221\377\377\377" \ + "\377\224\377\377\377\1\235\235\235\211::<\2\221\221\223\376\376\376\215" \ + "\377\377\377\1\234\234\236\265::<\1kkm\377\377\377\377\207\377\377\377" \ + "\1\377\376\377\202\377\377\375\202\377\377\377\202\377\377\375\1\377" \ + "\377\377\202\376\377\377\1\377\377\377\202\377\377\375\5\376\376\377" \ + "\377\377\377\377\377\373\377\377\377\376\376\376\203\377\377\377\27\376" \ + "\376\376\377\377\375\376\377\372\347\365\333\225\311K\217\304>\214\305" \ + "B\215\307\77\212\306B\214\306>\215\306A\214\306>\215\305>\214\306>\215" \ + "\305>\217\304@\215\307\77\215\307=\242\320c\367\375\361\376\376\377\377" \ + "\376\377\376\376\376\202\377\377\375\2\374\377\377\377\376\377\355\377" \ + "\377\377\1\316\316\316\266::<\214\377\377\377\1\376\376\376\203\377\377" \ + "\377\3\250\250\252::<;;=\203::<\202;;=\202::<\1kkk\377\377\377\377\224" \ + "\377\377\377\4www;;=::<;;=\202::<\202;;=\202::<\1\234\234\236\216\377" \ + "\377\377\1\234\234\236\265::<\1kkm\377\377\377\377\207\377\377\377\15" \ + "\367\374\365\343\361\316\316\346\254\305\342\240\304\343\240\303\342" \ + "\236\305\342\237\312\346\251\345\356\317\365\373\357\376\377\377\376" \ + "\376\377\377\377\375\214\377\377\377\24\350\365\333\223\312K\216\306" \ + "\77\212\307>\215\304B\214\306>\215\307=\214\306>\215\306A\212\306@\212" \ + "\307>\214\306>\212\307<\244\317c\370\373\364\377\377\377\377\375\376" \ + "\377\377\375\376\377\377\377\377\377\202\377\376\377\356\377\377\377" \ + "\1\316\316\316\266::<\217\377\377\377\2\376\376\376\316\316\320\207:" \ + ":<\3;;=::\10\212\306@\212\307>\232\315W\277\337\224" \ + "\352\364\333\377\377\377\377\376\377\377\377\375\202\376\377\377\202" \ + "\377\377\377\2\377\376\377\377\377\375\202\377\377\377\17\377\377\375" \ + "\377\376\377\347\365\333\226\312L\215\306A\213\310=\212\306@\217\304" \ + ">\216\307<\214\305@\215\305<\214\305@\215\307=\244\317c\366\373\364\377" \ + "\377\377\377\276\377\377\377\6\346\346\346;;=99;;;=::<;;=\205::<\377" \ + "\377\377\377\224\377\377\377\1::<\202;;=\2::<;;=\203::<\4;;=::<\316\316" \ + "\316\376\376\376\377\377\377\377\274\377\377\377\14\377\375\377\377\377" \ + "\377\376\376\374\377\377\375\377\376\377\377\377\375\376\377\377\377" \ + "\377\377\376\377\377\377\376\377\324\353\265\231\316Z\202\214\306<\1" \ + "\215\305>\210\214\306>\202\215\305>\16\214\306>\213\307A\211\306;\233" \ + "\314V\324\353\265\377\377\377\377\376\377\377\377\375\375\377\376\376" \ + "\377\377\377\377\377\377\376\377\376\377\377\377\377\373\202\377\377" \ + "\377\6\376\376\377\350\365\333\222\312K\215\306A\217\304>\212\306@\202" \ + "\214\305@\6\213\310\77\212\307>\242\322d\370\373\364\377\377\377\377" \ + "\377\375\377\377\377\377\276\377\377\377\203::<\3;;=::<99;\202;;=\202" \ + "::<\1\346\346\350\377\377\377\377\222\377\377\377\2\376\376\376;;=\202" \ + "::<\202;;=\205::<\377\377\377\377\275\377\377\377\4\377\377\375\377\377" \ + "\377\377\377\373\377\376\374\202\376\377\377\12\377\377\375\377\377\377" \ + "\376\377\375\342\360\317\232\315V\214\306<\220\306=\215\306A\215\306" \ + "C\215\306A\210\214\306>\202\215\307\77\7\215\306A\214\306>\214\305@\213" \ + "\307A\214\305@\230\315W\341\361\315\203\377\377\377\2\376\376\374\374" \ + "\377\375\202\377\377\377\2\377\377\375\377\376\377\202\377\377\377\13" \ + "\352\364\331\221\311J\215\306A\213\310=\216\306\77\214\305@\214\306<" \ + "\242\322e\370\373\364\376\376\377\377\377\375\377\377\377\377\277\377" \ + "\377\377\1``b\202::<\2;;=99;\202;;=\4::<;;=::<\316\316\320\377\377\377" \ + "\377\222\377\377\377\4\316\316\316;;=::<99;\202::<\2;;=::<\202;;=\3:" \ + ":<\376\376\376\377\377\377\202\376\376\376\377\377\377\377\271\377\377" \ + "\377\17\376\377\377\376\376\374\377\376\374\376\377\377\377\377\377\377" \ + "\377\375\376\377\377\370\373\364\277\336\222\215\305<\214\305@\215\307" \ + "\77\212\307>\215\307\77\213\307A\211\214\306>\16\216\306A\214\305B\213" \ + "\307A\214\306>\215\305<\213\305=\215\306A\214\306<\215\305>\300\337\223" \ + "\370\373\362\376\376\377\377\377\375\376\377\377\204\377\377\377\16\377" \ + "\376\377\376\376\377\376\377\377\352\364\331\222\312K\215\306A\214\306" \ + "<\214\305@\243\321d\371\373\360\376\376\377\376\377\377\377\377\377\376" \ + "\377\377\377\377\377\377\273\377\377\377\4\376\376\376\377\377\377\376" \ + "\376\376lln\203::<\1;;=\20299;\1;;=\202::<\1\266\266\270\377\377\377" \ + "\377\222\377\377\377\5\316\316\316::<;;=::<;;=\205::<\3kkm\377\377\377" \ + "\376\376\376\377\377\377\377\274\377\377\377\14\377\377\375\376\377\377" \ + "\377\377\377\377\377\375\376\376\376\367\374\365\244\317c\214\305@\215" \ + "\307=\211\306=\213\307A\215\306A\202\212\306@\1\213\310<\210\214\306" \ + ">\202\212\307>\3\212\307<\214\306>\216\306\77\202\214\306>\12\215\305" \ + "<\215\307\77\212\306@\242\322b\371\374\365\377\377\375\376\376\374\376" \ + "\377\377\377\376\377\376\377\377\202\377\377\377\13\376\377\375\376\376" \ + "\377\377\377\377\350\365\333\225\311K\214\305B\242\320c\371\374\361\377" \ + "\377\377\376\377\377\377\376\377\377\377\377\377\300\377\377\377\7\221" \ + "\221\223::<99;::<;;=::<;;=\203::<\1\234\234\236\377\377\377\377\222\377" \ + "\377\377\2\250\250\25099;\206::<\3;;=::\216\306" \ + "\77\215\305>\215\305@\210\214\306>\37\215\305@\215\307\77\212\306@\215" \ + "\307\77\214\304\77\215\306A\212\307;\212\306@\214\306>\216\307B\214\306" \ + ">\222\312K\354\364\334\377\376\377\377\377\377\377\377\373\376\377\377" \ + "\377\375\376\376\377\375\377\377\377\377\376\377\377\377\377\376\376" \ + "\377\347\365\333\260\327z\371\374\363\375\377\376\376\377\377\377\376" \ + "\377\377\377\377\377\377\375\377\377\377\377\276\377\377\377\3\376\376" \ + "\376\234\234\23699;\203;;=\205::<\1\221\221\223\377\377\377\377\222\377" \ + "\377\377\2\234\234\234;;=\204::<\202;;=\3::<;;=\235\235\237\377\377\377" \ + "\377\276\377\377\377\202\377\377\375\15\376\377\377\367\374\365\223\312" \ + "K\214\306>\213\310\77\215\305@\214\306<\215\307=\214\305@\213\307A\211" \ + "\305\77\215\307\77\215\305>\210\214\306>\20\215\306A\213\305=\215\307" \ + "=\214\305@\215\306A\214\306>\213\304A\220\305\77\216\306\77\212\306@" \ + "\215\305@\213\307A\221\311L\367\375\363\376\377\377\377\377\377\202\377" \ + "\377\373\1\377\375\376\202\377\377\377\4\377\376\377\376\377\377\377" \ + "\376\377\376\377\377\203\377\377\377\3\377\376\377\376\376\377\374\377" \ + "\375\377\377\377\377\277\377\377\377\2\265\265\267<<>\20299;\7::<;;=" \ + "::<99;;;=::\214\305" \ + "@\210\214\306>\22\216\306A\215\307\77\213\305=\216\306\77\214\306>\212" \ + "\307>\213\310\77\214\305@\215\306C\214\306<\215\307=\215\305>\213\310" \ + "=\242\320d\372\372\362\376\377\375\377\375\377\377\377\375\202\376\377" \ + "\377\5\377\377\377\377\377\375\377\377\377\377\377\375\377\377\377\202" \ + "\377\376\377\5\376\377\375\376\377\377\377\377\377\377\375\376\377\377" \ + "\375\377\377\377\377\274\377\377\377\5\376\376\376\377\377\377\316\316" \ + "\320::<;;=\202::<\1;;=\202::<\3""99;::\214" \ + "\306<\214\306>\211\307>\231\214\306>\1\216\306\77\203\214\306>\2\214" \ + "\305@\266\334\207\202\377\377\377\7\377\376\377\377\377\377\377\376\377" \ + "\377\377\375\377\377\377\377\377\375\376\377\377\377\377\377\377\303" \ + "\377\377\377\1\376\376\376\202\377\377\377\1\316\316\316\206::<\6;;=" \ + "::<;;=FFH\377\377\377\376\376\376\205\377\377\377\1\376\376\376\377\377" \ + "\377\377\212\377\377\377\1lln\202::<\3;;=99;;;=\204::<\3\317\317\317" \ + "\377\377\377\376\376\376\377\377\377\377\273\377\377\377\10\377\375\377" \ + "\374\377\375\343\361\320\214\306>\215\306A\214\304=\212\307>\215\305" \ + ">\230\214\306>\20\214\306<\213\304\77\212\307>\212\306B\214\306<\212" \ + "\307>\220\304>\337\363\316\377\376\377\377\377\377\376\377\377\377\377" \ + "\377\376\376\377\377\377\377\376\376\376\376\377\377\377\377\377\377" \ + "\302\377\377\377\1\376\376\376\202\377\377\377\2\376\376\376\377\377" \ + "\377\204::<\1;;=\202::<\3;;=99;;;=\203\377\377\377\1\376\376\376\202" \ + "\377\377\377\1\376\376\376\377\377\377\377\213\377\377\377\2SSU;;=\202" \ + "::<\2;;=99;\204::<\1\315\315\315\203\377\377\377\1\376\376\376\377\377" \ + "\377\377\271\377\377\377\10\376\376\376\377\377\377\233\316W\214\305" \ + "@\212\306@\216\306=\214\305@\215\305@\230\214\306>\17\214\306<\215\306" \ + "C\211\306=\213\307A\214\304\77\212\306@\214\305B\234\313W\376\377\375" \ + "\377\377\377\376\377\375\377\377\375\376\377\377\376\376\377\376\377" \ + "\375\377\377\377\377\302\377\377\377\1\376\376\376\202\377\377\377\4" \ + "\376\376\376\377\377\377\376\376\376;;=\206::<\202;;=\3::<\377\377\377" \ + "\376\376\376\203\377\377\377\3\376\376\376\377\377\377\376\376\376\377" \ + "\377\377\377\212\377\377\377\3::<99;;;=\202::<\10;;=::<;;=99;;;=\363" \ + "\363\363\377\377\377\376\376\376\377\377\377\377\274\377\377\377\7\323" \ + "\354\265\214\305@\215\307\77\215\306A\216\305C\213\304\77\212\307<\230" \ + "\214\306>\20\215\307\77\215\304B\214\305@\214\306>\215\305>\215\307=" \ + "\212\307<\215\307\77\323\351\270\377\376\377\377\377\377\376\376\376" \ + "\376\377\375\376\376\376\376\377\377\377\376\374\377\377\377\377\302" \ + "\377\377\377\202\376\376\376\202\377\377\377\2\376\376\376FFH\210::<" \ + "\2;;=\316\316\316\202\377\377\377\1\376\376\376\377\377\377\377\215\377" \ + "\377\377\1\376\376\376\202;;=\4""99;;;=::<;;=\202::<\2;;=::<\377\377" \ + "\377\377\277\377\377\377\7\231\316X\220\304>\214\305@\215\307\77\214" \ + "\306<\214\311>\214\305@\231\214\306>\11\215\304B\214\306>\215\306A\214" \ + "\306<\215\306A\214\305B\215\307\77\234\315X\375\377\374\204\377\377\377" \ + "\2\376\377\377\377\376\377\377\377\377\377\304\377\377\377\202\376\376" \ + "\376\4\377\377\377jjl::<99;\202;;=\205::<\7\316\316\316\377\377\377\376" \ + "\376\376\377\377\377\376\376\376\377\377\377\376\376\376\377\377\377" \ + "\377\212\377\377\377\6\363\363\363::<99;;;=::<;;=\202::<\1;;=\202::<" \ + "\377\377\377\377\276\377\377\377\2\342\361\320\214\306<\202\215\305>" \ + "\4\212\307>\215\307=\211\306=\215\305>\230\214\306>\2\213\310=\214\306" \ + "<\202\214\305@\7\215\306A\214\306>\215\307=\214\304\77\211\310<\343\362" \ + "\321\377\377\375\202\377\376\377\2\377\377\375\376\376\376\377\377\377" \ + "\377\310\377\377\377\4kkm::<;;=::<\202;;=\202::<\3;;=::<\316\316\316" \ + "\202\377\377\377\1\376\376\376\377\377\377\377\215\377\377\377\3\316" \ + "\316\316::<;;=\202::<\1;;=\204::<\1__a\202\377\377\377\3\376\376\376" \ + "\377\377\377\376\376\376\377\377\377\377\271\377\377\377\4\270\333\207" \ + "\214\306>\214\305@\214\306>\203\214\305@\1\215\305>\230\214\306>\17\215" \ + "\306A\213\310=\212\307<\214\306>\214\306<\215\306A\214\306>\214\305@" \ + "\213\306E\267\332\206\377\377\375\376\377\377\377\377\375\377\377\377" \ + "\377\377\375\377\377\377\377\303\377\377\377\1\376\376\376\204\377\377" \ + "\377\6lln;;=::<99;::<;;=\204::<\1\250\250\250\204\377\377\377\1\376\376" \ + "\376\377\377\377\377\213\377\377\377\1\316\316\316\203::<\1;;=\205::" \ + "<\1lln\203\377\377\377\1\376\376\376\377\377\377\377\272\377\377\377" \ + "\10\232\315V\215\305@\212\306@\215\305>\214\306<\215\304D\215\305<\212" \ + "\306@\230\214\306>\3\217\304@\214\306<\215\306A\202\215\305@\7\214\306" \ + ">\214\305@\212\307>\215\305<\233\316W\376\376\377\376\377\375\203\377" \ + "\377\377\1\376\377\377\377\377\377\377\305\377\377\377\3\376\376\376" \ + "\377\377\377\234\234\236\203::<\2;;=99;\204::<\1\234\234\234\202\377" \ + "\377\377\1\376\376\376\377\377\377\377\215\377\377\377\5\316\316\320" \ + "::<;;=::<;;=\202::<\1;;=\202::<\1kkm\377\377\377\377\266\377\377\377" \ + "\10\375\377\374\376\377\377\376\376\376\377\377\375\377\377\377\376\377" \ + "\377\377\377\375\360\371\350\250\214\306>\4\214\305@\212\307>\360\371" \ + "\346\376\377\375\202\377\377\377\1\377\377\375\377\377\377\377\304\377" \ + "\377\377\1\376\376\376\203\377\377\377\1\234\234\234\211::<\1\234\234" \ + "\234\205\377\377\377\1\376\376\376\377\377\377\377\212\377\377\377\4" \ + "\316\316\320llnkkmlln\203kkm\1jjl\202kkm\1\221\221\223\377\377\377\377" \ + "\270\377\377\377\1\377\376\377\202\377\377\377\3\375\376\377\377\377" \ + "\375\341\361\315\251\214\306>\2\215\307\77\342\360\314\377\377\377\377" \ + "\310\377\377\377\202\376\376\376\202\377\377\377\2\266\266\266kkk\210" \ + "kkm\1\265\265\265\206\377\377\377\1\376\376\376\377\377\377\377\211\377" \ + "\377\377\1\376\376\376\203\377\377\377\3\376\376\376\377\377\377\376" \ + "\376\376\202\377\377\377\1\376\376\376\202\377\377\377\1\376\376\376" \ + "\377\377\377\377\264\377\377\377\1\377\376\377\205\377\377\377\2\375" \ + "\377\374\310\340\246\252\214\306>\1\310\340\246\377\377\377\377\307\377" \ + "\377\377\1\376\376\376\202\377\377\377\3\375\375\375\377\377\377\376" \ + "\376\376\211\377\377\377\7\376\376\376\377\377\377\376\376\376\377\377" \ + "\377\376\376\376\377\377\377\376\376\376\377\377\377\377\213\377\377" \ + "\377\1\376\376\376\204\377\377\377\1\376\376\376\206\377\377\377\1\376" \ + "\376\376\377\377\377\377\263\377\377\377\1\377\376\377\204\377\377\377" \ + "\3\376\376\377\376\377\375\304\342\234\251\214\306>\7\215\305@\305\343" \ + "\235\376\376\377\377\377\377\376\376\377\377\376\377\377\377\375\377" \ + "\377\377\377\306\377\377\377\1\376\376\376\217\377\377\377\3\376\376" \ + "\376\377\377\377\376\376\376\377\377\377\377\214\377\377\377\5\376\376" \ + "\376\377\377\377\376\376\376\377\377\377\376\376\376\203\377\377\377" \ + "\1\376\376\376\377\377\377\377\267\377\377\377\1\377\377\375\202\377" \ + "\377\377\3\377\376\377\376\377\375\305\342\237\251\214\306>\3\215\305" \ + "@\303\344\235\376\376\376\202\377\377\377\1\377\376\377\377\377\377\377" \ + "\305\377\377\377\1\376\376\376\203\377\377\377\1\376\376\376\214\377" \ + "\377\377\1\376\376\376\377\377\377\377\216\377\377\377\1\376\376\376" \ + "\203\377\377\377\1\376\376\376\206\377\377\377\1\376\376\376\377\377" \ + "\377\377\266\377\377\377\5\376\377\377\376\376\377\377\376\377\377\377" \ + "\377\305\342\242\251\214\306>\4\215\306A\302\341\236\377\377\375\376" \ + "\376\376\377\377\377\377\305\377\377\377\1\376\376\376\203\377\377\377" \ + "\1\376\376\376\214\377\377\377\1\376\376\376\377\377\377\377\231\377" \ + "\377\377\3\376\376\376\377\377\377\376\376\376\377\377\377\377\264\377" \ + "\377\377\2\376\376\376\377\376\377\202\376\377\377\202\377\377\377\1" \ + "\305\342\240\251\214\306>\7\214\305@\306\343\240\377\376\374\377\377" \ + "\377\376\377\377\377\377\377\376\376\376\377\377\377\377\325\377\377" \ + "\377\1\376\376\376\377\377\377\377\222\377\377\377\1\376\376\376\205" \ + "\377\377\377\1\376\376\376\377\377\377\377\265\377\377\377\4\377\377" \ + "\375\377\376\377\375\377\376\376\377\375\202\377\377\377\1\305\343\235" \ + "\251\214\306>\4\213\310\77\306\341\234\377\376\377\377\377\377\202\376" \ + "\377\375\377\377\377\377\311\377\377\377\1\377\377\375\215\377\377\377" \ + "\1\376\376\376\377\377\377\377\377\377\377\377\314\377\377\377\3\377" \ + "\377\375\377\377\377\376\377\375\203\377\377\377\11\376\377\377\345\360" \ + "\320\214\305@\214\306>\214\305@\214\304\77\214\306<\215\305>\212\307" \ + ">\231\214\306>\1\214\305@\202\215\307\77\205\214\306>\5\212\307>\214" \ + "\306>\342\360\315\377\377\377\376\376\376\202\377\377\377\1\377\377\375" \ + "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\244" \ + "\377\377\377\3\377\376\377\377\377\377\376\377\375\203\377\377\377\11" \ + "\376\377\377\362\371\347\214\306>\214\305B\215\310<\215\306A\214\305" \ + "@\215\307\77\214\305@\231\214\306>\4\215\307\77\213\305=\214\306>\215" \ + "\307\77\202\214\306>\5\215\307\77\214\306>\216\306\77\215\306A\360\367" \ + "\345\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ + "\251\377\377\377\2\377\376\377\377\377\375\203\377\377\377\13\377\377" \ + "\375\377\377\377\375\377\374\233\316W\214\305@\213\304\77\212\306@\215" \ + "\307\77\214\305@\215\306A\214\305@\230\214\306>\3\215\307\77\214\306" \ + ">\215\306A\203\214\305@\7\215\306A\214\305@\215\304B\232\315T\377\377" \ + "\375\376\377\377\377\377\375\377\377\377\377\377\377\377\377\377\377" \ + "\377\377\377\377\377\377\250\377\377\377\1\377\377\375\205\377\377\377" \ + "\11\377\376\377\267\333\204\213\307A\213\307C\215\307\77\213\304\77\215" \ + "\307\77\215\305<\212\306@\231\214\306>\1\215\307\77\203\214\305@\202" \ + "\214\306>\7\215\307\77\212\306@\267\333\204\377\376\377\376\377\377\377" \ + "\377\375\376\376\376\377\377\377\377\377\377\377\377\377\377\377\377" \ + "\377\377\377\377\247\377\377\377\17\377\377\375\377\377\377\377\377\375" \ + "\376\376\376\377\377\377\377\377\375\376\376\377\334\354\305\211\306" \ + "=\213\307A\213\305;\215\306A\214\306<\215\305>\213\307A\232\214\306>" \ + "\202\214\305@\11\214\306>\214\306<\214\306>\215\307\77\212\311=\333\355" \ + "\305\377\376\377\377\377\377\376\376\376\377\377\377\377\377\377\377" \ + "\377\377\377\377\377\377\377\377\377\252\377\377\377\3\377\377\375\377" \ + "\377\377\377\376\377\203\377\377\375\7\233\314V\215\307\77\215\305>\214" \ + "\306>\215\307\77\214\305@\212\307>\232\214\306>\14\214\305@\214\306>" \ + "\214\306<\215\307=\215\307\77\214\305@\232\315V\374\377\373\376\376\377" \ + "\377\377\375\377\377\377\376\376\376\377\377\377\377\377\377\377\377" \ + "\377\377\377\377\377\377\377\377\255\377\377\377\10\377\377\375\377\376" \ + "\377\324\353\267\214\304\77\215\305>\214\305@\212\307<\214\305@\232\214" \ + "\306>\2\215\307\77\215\306A\202\214\306>\4\215\307\77\213\304\77\215" \ + "\306E\316\346\254\202\377\377\377\3\377\377\375\376\376\377\376\377\377" \ + "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\247" \ + "\377\377\377\1\376\376\376\206\377\377\377\10\377\377\373\375\376\377" \ + "\232\315W\214\306>\215\307=\211\307>\215\306A\215\305>\232\214\306>\1" \ + "\214\305@\202\215\307\77\13\214\305@\215\306E\227\317P\377\377\377\377" \ + "\377\375\376\377\377\377\377\377\377\377\375\375\377\376\377\377\377" \ + "\377\377\375\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ + "\377\377\254\377\377\377\20\376\377\377\377\375\377\331\356\303\215\305" \ + "@\213\310\77\215\305>\216\306\77\213\307A\215\306A\214\306<\214\306>" \ + "\216\306\77\213\304\77\212\307<\214\306>\215\305@\210\214\306>\1\214" \ + "\305@\202\215\307\77\205\214\306>\10\214\305@\212\307>\215\305>\214\305" \ + "@\215\305>\214\305@\215\305>\331\356\305\377\377\377\377\377\377\377" \ + "\377\377\377\377\377\377\377\377\377\264\377\377\377\20\376\376\374\377" \ + "\377\375\376\376\374\261\330{\214\306>\216\306A\214\306>\213\307A\215" \ + "\305>\215\306A\215\307\77\213\304A\215\307\77\214\305@\214\306<\216\306" \ + "A\210\214\306>\4\215\307\77\213\305=\214\306>\215\307\77\202\214\306" \ + ">\12\215\307\77\214\306>\212\307>\220\305\77\212\307>\214\306>\213\310" \ + "=\214\306<\262\327z\376\377\377\377\377\377\377\377\377\377\377\377\377" \ + "\377\377\377\377\377\377\265\377\377\377\17\374\377\377\377\377\377\370" \ + "\373\362\241\321d\211\310<\215\305>\215\305@\216\306=\214\305@\214\306" \ + ">\215\307\77\214\306>\212\307<\212\306@\212\307<\210\214\306>\3\215\307" \ + "\77\214\306>\215\306A\203\214\305@\12\215\306A\214\305@\215\305>\212" \ + "\307>\213\307A\216\305C\215\307=\242\322e\371\372\364\375\377\376\377" \ + "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\264\377" \ + "\377\377\1\375\377\374\203\377\377\377\4\352\364\333\223\311O\212\306" \ + "@\215\305@\202\213\310\77\202\214\306>\4\216\307F\213\305=\215\307\77" \ + "\215\305@\211\214\306>\1\215\307\77\203\214\305@\202\214\306>\1\215\307" \ + "\77\202\214\305@\6\216\305C\215\307\77\225\311K\351\363\332\377\377\377" \ + "\376\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ + "\377\377\265\377\377\377\17\377\375\376\377\376\377\377\377\377\377\377" \ + "\375\352\365\327\223\313L\212\307<\215\305>\214\305@\215\307=\214\305" \ + "@\214\306<\213\310\77\213\304\77\220\305A\212\214\306>\202\214\305@\12" \ + "\214\306>\214\306<\214\306>\215\307\77\214\306>\213\310=\215\307=\225" \ + "\311K\347\365\334\377\377\375\377\377\377\377\377\377\377\377\377\377" \ + "\377\377\377\377\377\377\267\377\377\377\1\377\377\375\202\377\377\377" \ + "\13\377\376\377\376\377\377\353\363\334\245\320d\214\305B\214\305@\215" \ + "\306A\213\305=\214\306>\213\307A\213\310=\213\214\306>\5\214\305@\214" \ + "\306>\214\306<\215\307=\215\307\77\202\214\305@\5\214\306<\242\322e\351" \ + "\363\332\377\377\375\376\376\376\377\377\377\377\377\377\377\377\377" \ + "\377\377\377\377\377\377\377\267\377\377\377\1\376\376\374\202\377\377" \ + "\375\6\376\377\377\377\376\377\377\377\375\371\372\364\255\330|\217\304" \ + ">\202\212\306@\2\215\306A\214\303A\202\214\305@\211\214\306>\2\215\307" \ + "\77\215\306A\202\214\306>\6\215\307\77\213\304\77\215\306E\215\305>\262" \ + "\327z\371\372\364\203\377\377\377\2\376\377\377\377\377\375\377\377\377" \ + "\377\377\377\377\377\377\377\377\377\377\377\377\377\264\377\377\377" \ + "\1\376\376\376\202\377\377\377\2\377\377\375\377\376\377\203\377\377" \ + "\377\6\377\377\375\331\356\303\233\314W\215\310<\214\305@\215\307\77" \ + "\214\214\306>\1\214\305@\202\215\307\77\7\214\305@\215\306E\227\317P" \ + "\331\356\305\376\377\377\375\377\376\376\377\377\202\377\377\377\2\377" \ + "\377\375\376\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ + "\377\377\377\377\274\377\377\377\10\377\377\375\377\376\377\365\375\362" \ + "\307\342\237\234\315Z\212\306@\212\307>\214\305@\202\215\307\77\16\214" \ + "\306>\215\307\77\214\306>\215\306A\214\306>\213\310\77\214\306>\215\305" \ + "<\216\306A\213\310\77\212\307>\232\315T\307\341\242\370\373\362\377\377" \ + "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\304\377\377" \ + "\377\1\377\377\375\202\377\377\377\10\377\376\377\376\376\374\335\354" \ + "\303\270\333\207\222\311J\214\305@\215\306A\213\305=\202\214\306>\13" \ + "\215\307\77\216\306\77\215\305>\212\306@\212\307>\226\312K\270\333\211" \ + "\334\354\307\376\377\377\376\376\376\377\377\375\377\377\377\377\377" \ + "\377\377\377\377\377\377\377\377\377\377\377\306\377\377\377\2\376\377" \ + "\375\376\377\377\204\377\377\377\16\350\366\334\332\354\302\311\341\245" \ + "\306\341\234\305\342\237\304\341\237\305\342\240\305\342\237\334\355" \ + "\303\352\364\333\377\377\375\377\375\376\377\376\377\377\377\375\377" \ + "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\307\377" \ + "\377\377\15\376\376\376\377\376\377\377\377\375\377\377\373\376\377\377" \ + "\376\377\375\376\377\377\377\377\375\377\377\377\376\376\376\376\377" \ + "\377\376\377\375\377\377\377\202\377\376\377\204\377\377\377\1\376\376" \ + "\376\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ + "\307\377\377\377\3\376\377\377\377\377\377\376\376\376\202\377\377\377" \ + "\1\376\376\376\210\377\377\377\3\375\377\376\376\377\377\377\377\377" \ + "\203\377\376\377\4\376\377\375\376\377\377\377\377\377\377\376\377\377" \ + "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\304\377" \ + "\377\377\10\377\377\375\377\376\377\377\377\373\377\377\377\375\377\376" \ + "\376\377\377\376\376\376\377\376\377\202\376\377\377\1\377\377\377\202" \ + "\376\376\376\202\377\377\377\202\376\377\377\5\376\377\375\377\377\377" \ + "\376\376\374\377\377\377\377\377\375\377\377\377\377\377\377\377\377" \ + "\377\377\377\377\377\377\377\377\307\377\377\377\1\376\376\377\202\377" \ + "\377\377\2\377\377\375\376\376\377\202\377\377\377\2\376\377\375\377" \ + "\377\375\204\377\377\377\202\377\377\375\1\376\377\375\202\376\377\377" \ + "\202\377\377\375\202\377\377\377\1\377\376\377\377\377\377\377\377\377" \ + "\377\377\377\377\377\377\377\377\377\377\310\377\377\377\5\377\377\375" \ + "\377\376\377\377\377\375\376\376\377\377\376\377\207\377\377\377\202" \ + "\377\376\377\1\376\376\376\377\377\377\377\377\377\377\377\377\377\377" \ + "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ + "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ + "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ + "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ + "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ + "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ + "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ + "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ + "\377\377\377\377\377\377\377\377\377\377\377\377\377\261\377\377\377" \ + "\1\376\376\376\210\377\377\377\3\376\376\376\377\377\377\376\376\376" \ + "\331\377\377\377\1\376\376\376\204\377\377\377\1\376\376\376\257\377" \ + "\377\377\1\376\376\376\212\377\377\377\1\376\376\376\211\377\377\377" \ + "\1\376\376\376\221\377\377\377\1\376\376\376\203\377\377\377\1\376\376" \ + "\376\205\377\377\377\1\376\376\376\312\377\377\377\1\376\376\376\214" \ + "\377\377\377\1\376\376\376\202\377\377\377\6\377\376\375\377\377\377" \ + "\376\377\377\377\377\377\377\376\377\376\377\377\270\377\377\377\7\376" \ + "\377\377\377\376\377\376\377\377\377\377\375\377\377\377\377\375\377" \ + "\377\376\377\273\377\377\377\1\376\376\376\202\377\377\377\1\376\376" \ + "\376\302\377\377\377\1\376\376\376\305\377\377\377\1\376\376\376\241" \ + "\377\377\377\1\376\376\376\214\377\377\377\1\376\376\376\235\377\377" \ + "\377\1\376\376\376\202\377\377\377\1\376\376\376\202\377\377\377\1\376" \ + "\376\376\202\377\377\377\1\376\376\376\252\377\377\377\1\376\376\376" \ + "\212\377\377\377\3\376\376\376\377\377\377\376\376\376\202\377\377\377" \ + "\1\376\376\376\251\377\377\377\202\376\376\376\215\377\377\377\1\376" \ + "\376\376\202\377\377\377\1\376\376\376\205\377\377\377\1\376\376\376" \ + "\224\377\377\377\1\376\376\376\203\377\377\377\1\376\376\376\202\377" \ + "\377\377\1\376\376\376\232\377\377\377\1\376\376\376\202\377\377\377" \ + "\1\376\376\376\202\377\377\377\1\376\376\376\206\377\377\377\1\376\376" \ + "\376\243\377\377\377\1\376\376\376\204\377\377\377\1\376\376\376\202" \ + "\377\377\377\3\376\376\376\377\377\377\376\376\376\202\377\377\377\2" \ + "\376\376\376\377\377\377\202\377\377\375\3\377\377\377\376\377\377\377" \ + "\377\375\202\377\376\377\1\377\377\377\270\377\376\377\14\377\377\377" \ + "\377\376\377\377\376\374\377\377\375\375\376\377\376\377\377\377\377" \ + "\375\376\376\376\377\377\377\376\376\376\377\377\377\376\376\376\203" \ + "\377\377\377\1\376\376\376\266\377\377\377\1\376\376\376\203\377\377" \ + "\377\1\376\376\376\202\377\377\377\1\376\376\376\214\377\377\377\202" \ + "\376\376\376\207\377\377\377\1\376\376\376\272\377\377\377\1\376\376" \ + "\376\252\377\377\377\202\376\376\376\247\377\377\377\5\376\376\376\377" \ + "\377\377\376\376\376\377\377\377\376\376\376\202\377\377\377\1\376\376" \ + "\376\203\377\377\377\1\376\376\376\311\377\377\377\1\376\376\376\221" \ + "\377\377\377\1\376\376\376\203\377\377\377\1\376\376\376\302\377\377" \ + "\377\1\376\376\376\207\377\377\377\1\346\346\346\204\316\316\316\10\317" \ + "\317\317\315\315\315\316\316\316\363\363\365\377\377\377\376\376\376" \ + "\377\377\377\376\376\376\204\377\377\377\1\376\376\376\202\377\377\377" \ + "\1\376\376\376\234\377\377\377\1\376\376\376\262\377\377\377\1\376\376" \ + "\376\213\377\377\377\1\377\377\375\202\376\377\377\1\376\376\377\202" \ + "\377\377\377\2\377\376\377\377\377\375\270\276\317\331\1\377\376\377" \ + "\205\377\377\377\3\376\377\375\377\377\375\376\376\376\257\377\377\377" \ + "\1\376\376\376\210\377\377\377\202\376\376\376\210\377\377\377\1\376" \ + "\376\376\220\377\377\377\1\376\376\376\207\377\377\377\1\376\376\376" \ + "\243\377\377\377\1\376\376\376\203\377\377\377\3\376\376\376\377\377" \ + "\377\376\376\376\207\377\377\377\1\376\376\376\331\377\377\377\12\376" \ + "\376\376\377\377\377\235\235\235kkmllnkkmllnjjlkkm\346\346\346\202\377" \ + "\377\377\1\376\376\376\237\377\377\377\2\346\346\346\317\317\317\204" \ + "\316\316\316\2\317\317\317\346\346\346\234\377\377\377\1\376\376\376" \ + "\203\377\377\377\1\376\376\376\202\377\377\377\1\332\332\332\203\316" \ + "\316\316\1\317\317\317\202\316\316\316\213\377\377\377\5\346\346\346" \ + "\317\317\317\315\315\315\316\316\316\315\315\315\252\316\316\316\1\363" \ + "\363\363\205\377\377\377\1\376\376\376\212\377\377\377\1\376\376\376" \ + "\211\377\377\377\4\346\346\346\250\250\250\204\204\206``b\202::<\1;;" \ + "=\202::<\3;;=99;;;=\203::<\4lln\220\220\222\266\266\266\363\363\363\202" \ + "\376\376\376\240\377\377\377\1\346\346\346\202\316\316\316\10\317\317" \ + "\317\315\315\315\317\317\317\316\316\316\332\332\332\376\376\376\377" \ + "\377\377\376\376\376\203\377\377\377\1\376\376\376\241\377\377\377\6" \ + "\376\376\376\377\377\377\346\346\346\316\316\320\317\317\321\316\316" \ + "\320\203\316\316\316\2\347\347\347\376\376\376\205\377\377\377\1\376" \ + "\376\376\202\377\377\375\5\376\377\377\377\377\375\377\377\377\317\334" \ + "\344\37V\177\270\0>i\12\37U{\317\334\344\377\376\374\377\377\375\376" \ + "\377\377\377\376\374\376\377\377\376\376\376\377\377\377\363\363\363" \ + "\202\316\316\316\1\315\315\315\202\317\317\317\251\316\316\316\1\332" \ + "\332\332\202\377\377\377\1\376\376\376\203\377\377\377\202\376\376\376" \ + "\204\377\377\377\3\346\346\346\316\316\316\316\316\320\204\316\316\316" \ + "\2\346\346\346\376\376\376\212\377\377\377\1\347\347\347\206\316\316" \ + "\316\2\317\317\317\363\363\363\250\377\377\377\2\376\376\376\331\331" \ + "\331\206\316\316\316\1\332\332\332\202\377\377\377\1\376\376\376\204" \ + "\377\377\377\1\376\376\376\203\377\377\377\3\332\332\332\316\316\316" \ + "\316\316\320\250\316\316\316\1\363\363\363\205\377\377\377\1\376\376" \ + "\376\242\377\377\377\4\346\346\346::<;;=99;\204::<\1\204\204\206\237" \ + "\377\377\377\1\376\376\376\202\377\377\377\3\235\235\235::<;;=\202::" \ + "<\3;;=::<\235\235\235\202\377\377\377\1\376\376\376\232\377\377\377\1" \ + "\376\376\376\205\377\377\377\4kkm;;;99;;;=\202::<\1;;;\213\377\377\377" \ + "\4\234\234\234:::::<;;=\202::<\1;;;\250::<\1\316\316\316\202\377\377" \ + "\377\1\376\376\376\203\377\377\377\1\376\376\376\212\377\377\377\203" \ + "\376\376\376\203\377\377\377\3\346\346\346\250\250\250```\204::<\202" \ + ";;=\202::<\3;;=::<;;=\203::<\1;;=\202::<\5;;=::<```\265\265\265\362\362" \ + "\362\203\377\377\377\1\376\376\376\233\377\377\377\1\234\234\236\204" \ + "::<\5""99;;;=::<\333\333\335\376\376\376\203\377\377\377\1\376\376\376" \ + "\241\377\377\377\4\376\376\376\377\377\377\363\363\363FFH\202::<\1;;" \ + "=\203::<\1\234\234\234\210\377\377\377\6\376\377\377\377\377\375\375" \ + "\376\377\356\363\366\40Vz\0\77h\270\0=i\20\0>i\22Ip\356\363\367\376\377" \ + "\377\377\377\375\377\377\377\376\376\377\377\376\377\377\377\377\315" \ + "\315\315:::::<;;=::<99;;;;\250::<\1kkm\205\377\377\377\1\376\376\376" \ + "\203\377\377\377\4\376\376\376\377\377\377\376\376\376\234\234\234\203" \ + "::<\6;;=::<:::\234\234\234\377\377\377\376\376\376\211\377\377\377\3" \ + "\332\332\332:::;;=\202::<\202;;=\2::<\204\204\206\250\377\377\377\2\364" \ + "\364\364FFF\204::<\202:::\1\234\234\234\206\377\377\377\1\376\376\376" \ + "\204\377\377\377\2kkk;;=\251::<\1\316\316\316\202\377\377\377\1\376\376" \ + "\376\203\377\377\377\1\376\376\376\240\377\377\377\6\376\376\376\234" \ + "\234\236::<;;=::<;;=\203::<\2FFH\362\362\362\235\377\377\377\1\376\376" \ + "\376\203\377\377\377\3\234\234\236::<;;=\202::<\3;;=::<\234\234\236\203" \ + "\377\377\377\1\376\376\376\233\377\377\377\1\376\376\376\203\377\377" \ + "\377\7kkm::<;;=::<;;=::<;;=\213\377\377\377\4\235\235\235::<;;=99;\202" \ + ";;=\251::<\1\315\315\315\203\377\377\377\202\376\376\376\213\377\377" \ + "\377\1\376\376\376\202\377\377\377\6\376\376\376\377\377\377\315\315" \ + "\315\205\205\205::<;;=\213::<\4;;=::<;;=::<\203;;=\204::<\4FFF\204\204" \ + "\204\346\346\346\376\376\376\234\377\377\377\3\234\234\236::<;;=\202" \ + "::<\4;;=99;::<``b\244\377\377\377\1\376\376\376\203\377\377\377\1xxz" \ + "\202::<\10;;=99;;;=::<;;=\233\233\235\377\377\377\376\376\376\202\377" \ + "\377\377\1\376\376\376\203\377\377\377\4\375\377\376\377\376\373\377" \ + "\377\375\235\267\310\202\0>i\271\0=i\4\0\77j\237\266\306\377\376\377" \ + "\377\375\374\202\376\377\377\4\377\377\377\376\376\376\316\316\31699" \ + ";\202;;=\2::<;;=\251::<\1kkm\203\377\377\377\1\376\376\376\210\377\377" \ + "\377\4\235\235\235::<99;;;=\203::<\1\235\235\235\214\377\377\377\2ll" \ + "n99;\202;;=\1::<\203;;=\2\362\362\364\376\376\376\245\377\377\377\2\376" \ + "\376\376\250\250\250\204::<\4;;=::<:::\346\346\346\203\377\377\377\1" \ + "\376\376\376\205\377\377\377\3\376\376\376\377\377\377jjl\252::<\1\315" \ + "\315\315\203\377\377\377\202\376\376\376\242\377\377\377\3\362\362\364" \ + "GGI::<\202;;=\2""99;;;=\202::<\2""99;\235\235\235\237\377\377\377\3\376" \ + "\376\376\377\377\377\235\235\237\202::<\202;;=\202::<\3\235\235\237\377" \ + "\377\377\376\376\376\233\377\377\377\1\376\376\376\203\377\377\377\4" \ + "\376\376\376\377\377\377kkm;;=\202::<\5""99;;;=99;\377\377\377\376\376" \ + "\376\211\377\377\377\1\233\233\233\202::<\3;;=::<99;\251::<\1\317\317" \ + "\317\205\377\377\377\1\376\376\376\214\377\377\377\3\376\376\376\347" \ + "\347\347xxz\203::<\1;;=\202::<\1;;=\204::<\1;;=\203::<\1;;=\205::<\1" \ + ";;=\203::<\1;;=\203::<\2\234\234\236\362\362\362\233\377\377\377\2\233" \ + "\233\235;;=\204::<\1;;=\202::<\1\234\234\236\245\377\377\377\4\376\376" \ + "\376\302\302\304::<;;=\206::<\1\235\235\237\202\377\377\377\1\376\376" \ + "\376\203\377\377\377\7\375\376\377\377\377\377\377\377\375\376\377\377" \ + "\377\377\377\177\235\265\0\77k\271\0\77j\7\0\77k\0\77j~\236\265\377\376" \ + "\377\376\377\377\375\377\374\377\377\375\202\377\377\377\5\315\315\315" \ + ";;=::<99;;;=\252::<\3kkm\377\377\377\376\376\376\203\377\377\377\1\376" \ + "\376\376\203\377\377\377\1\376\376\376\202\377\377\377\3\233\233\233" \ + "::<;;=\202::<\3;;=::<\234\234\234\202\377\377\377\1\376\376\376\211\377" \ + "\377\377\4\264\264\264;;=::<;;=\204::<\3\247\247\251\377\377\377\376" \ + "\376\376\245\377\377\377\1SSS\203::<\1;;=\202::<\1\204\204\204\213\377" \ + "\377\377\4\376\376\376lln::<:9>\250::<\1\317\317\317\205\377\377\377" \ + "\1\376\376\376\241\377\377\377\1\265\265\267\204::<\1;;=\204::<\1FFF" \ + "\241\377\377\377\2\234\234\236;;=\204::<\2;;=\234\234\236\234\377\377" \ + "\377\3\376\376\376\377\377\377\376\376\376\204\377\377\377\1kkm\203:" \ + ":<\4;;=::<;;=\376\376\376\212\377\377\377\1\234\234\234\204::<\1;;=\251" \ + "::<\1\316\316\316\203\377\377\377\202\376\376\376\215\377\377\377\4\234" \ + "\234\234;;=::<;;=\202::<\1""99;\204::<\1;;=\203::<\1;;=\211::<\1""99" \ + ";\207::<\2FFF\301\301\301\232\377\377\377\2\234\234\23699;\210::<\1\333" \ + "\333\333\241\377\377\377\6\376\376\376\377\377\377\376\376\376\363\363" \ + "\363FFH;;=\205::<\3;;=::<\234\234\236\206\377\377\377\7\377\376\377\377" \ + "\377\377\377\377\375\375\376\377\377\376\377\201\235\263\0>g\272\0>i" \ + "\13\0>e\177\236\263\377\375\374\377\377\377\377\377\375\376\376\376\377" \ + "\376\377\377\377\377\316\316\316::<;;=\202::<\2""99;;;=\250::<\1kkm\204" \ + "\377\377\377\5\376\376\376\377\377\377\376\376\376\377\377\377\376\376" \ + "\376\202\377\377\377\2\376\376\376\234\234\234\206::<\1\234\234\234\215" \ + "\377\377\377\2RRT;;=\205::<\1SSU\246\377\377\377\2\316\316\316999\206" \ + "::<\1\316\316\316\202\377\377\377\3\376\376\376\377\377\377\376\376\376" \ + "\207\377\377\377\3jjl::<:9>\250::<\1\316\316\316\203\377\377\377\202" \ + "\376\376\376\242\377\377\377\2SSU99;\202;;=\204::<\4;;=99;::<\264\264" \ + "\266\240\377\377\377\1\234\234\234\206::<\1\234\234\234\243\377\377\377" \ + "\1kkm\206::<\213\377\377\377\2\234\234\236;;=\216::<\4""99;;;=::<;;=" \ + "\206::<\3;;=::<;;=\222::<\1\316\316\316\205\377\377\377\1\376\376\376" \ + "\207\377\377\377\1\376\376\376\202\377\377\377\2\346\346\350__a\202:" \ + ":<\3;;=::<;;=\204::<\1;;=\202::<\3;;=::<;;=\203::<\1;;=\202::<\2""99" \ + ";;;=\202::<\1;;=\204::<\7;;=::<;;=::<;;=\204\204\206\363\363\363\203" \ + "\377\377\377\3\376\376\376\377\377\377\376\376\376\222\377\377\377\4" \ + "\234\234\236::<;;=99;\204::<\3;;=::<__a\244\377\377\377\1xxx\205::<\1" \ + ";;=\203::<\1\234\234\236\213\377\377\377\3\177\236\263\0=i\0>i\211\0" \ + "=i\2\0>j\0=i\202\1>j\2\0\77k\0>j\232\0>i\2\0>j\0\77k\202\1>j\2\0=i\0" \ + ">j\211\0=i\3\0>i\0=i\177\236\263\206\377\377\377\6\316\316\316:::::<" \ + ";;=::<;;=\217::<\1;;=\203::<\1;;=\202::<\1;;=\222::<\1kkk\205\377\377" \ + "\377\1\376\376\376\206\377\377\377\1\234\234\236\206::<\1\234\234\236" \ + "\215\377\377\377\3\234\234\234;;=::<\202;;=\203::<\3\316\316\320\377" \ + "\377\377\376\376\376\240\377\377\377\1\376\376\376\202\377\377\377\3" \ + "xxz::<;;=\202::<\3;;=::<__a\215\377\377\377\1kkm\204::<\1;;=\202::<\1" \ + ";;=\242::<\1\316\316\316\205\377\377\377\1\376\376\376\240\377\377\377" \ + "\1\265\265\265\202::<\5;;=::<;;=::<;;=\204::<\2TTV\376\376\376\237\377" \ + "\377\377\1\234\234\234\206::<\1\234\234\234\243\377\377\377\1kkm\206" \ + "::<\213\377\377\377\3\234\234\23499;;;=\214::<\1""99;\207::<\1;;=\227" \ + "::<\1\316\316\316\204\377\377\377\3\376\376\376\377\377\377\376\376\376" \ + "\203\377\377\377\1\376\376\376\204\377\377\377\2\333\333\335FFH\214:" \ + ":<\16``b\221\221\223\251\251\251\315\315\315\316\316\316\363\363\363" \ + "\377\377\377\332\332\332\316\316\316\301\301\301\235\235\237jjlFFH;;" \ + "=\207::<\1;;=\202::<\3;;=__a\363\363\363\227\377\377\377\4\234\234\236" \ + "99;::<;;=\205::<\3;;=::<\233\233\233\240\377\377\377\12\376\376\376\377" \ + "\377\377\301\301\301;;=::<;;=::<;;=::<99;\203::<\1\234\234\236\213\377" \ + "\377\377\3\177\236\263\0=i\0>i\211\0=i\7\1>j\0=i\1>j\0=i\0>g\3>h\2=g" \ + "\230\0=i\7\2=g\3>h\0>g\0=i\1>j\0=i\1>j\211\0=i\3\0>i\0=i\177\236\263" \ + "\206\377\377\377\2\317\317\317:::\221::<\202;;=\202::<\3;;=::<99;\203" \ + "::<\2;;=99;\220::<\1kkk\214\377\377\377\1\234\234\236\206::<\1\234\234" \ + "\236\213\377\377\377\3\376\376\376\377\377\377\363\363\363\204::<\4;" \ + ";=::<;;=xxz\202\377\377\377\1\376\376\376\236\377\377\377\1\376\376\376" \ + "\202\377\377\377\3\346\346\346::<;;=\202::<\4;;=99;;;=\266\266\270\215" \ + "\377\377\377\1kkm\203::<\1;;=\202::<\1;;=\243::<\1\316\316\316\204\377" \ + "\377\377\3\376\376\376\377\377\377\376\376\376\232\377\377\377\1\376" \ + "\376\376\204\377\377\377\1kkm\202;;=\202::<\202;;=\2::<;;=\204::<\3\317" \ + "\317\317\377\377\377\376\376\376\235\377\377\377\1\234\234\234\206::" \ + "<\1\234\234\234\243\377\377\377\1kkm\206::<\212\377\377\377\1\376\376" \ + "\376\224\377\377\377\1lln\203::<\1;;=\202::<\1\234\234\236\234\377\377" \ + "\377\1\376\376\376\204\377\377\377\4\376\376\376\265\265\267::<;;=\202" \ + "::<\1;;=\202::<\1;;=\203::<\5__a\266\266\270\363\363\363\377\377\377" \ + "\376\376\376\204\377\377\377\1\376\376\376\203\377\377\377\1\376\376" \ + "\376\202\377\377\377\4\301\301\303\204\204\206;;=::<\203;;=\202::<\2" \ + ";;=::<\202;;=\3GGI\332\332\334\376\376\376\203\377\377\377\1\376\376" \ + "\376\221\377\377\377\2\235\235\237::<\202;;=\202::<\1;;=\202::<\4""9" \ + "9;::<;;=\331\331\331\240\377\377\377\2\363\363\363GGI\203::<\2;;=::<" \ + "\203;;=\202::<\1\234\234\236\213\377\377\377\3\177\236\263\0=i\0>i\210" \ + "\0=i\10\0\77k\0=i\1>j\0>i\0\77j\0=i\0>i\0>j\230\0>i\10\0>j\0>i\0=i\0" \ + "\77j\0>i\1>j\0=i\0\77k\210\0=i\3\0>i\0=i\177\236\263\206\377\377\377" \ + "\1\376\376\376\217\377\377\377\1\376\376\376\203\377\377\377\1\315\315" \ + "\317\204::<\3;;=::i\211\0=i\202\0>i\5\0j\0=i\1>j" \ + "\0>i\230\0=i\5\0>i\1>j\0=i\1>j\0i\211\0=i\3\0>i\0=i\177\236" \ + "\263\212\377\377\377\3\376\376\376\377\377\377\376\376\376\212\377\377" \ + "\377\1\376\376\376\202\377\377\377\10\316\316\320::<;;=::<;;=99;::::<99;::<99;\202;;=\203::<\1" \ + "\234\234\236\213\377\377\377\3\177\236\263\0=i\0>i\210\0=i\7\2=g\0>i" \ + "\0>j\0\77j\0=i\0\77j\0=h\232\1>j\7\0=h\0\77j\0=i\0\77j\0>j\0>i\2=g\210" \ + "\0=i\3\0>i\0=i\177\236\263\213\377\377\377\1\376\376\376\216\377\377" \ + "\377\1\317\317\321\202::<\6;;=::<;;=::i\210\0=i\10\0\77j\0>j\0\77k\0=i\3>h\2=" \ + "g\1>j\0\77k\230\0=i\10\0\77k\1>j\2=g\3>h\0=i\0\77k\0>j\0\77j\210\0=i" \ + "\3\0>i\0=i\177\236\263\232\377\377\377\12\316\316\316;;=::<;;=::<;;=" \ + "::i\210\0=i\10\0>i\0=i\0>i\0\77k\0>j\2=g\1\77h\0>l\230\0>i\10\0>l\1\77" \ + "h\2=g\0>j\0\77k\0>i\0=i\0>i\210\0=i\3\0>i\0=i\177\236\263\205\377\377" \ + "\377\1\376\376\376\202\377\377\377\1\376\376\376\221\377\377\377\3\316" \ + "\316\316::<;;=\204::<\1kkm\225\377\377\377\202\376\376\376\211\377\377" \ + "\377\1\234\234\236\206::<\1\234\234\236\217\377\377\377\3\376\376\376" \ + "TTV99;\202::<\4""99;;;=::i\210\0=i\7\0>j\2=g\0>g\0>j\40V|o\224\256\177\236\262\232" \ + "\177\236\263\7\177\236\262o\224\256\40V|\0>j\0>g\2=g\0>j\210\0=i\3\0" \ + ">i\0=i\177\236\263\232\377\377\377\3\316\316\316::<;;=\203::<\2;;=kk" \ + "m\232\377\377\377\1\376\376\376\205\377\377\377\1\234\234\236\206::<" \ + "\1\234\234\236\220\377\377\377\2\233\233\235;;=\202::<\1<<>\203::<\1" \ + "\346\346\346\237\377\377\377\1\204\204\204\206::<\2SSU\376\376\376\217" \ + "\377\377\377\1kkm\203::<\4;;=::<;;=\316\316\320\304\377\377\377\1\376" \ + "\376\376\202\377\377\377\2\234\234\236;;=\202::<\4;;=::<;;=\234\234\234" \ + "\203\377\377\377\1\346\346\346\205::<\3;;=FFH\363\363\365\203\377\377" \ + "\377\1\376\376\376\230\377\377\377\1\234\234\234\206::<\1\234\234\234" \ + "\243\377\377\377\1kkm\206::<\237\377\377\377\1kkm\206::<\1\234\234\236" \ + "\235\377\377\377\2\316\316\316;;=\202::<\6;;=::<;;=::<:::\265\265\265" \ + "\237\377\377\377\7\376\376\376\363\363\363___::<;;=::<;;=\203::<\2GG" \ + "I\363\363\363\204\377\377\377\1\376\376\376\214\377\377\377\1\234\234" \ + "\234\203::<\202;;=\5::<\266\266\266GGI99;;;=\202::<\1;;=\202::<\1\332" \ + "\332\332\206\377\377\377\1\376\376\376\211\377\377\377\1\376\376\376" \ + "\207\377\377\377\2\363\363\363FFH\206::<\3FFH\301\301\30399;\202::<\202" \ + ";;=\2::<\234\234\236\206\377\377\377\7\377\377\375\377\377\377\377\377" \ + "\375\376\377\377\376\376\376\200\237\263\0\77i\211\0>i\7\0>g\1>j\0>g" \ + "_\210\236\377\377\377\376\377\377\377\376\377\231\377\377\377\10\377" \ + "\377\375\376\377\375\377\377\377\377\377\375`\210\242\3>h\0\77j\1\77" \ + "h\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316\316\206::<" \ + "\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236\220\377\377" \ + "\377\1\363\363\363\204::<\202;;=\2""99;\205\205\207\207\377\377\377\1" \ + "\376\376\376\224\377\377\377\4\376\376\376\377\377\377\363\363\363FF" \ + "H\202::<\5;;=99;;;=::<\265\265\265\220\377\377\377\1kkm\206::<\1\316" \ + "\316\316\305\377\377\377\5\376\376\376\364\364\364FFH::<;;=\202::<\4" \ + ";;=FFH\363\363\363\377\377\377\202\376\376\376\6\377\377\377xxz::<;;" \ + "=::<;;=\202::<\1\234\234\236\206\377\377\377\202\376\376\376\224\377" \ + "\377\377\1\234\234\234\206::<\1\234\234\234\243\377\377\377\1kkm\206" \ + "::<\237\377\377\377\1kkm\206::<\1\234\234\236\225\377\377\377\1\376\376" \ + "\376\207\377\377\377\2SSS;;=\202::<\1;;=\203::<\1\234\234\234\202\377" \ + "\377\377\3\376\376\376\377\377\377\376\376\376\232\377\377\377\1\376" \ + "\376\376\202\377\377\377\4\332\332\332FFH::<;;=\202::<\1;;=\202::<\1" \ + "\222\222\224\205\377\377\377\1\376\376\376\213\377\377\377\3\234\234" \ + "\234::<;;=\202::<\5""99;;;=\315\315\315\250\250\252;;=\206::<\2``b\376" \ + "\376\376\202\377\377\377\1\376\376\376\216\377\377\377\1\376\376\376" \ + "\205\377\377\377\2xxx;;=\202::<\1;;=\203::<\2\300\300\300\317\317\321" \ + "\203::<\1;;=\202::<\1\234\234\236\207\377\377\377\1\377\376\377\202\377" \ + "\377\377\4\377\376\377\201\235\263\0=j\3>j\210\0=i\5\1>j\0=j\37V\177" \ + "\377\376\377\376\376\376\202\377\377\377\1\376\377\377\230\377\377\377" \ + "\10\376\377\377\377\377\375\374\377\377\377\376\374\376\377\377#W\177" \ + "\0>g\0\77i\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316\316" \ + "\206::<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236\220\377" \ + "\377\377\2\376\376\376\204\204\206\205::<\3;;=FFH\362\362\362\204\377" \ + "\377\377\202\376\376\376\2\377\377\377\376\376\376\224\377\377\377\3" \ + "\376\376\376\265\265\265;;=\203::<\4;;=99;FFH\363\363\363\220\377\377" \ + "\377\1kkm\206::<\1\316\316\316\306\377\377\377\4\265\265\26599;;;=::" \ + "<\202;;=\2""99;\222\222\224\204\377\377\377\12\376\376\376\316\316\320" \ + ";;=::<;;=99;;;=99;SSU\376\376\376\202\377\377\377\3\376\376\376\377\377" \ + "\377\376\376\376\226\377\377\377\1\234\234\234\206::<\1\234\234\234\243" \ + "\377\377\377\1kkm\206::<\237\377\377\377\1kkm\206::<\1\234\234\236\234" \ + "\377\377\377\11\234\234\234::<;;=99;;;=99;::<;;=kkm\241\377\377\377\1" \ + "\376\376\376\202\377\377\377\1\301\301\303\203::<\6;;=99;::<;;=::<\346" \ + "\346\350\203\377\377\377\1\376\376\376\214\377\377\377\1\234\234\234" \ + "\203::<\202;;=\10""99;\316\316\316\377\377\377kkm::<;;=::<;;=\203::<" \ + "\1\235\235\237\203\377\377\377\1\376\376\376\214\377\377\377\1\376\376" \ + "\376\205\377\377\377\3\302\302\304::<;;=\202::<\7""99;;;=99;xxz\377\377" \ + "\377\315\315\315;;=\203::<\3:9>::<\234\234\236\206\377\377\377\3\376" \ + "\377\377\377\377\375\377\377\377\202\377\377\375\3|\237\265\0\77k\0>" \ + "g\210\0=i\10\0@h\3j\210\0=i\3\0>i\0=i\177" \ + "\236\263\232\377\377\377\1\316\316\316\206::<\1kkm\240\377\377\377\1" \ + "\234\234\236\206::<\1\234\234\236\215\377\377\377\1\376\376\376\203\377" \ + "\377\377\2\332\332\334;;=\206::<\2\266\266\266\376\376\376\202\377\377" \ + "\377\1\376\376\376\202\377\377\377\1\376\376\376\222\377\377\377\1\376" \ + "\376\376\203\377\377\377\1SSS\203::<\4""99;::<;;=\221\221\223\221\377" \ + "\377\377\1kkm\206::<\1\316\316\316\306\377\377\377\4RRT;;=::<;;=\202" \ + "::<\2;;=\345\345\345\202\377\377\377\1\376\376\376\203\377\377\377\2" \ + "__a;;=\202::<\1;;=\202::<\1\264\264\264\206\377\377\377\1\376\376\376" \ + "\224\377\377\377\1\234\234\234\206::<\1\234\234\234\243\377\377\377\1" \ + "kkm\206::<\237\377\377\377\1kkm\206::<\1\234\234\236\226\377\377\377" \ + "\1\376\376\376\204\377\377\377\2\363\363\363FFH\203::<\1;;=\202::<\2" \ + "FFH\346\346\346\204\377\377\377\1\376\376\376\233\377\377\377\1\376\376" \ + "\376\203\377\377\377\3\376\376\376xxz99;\202::<\1""99;\202::<\4;;=\204" \ + "\204\206\377\377\377\376\376\376\202\377\377\377\1\376\376\376\213\377" \ + "\377\377\1\234\234\234\202::<\10;;=99;;;=::<\317\317\317\376\376\376" \ + "\363\363\363GGI\203::<\1;;=\203::<\3\331\331\331\377\377\377\376\376" \ + "\376\202\377\377\377\1\376\376\376\217\377\377\377\5\363\363\363GGI;" \ + ";=::<;;=\202::<\7""99;FFH\363\363\363\377\377\377\316\316\316::<;;=\202" \ + "::<\3:9>::<\234\234\236\207\377\377\377\7\376\377\377\376\376\376\377" \ + "\377\377\377\377\375\377\377\377\377\375\374\376\377\377\210\377\377" \ + "\377\10\376\376\374\376\377\377\354\364\366\377\377\375\376\377\377\377" \ + "\376\374\377\377\375\376\377\377\230\377\377\377\10\377\377\375\376\377" \ + "\377\377\376\375\375\376\377\376\377\377\301\317\330\0>g\0>j\210\0=i" \ + "\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316\316\206::<\1kkm\240" \ + "\377\377\377\1\234\234\236\206::<\1\234\234\236\220\377\377\377\5\376" \ + "\376\376\377\377\377kkm::<;;=\202::<\3""99;::<^^`\204\377\377\377\1\376" \ + "\376\376\227\377\377\377\1\316\316\316\202::<\203;;=\202::<\1\347\347" \ + "\347\221\377\377\377\1kkm\206::<\1\316\316\316\303\377\377\377\12\376" \ + "\376\376\377\377\377\301\301\301;;=::<;;=::<99;::<\204\204\206\204\377" \ + "\377\377\4\376\376\376\377\377\377\376\376\376\266\266\266\202::<\5;" \ + ";=::<;;=::<``b\203\377\377\377\1\376\376\376\227\377\377\377\1\234\234" \ + "\234\206::<\1\234\234\234\243\377\377\377\1kkm\206::<\237\377\377\377" \ + "\1kkm\206::<\1\234\234\236\233\377\377\377\1\265\265\267\204::<\4""9" \ + "9;;;=::<\234\234\234\203\377\377\377\3\376\376\376\377\377\377\376\376" \ + "\376\231\377\377\377\5\376\376\376\377\377\377\376\376\376\377\377\377" \ + "\376\376\376\202\377\377\377\5\363\363\363GGI99;::<;;=\202::<\3;;=::" \ + "<\346\346\346\204\377\377\377\1\376\376\376\212\377\377\377\3\234\234" \ + "\234::<99;\202;;=\202::<\1\315\315\315\202\377\377\377\3\301\301\303" \ + ";;=99;\202;;=\5::<;;=::<``b\376\376\376\202\377\377\377\1\376\376\376" \ + "\215\377\377\377\6\376\376\376\377\377\377\376\376\376xxz::<;;=\203:" \ + ":<\202;;=\1\300\300\302\202\377\377\377\3\316\316\316;;=99;\202::<\3" \ + ";:\77::<\234\234\236\206\377\377\377\2\377\377\375\376\377\375\202\376" \ + "\377\377\4\377\377\375\377\377\377\377\376\377\377\377\375\211\377\377" \ + "\377\1\376\376\374\202\377\377\377\3\377\376\377\377\377\377\375\376" \ + "\377\231\377\377\377\202\376\377\377\5\377\376\377\376\377\377\377\377" \ + "\375\277\320\332\0\77j\211\0=i\3\0>i\0=i\177\236\263\232\377\377\377" \ + "\1\316\316\316\206::<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234" \ + "\234\236\213\377\377\377\3\376\376\376\377\377\377\376\376\376\204\377" \ + "\377\377\1\265\265\265\202::<\1;;=\204::<\1\315\315\317\204\377\377\377" \ + "\1\376\376\376\202\377\377\377\1\376\376\376\220\377\377\377\1\376\376" \ + "\376\202\377\377\377\3\204\204\204::<;;=\204::<\2yy{\376\376\376\221" \ + "\377\377\377\1kkm\206::<\1\316\316\316\305\377\377\377\4kkm;;=::<;;=" \ + "\203::<\1\316\316\316\210\377\377\377\1TTV\206::<\2\317\317\321\376\376" \ + "\376\231\377\377\377\1\234\234\234\206::<\1\234\234\234\243\377\377\377" \ + "\1kkm\206::<\237\377\377\377\1kkm\206::<\1\234\234\236\233\377\377\377" \ + "\1TTV\202::<\7;;=::<;;=::i\0=i\177\236\263\232\377\377" \ + "\377\1\316\316\316\206::<\1kkm\240\377\377\377\1\234\234\236\206::<\1" \ + "\234\234\236\221\377\377\377\4\376\376\376\377\377\377SSU;;=\202::<\4" \ + ";;=99;;;=\204\204\206\203\377\377\377\1\376\376\376\226\377\377\377\11" \ + "\363\363\36399;;;=::<;;=::<;;=::<\316\316\316\202\377\377\377\1\376\376" \ + "\376\217\377\377\377\1kkm\206::<\1\316\316\316\304\377\377\377\1\316" \ + "\316\316\206::<\1kkk\211\377\377\377\2\235\235\23599;\202;;=\6::<;;=" \ + "::99;\202::<\3;;" \ + "=::<\234\234\236\211\377\377\377\4\377\375\376\376\377\377\254\334\363" \ + "Z\266\347\211[\267\350\6\\\266\350X\267\347\326\354\367\377\376\377\376" \ + "\377\377\377\377\375\232\377\377\377\3\377\377\373\375\377\376\376\377" \ + "\377\202\377\377\375\3\276\320\336\0>g\0>i\210\0=i\3\0>i\0=i\177\236" \ + "\263\232\377\377\377\1\316\316\316\206::<\1kkm\240\377\377\377\1\234" \ + "\234\236\206::<\1\234\234\236\223\377\377\377\1\235\235\237\204::<\4" \ + "<<>::<;;=\363\363\363\206\377\377\377\1\376\376\376\222\377\377\377\2" \ + "\234\234\234;;=\205::<\1SSU\204\377\377\377\1\376\376\376\216\377\377" \ + "\377\1kkm\206::<\1\316\316\316\304\377\377\377\1\204\204\204\203::<\1" \ + "99;\202::<\1\265\265\265\211\377\377\377\2\363\363\363FFH\205::<\2;;" \ + "=\346\346\346\231\377\377\377\1\234\234\234\206::<\1\234\234\234\243" \ + "\377\377\377\1kkm\206::<\237\377\377\377\1kkm\206::<\1\234\234\236\232" \ + "\377\377\377\1\222\222\222\202::<\1;;=\202::<\3;;=FFH\362\362\364\251" \ + "\377\377\377\1\235\235\235\203::<\7;;=::<;;=;;;\331\331\331\377\377\377" \ + "\376\376\376\214\377\377\377\2\234\234\234;;=\205::<\1\316\316\316\202" \ + "\377\377\377\3\376\376\376\377\377\377\301\301\301\205::<\4;;=::<__a" \ + "\376\376\376\216\377\377\377\4\376\376\376yyy::<;;=\205::<\1\316\316" \ + "\320\204\377\377\377\2\316\316\31699;\203::<\3""99;::<\234\234\236\207" \ + "\377\377\377\2\376\377\377\376\376\374\202\377\376\377\3\254\332\362" \ + "Y\267\352[\267\350\210Y\270\350\7[\267\350Y\267\352\326\356\370\376\376" \ + "\377\377\376\377\377\375\377\376\377\377\231\377\377\377\10\377\377\375" \ + "\376\377\377\377\377\377\377\376\377\377\377\375\276\317\331\1>j\0>j" \ + "\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316\316\206::<\1" \ + "kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236\220\377\377\377" \ + "\1\376\376\376\202\377\377\377\4\363\363\365;;=::<;;=\204::<\1\234\234" \ + "\234\231\377\377\377\1SSS\202::<\1;;=\203::<\1\265\265\267\223\377\377" \ + "\377\1kkm\206::<\1\316\316\316\300\377\377\377\1\376\376\376\202\377" \ + "\377\377\1\346\346\350\203::<\4;;=::<;;=SSU\213\377\377\377\1\204\204" \ + "\204\203::<\1;;=\202::<\1\204\204\206\202\377\377\377\1\376\376\376\226" \ + "\377\377\377\1\234\234\234\206::<\1\234\234\234\243\377\377\377\1kkm" \ + "\206::<\237\377\377\377\1kkm\206::<\1\234\234\236\227\377\377\377\1\376" \ + "\376\376\202\377\377\377\3TTV::<;;=\203::<\2;;=\205\205\205\252\377\377" \ + "\377\1\347\347\347\202::<\202;;=\203::<\1\235\235\237\204\377\377\377" \ + "\1\376\376\376\211\377\377\377\1\234\234\234\206::<\1\316\316\316\205" \ + "\377\377\377\1\205\205\205\202::<\6;;=::<;;=::<;;=\234\234\236\213\377" \ + "\377\377\1\376\376\376\202\377\377\377\1\302\302\302\202;;=\203::<\3" \ + ";;=::<\221\221\221\202\377\377\377\1\376\376\376\202\377\377\377\1\316" \ + "\316\316\206::<\1\234\234\236\213\377\377\377\2\255\333\363Y\270\350" \ + "\211[\267\350\3Y\270\350[\267\350\326\354\371\242\377\377\377\3\276\317" \ + "\331\0=i\0>i\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316" \ + "\316\206::<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236\224" \ + "\377\377\377\4\204\204\204;;=::<;;=\203::<\1TTT\204\377\377\377\1\376" \ + "\376\376\223\377\377\377\1\300\300\300\203::<\5;;=::<;;=FFF\363\363\363" \ + "\223\377\377\377\1kkm\203::<\4;;=::<;;=\316\316\320\277\377\377\377\14" \ + "\376\376\376\377\377\377\376\376\376\377\377\377\204\204\206::<;;=::" \ + "<99;<<>99;\265\265\267\213\377\377\377\3\346\346\346::<;;=\202::<\1;" \ + ";=\202::<\2\347\347\347\376\376\376\227\377\377\377\1\234\234\234\206" \ + "::<\1\234\234\234\243\377\377\377\1kkm\206::<\237\377\377\377\1kkm\206" \ + "::<\1\234\234\236\226\377\377\377\4\376\376\376\377\377\377\376\376\376" \ + "\346\346\350\202;;=\203::<\3""99;<<>\301\301\301\253\377\377\377\1aa" \ + "c\202::<\1;;=\202::<\2;;=jjl\205\377\377\377\1\376\376\376\210\377\377" \ + "\377\1\234\234\234\206::<\1\316\316\316\202\377\377\377\1\376\376\376" \ + "\202\377\377\377\3\362\362\362SSU;;=\205::<\2;;=\332\332\332\210\377" \ + "\377\377\1\376\376\376\203\377\377\377\2\363\363\363FFH\202::<\202;;" \ + "=\5::<;;=SSS\363\363\363\376\376\376\204\377\377\377\1\316\316\316\206" \ + "::<\1\234\234\236\213\377\377\377\2\255\333\363Y\270\350\211[\267\350" \ + "\3Y\270\350[\267\350\326\354\371\242\377\377\377\3\276\317\331\0=i\0" \ + ">i\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316\316\206::" \ + "<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236\224\377\377" \ + "\377\1\332\332\332\207::<\1\301\301\301\227\377\377\377\1lll\204::<\3" \ + ";;=::<\221\221\221\202\377\377\377\3\376\376\376\377\377\377\376\376" \ + "\376\217\377\377\377\1kkm\204::<\3;;=99;\316\316\316\241\377\377\377" \ + "\1\376\376\376\234\377\377\377\10\376\376\376\377\377\377\376\376\376" \ + "\377\377\377\363\363\363FFH;;=::<\202;;=\3::i\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316" \ + "\316\316\206::<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236" \ + "\225\377\377\377\1__a\204;;=\5""99;::99;\202::<\4;;=::<;;=\331\331\331\215\377\377\377\1\234\234\234" \ + "\206::<\1\316\316\316\207\377\377\377\1\222\222\224\202::<\3;;=99;<<" \ + ">\202::<\4\234\234\236\376\376\376\377\377\377\376\376\376\203\377\377" \ + "\377\1\376\376\376\203\377\377\377\6\302\302\304;;=99;;;=::<;;=\202:" \ + ":<\1\234\234\234\202\377\377\377\1\376\376\376\204\377\377\377\1\316" \ + "\316\316\206::<\1\234\234\236\213\377\377\377\2\255\333\363Y\270\350" \ + "\211[\267\350\3Y\270\350[\267\350\326\354\371\242\377\377\377\3\276\317" \ + "\331\0=i\0>i\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316" \ + "\316\206::<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236\225" \ + "\377\377\377\2\265\265\265;;=\202::<\2""99;;;=\202::<\2\347\347\347\376" \ + "\376\376\215\377\377\377\3\376\376\376\377\377\377\376\376\376\204\377" \ + "\377\377\3\221\221\223;;=99;\204::<\3xxz\377\377\377\376\376\376\202" \ + "\377\377\377\202\376\376\376\217\377\377\377\1kkm\202::<\5;;=99;;;=9" \ + "9;\317\317\317\233\377\377\377\1\376\376\376\237\377\377\377\1\376\376" \ + "\376\204\377\377\377\3\376\376\376\377\377\377GGI\202::<\5;;=::<;;=:" \ + ":<\346\346\346\213\377\377\377\1\376\376\376\202\377\377\377\2``b99;" \ + "\202;;=\203::<\3\247\247\247\377\377\377\376\376\376\225\377\377\377" \ + "\1\234\234\234\206::<\1\234\234\234\243\377\377\377\1kkm\206::<\237\377" \ + "\377\377\1kkm\206::<\1\234\234\236\231\377\377\377\10kkm::<;;=::<;;=" \ + "99;::<\235\235\237\255\377\377\377\202::<\1;;=\204::<\1\301\301\301\215" \ + "\377\377\377\1\234\234\234\206::<\1\316\316\316\206\377\377\377\5\376" \ + "\376\376\364\364\364TTV::<99;\202;;=\203::<\4\332\332\334\376\376\376" \ + "\377\377\377\376\376\376\203\377\377\377\6\376\376\376\377\377\377\363" \ + "\363\363FFH::<;;=\204::<\1__a\210\377\377\377\1\316\316\316\206::<\1" \ + "\234\234\236\213\377\377\377\2\255\333\363Y\270\350\211[\267\350\3Y\270" \ + "\350[\267\350\326\354\371\242\377\377\377\3\276\317\331\0=i\0>i\210\0" \ + "=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316\316\206::<\1kkm\240" \ + "\377\377\377\1\234\234\236\206::<\1\234\234\236\224\377\377\377\5\376" \ + "\376\376\377\377\377GGI::<;;=\203::<\4;;=\220\220\222\377\377\377\376" \ + "\376\376\214\377\377\377\1\376\376\376\203\377\377\377\10\376\376\376" \ + "\377\377\377\363\363\363FFH::<;;=99;;;=\202::<\1\316\316\320\202\377" \ + "\377\377\1\376\376\376\204\377\377\377\1\376\376\376\215\377\377\377" \ + "\1kkm\206::<\1\316\316\316\277\377\377\377\3\376\376\376\377\377\377" \ + "\265\265\267\204::<\3;;=::<\205\205\205\213\377\377\377\1\376\376\376" \ + "\202\377\377\377\2\376\376\376\265\265\265\202::<\5""99;<<>::<;;=SSU" \ + "\202\377\377\377\1\376\376\376\224\377\377\377\1\234\234\234\206::<\1" \ + "\234\234\234\243\377\377\377\1kkm\206::<\237\377\377\377\1kkm\206::<" \ + "\1\234\234\236\230\377\377\377\2\376\376\376SSU\204::<\3;;=::<\266\266" \ + "\266\253\377\377\377\3\376\376\376\377\377\377^^`\206::<\1\234\234\234" \ + "\202\377\377\377\1\376\376\376\212\377\377\377\1\234\234\234\206::<\1" \ + "\316\316\316\205\377\377\377\6\376\376\376\377\377\377\376\376\376\315" \ + "\315\317::<;;=\202::<\4;;=99;::<``b\210\377\377\377\4xxz99;<<>::<\202" \ + ";;=\202::<\1\332\332\332\203\377\377\377\1\376\376\376\204\377\377\377" \ + "\1\316\316\316\206::<\1\234\234\236\213\377\377\377\2\255\333\363Y\270" \ + "\350\211[\267\350\3Y\270\350[\267\350\326\354\371\242\377\377\377\3\276" \ + "\317\331\0=i\0>i\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316" \ + "\316\316\206::<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236" \ + "\226\377\377\377\1\234\234\234\206::<\2FFH\376\376\376\214\377\377\377" \ + "\1\376\376\376\202\377\377\377\1\376\376\376\203\377\377\377\3\265\265" \ + "\265;;=99;\202;;=\202::<\1SSU\202\377\377\377\1\376\376\376\223\377\377" \ + "\377\1kkm\203::<\4""99;::<;;=\316\316\320\275\377\377\377\202\376\376" \ + "\376\4\377\377\377\376\376\376SSU;;=\202::<\4;;=::<;;=\332\332\332\215" \ + "\377\377\377\5\376\376\376\377\377\377\376\376\376SSU;;=\204::<\2;;=" \ + "\264\264\264\226\377\377\377\1\234\234\234\206::<\1\234\234\234\243\377" \ + "\377\377\1kkm\206::<\237\377\377\377\1kkm\206::<\1\234\234\236\231\377" \ + "\377\377\207::<\1\316\316\316\254\377\377\377\2\376\376\376lln\202::" \ + "<\1;;=\202::<\4;;=\233\233\233\377\377\377\376\376\376\202\377\377\377" \ + "\1\376\376\376\210\377\377\377\1\234\234\234\206::<\1\316\316\316\203" \ + "\377\377\377\202\376\376\376\204\377\377\377\1\234\234\234\207::<\1\234" \ + "\234\236\205\377\377\377\4\376\376\376\300\300\302::<;;=\205::<\2\234" \ + "\234\234\376\376\376\202\377\377\377\1\376\376\376\205\377\377\377\1" \ + "\316\316\316\206::<\1\234\234\236\213\377\377\377\2\255\333\363Y\270" \ + "\350\211[\267\350\3Y\270\350[\267\350\326\354\371\242\377\377\377\3\276" \ + "\317\331\0=i\0>i\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316" \ + "\316\316\206::<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236" \ + "\226\377\377\377\1\347\347\347\204::<\5;;=99;;;=\265\265\265\376\376" \ + "\376\222\377\377\377\2___99;\202::<\4;;=::<;;=\265\265\265\207\377\377" \ + "\377\1\376\376\376\216\377\377\377\1kkm\203::<\1;;=\202::<\1;;=\233:" \ + ":<\5""99;;;=::<:::\234\234\234\240\377\377\377\2\316\316\316;;=\204:" \ + ":<\2;;=kkm\221\377\377\377\1\234\234\236\203::<\1;;=\202::<\3kkk\377" \ + "\377\377\376\376\376\224\377\377\377\1\234\234\234\206::<\1\234\234\234" \ + "\243\377\377\377\1kkm\206::<\237\377\377\377\1kkm\206::<\1\234\234\236" \ + "\231\377\377\377\207::<\1\316\316\316\255\377\377\377\2\221\221\221;" \ + ";=\205::<\1\204\204\204\203\377\377\377\1\376\376\376\211\377\377\377" \ + "\1\234\234\234\206::<\1\316\316\316\210\377\377\377\3\376\376\376\377" \ + "\377\377``b\202::<\7;;=::<;;=::<;;=\332\332\332\376\376\376\202\377\377" \ + "\377\3\376\376\376\363\363\363GGI\203::<\4;;=::<;;=__a\206\377\377\377" \ + "\1\376\376\376\203\377\377\377\1\316\316\316\206::<\1\234\234\236\213" \ + "\377\377\377\2\255\333\363Y\270\350\211[\267\350\3Y\270\350[\267\350" \ + "\326\354\371\242\377\377\377\3\276\317\331\0=i\0>i\210\0=i\3\0>i\0=i" \ + "\177\236\263\232\377\377\377\1\316\316\316\206::<\1kkm\240\377\377\377" \ + "\1\234\234\236\206::<\1\234\234\236\227\377\377\377\1\204\204\206\204" \ + "::<\3;;=::i\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316\316" \ + "\206::<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236\227\377" \ + "\377\377\1\315\315\315\205::<\3;;=::<\332\332\334\221\377\377\377\1\204" \ + "\204\206\205::<\2;;=\205\205\205\227\377\377\377\1kkm\203::<\3;;=::<" \ + ";;=\234::<\1:9>\203::<\1\234\234\236\237\377\377\377\1\331\331\331\202" \ + ";;=\204::<\1SSU\217\377\377\377\5\376\376\376\377\377\377\376\376\376" \ + "\377\377\377\204\204\204\204::<\3;;=99;yyy\203\377\377\377\1\376\376" \ + "\376\221\377\377\377\1\234\234\234\206::<\1\234\234\234\235\377\377\377" \ + "\1\376\376\376\205\377\377\377\1kkm\206::<\237\377\377\377\1kkm\206:" \ + ":<\1\234\234\236\231\377\377\377\203::<\1;;=\203::<\202\377\377\377\1" \ + "\376\376\376\253\377\377\377\2\233\233\235;;=\205::<\3kkm\377\377\377" \ + "\376\376\376\202\377\377\377\1\376\376\376\210\377\377\377\1\234\234" \ + "\234\206::<\1\316\316\316\213\377\377\377\1\234\234\236\202;;=\1""99" \ + ";\203::<\5;;=\235\235\235\377\377\377\376\376\376\302\302\302\207::<" \ + "\1\251\251\251\213\377\377\377\1\316\316\316\206::<\1\234\234\236\213" \ + "\377\377\377\2\255\333\363Y\270\350\211[\267\350\3Y\270\350[\267\350" \ + "\326\354\371\242\377\377\377\3\276\317\331\0=i\0>i\210\0=i\3\0>i\0=i" \ + "\177\236\263\232\377\377\377\1\316\316\316\206::<\1kkm\240\377\377\377" \ + "\1\234\234\236\206::<\1\234\234\236\223\377\377\377\1\376\376\376\204" \ + "\377\377\377\1^^`\202::<\202;;=\3::<<<>\204\204\206\213\377\377\377\1" \ + "\376\376\376\204\377\377\377\1\363\363\363\205::<\3;;=::<\346\346\346" \ + "\227\377\377\377\1kkm\204::<\3;;=::<;;=\234::<\1;;=\202::<\1\234\234" \ + "\236\237\377\377\377\4\204\204\20499;::<;;=\203::<\3\266\266\270\377" \ + "\377\377\376\376\376\221\377\377\377\5\346\346\346;;=::<;;=::<\202;;" \ + "=\4::<\346\346\350\377\377\377\376\376\376\202\377\377\377\1\376\376" \ + "\376\217\377\377\377\1\234\234\234\206::<\1\234\234\234\237\377\377\377" \ + "\202\376\376\376\202\377\377\377\1kkm\206::<\237\377\377\377\1kkm\206" \ + "::<\1\234\234\236\224\377\377\377\6\376\376\376\377\377\377\376\376\376" \ + "\377\377\377\376\376\376;;=\206::<\1\331\331\331\255\377\377\377\1\234" \ + "\234\236\202::<\1;;=\203::<\2kkm\376\376\376\202\377\377\377\1\376\376" \ + "\376\211\377\377\377\1\234\234\234\206::<\1\316\316\316\212\377\377\377" \ + "\3\376\376\376\377\377\377___\204::<\7;;=99;::<\332\332\332\363\363\365" \ + "FFH;;=\204::<\3;;=kkm\376\376\376\213\377\377\377\1\316\316\316\206:" \ + ":<\1\234\234\236\213\377\377\377\2\255\333\363Y\270\350\211[\267\350" \ + "\3Y\270\350[\267\350\326\354\371\242\377\377\377\3\276\317\331\0=i\0" \ + ">i\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316\316\206::" \ + "<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236\224\377\377" \ + "\377\1\376\376\376\203\377\377\377\4\265\265\267::<;;=::<\202;;=\3::" \ + "i\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316\316\206" \ + "::<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236\231\377\377" \ + "\377\10FFH::<;;=99;;;=::<;;=\265\265\265\216\377\377\377\4\376\376\376" \ + "TTV99;;;=\202::<\202;;=\1\301\301\301\230\377\377\377\1kkm\202::<\1;" \ + ";=\204::<\3;;=::<;;=\232::<\5;;=::<\234\234\234\377\377\377\376\376\376" \ + "\232\377\377\377\3\376\376\376\377\377\377\221\221\221\202::<\1""99;" \ + "\203::<\5\234\234\236\377\377\377\376\376\376\377\377\377\376\376\376" \ + "\216\377\377\377\1\376\376\376\202\377\377\377\2\316\316\320::<\202;" \ + ";=\204::<\2\363\363\363\376\376\376\202\377\377\377\1\376\376\376\217" \ + "\377\377\377\1\234\234\234\206::<\1\234\234\234\243\377\377\377\1kkm" \ + "\206::<\237\377\377\377\1kkm\206::<\1\234\234\236\224\377\377\377\1\376" \ + "\376\376\204\377\377\377\1""99;\202::<\1;;=\203::<\1\316\316\316\252" \ + "\377\377\377\10\376\376\376\377\377\377\376\376\376kkm;;=::<;;=99;\202" \ + "::<\1\234\234\236\215\377\377\377\1\234\234\234\206::<\1\316\316\316" \ + "\215\377\377\377\5\247\247\247;;=99;::<;;=\210::<\5""99;::<\250\250\252" \ + "\377\377\377\376\376\376\213\377\377\377\1\316\316\316\206::<\1\234\234" \ + "\236\213\377\377\377\2\255\333\363Y\270\350\211[\267\350\3Y\270\350[" \ + "\267\350\326\354\371\242\377\377\377\3\276\317\331\0=i\0>i\210\0=i\3" \ + "\0>i\0=i\177\236\263\232\377\377\377\1\316\316\316\206::<\1kkm\240\377" \ + "\377\377\1\234\234\236\206::<\1\234\234\236\223\377\377\377\3\376\376" \ + "\376\377\377\377\376\376\376\203\377\377\377\1\234\234\236\202::<\1;" \ + ";=\202::<\2""99;SSU\214\377\377\377\5\376\376\376\377\377\377\301\301" \ + "\301;;=<<>\202::<\3;;=::i\210\0=i\3\0>i\0=i\177\236\263" \ + "\232\377\377\377\1\316\316\316\206::<\1kkm\240\377\377\377\1\234\234" \ + "\236\206::<\1\234\234\236\224\377\377\377\1\376\376\376\204\377\377\377" \ + "\2\346\346\34699;\202::<\2;;=::<\202;;=\1\315\315\315\212\377\377\377" \ + "\1\376\376\376\202\377\377\377\1yy{\203::<\4;;=99;;;=\250\250\250\202" \ + "\377\377\377\1\376\376\376\226\377\377\377\1kkm\206::<\1\317\317\317" \ + "\240\377\377\377\1\376\376\376\234\377\377\377\1\234\234\234\202::<\2" \ + "99;;;=\202::<\1\204\204\206\203\377\377\377\1\376\376\376\220\377\377" \ + "\377\1\376\376\376\202\377\377\377\2\264\264\264::<\202;;=\203::<\3G" \ + "GI\364\364\364\376\376\376\202\377\377\377\1\376\376\376\216\377\377" \ + "\377\1\234\234\234\206::<\1\234\234\234\241\377\377\377\3\376\376\376" \ + "\377\377\377kkm\206::<\237\377\377\377\1kkm\206::<\1\234\234\236\225" \ + "\377\377\377\202\376\376\376\202\377\377\377\12kkm::<;;=99;::<;;=::<" \ + "\204\204\204\377\377\377\376\376\376\251\377\377\377\4\376\376\376\377" \ + "\377\377::<99;\202;;=\203::<\1\316\316\320\215\377\377\377\1\234\234" \ + "\234\206::<\1\316\316\316\216\377\377\377\5\346\346\350GGI;;=::<;;=\202" \ + "::<\2""99;;;=\202::<\3;;=GGI\346\346\350\216\377\377\377\1\316\316\316" \ + "\206::<\1\234\234\236\213\377\377\377\2\255\333\363Y\270\350\211[\267" \ + "\350\3Y\270\350[\267\350\326\354\371\242\377\377\377\3\276\317\331\0" \ + "=i\0>i\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316\316\206" \ + "::<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236\231\377\377" \ + "\377\2\376\376\376\205\205\205\202::<\5""99;;;=::<;;=\205\205\207\213" \ + "\377\377\377\12\376\376\376\346\346\346::<;;=99;::<99;;;=FFH\363\363" \ + "\363\231\377\377\377\1kkm\202::<\2;;=::<\202;;=\3\316\316\316\377\377" \ + "\377\376\376\376\234\377\377\377\1\376\376\376\236\377\377\377\1SSS\204" \ + "::<\3;;=99;\347\347\351\204\377\377\377\1\376\376\376\215\377\377\377" \ + "\1\376\376\376\205\377\377\377\1SSU\203::<\4;;=99;::<\265\265\265\202" \ + "\377\377\377\1\376\376\376\217\377\377\377\1\234\234\234\206::<\1\234" \ + "\234\234\242\377\377\377\2\376\376\376SSU\206::<\237\377\377\377\1kk" \ + "m\206::<\1\234\234\236\231\377\377\377\4\221\221\223;;=::<;;=\202::<" \ + "\3;;=___\376\376\376\253\377\377\377\1\332\332\332\204::<\1;;=\202::" \ + "<\1\346\346\350\203\377\377\377\1\376\376\376\211\377\377\377\1\234\234" \ + "\234\206::<\1\316\316\316\217\377\377\377\1\250\250\252\204::<\202;;" \ + "=\2::<;;=\202::<\1\265\265\267\217\377\377\377\1\316\316\316\206::<\1" \ + "\234\234\236\213\377\377\377\2\255\333\363Y\270\350\211[\267\350\3Y\270" \ + "\350[\267\350\326\354\371\242\377\377\377\3\276\317\331\0=i\0>i\210\0" \ + "=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316\316\206::<\1kkm\240" \ + "\377\377\377\1\234\234\236\206::<\1\234\234\236\232\377\377\377\1\316" \ + "\316\316\203::<\2""99;<<>\202::<\1\346\346\350\213\377\377\377\4\221" \ + "\221\223;;=::<;;=\203::<\1\204\204\206\232\377\377\377\1kkm\203::<\1" \ + ";;=\202::<\1\316\316\316\274\377\377\377\2\265\265\267;;=\205::<\1xx" \ + "x\231\377\377\377\1\250\250\250\206::<\1TTV\222\377\377\377\1\234\234" \ + "\234\204::<\3;;=::<\235\235\235\203\377\377\377\1\376\376\376\237\377" \ + "\377\377\202;;=\203::<\3;;=::<\376\376\376\236\377\377\377\1kkm\206:" \ + ":<\1\234\234\236\225\377\377\377\1\376\376\376\203\377\377\377\1\265" \ + "\265\267\204::<\1;;=\202::<\1\363\363\363\253\377\377\377\1\250\250\250" \ + "\204::<\3;;=::j\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316\316" \ + "\206::<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236\233\377" \ + "\377\377\1``b\205::<\2;;=\235\235\237\210\377\377\377\1\376\376\376\202" \ + "\377\377\377\2FFH;;=\205::<\1\346\346\346\202\377\377\377\1\376\376\376" \ + "\227\377\377\377\1kkm\206::<\1\316\316\316\266\377\377\377\1\376\376" \ + "\376\205\377\377\377\5__a::<;;=::<;;=\202::<\1SSU\202kkm\1lln\203kkm" \ + "\1lln\222kkm\4__a;;=99;;;=\204::<\3\301\301\301\377\377\377\376\376\376" \ + "\215\377\377\377\202\376\376\376\1\235\235\235\204::<\3""99;;;=\221\221" \ + "\221\243\377\377\377\203::<\1;;=\202::<\1""99;\237\377\377\377\1kkm\206" \ + "::<\1\234\234\236\231\377\377\377\1\332\332\332\202::<\3;;=::<99;\202" \ + ";;=\1\264\264\264\210\377\377\377\1\376\376\376\232\377\377\377\1\376" \ + "\376\376\206\377\377\377\2\376\376\376xxx\202::<\1;;=\203::<\1xxz\216" \ + "\377\377\377\1\234\234\234\206::<\1\316\316\316\220\377\377\377\3\363" \ + "\363\365FFH;;=\202::<\1;;=\202::<\2FFH\363\363\363\220\377\377\377\1" \ + "\316\316\316\206::<\1\234\234\236\213\377\377\377\2\255\333\363Y\270" \ + "\350\211[\267\350\10X\267\347Y\267\352\326\354\371\377\377\377\376\376" \ + "\376\377\376\377\377\377\377\377\376\377\234\377\377\377\2\376\376\374" \ + "\277\320\330\212\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316" \ + "\316\206::<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236\233" \ + "\377\377\377\1\265\265\267\203::<\4""99;;;=::9" \ + "9;::<;;=::<99;\203::<\2;;=99;\202::<\1;;=\224::<\1;;=\202::<\1;;=\203" \ + "::<\1kkm\203\377\377\377\1\376\376\376\215\377\377\377\1\300\300\300" \ + "\202::<\11;;=::<99;;;=jjl\377\377\377\376\376\376\377\377\377\376\376" \ + "\376\236\377\377\377\1\346\346\350\206::<\1__a\237\377\377\377\1kkm\206" \ + "::<\1\234\234\236\231\377\377\377\2\376\376\376SSU\206::<\2yy{\376\376" \ + "\376\206\377\377\377\1\376\376\376\234\377\377\377\1\376\376\376\205" \ + "\377\377\377\4\363\363\363::<<<>99;\202::<\3;;=::<\265\265\267\203\377" \ + "\377\377\3\376\376\376\377\377\377\376\376\376\210\377\377\377\1\234" \ + "\234\234\206::<\1\316\316\316\221\377\377\377\4\301\301\30199;::<;;=" \ + "\202::<\6;;=\301\301\301\377\377\377\376\376\376\377\377\377\376\376" \ + "\376\215\377\377\377\1\316\316\316\206::<\1\234\234\236\213\377\377\377" \ + "\2\255\333\363Y\270\350\211[\267\350\6Y\270\350Y\267\352\325\353\370" \ + "\377\377\377\376\377\375\377\375\377\234\377\377\377\5\376\376\376\377" \ + "\377\377\377\377\375\276\317\327\2\77k\211\0=i\3\0>i\0=i\177\236\263" \ + "\232\377\377\377\1\316\316\316\206::<\1kkm\240\377\377\377\1\234\234" \ + "\236\206::<\1\234\234\236\234\377\377\377\1GGI\203::<\1;;=\202::<\2\301" \ + "\301\301\376\376\376\204\377\377\377\1\376\376\376\203\377\377\377\3" \ + "lln::<;;=\202::<\202;;=\4\301\301\303\376\376\376\377\377\377\376\376" \ + "\376\230\377\377\377\1kkm\206::<\1\316\316\316\265\377\377\377\1\376" \ + "\376\376\205\377\377\377\3kkm::<;;=\202::<\2""99;<<>\202::<\3;;=::<;" \ + ";=\202::<\1;;=\222::<\4""99;;;=::<;;=\203::<\1;;=\202::<\3\316\316\316" \ + "\377\377\377\376\376\376\215\377\377\377\3\376\376\376\316\316\316;;" \ + "=\203::<\3;;=::\204::<\3\346" \ + "\346\346\377\377\377\376\376\376\202\377\377\377\1\376\376\376\211\377" \ + "\377\377\1\234\234\234\206::<\1\316\316\316\220\377\377\377\14\376\376" \ + "\376\377\377\377yy{::<99;;;=::j\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316" \ + "\316\206::<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236\234" \ + "\377\377\377\1\234\234\234\206::<\3jjj\377\377\377\376\376\376\204\377" \ + "\377\377\4\376\376\376\377\377\377\332\332\33299;\203::<\3;;=::j\210\0=i\3\0>i\0=i\177" \ + "\236\263\232\377\377\377\1\316\316\316\206::<\1kkm\240\377\377\377\1" \ + "\234\234\236\206::<\1\234\234\236\233\377\377\377\2\376\376\376\347\347" \ + "\347\202::<\2;;=::<\203;;=\1\346\346\346\207\377\377\377\5\204\204\204" \ + "<<>99;::<;;=\202::<\2\251\251\251\376\376\376\205\377\377\377\1\376\376" \ + "\376\225\377\377\377\1kkm\206::<\1\316\316\316\264\377\377\377\1\376" \ + "\376\376\205\377\377\377\3\204\204\206::<;;=\203::<\1;;=\205::<\1;;=" \ + "\225::<\3;;=::<;;=\202::<\1;;=\202::<\1;;=\202::<\1\347\347\347\220\377" \ + "\377\377\2SSU;;=\203::<\3;;=::<\265\265\265\237\377\377\377\7\376\376" \ + "\376\377\377\377lln99;::<;;=99;\202::<\1\265\265\267\237\377\377\377" \ + "\1kkm\206::<\1\234\234\236\225\377\377\377\1\376\376\376\204\377\377" \ + "\377\3\376\376\376SSU;;=\204::<\3;;=FFH\346\346\346\202\377\377\377\1" \ + "\376\376\376\237\377\377\377\1\376\376\376\204\377\377\377\2\265\265" \ + "\267;;=\202::<\1;;=\203::<\1\265\265\265\217\377\377\377\1\234\234\234" \ + "\206::<\1\316\316\316\223\377\377\377\4\301\301\301::<:::\302\302\302" \ + "\223\377\377\377\1\316\316\316\206::<\1\234\234\236\213\377\377\377\2" \ + "\255\333\363Y\270\350\212[\267\350\2Y\270\350\332\354\370\202\377\377" \ + "\377\3\376\376\376\376\377\377\377\376\373\235\377\377\377\1\276\317" \ + "\331\202\0>i\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316" \ + "\316\206::<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236\235" \ + "\377\377\377\1\204\204\204\206::<\1\221\221\223\206\377\377\377\2\363" \ + "\363\363GGI\202::<\5""99;;;=::i\210\0=i\3\0>i\0=i\177\236" \ + "\263\232\377\377\377\1\316\316\316\206::<\1kkm\240\377\377\377\1\234" \ + "\234\236\206::<\1\234\234\236\235\377\377\377\1\316\316\316\206::<\1" \ + "FFH\203\377\377\377\1\376\376\376\202\377\377\377\1\250\250\250\203:" \ + ":<\1;;=\202::<\1\204\204\206\203\377\377\377\1\376\376\376\231\377\377" \ + "\377\1kkm\206::<\1\316\316\316\271\377\377\377\1\234\234\236\204::<\4" \ + ";;=::j\0>i\210\0=i\3\0>i\0=i\177\236\263\232" \ + "\377\377\377\1\316\316\316\206::<\1kkm\240\377\377\377\1\234\234\236" \ + "\206::<\1\234\234\236\236\377\377\377\2__a;;=\204::<\5;;=\265\265\265" \ + "\376\376\376\377\377\377\376\376\376\202\377\377\377\1SSU\204::<\3;;" \ + "=::<\346\346\350\235\377\377\377\1kkm\206::<\1\316\316\316\270\377\377" \ + "\377\2\363\363\365GGI\205::<\3;;=\333\333\333\376\376\376\237\377\377" \ + "\377\10FFH::<;;=::<;;=99;;;=\233\233\235\217\377\377\377\5\346\346\346" \ + "::<;;=::<;;=\203::<\1\234\234\234\210\377\377\377\1\376\376\376\217\377" \ + "\377\377\1\376\376\376\206\377\377\377\1TTT\205::<\3;;=\221\221\221\376" \ + "\376\376\237\377\377\377\1kkm\206::<\1\234\234\236\234\377\377\377\12" \ + "\233\233\233::<;;=::<;;=::<;;=::l\0\77j\210\0=i\3\0>i\0=" \ + "i\177\236\263\232\377\377\377\1\316\316\316\206::<\1kkm\240\377\377\377" \ + "\1\234\234\236\206::<\1\234\234\236\236\377\377\377\1\265\265\265\204" \ + "::<\3;;=::<__a\204\377\377\377\1\317\317\321\206::<\1kkk\236\377\377" \ + "\377\1kkm\206::<\1\316\316\316\267\377\377\377\3\376\376\376\250\250" \ + "\25299;\202;;=\203::<\1kkm\233\377\377\377\1\376\376\376\205\377\377" \ + "\377\10\234\234\236;;=::<;;=::<;;=99;GGI\204\377\377\377\3\376\376\376" \ + "\377\377\377\376\376\376\210\377\377\377\5\376\376\376__a::<;;=99;\203" \ + ";;=\2FFH\363\363\363\204\377\377\377\3\376\376\376\377\377\377\376\376" \ + "\376\224\377\377\377\5\376\376\376\377\377\377\301\301\301:::;;=\202" \ + "::<\202;;=\4::<\332\332\332\377\377\377\376\376\376\236\377\377\377\1" \ + "kkm\206::<\1\234\234\236\233\377\377\377\3\376\376\376\364\364\364FF" \ + "H\205::<\4;;=99;xxx\376\376\376\203\377\377\377\1\376\376\376\203\377" \ + "\377\377\1\376\376\376\202\377\377\377\1\376\376\376\224\377\377\377" \ + "\4\376\376\376\377\377\377\362\362\362GGI\202::<\6;;=::<;;=::<99;\250" \ + "\250\252\221\377\377\377\1\234\234\234\206::<\1\316\316\316\252\377\377" \ + "\377\1\316\316\316\206::<\1\234\234\236\213\377\377\377\2\255\333\363" \ + "Y\270\350\211[\267\350\7Y\267\352X\267\347[\266\353\301\344\367\377\377" \ + "\377\376\376\376\376\377\377\211\377\377\377\6\377\376\377\377\377\377" \ + "\377\375\376\377\377\377\377\377\375\377\376\377\202\377\377\377\210" \ + "\377\376\377\10\377\377\375\376\377\377\377\377\377\376\377\375\237\266" \ + "\306\0=i\2=g\0>e\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316" \ + "\316\316\206::<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236" \ + "\237\377\377\377\1EEG\202::<\202;;=\11""99;;;=\332\332\332\377\377\377" \ + "\376\376\376\377\377\377xxz::<;;=\204::<\1\302\302\302\236\377\377\377" \ + "\1kkm\206::<\1\316\316\316\266\377\377\377\4\376\376\376\377\377\377" \ + "SSU;;=\202::<\1;;=\202::<\1\316\316\320\235\377\377\377\15\376\376\376" \ + "\377\377\377\376\376\376\377\377\377\363\363\365::<;;=99;;;=::<;;=::" \ + "<\265\265\265\215\377\377\377\3\376\376\376\377\377\377\266\266\270\202" \ + "::<\1;;=\203::<\2;;=\204\204\206\205\377\377\377\3\376\376\376\377\377" \ + "\377\376\376\376\213\377\377\377\1\376\376\376\205\377\377\377\1\376" \ + "\376\376\202\377\377\377\2\363\363\363SSU\203::<\4;;=99;;;=SSU\241\377" \ + "\377\377\1kkm\206::<\1\234\234\236\235\377\377\377\3\265\265\265;;=9" \ + "9;\202::<\1;;=\203::<\1\204\204\206\206\377\377\377\1\376\376\376\216" \ + "\377\377\377\3\376\376\376\377\377\377\376\376\376\206\377\377\377\6" \ + "\376\376\376\377\377\377\362\362\364``b::<;;=\202::<\1;;=\202::<\2aa" \ + "c\376\376\376\221\377\377\377\1\234\234\234\206::<\1\316\316\316\252" \ + "\377\377\377\1\316\316\316\206::<\1\234\234\236\213\377\377\377\2\255" \ + "\333\363Y\270\350\211[\267\350\10X\267\347[\267\346[\265\347[\267\346" \ + "\230\320\361\327\360\367\325\356\365\331\355\370\210\326\354\371\10\325" \ + "\355\367\323\355\372\366\373\377\377\376\374\376\377\375\276\320\332" \ + "\277\320\330\301\317\330\210\276\317\331\10\276\317\327\276\320\334\301" \ + "\316\327_\207\241\0>i\0=l\0\77k\0>i\210\0=i\3\0>i\0=i\177\236\263\232" \ + "\377\377\377\1\316\316\316\206::<\1kkm\240\377\377\377\1\234\234\236" \ + "\206::<\1\234\234\236\237\377\377\377\3\222\222\224::<;;=\202::<\3;;" \ + "=99;\205\205\207\202\377\377\377\2\346\346\346;;=\202::<\1;;=\202::<" \ + "\1SSU\237\377\377\377\1kkm\206::<\1\316\316\316\267\377\377\377\5\265" \ + "\265\26799;;;=::<;;=\202::<\1TTV\243\377\377\377\1\204\204\206\205::" \ + "<\2;;=SSU\206\377\377\377\1\376\376\376\210\377\377\377\3\376\376\376" \ + "GGI;;=\202::<\5;;=::<;;=::<\301\301\303\203\377\377\377\1\376\376\376" \ + "\214\377\377\377\1\376\376\376\202\377\377\377\1\376\376\376\202\377" \ + "\377\377\1\376\376\376\204\377\377\377\3\204\204\206;;=::<\202;;=\203" \ + "::<\1\265\265\265\241\377\377\377\1kkm\206::<\1\234\234\236\236\377\377" \ + "\377\12kkk::<99;;;=::<99;;;=::<;;=\204\204\206\210\377\377\377\202\376" \ + "\376\376\213\377\377\377\1\376\376\376\202\377\377\377\1\376\376\376" \ + "\202\377\377\377\1\376\376\376\202\377\377\377\2\364\364\366__a\206:" \ + ":<\3;;=::<\332\332\332\222\377\377\377\1\234\234\234\206::<\1\316\316" \ + "\316\252\377\377\377\1\316\316\316\206::<\1\234\234\236\213\377\377\377" \ + "\2\255\333\363Y\270\350\211[\267\350\3\\\266\350X\270\352\\\266\352\202" \ + "[\267\350\3X\267\347Y\270\350Z\266\347\210Y\270\350\10[\267\350[\265" \ + "\351\327\355\372\376\377\377\377\377\375\0>j\0>i\1\77h\210\0>i\10\0\77" \ + "k\0>g\2=g\0=i\0\77j\0j\210\0=i\3\0>i\0=i\177\236\263\232\377" \ + "\377\377\1\316\316\316\206::<\1kkm\240\377\377\377\1\234\234\236\206" \ + "::<\1\234\234\236\236\377\377\377\2\376\376\376\346\346\346\202::<\10" \ + ";;=::<99;;;=::<\363\363\363\377\377\377\234\234\236\202::<\6;;=::<;;" \ + "=::<\250\250\250\376\376\376\236\377\377\377\1kkm\206::<\1\316\316\316" \ + "\267\377\377\377\10kkm;;=::<;;=99;::<;;=\264\264\266\236\377\377\377" \ + "\1\376\376\376\204\377\377\377\2\346\346\346;;=\202::<\202;;=\202::<" \ + "\2\316\316\320\376\376\376\203\377\377\377\1\376\376\376\205\377\377" \ + "\377\3\376\376\376\377\377\377\376\376\376\202\377\377\377\3\234\234" \ + "\234::<;;=\202::<\6;;=::<;;=GGI\332\332\332\376\376\376\224\377\377\377" \ + "\1\376\376\376\203\377\377\377\2\266\266\266;;=\202::<\6;;=::<;;=::<" \ + "SSU\376\376\376\241\377\377\377\1kkm\206::<\1\234\234\236\236\377\377" \ + "\377\2\363\363\363GGI\203::<\1;;=\203::<\3""99;\204\204\204\363\363\363" \ + "\225\377\377\377\1\376\376\376\204\377\377\377\4\376\376\376\346\346" \ + "\346``b::<\202;;=\3::<99;<<>\202::<\1\250\250\250\223\377\377\377\1\234" \ + "\234\234\206::<\1\316\316\316\252\377\377\377\1\316\316\316\206::<\1" \ + "\234\234\236\213\377\377\377\2\255\333\363Y\270\350\211[\267\350\10Y" \ + "\270\350X\270\353Y\267\352X\266\351X\271\346[\267\350\\\266\353[\267" \ + "\350\210Y\270\350\7X\267\345]\267\351\323\355\372\377\376\377\376\377" \ + "\377\4=h\0>g\211\0=i\10\2=i\0@j\0>i\1>j\0>i\1\77h\0>g\0>j\210\0=i\3\0" \ + ">i\0=i\177\236\263\232\377\377\377\1\316\316\316\206::<\1kkm\240\377" \ + "\377\377\1\234\234\236\206::<\1\234\234\236\237\377\377\377\6\376\376" \ + "\376yy{::<;;=::<;;=\202::<\4\251\251\251\376\376\376SSU;;=\203::<\3;" \ + ";=FFH\363\363\363\237\377\377\377\1kkm\206::<\1\316\316\316\264\377\377" \ + "\377\5\376\376\376\377\377\377\315\315\317::<;;=\204::<\2FFH\376\376" \ + "\376\237\377\377\377\1\376\376\376\203\377\377\377\3\376\376\376kkm;" \ + ";=\204::<\6""99;lln\377\377\377\376\376\376\377\377\377\376\376\376\202" \ + "\377\377\377\3\376\376\376\377\377\377\376\376\376\205\377\377\377\10" \ + "\376\376\376\377\377\377SSU::<99;;;=99;;;=\202::<\2FFF\332\332\332\203" \ + "\377\377\377\1\376\376\376\212\377\377\377\1\376\376\376\210\377\377" \ + "\377\1\265\265\265\206::<\3""99;::<\265\265\265\203\377\377\377\1\376" \ + "\376\376\236\377\377\377\1kkm\206::<\1\234\234\236\233\377\377\377\1" \ + "\376\376\376\203\377\377\377\1\331\331\331\204::<\3""99;;;=99;\202;;" \ + "=\2^^^\332\332\332\202\377\377\377\1\376\376\376\216\377\377\377\1\376" \ + "\376\376\206\377\377\377\5\376\376\376\316\316\316FFH::<;;=\204::<\7" \ + "99;::<\204\204\204\377\377\377\376\376\376\377\377\377\376\376\376\220" \ + "\377\377\377\1\234\234\234\206::<\1\316\316\316\252\377\377\377\1\316" \ + "\316\316\206::<\1\234\234\236\213\377\377\377\2\255\333\363Y\270\350" \ + "\213[\267\350\6Y\270\350[\266\353[\267\350]\267\351X\266\351X\270\350" \ + "\210[\267\350\10X\266\351Z\266\351\326\354\367\377\376\377\376\377\372" \ + "\0>j\0>i\1>j\210\0=i\10\1\77h\0=h\0>i\1\77h\0>j\0=i\0>i\1>j\210\0=i\3" \ + "\0>i\0=i\177\236\263\232\377\377\377\1\316\316\316\206::<\1kkm\240\377" \ + "\377\377\1\234\234\236\206::<\1\234\234\236\237\377\377\377\2\376\376" \ + "\376\316\316\316\203::<\1;;=\202::<\4SSU\265\265\267;;=99;\202::<\5;" \ + ";=99;\204\204\204\377\377\377\376\376\376\236\377\377\377\1kkm\206::" \ + "<\1\316\316\316\263\377\377\377\1\376\376\376\202\377\377\377\1xxz\202" \ + "::<\1;;=\202::<\3""99;\234\234\236\376\376\376\236\377\377\377\1\375" \ + "\375\375\202\377\377\377\1\376\376\376\202\377\377\377\5\317\317\317" \ + "99;::<;;=::<\202;;=\2::<\332\332\332\210\377\377\377\3\376\376\376\377" \ + "\377\377\376\376\376\204\377\377\377\2\316\316\316;;=\206::<\3;;=::<" \ + "\250\250\252\217\377\377\377\1\376\376\376\204\377\377\377\2\363\363" \ + "\363\222\222\224\202::<\2;;=::<\202;;=\3""99;;;=kkm\205\377\377\377\1" \ + "\376\376\376\235\377\377\377\1kkm\206::<\1\234\234\236\235\377\377\377" \ + "\1\376\376\376\202\377\377\377\2\266\266\26699;\202::<\3;;=::<;;=\202" \ + "::<\3;;=FFH\234\234\234\202\377\377\377\1\376\376\376\223\377\377\377" \ + "\2\364\364\364\204\204\206\202::<\1;;=\202::<\1;;=\202::<\3""99;``b\376" \ + "\376\376\224\377\377\377\1\234\234\234\206::<\1\316\316\316\252\377\377" \ + "\377\1\316\316\316\206::<\1\234\234\236\213\377\377\377\2\255\333\363" \ + "Y\270\350\211[\267\350\10Y\271\353Z\266\347\\\267\344[\267\346X\267\347" \ + "[\267\350X\270\353Z\266\347\210Y\270\350\10Y\267\352\\\267\346\325\355" \ + "\371\377\377\377\376\377\377\0>g\0\77k\0>i\210\0\77j\10\0>i\3>h\0=i\0" \ + "\77i\0=j\0>g\0=j\0=f\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1" \ + "\316\316\316\206::<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234" \ + "\236\234\377\377\377\3\376\376\376\377\377\377\376\376\376\202\377\377" \ + "\377\2SSU;;=\202::<\202;;=\3::j\0=i\1>j\210\0>i\10\0\77j\1\77h\0>j\0>g\3>j\0\77i\0=j\0>i\210" \ + "\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316\316\206::<\1kkm" \ + "\240\377\377\377\1\234\234\236\206::<\1\234\234\236\241\377\377\377\6" \ + "\266\266\270::<;;=::<99;::<\202;;=\205::<\2kkm\376\376\376\240\377\377" \ + "\377\1kkm\206::<\1\316\316\316\265\377\377\377\4\205\205\205;;=::<;;" \ + "=\203::<\3\204\204\206\377\377\377\376\376\376\245\377\377\377\1\265" \ + "\265\267\207::<\2\346\346\346\376\376\376\216\377\377\377\4\376\376\376" \ + "lll::<;;=\202::<\13;;=::<;;=::<;;=::g\1\1>k\220\0=i\15\0>g\1>j\0>" \ + "i\0\77j\1>j\0=i\0\77j\0>j\0=i\199;\203::<\1;;=\202::<\2""99;;;=\203::<\1\204\204\206" \ + "\206\377\377\377\1\376\376\376\221\377\377\377\10\234\234\234;;=::<9" \ + "9;;;=::<99;\316\316\316\252\377\377\377\4\317\317\317;;=88:;;=\202::" \ + "<\3;;=\234\234\234\376\376\376\205\377\377\377\1\377\375\377\202\377" \ + "\377\375\6\377\376\377\377\377\375\253\333\362Y\270\350X\267\347Z\266" \ + "\347\202Y\270\350\1[\267\350\202Z\266\347\2[\267\350Z\266\347\220[\267" \ + "\350\5[\267\352Z\266\351\327\355\372\377\375\376\377\376\377\202\1>j" \ + "\1\1>k\220\0>i\202\0=i\14\0\77k\0>i\0=i\1>j\0=i\0=j\0\77k\0=i\177\236" \ + "\263\377\377\377\376\377\377\375\376\377\224\377\377\377\1\376\376\376" \ + "\202\377\377\377\1\316\316\316\203::<\202;;=\3""99;kkm\376\376\376\234" \ + "\377\377\377\1\376\376\376\202\377\377\377\1\233\233\233\202::<\7;;=" \ + "::<;;=::<\234\234\236\377\377\377\376\376\376\233\377\377\377\3\376\376" \ + "\376\377\377\377\376\376\376\202\377\377\377\4\221\221\221;;=99;;;=\202" \ + "::<\202;;=\203::<\1SSU\203\377\377\377\1\376\376\376\233\377\377\377" \ + "\10\376\376\376\377\377\377\376\376\376kkm::<;;=::<;;=\202::<\1;;=\202" \ + "::<\1;;=\240::<\1kkk\207\377\377\377\1\376\376\376\203\377\377\377\3" \ + "\375\375\375\377\377\377\376\376\376\202\377\377\377\2\233\233\235::" \ + "<\202;;=\203::<\1xxz\251\377\377\377\1\235\235\237\202::<\1;;=\203::" \ + "<\3GGI\363\363\363\376\376\376\217\377\377\377\2\363\363\363yyy\204:" \ + ":<\1;;=\203::<\1;;=\206::<\1""99;\203::<\1;;=\203::<\6;;=99;;;=::<;;" \ + "=99;\202;;=\3""99;GGI\301\301\301\206\377\377\377\1\376\376\376\232\377" \ + "\377\377\1\376\376\376\204\377\377\377\1lln\202::<\1;;=\202::<\2;;=\234" \ + "\234\236\241\377\377\377\1\376\376\376\202\377\377\377\2\332\332\334" \ + "__a\211::<\1;;=\205::<\1;;=\202::<\1;;=\202::<\4;;=::<99;;;=\202::<\1" \ + ";;=\202::<\1;;=\203::<\2FFH\265\265\267\206\377\377\377\3\376\376\376" \ + "\377\377\377\376\376\376\220\377\377\377\3\234\234\236::<;;=\203::<\2" \ + ";;=\316\316\316\252\377\377\377\2\315\315\31599;\203::<\5;;=::<\234\234" \ + "\234\377\377\377\376\376\376\205\377\377\377\7\377\377\375\375\377\376" \ + "\377\377\377\375\376\377\255\333\365Z\266\345[\267\350\202Y\270\350\1" \ + "X\267\347\202Y\267\352\3Z\266\351Z\266\347Y\270\350\221[\267\350\2[\267" \ + "\352\323\355\372\202\376\377\377\1\0=j\222\0=i\204\0>i\14\1\77h\0>g\0" \ + "=f\1>j\0\77i\0>i\177\237\266\377\377\375\377\376\375\377\377\377\376" \ + "\377\377\377\376\377\225\377\377\377\2\316\316\316::<\202;;=\202::<\4" \ + ";;=kkm\377\377\377\376\376\376\235\377\377\377\2\376\376\376\235\235" \ + "\235\202::<\1;;=\202::<\2;;=\234\234\236\242\377\377\377\3\346\346\346" \ + "::<;;=\210::<\2\235\235\237\376\376\376\234\377\377\377\1\376\376\376" \ + "\204\377\377\377\1lln\202::<\3;;=::<;;=\203::<\2;;=99;\240::<\1kkk\210" \ + "\377\377\377\11\376\376\376\377\377\377\376\376\376\377\377\377\376\376" \ + "\376\377\377\377\376\376\376\364\364\366GGI\205::<\6;;=\316\316\316\377" \ + "\377\377\376\376\376\377\377\377\376\376\376\245\377\377\377\11\345\345" \ + "\345;;=::<;;=::<;;=::<;;=\234\234\236\222\377\377\377\7\234\234\234;" \ + ";=::<;;=99;;;=99;\203::<\1;;=\202::<\203;;=\2::<;;=\202::<\1;;=\202:" \ + ":<\1;;=\202::<\12;;=::<;;=99;::<``b\332\332\332\376\376\376\377\377\377" \ + "\376\376\376\202\377\377\377\5\376\376\376\377\377\377\376\376\376\377" \ + "\377\377\376\376\376\232\377\377\377\5\376\376\376\377\377\377\376\376" \ + "\376kkm;;=\202::<\1;;=\202::<\1\234\234\236\236\377\377\377\1\376\376" \ + "\376\207\377\377\377\2\234\234\236;;=\202::<\1;;=\204::<\1;;=\211::<" \ + "\1;;=\202::<\1;;=\202::<\1;;=\202::<\1;;=\203::<\3;;=kkm\346\346\346" \ + "\203\377\377\377\1\376\376\376\204\377\377\377\1\376\376\376\221\377" \ + "\377\377\2\234\234\236;;=\202::<\1;;=\202::<\1\316\316\316\252\377\377" \ + "\377\4\316\316\316;;=99;;;=\203::<\1\234\234\234\210\377\377\377\7\376" \ + "\377\377\377\375\376\377\377\375\256\332\363Y\270\350Y\267\352[\267\352" \ + "\202[\267\350\5X\270\350X\270\352Y\267\352Y\270\350X\267\347\220[\267" \ + "\350\5X\267\347[\267\350\325\355\367\377\377\373\377\377\375\202\0\77" \ + "j\1\0>g\220\0>i\1\0\77j\203\0>i\202\0=i\6\1>j\0>i\0\77h\0>g\177\236\263" \ + "\377\377\375\203\377\377\377\1\377\376\377\222\377\377\377\1\376\376" \ + "\376\202\377\377\377\1\316\316\316\203::<\1;;=\202::<\2kkm\376\376\376" \ + "\233\377\377\377\1\376\376\376\203\377\377\377\5\234\234\234::<;;=::" \ + "<;;=\202::<\1\234\234\236\235\377\377\377\202\376\376\376\202\377\377" \ + "\377\5\376\376\376\377\377\377xxz99;;;=\204::<\4;;=::<;;=\362\362\362" \ + "\237\377\377\377\5\376\376\376\377\377\377\376\376\376kkm;;=\207::<\2" \ + "99;;;=\240::<\1lll\205\377\377\377\1\376\376\376\203\377\377\377\1\376" \ + "\376\376\202\377\377\377\1\376\376\376\202\377\377\377\4\265\265\267" \ + ";;=::<;;=\202::<\2;;=__a\205\377\377\377\1\376\376\376\245\377\377\377" \ + "\3\204\204\206::<;;=\204::<\2SSU\376\376\376\215\377\377\377\1\376\376" \ + "\376\204\377\377\377\2\316\316\316__a\206::<\1;;=\214::<\5;;=::<;;=:" \ + ":<;;=\203::<\2\234\234\234\363\363\363\204\377\377\377\1\376\376\376" \ + "\243\377\377\377\1lln\206::<\2\233\233\235\376\376\376\233\377\377\377" \ + "\1\376\376\376\202\377\377\377\1\376\376\376\207\377\377\377\3\345\345" \ + "\345lln;;=\204::<\5;;=99;::<99;;;=\205::<\1;;=\203::<\3""99;;;=99;\206" \ + "::<\2TTV\265\265\265\234\377\377\377\10\234\234\234;;=::<;;=::<;;=::" \ + "<\316\316\316\252\377\377\377\1\315\315\315\206::<\4\235\235\235\376" \ + "\376\376\377\377\377\376\376\376\205\377\377\377\12\377\377\373\377\377" \ + "\377\377\377\375\267\340\366[\270\344Z\266\351[\267\352Z\266\351[\265" \ + "\347[\267\350\202Y\270\350\2\\\270\351Z\266\347\220[\267\350\10X\267" \ + "\347X\266\351\325\355\371\377\376\377\377\377\377\0\77k\0=h\3>j\220\0" \ + "\77j\16\1>j\0=i\1>j\0=i\0\77j\0>i\0=h\0\77j\0\77h\1g\0\77h\221\0=i\1\0>g\202\1\77h\1\0=i\202\0>i\11\0\77j\0>g\0>" \ + "j\0\77m\336\347\354\376\377\377\377\376\377\376\377\377\377\377\375\222" \ + "\377\377\377\1\376\376\376\203\377\377\377\1\316\316\316\202::<\1;;=" \ + "\203::<\2kkm\376\376\376\233\377\377\377\1\376\376\376\202\377\377\377" \ + "\3\376\376\376\234\234\234;;=\202::<\6""99;::<;;=\234\234\236\377\377" \ + "\377\376\376\376\237\377\377\377\1\376\376\376\202\377\377\377\1SSS\202" \ + ";;=\1""99;\204;;=\3\331\331\331\377\377\377\376\376\376\234\377\377\377" \ + "\3\376\376\376\377\377\377\376\376\376\202\377\377\377\3lll::<;;=\202" \ + "::<\202;;=\203::<\1;;=\240::<\1kkk\204\377\377\377\1\376\376\376\211" \ + "\377\377\377\3\302\302\302;;;999\202::<\3;;=::g\0" \ + "\77m\220\0=i\6\0\77j\0>i\0=h\0\77j\0=i\0\77j\202\0>g\2\1\77h\240\266" \ + "\304\204\377\377\377\2\376\376\376\377\377\375\223\377\377\377\14\376" \ + "\376\376\377\377\377\315\315\315;;=::<:::;;;:::;;;kkk\377\377\377\376" \ + "\376\376\233\377\377\377\1\376\376\376\202\377\377\377\10\235\235\235" \ + "99;::<999;;;:::;;;\233\233\233\234\377\377\377\1\376\376\376\207\377" \ + "\377\377\1\265\265\265\202::<\1;;=\203::<\1kkk\203\377\377\377\1\376" \ + "\376\376\240\377\377\377\2kkk:::\202::<\3;;=99;;;=\244::<\1kkk\205\377" \ + "\377\377\1\376\376\376\210\377\377\377\1\346\346\346\206\316\316\316" \ + "\3\332\332\332\377\377\377\377\377\375\253\377\377\377\2\346\346\346" \ + "\316\316\316\202\316\316\320\203\316\316\316\1\315\315\315\225\377\377" \ + "\377\202\376\376\376\202\377\377\377\4\316\316\320\234\234\236kkmSSU" \ + "\205::<\1;;=\203::<\5kkm\204\204\206\264\264\266\346\346\350\376\376" \ + "\376\214\377\377\377\1\376\376\376\202\377\377\377\202\376\376\376\231" \ + "\377\377\377\1\376\376\376\203\377\377\377\2\331\331\331\317\317\317" \ + "\205\316\316\316\1\347\347\347\243\377\377\377\1\376\376\376\211\377" \ + "\377\377\5\376\376\377\347\347\351\265\265\267\204\204\206lln\212::<" \ + "\4``bxxz\234\234\236\332\332\332\207\377\377\377\1\376\376\376\210\377" \ + "\377\377\1\376\376\376\222\377\377\377\1\346\346\346\203\316\316\320" \ + "\4\316\316\316\316\316\320\315\315\315\364\364\364\251\377\377\377\2" \ + "\376\376\376\364\364\364\205\316\316\316\2\316\316\320\346\346\346\210" \ + "\377\377\377\16\377\376\377\377\377\375\376\377\377\377\377\377\377\375" \ + "\377\326\354\371\241\326\366\206\310\352\200\312\357\202\312\362\204" \ + "\310\357\204\312\356\203\311\355\205\311\360\220\204\312\356\10\203\311" \ + "\355\201\311\361\342\360\371\376\377\377\377\377\375>n\222Bm\215@n\220" \ + "\220@n\217\3@l\217An\217Bo\220\202An\217\5@m\214Dm\213l\223\260\277\320" \ + "\332\376\377\377\202\377\377\377\1\377\377\375\202\377\377\377\1\376" \ + "\377\377\225\377\377\377\3\363\363\363\317\317\321\316\316\320\204\316" \ + "\316\316\1\332\332\332\240\377\377\377\1\346\346\346\202\316\316\320" \ + "\204\316\316\316\1\347\347\347\243\377\377\377\3\376\376\376\363\363" \ + "\363lln\202kkm\1lln\202kkm\1\301\301\301\240\377\377\377\1\376\376\376" \ + "\203\377\377\377\2\331\331\331\317\317\317\202\316\316\316\202\317\317" \ + "\317\245\316\316\316\2\332\332\332\376\376\376\351\377\377\377\5\332" \ + "\332\332\315\315\315\316\316\316\315\315\315\363\363\363\361\377\377" \ + "\377\202\316\316\316\1\317\317\317\202\316\316\316\2\315\315\315\363" \ + "\363\363\377\377\377\377\377\377\377\377\377\377\377\377\334\377\377" \ + "\377\1\376\376\376\375\377\377\377\1\376\376\376\377\377\377\377\377" \ + "\377\377\377\377\377\377\377\340\377\377\377\1\376\376\376\370\377\377" \ + "\377\1\376\376\376\377\377\377\377\377\377\377\377\377\377\377\377\342" \ + "\377\377\377\1\376\376\376\377\377\377\377\377\377\377\377\377\377\377" \ + "\377\377\377\377\377\334\377\377\377\1\376\376\376\362\377\377\377\1" \ + "\376\376\376\377\377\377\377\377\377\377\377\377\377\377\377\346\377" \ + "\377\377\1\376\376\376\363\377\377\377\1\376\376\376\377\377\377\377" \ + "\377\377\377\377\377\377\377\377\342\377\377\377\1\376\376\376\373\377" \ + "\377\377\1\376\376\376\377\377\377\377\377\377\377\377\377\377\377\377" \ + "\340\377\377\377\3\376\376\376\377\377\377\376\376\376\377\377\377\377" \ + "\377\377\377\377\377\377\377\377\377\377\377\377\243\377\377\377\3\376" \ + "\376\376\377\377\377\376\376\376\203\377\377\377\1\376\376\376\233\377" \ + "\377\377\1\376\376\376\205\377\377\377\1\376\376\376\214\377\377\377" \ + "\1\376\376\376\205\377\377\377\1\376\376\376\260\377\377\377\3\376\376" \ + "\376\377\377\377\376\376\376\300\377\377\377\1\376\376\376\306\377\377" \ + "\377\1\376\376\376\233\377\377\377\4\376\377\377\376\376\376\377\376" \ + "\377\377\377\377\203\376\377\375\203\377\377\377\3\377\377\375\376\377" \ + "\375\376\377\377\265\377\377\377\4\377\377\375\377\376\377\376\377\377" \ + "\377\377\375\202\377\376\377\210\377\377\377\7\377\377\375\376\377\377" \ + "\377\377\377\375\377\376\376\377\377\377\376\377\376\377\377\211\377" \ + "\377\377\4\376\377\375\377\377\377\376\376\376\377\377\375\202\377\377" \ + "\377\2\377\377\375\376\376\376\220\377\377\377\1\376\377\375\202\377" \ + "\377\375\5\377\376\377\377\377\373\377\377\377\375\377\376\377\377\375" \ + "\210\377\377\377\1\377\376\377\202\377\377\375\202\377\377\377\3\376" \ + "\377\377\377\377\375\377\376\377\213\377\377\377\3\376\377\377\376\377" \ + "\375\377\377\375\203\377\377\377\203\376\377\375\4\377\377\377\377\376" \ + "\377\376\376\376\376\377\377\233\377\377\377\3\376\377\377\376\377\375" \ + "\377\377\375\203\377\377\377\203\376\377\375\4\377\377\377\377\376\377" \ + "\376\376\376\376\377\377\210\377\377\377\1\377\376\377\203\377\377\377" \ + "\4\376\377\377\377\377\375\377\376\377\376\377\373\211\377\377\377\4" \ + "\376\377\377\376\376\374\377\376\377\377\375\376\226\377\377\377\5\376" \ + "\377\377\375\377\374\377\377\375\376\375\377\377\377\375\210\377\377" \ + "\377\1\377\377\375\202\376\377\377\1\377\377\373\242\377\377\377\1\376" \ + "\376\376\212\377\377\377\1\376\376\376\207\377\377\377\1\376\376\376" \ + "\237\377\377\377\1\376\376\376\203\377\377\377\1\376\376\376\214\377" \ + "\377\377\1\376\376\376\204\377\377\377\202\376\376\376\257\377\377\377" \ + "\1\376\376\376\202\377\377\377\1\376\376\376\202\377\377\377\1\376\376" \ + "\376\246\377\377\377\1\376\376\376\224\377\377\377\1\376\376\376\250" \ + "\377\377\377\1\376\376\376\202\377\377\377\1\376\376\376\236\377\377" \ + "\377\3\376\376\376\377\377\377\376\376\376\230\377\377\377\4\377\377" \ + "\373\376\377\377\376\376\376\377\376\377\203\377\377\377\1\377\377\375" \ + "\202\377\377\377\1\377\376\377\202\377\377\375\3\377\377\377\377\377" \ + "\375\376\376\374\260\377\377\377\2\377\377\375\376\376\376\203\377\376" \ + "\377\214\377\377\377\7\376\377\377\377\376\377\377\377\375\377\377\377" \ + "\377\376\377\375\377\376\377\377\375\210\377\377\377\7\377\376\374\377" \ + "\377\375\377\376\377\377\377\375\376\376\376\377\377\377\376\376\376" \ + "\221\377\377\377\1\377\376\377\203\377\377\377\202\377\377\375\212\377" \ + "\377\377\2\377\377\375\377\377\377\202\377\377\375\214\377\377\377\3" \ + "\376\376\374\377\377\375\377\377\377\202\377\377\375\1\377\376\377\202" \ + "\377\377\377\1\377\377\375\203\377\377\377\4\377\376\377\376\376\376" \ + "\376\377\377\377\377\373\230\377\377\377\3\376\376\374\377\377\375\377" \ + "\377\377\202\377\377\375\1\377\376\377\202\377\377\377\1\377\377\375" \ + "\203\377\377\377\4\377\376\377\376\376\376\376\377\377\377\377\373\213" \ + "\377\377\377\1\377\376\374\214\377\377\377\2\377\377\375\377\376\377" \ + "\202\377\377\375\3\376\377\377\377\377\377\377\377\373\221\377\377\377" \ + "\3\376\377\375\376\377\377\377\376\377\204\377\377\377\1\377\377\375" \ + "\212\377\377\377\5\377\376\377\377\377\375\377\377\377\376\377\375\376" \ + "\377\373\243\377\377\377\1\376\376\376\205\377\377\377\1\376\376\376" \ + "\204\377\377\377\1\376\376\376\242\377\377\377\1\376\376\376\205\377" \ + "\377\377\1\376\376\376\213\377\377\377\1\376\376\376\206\377\377\377" \ + "\1\376\376\376\263\377\377\377\3\376\376\376\377\377\377\376\376\376" \ + "\270\377\377\377\1\376\376\376\312\377\377\377\1\376\376\376\234\377" \ + "\377\377\1\377\377\375\202\376\377\377\7\377\376\377\377\377\377\376" \ + "\377\377\377\376\377\377\377\375\377\377\377\376\377\377\202\377\376" \ + "\377\2\376\377\375\376\377\377\262\377\377\377\10\377\377\375\376\377" \ + "\377\377\376\377\377\377\373\377\377\377\377\376\377\376\377\375\377" \ + "\377\375\211\377\377\377\3\376\377\377\377\376\377\377\377\375\202\377" \ + "\377\377\2\376\377\377\376\376\376\210\377\377\377\202\377\376\377\4" \ + "\374\377\377\376\377\377\377\376\377\377\377\375\222\377\377\377\4\377" \ + "\376\375\376\377\377\377\377\377\376\377\377\202\377\376\377\202\377" \ + "\377\375\210\377\377\377\4\377\377\375\377\377\377\377\377\375\377\377" \ + "\377\202\377\376\377\2\377\377\377\376\377\377\212\377\377\377\2\376" \ + "\377\377\376\377\375\202\377\376\377\7\376\377\377\377\377\377\377\377" \ + "\375\377\376\377\376\377\377\377\377\377\377\376\377\202\376\377\377" \ + "\1\377\377\375\232\377\377\377\2\376\377\377\376\377\375\202\377\376" \ + "\377\7\376\377\377\377\377\377\377\377\375\377\376\377\376\377\377\377" \ + "\377\377\377\376\377\202\376\377\377\1\377\377\375\210\377\377\377\1" \ + "\377\377\375\202\377\377\377\4\377\377\375\377\376\377\377\377\377\376" \ + "\377\377\211\377\377\377\7\375\376\377\377\377\375\377\376\377\376\376" \ + "\377\376\377\375\375\377\376\377\377\375\222\377\377\377\6\376\377\377" \ + "\377\376\377\377\377\377\377\377\375\377\376\377\376\377\377\213\377" \ + "\377\377\202\377\376\377\3\377\377\375\376\377\377\376\377\375\236\377" \ + "\377\377\1\376\376\376\203\377\377\377\1\376\376\376\202\377\377\377" \ + "\1\376\376\376\203\377\377\377\2\376\376\376\377\377\377\202\376\376" \ + "\376\202\377\377\377\1\376\376\376\202\377\377\377\1\376\376\376\204" \ + "\377\377\377\1\376\376\376\235\377\377\377\1\376\376\376\217\377\377" \ + "\377\1\376\376\376\206\377\377\377\1\376\376\376\260\377\377\377\3\376" \ + "\376\376\377\377\377\376\376\376\241\377\377\377\202\376\376\376\204" \ + "\377\377\377\1\376\376\376\222\377\377\377\1\376\376\376\205\377\377" \ + "\377\1\376\376\376\246\377\377\377\1\376\376\376\233\377\377\377\3\376" \ + "\376\376\377\377\377\376\376\376\234\377\377\377\15\376\376\376\377\377" \ + "\377\377\376\377\377\377\375\375\377\376\377\377\377\376\377\375\377" \ + "\377\377\375\376\377\377\377\377\377\377\375\376\377\377\377\377\377" \ + "\202\377\376\377\260\377\377\377\7\377\376\377\376\377\377\377\377\377" \ + "\376\377\377\377\377\377\377\377\375\376\377\377\212\377\377\377\1\376" \ + "\376\374\203\377\377\377\3\376\376\377\377\377\375\376\377\377\210\377" \ + "\377\377\10\376\377\377\377\376\377\374\377\373\376\377\373\377\376\377" \ + "\376\376\376\377\377\377\376\377\375\220\377\377\377\2\377\376\377\377" \ + "\377\377\202\377\377\375\202\377\377\377\2\376\376\374\376\377\377\210" \ + "\377\377\377\1\376\377\377\202\377\377\377\5\376\377\377\377\377\377" \ + "\376\376\376\377\377\377\376\377\375\210\377\377\377\202\377\376\377" \ + "\15\377\377\377\376\377\377\377\377\375\377\377\377\375\376\377\377\377" \ + "\377\376\377\375\377\377\377\375\377\376\377\377\375\377\376\377\377" \ + "\377\377\376\376\376\231\377\377\377\202\377\376\377\15\377\377\377\376" \ + "\377\377\377\377\375\377\377\377\375\376\377\377\377\377\376\377\375" \ + "\377\377\377\375\377\376\377\377\375\377\376\377\377\377\377\376\376" \ + "\376\211\377\377\377\4\377\376\377\377\377\377\376\377\375\376\377\377" \ + "\202\377\377\377\2\376\377\377\376\377\375\210\377\377\377\1\376\377" \ + "\375\202\376\376\376\202\377\377\377\2\377\377\375\375\376\377\221\377" \ + "\377\377\10\377\377\375\377\377\377\376\376\374\376\377\373\376\376\376" \ + "\377\376\377\376\377\377\377\377\375\210\377\377\377\6\376\376\376\377" \ + "\377\377\377\377\375\377\377\377\374\375\377\377\377\375\242\377\377" \ + "\377\1\376\376\376\214\377\377\377\1\376\376\376\204\377\377\377\3\376" \ + "\376\376\377\377\377\376\376\376\235\377\377\377\1\376\376\376\203\377" \ + "\377\377\202\376\376\376\212\377\377\377\1\376\376\376\202\377\377\377" \ + "\202\376\376\376\264\377\377\377\5\376\376\376\377\377\377\376\376\376" \ + "\377\377\377\376\376\376\242\377\377\377\3\376\376\376\377\377\377\376" \ + "\376\376\202\377\377\377\1\376\376\376\223\377\377\377\1\376\376\376" \ + "\244\377\377\377\1\376\376\376\203\377\377\377\1\376\376\376\233\377" \ + "\377\377\1\376\376\376\202\377\377\377\1\376\376\376\234\377\377\377" \ + "\1\375\377\372\202\377\377\377\3\376\376\376\377\377\375\377\377\377" \ + "\202\376\377\377\204\377\377\377\4\376\377\377\377\377\377\377\376\377" \ + "\375\377\372\260\377\377\377\202\377\377\375\2\377\377\377\376\375\377" \ + "\202\377\377\377\1\375\377\376\212\377\377\377\6\377\377\375\377\377" \ + "\377\376\377\375\377\377\375\377\376\377\377\376\375\212\377\377\377" \ + "\1\377\376\377\202\377\377\377\4\377\375\376\377\377\377\377\377\373" \ + "\376\375\377\221\377\377\377\203\376\376\376\4\377\377\375\376\376\374" \ + "\377\376\377\376\376\374\210\377\377\377\5\377\376\377\377\377\375\377" \ + "\376\377\376\376\376\376\377\375\202\377\377\377\1\376\376\376\210\377" \ + "\377\377\4\375\377\372\377\376\377\377\377\377\376\377\377\204\377\377" \ + "\377\202\376\377\377\3\377\377\377\377\377\375\376\376\376\202\377\377" \ + "\377\1\375\377\372\230\377\377\377\4\375\377\372\377\376\377\377\377" \ + "\377\376\377\377\204\377\377\377\202\376\377\377\3\377\377\377\377\377" \ + "\375\376\376\376\202\377\377\377\1\375\377\372\210\377\377\377\3\376" \ + "\377\377\377\377\377\376\376\376\202\376\377\377\202\377\377\377\1\376" \ + "\377\375\210\377\377\377\7\376\376\377\377\377\375\376\377\375\376\376" \ + "\376\377\376\377\377\377\377\376\377\377\221\377\377\377\5\376\376\376" \ + "\376\377\377\377\377\377\375\375\375\377\376\377\202\377\377\377\1\377" \ + "\377\375\211\377\377\377\7\377\376\377\376\376\374\376\377\377\377\377" \ + "\377\377\376\377\377\377\375\377\377\373\233\377\377\377\1\376\376\376" \ + "\205\377\377\377\1\376\376\376\203\377\377\377\1\376\376\376\203\377" \ + "\377\377\1\376\376\376\204\377\377\377\3\376\376\376\377\377\377\376" \ + "\376\376\204\377\377\377\1\376\376\376\237\377\377\377\1\376\376\376" \ + "\212\377\377\377\1\376\376\376\213\377\377\377\1\376\376\376\255\377" \ + "\377\377\1\376\376\376\247\377\377\377\1\376\376\376\202\377\377\377" \ + "\1\376\376\376\224\377\377\377\1\376\376\376\247\377\377\377\1\376\376" \ + "\376\236\377\377\377\1\376\376\376\203\377\377\377\1\376\376\376\232" \ + "\377\377\377\10\377\376\377\377\377\375\377\377\377\376\377\377\376\376" \ + "\376\377\376\377\377\377\375\377\376\377\202\377\377\375\1\377\376\377" \ + "\202\377\377\377\3\377\376\377\377\375\376\377\376\377\260\377\377\377" \ + "\2\377\376\377\377\377\377\202\377\376\377\4\377\377\375\376\376\374" \ + "\377\375\377\377\376\377\210\377\377\377\3\376\376\374\377\376\377\376" \ + "\376\376\204\377\377\377\1\376\377\375\210\377\377\377\4\375\377\374" \ + "\377\377\377\377\375\376\377\376\377\203\377\377\377\1\377\377\375\220" \ + "\377\377\377\3\376\377\377\377\377\375\376\377\377\202\377\377\377\3" \ + "\377\376\377\373\377\377\376\377\377\211\377\377\377\202\376\377\375" \ + "\1\377\377\375\203\377\377\377\1\377\376\377\210\377\377\377\3\377\376" \ + "\377\377\375\376\377\376\377\202\377\377\377\1\377\376\377\202\377\377" \ + "\375\10\377\376\377\377\377\375\377\376\377\376\376\376\376\377\377\377" \ + "\377\377\377\377\375\377\376\377\230\377\377\377\3\377\376\377\377\375" \ + "\376\377\376\377\202\377\377\377\1\377\376\377\202\377\377\375\10\377" \ + "\376\377\377\377\375\377\376\377\376\376\376\376\377\377\377\377\377" \ + "\377\377\375\377\376\377\210\377\377\377\2\377\377\375\375\376\371\202" \ + "\377\376\377\3\377\377\377\377\377\375\377\376\377\212\377\377\377\1" \ + "\377\375\376\202\377\377\377\4\377\377\375\376\376\376\376\377\377\377" \ + "\376\377\220\377\377\377\2\376\377\377\376\376\377\202\377\377\377\2" \ + "\376\377\375\375\377\374\212\377\377\377\10\373\377\376\377\377\377\377" \ + "\377\375\376\376\374\377\377\375\377\376\377\377\377\377\376\377\377" \ + "\235\377\377\377\1\376\376\376\202\377\377\377\7\316\316\320\250\250" \ + "\252\221\221\223llnjjlGGI99;\204::<\7TTVkkmyy{\234\234\236\265\265\267" \ + "\332\332\332\376\376\376\237\377\377\377\3\376\376\376\377\377\377\376" \ + "\376\376\222\377\377\377\1\376\376\376\205\377\377\377\3\376\376\376" \ + "\377\377\377\376\376\376\255\377\377\377\1\376\376\376\246\377\377\377" \ + "\1\376\376\376\227\377\377\377\1\376\376\376\252\377\377\377\1\376\376" \ + "\376\233\377\377\377\1\376\376\376\236\377\377\377\17\305\344\240\303" \ + "\342\237\304\343\240\304\343\237\307\342\237\303\342\236\305\342\240" \ + "\303\342\236\305\342\237\304\343\240\304\343\237\304\341\237\304\343" \ + "\237\323\352\266\376\377\375\250\377\377\377\210\305\342\240\10\305\342" \ + "\237\303\342\234\304\343\237\306\341\236\304\343\240\322\352\270\376" \ + "\377\377\375\377\376\211\377\377\377\5\377\376\377\376\376\376\377\376" \ + "\377\360\371\350\305\342\237\202\304\341\236\210\305\342\240\5\304\341" \ + "\236\327\356\302\376\377\377\377\377\373\376\377\375\202\377\377\375" \ + "\1\377\376\377\220\377\377\377\202\377\377\375\2\376\377\377\377\377" \ + "\377\202\377\377\375\2\304\343\237\306\341\236\210\305\342\240\5\307" \ + "\342\237\303\342\236\304\341\236\341\357\314\377\377\375\213\377\377" \ + "\377\17\376\377\375\323\352\266\304\343\237\304\341\237\304\343\237\304" \ + "\343\240\305\342\237\303\342\236\305\342\240\303\342\236\307\342\237" \ + "\304\343\237\304\343\240\303\342\237\305\344\240\231\377\377\377\17\376" \ + "\377\375\323\352\266\304\343\237\304\341\237\304\343\237\304\343\240" \ + "\305\342\237\303\342\236\305\342\240\303\342\236\307\342\237\304\343" \ + "\237\304\343\240\303\342\237\305\344\240\211\377\377\377\10\360\367\347" \ + "\306\343\241\303\342\237\307\342\237\303\342\237\304\343\235\307\341" \ + "\240\304\343\240\210\305\342\240\7\315\347\252\376\377\375\377\375\376" \ + "\376\377\375\377\377\377\377\377\373\376\377\377\221\377\377\377\10\377" \ + "\377\375\376\377\375\323\352\266\307\341\240\307\342\237\305\342\240" \ + "\307\340\236\306\341\236\210\305\342\240\4\304\343\237\311\335\236\377" \ + "\377\377\377\376\377\203\377\377\377\1\376\377\377\230\377\377\377\1" \ + "\376\376\376\203\377\377\377\3\346\346\346\251\251\251jjl\202;;=\210" \ + "::<\1;;=\202::<\2;;=99;\203::<\5FFHxxx\265\265\265\363\363\363\376\376" \ + "\376\234\377\377\377\2\376\376\376\346\346\346\214\234\234\234\1\235" \ + "\235\235\203\234\234\234\3\235\235\235\234\234\234\250\250\250\203\316" \ + "\316\316\1\346\346\346\263\377\377\377\202\250\250\250\245\377\377\377" \ + "\1\316\316\316\222\234\234\234\1\302\302\302\203\316\316\316\1\363\363" \ + "\363\247\377\377\377\3\316\316\316\234\234\234\235\235\235\240\234\234" \ + "\234\1\316\316\316\231\377\377\377\6\215\305>\216\306A\215\305@\213\310" \ + "=\215\305>\212\307>\202\214\305@\6\214\306>\212\306@\214\306<\215\304" \ + "B\214\306>\252\323m\251\377\377\377\210\214\306>\10\215\305@\215\307" \ + "\77\212\307>\217\304@\214\305@\251\323m\377\377\377\377\377\375\213\377" \ + "\377\377\5\377\375\377\341\363\315\215\305>\212\307>\215\305@\210\214" \ + "\306>\6\215\306A\220\305\77\350\365\333\377\377\377\376\377\377\377\376" \ + "\377\202\376\377\377\225\377\377\377\3\377\376\377\214\306>\215\306A" \ + "\210\214\306>\6\215\305>\212\310\77\215\305@\307\341\240\376\377\377" \ + "\377\376\377\213\377\377\377\6\252\323m\214\306>\215\304B\214\306<\212" \ + "\306@\214\306>\202\214\305@\6\212\307>\215\305>\213\310=\215\305@\216" \ + "\306A\215\305>\232\377\377\377\6\252\323m\214\306>\215\304B\214\306<" \ + "\212\306@\214\306>\202\214\305@\6\212\307>\215\305>\213\310=\215\305" \ + "@\216\306A\215\305>\211\377\377\377\4\376\377\377\242\321a\213\307A\215" \ + "\305>\202\214\306>\2\215\305@\215\307\77\210\214\306>\7\215\305<\332" \ + "\354\304\377\377\377\376\377\375\376\376\376\377\376\377\376\376\376" \ + "\221\377\377\377\10\377\376\377\342\362\316\215\305>\213\310\77\212\305" \ + "D\212\307<\216\306\77\211\307>\211\214\306>\4\304\343\240\373\377\376" \ + "\377\377\377\375\377\376\202\377\377\377\1\377\377\375\225\377\377\377" \ + "\1\376\376\376\204\377\377\377\6\265\265\267__a99;;;=::<;;=\202::<\1" \ + ";;=\202::<\1;;=\202::<\1;;=\203::<\1;;=\203::<\3;;=::<99;\202::<\2xx" \ + "z\301\301\301\202\377\377\377\1\376\376\376\202\377\377\377\1\376\376" \ + "\376\206\377\377\377\1\376\376\376\217\377\377\377\1\316\316\316\205" \ + "::<\202;;=\221::<\4TTVwwy\250\250\252\346\346\350\255\377\377\377\1\316" \ + "\316\320\202::<\1\316\316\316\244\377\377\377\1\234\234\236\204::<\1" \ + ";;=\205::<\3;;=::<;;=\206::<\1;;=\204::<\6SSUkkm\204\204\206\250\250" \ + "\250\316\316\316\376\376\376\206\377\377\377\1\376\376\376\231\377\377" \ + "\377\1\234\234\234\206::<\3;;=::<;;=\222::<\1;;=\204::<\3;;=::<\234\234" \ + "\236\231\377\377\377\3\214\305@\214\306>\214\305@\207\214\306>\4\214" \ + "\305@\215\305>\214\306>\252\324p\251\377\377\377\215\214\306>\1\250\325" \ + "p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\210\214\306>" \ + "\15\212\306@\215\307\77\233\316W\365\374\364\377\376\375\376\377\377" \ + "\377\376\377\377\377\375\377\377\377\377\377\375\376\376\376\377\377" \ + "\377\376\376\374\202\377\377\377\1\376\376\376\216\377\377\377\213\214" \ + "\306>\3\215\305>\214\306>\305\342\240\215\377\377\377\4\252\324p\214" \ + "\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\232" \ + "\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3\214" \ + "\305@\214\306>\214\305@\212\377\377\377\7\350\364\334\215\305>\212\307" \ + "<\214\305@\215\304B\215\305@\213\310\77\210\214\306>\10\214\305@\225" \ + "\311J\370\373\362\377\376\377\376\377\377\377\377\375\377\377\377\376" \ + "\377\377\210\377\377\377\40\376\377\377\376\377\375\377\376\377\377\377" \ + "\377\375\376\377\377\377\375\377\376\377\376\377\377\370\373\364\233" \ + "\314W\215\307\77\214\304=\212\306@\215\307\77\213\305=\215\307\77\214" \ + "\306>\217\304@\215\306A\212\307>\214\306<\215\306A\214\306>\211\307@" \ + "\242\321a\377\377\377\377\376\377\376\377\377\377\376\377\377\377\377" \ + "\376\377\377\377\376\377\223\377\377\377\7\376\376\376\377\377\377\376" \ + "\376\376\377\377\377\363\363\365\234\234\236FFH\202::<\10;;=99;;;=::" \ + "<;;=::<99;;;=\203::<\1;;=\203::<\2;;=99;\204::<\11""99;;;=::<;;=::<;" \ + ";=TTV\265\265\265\363\363\363\203\377\377\377\1\376\376\376\207\377\377" \ + "\377\1\376\376\376\215\377\377\377\1\316\316\316\205::<\3;;=::<;;=\202" \ + "::<\1;;=\214::<\3;;=99;;;=\202::<\4lln\316\316\316\376\376\376\377\377" \ + "\377\202\376\376\376\246\377\377\377\2\376\376\376xxz\202::<\2xxx\376" \ + "\376\376\243\377\377\377\1\234\234\236\204::<\202;;=\205::<\1;;=\204" \ + "::<\1;;=\202::<\1""99;\206::<\1;;=\202::<\6;;=kkk\250\250\250\346\346" \ + "\346\377\377\377\376\376\376\205\377\377\377\1\376\376\376\225\377\377" \ + "\377\1\234\234\234\204::<\1;;=\202::<\4;;=::<99;;;=\225::<\3;;=::<\234" \ + "\234\236\231\377\377\377\3\214\305@\214\306>\214\305@\207\214\306>\4" \ + "\214\305@\215\305>\214\306>\252\324p\251\377\377\377\215\214\306>\1\250" \ + "\325p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\210\214\306" \ + ">\4\215\306A\213\304\77\215\305@\262\327x\202\377\377\377\1\376\377\375" \ + "\203\377\377\375\204\377\377\377\1\376\376\376\217\377\377\377\213\214" \ + "\306>\3\215\305>\214\306>\305\342\240\215\377\377\377\4\252\324p\214" \ + "\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\232" \ + "\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3\214" \ + "\305@\214\306>\214\305@\212\377\377\377\7\376\376\376\305\342\237\212" \ + "\307>\214\306>\212\307<\214\306>\212\307>\210\214\306>\3\214\306<\215" \ + "\306A\300\337\221\202\377\377\377\3\377\376\377\376\376\376\377\377\375" \ + "\210\377\377\377\1\377\375\377\202\377\377\377\2\376\376\377\376\377" \ + "\375\202\377\376\377\30\377\377\377\277\340\221\215\306A\213\305=\215" \ + "\305>\212\306B\214\306>\216\306\77\214\306<\212\307>\215\307=\213\305" \ + ";\215\307\77\216\305C\214\306>\214\305@\216\306\77\347\365\333\377\376" \ + "\377\377\377\375\376\377\377\377\376\374\377\377\377\377\377\375\222" \ + "\377\377\377\1\376\376\376\204\377\377\377\12\265\265\267FFH;;=::<;;" \ + "=99;::<;;=::<;;=\202::<\4<<>99;::<;;=\202::<\1;;=\203::<\1<<>\204::<" \ + "\5<<>99;;;=99;;;=\202::<\4:::SSS\266\266\266\376\376\376\203\377\377" \ + "\377\1\376\376\376\204\377\377\377\1\376\376\376\216\377\377\377\1\316" \ + "\316\316\204::<\3;;=::<;;=\204::<\1;;=\214::<\1;;=\202::<\1;;=\202::" \ + "<\2yyy\363\363\363\202\377\377\377\1\376\376\376\245\377\377\377\3\346" \ + "\346\346::<;;=\202::<\1\347\347\347\202\377\377\377\1\376\376\376\240" \ + "\377\377\377\1\234\234\236\203::<\4;;=99;::<;;=\202::<\7;;=::<;;=99;" \ + ";;=::<;;=\203::<\202;;=\210::<\1""99;\202::<\4;;=xxz\317\317\317\376" \ + "\376\376\202\377\377\377\1\376\376\376\227\377\377\377\1\234\234\234" \ + "\204::<\1""99;\203;;=\224::<\1;;=\204::<\2<<>\234\234\236\231\377\377" \ + "\377\3\214\305@\214\306>\214\305@\207\214\306>\4\214\305@\215\305>\214" \ + "\306>\252\324p\251\377\377\377\215\214\306>\1\250\325p\216\377\377\377" \ + "\1\342\361\320\202\214\306>\1\214\305@\210\214\306>\10\215\305>\214\306" \ + ">\213\307A\214\306>\315\345\253\377\377\375\377\376\377\376\377\377\226" \ + "\377\377\377\213\214\306>\3\215\305>\214\306>\305\342\240\215\377\377" \ + "\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3\214\305@\214" \ + "\306>\214\305@\232\377\377\377\4\252\324p\214\306>\215\305>\214\305@" \ + "\207\214\306>\3\214\305@\214\306>\214\305@\211\377\377\377\7\377\377" \ + "\375\377\376\377\376\376\376\241\321a\212\307>\211\305\77\215\306A\211" \ + "\214\306>\4\213\310\77\214\305@\213\305=\342\361\320\202\377\376\377" \ + "\2\377\377\375\377\376\377\210\377\377\377\1\377\376\377\202\377\377" \ + "\377\30\377\377\375\376\377\377\377\377\375\376\377\377\351\366\334\214" \ + "\305B\211\306;\215\307\77\214\306>\212\306@\215\305>\215\305@\212\307" \ + ">\214\305@\212\306B\214\306>\213\305=\213\310\77\215\305>\215\307\77" \ + "\314\345\253\377\375\377\377\376\374\376\377\377\203\377\377\377\1\377" \ + "\376\374\225\377\377\377\2\345\345\345kkm\205::<\202;;=\203::<\1;;=\203" \ + "::<\1;;=\202::<\202;;=\202::<\1;;=\210::<\2;;=99;\205::<\2```\331\331" \ + "\331\211\377\377\377\1\376\376\376\214\377\377\377\1\316\316\316\206" \ + "::<\5""99;::<;;=::<99;\212::<\1;;=\202::<\1;;=\204::<\4;;=::\214\305@" \ + "\207\214\306>\4\214\305@\215\305>\214\306>\252\324p\251\377\377\377\215" \ + "\214\306>\1\250\325p\216\377\377\377\1\342\361\320\202\214\306>\1\214" \ + "\305@\210\214\306>\10\215\305@\212\307>\214\305@\215\306A\214\305@\352" \ + "\364\334\376\376\377\377\377\373\202\377\377\377\3\376\376\376\377\377" \ + "\377\377\377\375\202\377\377\377\1\376\376\374\216\377\377\377\213\214" \ + "\306>\3\215\305>\214\306>\305\342\240\215\377\377\377\4\252\324p\214" \ + "\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\232" \ + "\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3\214" \ + "\305@\214\306>\214\305@\211\377\377\377\1\376\377\377\202\377\377\375" \ + "\5\347\364\332\215\307\77\215\306C\214\307;\216\306\77\210\214\306>\10" \ + "\214\305@\214\305D\215\307\77\233\314V\371\374\363\376\377\377\377\377" \ + "\377\377\377\375\210\377\377\377\20\375\377\374\377\376\377\376\376\377" \ + "\376\377\377\377\376\377\376\377\375\376\377\377\244\317d\212\307>\215" \ + "\306A\215\305@\214\305@\211\306=\215\307=\215\306A\214\305@\204\214\306" \ + ">\14\211\305A\212\307>\251\324k\377\376\377\377\375\376\376\377\377\377" \ + "\377\377\377\377\375\377\377\377\377\377\375\377\377\377\377\377\375" \ + "\217\377\377\377\1\376\376\376\203\377\377\377\2\265\265\267FFH\205:" \ + ":<\1;;=\203::<\202;;=\7:::TTT\203\203\203\235\235\235\316\316\316\332" \ + "\332\332\377\377\377\202\376\376\376\202\377\377\377\5\316\316\316\317" \ + "\317\317\234\234\234yyyFFF\202::<\1;;=\202::<\3""99;;;=99;\204::<\2;" \ + ";=\233\233\233\206\377\377\377\1\376\376\376\216\377\377\377\1\316\316" \ + "\316\204::<\1;;=\205::<\1;;=\212::<\3""99;::<;;=\202::<\2;;=99;\204:" \ + ":<\2;;=\265\265\265\245\377\377\377\4\346\346\346::<99;;;=\202::<\4""9" \ + "9;\347\347\347\377\377\377\376\376\376\240\377\377\377\1\234\234\236" \ + "\205::<\1;;=\203::<\202;;=\1""99;\203;;=\2::<;;=\203::<\1;;=\202::<\2" \ + ";;=::<\202;;=\7::<;;=99;::<;;=99;;;=\202::<\3;;=xxx\362\362\362\227\377" \ + "\377\377\1\234\234\234\205::<\202;;=\4::<;;=::<;;=\223::<\2;;=99;\202" \ + ";;=\1\234\234\236\231\377\377\377\3\214\305@\214\306>\214\305@\207\214" \ + "\306>\4\214\305@\215\305>\214\306>\252\324p\251\377\377\377\215\214\306" \ + ">\1\250\325p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\210" \ + "\214\306>\12\212\307>\215\306A\214\305@\215\307\77\213\306:\226\312N" \ + "\372\374\361\375\376\377\377\377\375\377\377\373\224\377\377\377\213" \ + "\214\306>\3\215\305>\214\306>\305\342\240\215\377\377\377\4\252\324p" \ + "\214\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305" \ + "@\232\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>" \ + "\3\214\305@\214\306>\214\305@\211\377\377\377\10\376\377\377\376\376" \ + "\377\376\377\377\377\375\376\307\342\237\214\306<\215\306A\214\305@\210" \ + "\214\306>\5\215\307\77\213\305=\216\306A\213\310\77\277\337\223\202\377" \ + "\377\375\1\377\376\377\210\377\377\377\14\376\377\375\376\376\376\377" \ + "\376\377\377\377\375\377\376\377\377\377\377\303\342\236\215\307\77\216" \ + "\306A\215\305>\214\306<\215\306A\203\214\306>\20\215\307\77\212\307>" \ + "\215\305@\216\306\77\214\305@\216\307<\223\312K\356\372\346\377\377\377" \ + "\376\377\377\375\377\376\377\377\377\377\376\377\377\377\375\377\377" \ + "\377\377\377\375\216\377\377\377\1\376\376\376\203\377\377\377\2\375" \ + "\375\375\205\205\207\202::<\202;;=\3::<;;=::<\202;;=\6::<:::SSS\250\250" \ + "\250\346\346\346\376\376\376\216\377\377\377\3\332\332\332\220\220\220" \ + "SSS\202::<\4;;=99;::<;;=\202::<\1""99;\202;;=\2__a\332\332\334\223\377" \ + "\377\377\1\316\316\316\204::<\6;;=RRT\235\235\237\235\235\235\233\233" \ + "\233\234\234\234\212\234\234\236\5xxzkkm__a99;;;=\204::<\202;;=\1""9" \ + "9;\202::<\1\316\316\316\244\377\377\377\4\204\204\206;;=::<;;=\202::" \ + "<\2;;=\220\220\222\203\377\377\377\1\376\376\376\236\377\377\377\1\234" \ + "\234\236\203::<\3;;=::\214\305" \ + "@\207\214\306>\4\214\305@\215\305>\214\306>\252\324p\251\377\377\377" \ + "\215\214\306>\1\250\325p\216\377\377\377\1\342\361\320\202\214\306>\1" \ + "\214\305@\210\214\306>\7\212\306@\214\306<\217\307@\214\304\77\214\311" \ + ">\214\306>\251\323m\202\376\377\377\4\376\376\374\377\377\375\377\377" \ + "\377\376\376\376\202\377\377\377\1\376\376\376\216\377\377\377\213\214" \ + "\306>\3\215\305>\214\306>\305\342\240\215\377\377\377\4\252\324p\214" \ + "\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\232" \ + "\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3\214" \ + "\305@\214\306>\214\305@\212\377\377\377\7\377\377\375\377\376\377\376" \ + "\377\377\377\376\377\251\323o\211\307>\214\305@\210\214\306>\7\212\307" \ + ">\215\305>\214\305@\214\306>\215\307\77\347\365\334\377\376\377\211\377" \ + "\377\377\2\377\376\377\375\377\374\203\377\376\377\15\352\364\333\212" \ + "\306@\215\306A\214\306>\215\307\77\213\310\77\214\306>\216\306A\215\306" \ + "A\214\306<\212\307>\213\310=\212\307>\202\214\305@\4\214\306>\314\345" \ + "\253\377\376\377\376\377\377\202\377\377\375\6\377\376\377\375\376\377" \ + "\377\377\377\377\376\377\376\377\375\377\376\377\217\377\377\377\3\376" \ + "\376\376\362\362\362lln\20299;\1;;=\204::<\202;;=\6::<\204\204\204\317" \ + "\317\317\376\376\376\377\377\377\376\376\376\206\377\377\377\1\376\376" \ + "\376\213\377\377\377\2\301\301\301kkm\211::<\6;;=FFH\301\301\301\376" \ + "\376\376\377\377\377\376\376\376\217\377\377\377\1\316\316\316\204::" \ + "<\3;;=kkm\376\376\376\221\377\377\377\3\316\316\316\204\204\204FFF\202" \ + "::<\1;;=\202::<\202;;=\2FFH\363\363\363\242\377\377\377\5\364\364\364" \ + "::<;;=99;;;=\203::<\3GGI\363\363\363\376\376\376\240\377\377\377\1\234" \ + "\234\236\205::<\1\234\234\236\210\377\377\377\1\376\376\376\204\377\377" \ + "\377\1\376\376\376\202\377\377\377\6\362\362\362\316\316\316\265\265" \ + "\265\234\234\234kkmFFH\202::<\2;;=99;\205::<\1;;=\202::<\1\221\221\221" \ + "\225\377\377\377\1\234\234\234\205::<\1\234\234\236\202\377\377\377\1" \ + "\376\376\376\225\377\377\377\1\375\375\375\235\377\377\377\3\214\305" \ + "@\214\306>\214\305@\207\214\306>\4\214\305@\215\305>\214\306>\252\324" \ + "p\251\377\377\377\215\214\306>\1\250\325p\216\377\377\377\1\342\361\320" \ + "\202\214\306>\1\214\305@\210\214\306>\4\215\307\77\214\306>\214\304\77" \ + "\214\306>\202\214\305@\6\215\307\77\307\341\240\376\377\375\376\377\377" \ + "\376\376\374\377\377\373\202\377\377\377\202\377\377\375\216\377\377" \ + "\377\213\214\306>\3\215\305>\214\306>\305\342\240\215\377\377\377\4\252" \ + "\324p\214\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214" \ + "\305@\232\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306" \ + ">\3\214\305@\214\306>\214\305@\212\377\377\377\7\377\376\377\376\376" \ + "\377\377\377\377\376\376\377\361\372\347\222\312K\215\305>\210\214\306" \ + ">\10\214\305@\215\306A\214\305@\214\306<\213\304A\243\322b\376\376\374" \ + "\376\377\375\211\377\377\377\24\377\377\373\377\377\377\376\377\377\377" \ + "\377\375\242\320c\215\307=\214\306>\213\310\77\213\304A\212\306@\215" \ + "\307\77\215\305@\214\306>\215\307\77\212\306@\215\305>\215\307\77\213" \ + "\310\77\213\306:\253\325q\202\377\377\377\11\377\377\375\377\376\377" \ + "\377\377\377\377\377\375\376\377\375\377\377\375\377\375\377\376\377" \ + "\377\377\377\375\214\377\377\377\7\376\376\376\377\377\377\376\376\376" \ + "\363\363\363__a::<;;=\203::<\202;;=\202::<\4xxz\347\347\351\377\377\377" \ + "\376\376\376\210\377\377\377\1\376\376\376\204\377\377\377\2\376\376" \ + "\376\377\377\377\203\376\376\376\205\377\377\377\2\316\316\320kkm\202" \ + "::<\3;;=::<;;=\202::<\202;;=\2:::\250\250\250\202\377\377\377\1\376\376" \ + "\376\216\377\377\377\1\316\316\316\205::<\1kkm\203\377\377\377\1\376" \ + "\376\376\215\377\377\377\1\376\376\376\202\377\377\377\3\363\363\363" \ + "xxx::<\202;;=\203::<\2;;=xxz\242\377\377\377\1\234\234\234\202::<\1;" \ + ";=\202::<\1;;=\202::<\1\234\234\234\241\377\377\377\1\234\234\236\202" \ + "::<\10;;=::<;;=\234\234\236\377\377\377\376\376\376\377\377\377\376\376" \ + "\376\216\377\377\377\1\376\376\376\203\377\377\377\3\332\332\332\221" \ + "\221\223FFH\205::<\2;;=::<\202;;=\2::<\204\204\204\224\377\377\377\1" \ + "\234\234\234\205::<\3\234\234\236\377\377\377\376\376\376\264\377\377" \ + "\377\3\214\305@\214\306>\214\305@\207\214\306>\4\214\305@\215\305>\214" \ + "\306>\252\324p\251\377\377\377\215\214\306>\1\250\325p\216\377\377\377" \ + "\1\342\361\320\202\214\306>\1\214\305@\210\214\306>\5\216\306\77\212" \ + "\307>\215\307=\212\306@\214\306>\202\215\305>\5\215\305@\345\356\317" \ + "\376\377\375\376\377\377\377\377\375\202\377\377\377\1\377\377\375\217" \ + "\377\377\377\213\214\306>\3\215\305>\214\306>\305\342\240\215\377\377" \ + "\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3\214\305@\214" \ + "\306>\214\305@\232\377\377\377\4\252\324p\214\306>\215\305>\214\305@" \ + "\207\214\306>\3\214\305@\214\306>\214\305@\211\377\377\377\4\376\377" \ + "\377\377\377\377\377\377\375\376\377\377\202\377\377\377\2\315\347\252" \ + "\212\306@\210\214\306>\10\216\306A\212\306@\212\307>\215\305<\213\310" \ + "\77\215\305>\307\341\240\376\377\377\212\377\377\377\10\375\377\374\377" \ + "\377\377\305\342\237\215\305@\212\306@\216\306\77\215\307=\215\305>\202" \ + "\214\306>\24\213\307A\213\310=\215\304B\214\306>\212\306@\215\304B\212" \ + "\307>\225\311K\370\373\362\377\377\377\376\377\375\377\377\375\377\377" \ + "\377\374\377\375\376\376\376\377\377\377\377\377\375\377\376\377\376" \ + "\377\377\377\377\375\211\377\377\377\1\376\376\376\205\377\377\377\1" \ + "___\204::<\1;;=\203::<\2SSS\316\316\316\235\377\377\377\2\317\317\317" \ + "``b\207::<\3;;=::<\204\204\206\220\377\377\377\1\316\316\316\205::<\1" \ + "kkm\226\377\377\377\3\204\204\206::<;;=\205::<\1\316\316\316\232\377" \ + "\377\377\1\376\376\376\205\377\377\377\2\364\364\364FFF\202;;=\202::" \ + "<\6;;=99;;;=::\214\305@\207\214\306>\4\214\305@\215" \ + "\305>\214\306>\252\324p\251\377\377\377\215\214\306>\1\250\325p\216\377" \ + "\377\377\1\342\361\320\202\214\306>\1\214\305@\220\214\306>\2\222\313" \ + "J\366\373\364\202\377\376\377\4\377\377\373\376\376\374\376\377\377\377" \ + "\376\377\216\377\377\377\213\214\306>\3\215\305>\214\306>\305\342\240" \ + "\215\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3" \ + "\214\305@\214\306>\214\305@\232\377\377\377\4\252\324p\214\306>\215\305" \ + ">\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\211\377\377\377" \ + "-\377\377\375\376\377\377\377\377\377\376\376\374\376\377\377\377\376" \ + "\377\376\377\377\252\324p\212\306@\215\305>\212\307<\215\305@\215\305" \ + "<\214\305B\215\305@\214\306<\212\307>\215\305>\214\306>\211\306=\215" \ + "\305>\212\307>\214\306<\350\364\334\374\377\377\377\376\377\376\376\376" \ + "\374\377\375\377\377\377\376\377\375\377\377\375\377\376\377\377\377" \ + "\375\377\377\377\377\376\377\357\367\350\223\312K\213\310\77\215\305" \ + ">\214\306>\215\305>\213\310\77\212\306@\214\306>\215\305@\202\214\306" \ + ">\10\214\305@\216\306=\212\307>\215\305>\333\355\303\376\376\374\377" \ + "\377\377\377\377\375\223\377\377\377\1\376\376\376\203\377\377\377\1" \ + "\203\203\203\206::<\4;;=::<\204\204\206\363\363\363\230\377\377\377\1" \ + "\376\376\376\207\377\377\377\1\235\235\237\202::<\1;;=\203::<\5;;=99" \ + ";;;=\204\204\204\376\376\376\216\377\377\377\1\316\316\316\205::<\1k" \ + "km\227\377\377\377\12\204\204\206::<;;=::<99;;;=::<\204\204\204\377\377" \ + "\377\376\376\376\232\377\377\377\1\376\376\376\203\377\377\377\2\234" \ + "\234\234;;=\203::<\1;;=\204::<\3<<>\250\250\250\376\376\376\237\377\377" \ + "\377\1\234\234\236\205::<\1\234\234\234\231\377\377\377\10\376\376\376" \ + "\377\377\377\265\265\265FFH::<;;=::<;;=\203::<\2;;=\204\204\204\222\377" \ + "\377\377\1\234\234\234\205::<\1\234\234\236\266\377\377\377\3\214\305" \ + "@\214\306>\214\305@\207\214\306>\4\214\305@\215\305>\214\306>\252\324" \ + "p\251\377\377\377\215\214\306>\1\250\325p\216\377\377\377\1\342\361\320" \ + "\202\214\306>\1\214\305@\220\214\306>\4\216\306\77\250\322n\376\377\375" \ + "\376\377\373\222\377\377\377\213\214\306>\3\215\305>\214\306>\305\342" \ + "\240\215\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306" \ + ">\3\214\305@\214\306>\214\305@\232\377\377\377\4\252\324p\214\306>\215" \ + "\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\211\377\377" \ + "\377\13\376\376\377\376\377\377\377\376\377\376\376\374\374\377\377\377" \ + "\377\375\377\376\377\356\372\346\225\311K\214\306>\213\310=\203\214\306" \ + ">\2\213\310\77\214\306>\202\214\305@\7\214\306<\213\307A\214\304\77\214" \ + "\305B\212\307>\244\317d\377\376\377\202\377\377\377\1\377\375\377\202" \ + "\377\377\377\25\376\377\377\377\376\377\377\377\377\374\377\375\376\376" \ + "\374\253\324n\214\306<\215\307\77\215\305>\211\307@\216\305C\214\305" \ + "@\215\307\77\214\305@\214\306<\212\307<\211\306=\214\306>\214\305@\213" \ + "\307A\263\327}\202\376\377\377\3\377\377\377\377\375\376\377\377\375" \ + "\221\377\377\377\1\376\376\376\203\377\377\377\1\250\250\250\204::<\1" \ + ";;=\202::<\2;;=\264\264\264\202\377\377\377\1\376\376\376\232\377\377" \ + "\377\1\376\376\376\205\377\377\377\2\332\332\332SSS\202::<\1;;=\204:" \ + ":<\4xxx\364\364\364\377\377\377\376\376\376\214\377\377\377\1\316\316" \ + "\316\205::<\1kkm\227\377\377\377\2\363\363\363SSU\202::<\4;;=99;::<;" \ + ";;\202\377\377\377\1\376\376\376\226\377\377\377\1\376\376\376\204\377" \ + "\377\377\11\376\376\376\363\363\363FFH99;;;=::<;;=99;;;=\203::<\4""9" \ + "9;SSU\377\377\377\376\376\376\236\377\377\377\1\234\234\236\205::<\1" \ + "\234\234\234\225\377\377\377\1\376\376\376\204\377\377\377\10\376\376" \ + "\376\377\377\377\363\363\363yyy::<;;=99;;;=\204::<\1\266\266\266\221" \ + "\377\377\377\1\234\234\234\205::<\1\234\234\236\266\377\377\377\3\214" \ + "\305@\214\306>\214\305@\207\214\306>\4\214\305@\215\305>\214\306>\252" \ + "\324p\251\377\377\377\215\214\306>\1\250\325p\216\377\377\377\1\342\361" \ + "\320\202\214\306>\1\214\305@\220\214\306>\4\214\306<\213\307A\275\335" \ + "\222\376\377\377\203\377\377\377\1\377\377\375\216\377\377\377\213\214" \ + "\306>\3\215\305>\214\306>\305\342\240\215\377\377\377\4\252\324p\214" \ + "\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\232" \ + "\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3\214" \ + "\305@\214\306>\214\305@\211\377\377\377\4\377\376\377\376\376\377\377" \ + "\377\377\377\377\375\202\376\377\377\5\377\375\376\377\376\377\315\346" \ + "\255\212\307>\214\305@\202\215\306A\22\214\305@\212\307<\214\305B\214" \ + "\306>\213\307A\214\306>\213\305=\214\306>\215\305>\213\307A\211\310<" \ + "\313\347\254\377\377\375\377\375\377\376\377\377\376\377\373\376\377" \ + "\377\377\376\377\202\376\377\377\10\377\377\377\315\346\254\212\307>" \ + "\212\306@\215\306A\216\306A\212\307>\214\306<\202\215\306A\10\215\306" \ + "C\214\305B\215\307\77\214\306<\214\305@\213\310<\222\310L\372\373\363" \ + "\225\377\377\377\1\376\376\376\202\377\377\377\6\376\376\376\333\333" \ + "\333::<;;=::<;;=\202::<\3;;=FFH\315\315\315\205\377\377\377\1\376\376" \ + "\376\225\377\377\377\202\376\376\376\202\377\377\377\1\376\376\376\202" \ + "\377\377\377\1\376\376\376\202\377\377\377\2\363\363\363xxx\204::<\2" \ + ";;=\203\203\203\220\377\377\377\1\316\316\316\205::<\1kkm\230\377\377" \ + "\377\3\266\266\27099;;;=\204::<\1\316\316\316\230\377\377\377\1\376\376" \ + "\376\202\377\377\377\1\376\376\376\202\377\377\377\3\265\265\267::<;" \ + ";=\204::<\202;;=\202::<\202;;=\1\265\265\265\237\377\377\377\1\234\234" \ + "\236\205::<\1\234\234\234\236\377\377\377\5\234\234\234::<;;=::<;;=\202" \ + "::<\3;;=FFH\332\332\332\220\377\377\377\1\234\234\234\205::<\1\234\234" \ + "\236\266\377\377\377\3\214\305@\214\306>\214\305@\207\214\306>\4\214" \ + "\305@\215\305>\214\306>\252\324p\251\377\377\377\215\214\306>\1\250\325" \ + "p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\220\214\306>" \ + "\4\215\307\77\214\304\77\213\310\77\333\355\303\202\377\377\377\1\376" \ + "\377\375\217\377\377\377\213\214\306>\3\215\305>\214\306>\305\342\240" \ + "\215\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3" \ + "\214\305@\214\306>\214\305@\232\377\377\377\4\252\324p\214\306>\215\305" \ + ">\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\213\377\377\377" \ + "\5\377\377\373\377\376\377\377\377\377\375\377\374\376\377\377\202\376" \ + "\376\376\22\260\331{\212\307>\214\306>\215\305>\215\305@\215\307\77\215" \ + "\307=\214\305@\214\306>\215\306A\214\306>\213\307C\214\306>\214\304;" \ + "\213\307A\222\312K\357\370\345\377\377\375\202\377\377\377\15\377\375" \ + "\376\377\377\375\376\376\376\377\377\375\361\367\351\222\311J\213\310" \ + "\77\214\305B\215\310<\213\305=\216\306\77\212\307<\214\305B\202\214\306" \ + ">\6\216\306\77\215\305@\215\306A\214\305@\215\305<\333\356\301\202\377" \ + "\376\377\3\377\377\375\377\377\377\377\376\377\225\377\377\377\1``b\202" \ + "::<\6;;=::<;;=::\214\305@\207\214\306>\4\214\305@\215" \ + "\305>\214\306>\252\324p\251\377\377\377\215\214\306>\1\250\325p\216\377" \ + "\377\377\1\342\361\320\202\214\306>\1\214\305@\220\214\306>\10\216\306" \ + "\77\215\306A\214\305@\224\310J\360\371\350\377\377\377\377\376\377\376" \ + "\377\377\216\377\377\377\213\214\306>\3\215\305>\214\306>\305\342\240" \ + "\215\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3" \ + "\214\305@\214\306>\214\305@\232\377\377\377\4\252\324p\214\306>\215\305" \ + ">\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\212\377\377\377" \ + "\1\377\377\375\202\377\377\377\2\377\376\377\377\377\377\202\376\377" \ + "\377\25\377\377\375\370\373\362\223\312K\212\307>\215\305>\216\306A\212" \ + "\307<\214\305B\215\307\77\214\305@\214\306>\214\305@\212\306@\215\307" \ + "=\216\306A\215\305>\214\306<\252\324n\376\377\377\376\376\376\377\376" \ + "\377\202\377\377\375\4\377\376\377\376\376\377\252\324n\215\306A\202" \ + "\214\306>\21\214\305@\215\307\77\215\305>\212\307>\214\306<\213\304A" \ + "\215\307=\214\304=\215\307\77\212\307>\214\306>\277\337\226\377\376\377" \ + "\376\377\375\377\377\375\377\377\377\376\376\376\225\377\377\377\3\234" \ + "\234\236::<;;=\204::<\4;;=\265\265\267\377\377\377\376\376\376\204\377" \ + "\377\377\202\376\376\376\202\377\377\377\1\376\376\376\225\377\377\377" \ + "\1\376\376\376\203\377\377\377\1\376\376\376\202\377\377\377\1\376\376" \ + "\376\202\377\377\377\3\250\250\250::<\204\204\206\205\377\377\377\1\376" \ + "\376\376\214\377\377\377\1\316\316\316\205::<\1kkm\226\377\377\377\1" \ + "\376\376\376\202\377\377\377\2kkm99;\202::<\4;;=::<\204\204\206\376\376" \ + "\376\202\377\377\377\1\376\376\376\224\377\377\377\1\376\376\376\203" \ + "\377\377\377\2\376\376\376\265\265\265\202::<\1;;=\202::<\3;;=\316\316" \ + "\320\316\316\316\204::<\3;;=::<\266\266\266\236\377\377\377\1\234\234" \ + "\236\205::<\1\234\234\234\226\377\377\377\202\376\376\376\2\377\377\377" \ + "\376\376\376\205\377\377\377\4\376\376\376\251\251\253;;=99;\202::<\4" \ + "<<>99;::<\250\250\252\217\377\377\377\1\234\234\234\205::<\1\234\234" \ + "\236\266\377\377\377\3\214\305@\214\306>\214\305@\207\214\306>\4\214" \ + "\305@\215\305>\214\306>\252\324p\251\377\377\377\215\214\306>\1\250\325" \ + "p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\220\214\306>" \ + "\202\214\305@\6\212\306@\215\307\77\243\321d\377\377\375\377\375\377" \ + "\376\377\377\216\377\377\377\213\214\306>\3\215\305>\214\306>\305\342" \ + "\240\215\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306" \ + ">\3\214\305@\214\306>\214\305@\232\377\377\377\4\252\324p\214\306>\215" \ + "\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\211\377\377" \ + "\377\2\376\377\377\377\377\375\202\377\377\377\1\376\376\376\202\377" \ + "\377\377\6\376\377\372\376\377\377\377\376\377\331\357\301\213\304\77" \ + "\215\307=\202\214\305@\25\214\305B\214\306<\215\305@\212\307<\214\306" \ + ">\216\306=\212\307>\212\306B\214\305@\215\306E\212\306@\313\347\255\376" \ + "\377\375\376\376\377\376\377\377\377\376\377\377\377\377\333\355\305" \ + "\212\307>\216\306\77\215\307\77\202\214\306>\1\215\307\77\202\214\306" \ + ">\13\215\305<\212\306@\212\307<\215\307\77\211\306=\213\307A\233\314" \ + "V\370\373\362\377\377\375\377\377\377\376\377\377\202\377\377\375\2\374" \ + "\377\377\377\375\376\222\377\377\377\3\363\363\363GGI::<\202;;=\202:" \ + ":<\2;;=\234\234\234\214\377\377\377\1\376\376\376\221\377\377\377\1\376" \ + "\376\376\202\377\377\377\3\376\376\376\377\377\377\376\376\376\206\377" \ + "\377\377\3\376\376\376\377\377\377\316\316\316\203\377\377\377\1\376" \ + "\376\376\203\377\377\377\1\376\376\376\213\377\377\377\1\316\316\316" \ + "\205::<\1kkm\227\377\377\377\5\376\376\376\377\377\377\235\235\237::" \ + "<;;=\203::<\2lln\376\376\376\203\377\377\377\1\376\376\376\224\377\377" \ + "\377\13\376\376\376\377\377\377\376\376\376\377\377\377RRR::<99;::<;" \ + ";=::\214\305@\207\214\306" \ + ">\4\214\305@\215\305>\214\306>\252\324p\251\377\377\377\215\214\306>" \ + "\1\250\325p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\221" \ + "\214\306>\5\213\307A\216\306\77\212\307<\214\306>\277\337\223\220\377" \ + "\377\377\213\214\306>\3\215\305>\214\306>\305\342\240\215\377\377\377" \ + "\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306" \ + ">\214\305@\232\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207" \ + "\214\306>\3\214\305@\214\306>\214\305@\211\377\377\377\4\376\377\377" \ + "\377\377\375\377\375\377\377\377\377\202\377\377\375\202\377\376\377" \ + "\202\376\377\377\22\377\376\377\262\331~\213\304\77\213\310\77\216\306" \ + "A\212\307<\215\306A\214\304=\213\310\77\214\305@\215\304B\214\305B\214" \ + "\306<\212\307>\212\307<\216\306A\221\312I\370\373\362\203\377\377\377" \ + "\13\370\373\364\226\310K\214\306>\212\307>\215\304B\214\306>\215\306" \ + "A\213\304\77\215\306A\214\306>\215\305@\202\212\306@\13\215\307\77\213" \ + "\310=\220\303@\336\362\315\377\376\377\377\377\377\374\377\377\377\376" \ + "\377\377\377\377\376\376\374\376\377\375\223\377\377\377\1\204\204\206" \ + "\203::<\4""99;;;=::\214\305@\207\214\306>\4\214\305@\215\305>\214" \ + "\306>\252\324p\251\377\377\377\215\214\306>\1\250\325p\216\377\377\377" \ + "\1\342\361\320\202\214\306>\1\214\305@\220\214\306>\10\215\304B\214\306" \ + "<\214\305@\215\305@\212\306@\215\305>\323\354\265\377\376\377\216\377" \ + "\377\377\213\214\306>\3\215\305>\214\306>\305\342\240\215\377\377\377" \ + "\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306" \ + ">\214\305@\232\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207" \ + "\214\306>\3\214\305@\214\306>\214\305@\212\377\377\377\3\375\377\376" \ + "\377\377\377\377\377\375\202\377\377\377\26\377\377\375\375\377\374\376" \ + "\377\377\377\376\377\377\377\375\365\375\362\225\311K\212\306@\214\306" \ + ">\214\305@\212\306@\216\306=\211\306;\215\306A\214\306>\215\307\77\217" \ + "\304@\214\306>\212\307>\215\305@\214\305@\262\327z\203\377\377\377\13" \ + "\260\331{\213\310\77\214\305B\214\305@\215\305@\215\307\77\212\307<\216" \ + "\306A\213\305;\214\305@\215\305>\202\214\306>\11\215\305@\214\306<\276" \ + "\340\224\377\376\375\377\377\375\376\377\377\377\376\375\376\377\375" \ + "\377\376\377\202\377\377\377\1\376\377\375\221\377\377\377\1\346\346" \ + "\346\206::<\2:::\346\346\346\202\377\377\377\1\376\376\376\276\377\377" \ + "\377\1\316\316\316\205::<\1kkm\216\377\377\377\1\376\376\376\202\377" \ + "\377\377\1\376\376\376\207\377\377\377\3\234\234\236::<;;=\203::<\1k" \ + "km\226\377\377\377\1\376\376\376\204\377\377\377\2\376\376\376lln\205" \ + "::<\1``b\204\377\377\377\1SSS\205::<\1kkm\235\377\377\377\1\234\234\236" \ + "\205::<\1\234\234\234\242\377\377\377\2\316\316\316:::\202::<\5;;=::" \ + "<;;=FFH\363\363\363\206\377\377\377\1\376\376\376\206\377\377\377\1\234" \ + "\234\234\205::<\1\234\234\236\266\377\377\377\3\214\305@\214\306>\214" \ + "\305@\207\214\306>\4\214\305@\215\305>\214\306>\252\324p\251\377\377" \ + "\377\215\214\306>\1\250\325p\216\377\377\377\1\342\361\320\202\214\306" \ + ">\1\214\305@\210\214\306>\27\215\306A\212\307>\215\305>\215\305@\215" \ + "\307=\217\304B\214\306<\214\305@\215\307\77\215\305@\215\307\77\214\305" \ + "@\216\306\77\211\310<\226\312L\347\364\332\377\377\377\377\376\377\377" \ + "\377\375\374\377\377\377\376\377\376\376\376\376\377\377\207\377\377" \ + "\377\213\214\306>\3\215\305>\214\306>\305\342\240\215\377\377\377\4\252" \ + "\324p\214\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214" \ + "\305@\232\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306" \ + ">\3\214\305@\214\306>\214\305@\221\377\377\377\1\377\377\375\203\377" \ + "\377\377\5\333\355\303\214\306>\212\307<\216\306A\214\305@\202\214\306" \ + ">\15\215\305@\214\306>\212\306@\213\310\77\215\305>\216\306A\211\306" \ + "=\212\306@\212\307<\334\354\305\377\377\375\335\354\303\212\307>\210" \ + "\214\306>\10\216\306A\212\307;\215\306A\216\306A\214\305@\241\321a\371" \ + "\374\361\375\376\377\223\377\377\377\1\376\376\376\204\377\377\377\2" \ + "\376\376\376\234\234\234\203::<\1""99;\202::<\1\234\234\234\302\377\377" \ + "\377\1\316\316\316\205::<\1kkm\217\377\377\377\1\376\376\376\202\377" \ + "\377\377\3\376\376\376\377\377\377\376\376\376\202\377\377\377\3\376" \ + "\376\376\377\377\377xxz\202::<\5""99;::<;;=xxz\376\376\377\232\377\377" \ + "\377\3\317\317\31799;;;=\202::<\5;;=::<\265\265\265\377\377\377\376\376" \ + "\376\202\377\377\377\2\265\265\265;;=\202::<\203;;=\1\332\332\332\203" \ + "\377\377\377\1\376\376\376\230\377\377\377\1\234\234\236\205::<\1\234" \ + "\234\234\242\377\377\377\4\376\376\376\204\204\204::<;;=\202::<\3;;=" \ + "::<\266\266\266\207\377\377\377\1\376\376\376\205\377\377\377\1\234\234" \ + "\234\205::<\1\234\234\236\266\377\377\377\3\214\305@\214\306>\214\305" \ + "@\207\214\306>\4\214\305@\215\305>\214\306>\252\324p\251\377\377\377" \ + "\215\214\306>\1\250\325p\216\377\377\377\1\342\361\320\202\214\306>\1" \ + "\214\305@\211\214\306>\27\216\306A\214\306>\212\306@\214\306<\213\310" \ + "\77\215\305@\215\307\77\213\305=\216\306\77\212\307;\212\306@\215\305" \ + ">\215\306A\212\307>\245\320d\367\375\361\376\377\377\377\376\377\377" \ + "\377\377\376\376\377\377\376\377\375\377\376\377\377\375\206\377\377" \ + "\377\213\214\306>\3\215\305>\214\306>\305\342\240\215\377\377\377\4\252" \ + "\324p\214\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214" \ + "\305@\232\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306" \ + ">\3\214\305@\214\306>\214\305@\221\377\377\377\6\376\376\376\377\376" \ + "\377\377\377\377\375\377\376\376\377\377\270\333\207\203\214\306>\17" \ + "\211\306=\212\307<\214\306<\214\305@\215\307\77\214\305@\216\305C\214" \ + "\306>\212\310A\215\305@\216\306\77\223\312K\360\371\346\222\311I\214" \ + "\305@\210\214\306>\10\214\305@\212\307>\214\305@\216\306A\215\307=\350" \ + "\364\334\375\377\376\377\376\377\225\377\377\377\7\376\376\376\377\377" \ + "\377\376\376\376\377\377\377SSS::<;;=\203::<\5FFH\364\364\364\376\376" \ + "\376\377\377\377\376\376\376\277\377\377\377\1\316\316\316\205::<\1k" \ + "km\222\377\377\377\1\376\376\376\204\377\377\377\3\376\376\376\377\377" \ + "\377SSU\205::<\1\234\234\236\202\377\377\377\1\376\376\376\202\377\377" \ + "\377\1\376\376\376\220\377\377\377\1\376\376\376\204\377\377\377\2kk" \ + "m;;=\202::<\5;;=::\214\305@\207\214\306>\4\214\305" \ + "@\215\305>\214\306>\252\324p\251\377\377\377\215\214\306>\1\250\325p" \ + "\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\211\214\306>\27" \ + "\214\304=\215\305>\213\307A\212\306@\214\305B\215\305<\213\310=\215\307" \ + "\77\215\304B\214\306<\213\307A\215\305>\216\306A\212\306@\212\307>\270" \ + "\332\204\377\376\377\377\377\377\377\376\377\376\376\374\377\377\373" \ + "\377\376\377\377\377\375\206\377\377\377\213\214\306>\3\215\305>\214" \ + "\306>\305\342\240\215\377\377\377\4\252\324p\214\306>\215\305>\214\305" \ + "@\207\214\306>\3\214\305@\214\306>\214\305@\232\377\377\377\4\252\324" \ + "p\214\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305" \ + "@\223\377\377\377\1\377\377\375\202\377\377\377\2\371\372\364\232\315" \ + "W\202\214\305@\4\214\306<\215\307\77\214\305B\215\306C\202\215\306A\1" \ + "\214\306<\202\212\307>\6\215\305@\212\307>\215\305>\212\306B\216\306" \ + "A\212\307>\210\214\306>\10\214\305B\215\307\77\214\306<\214\306>\304" \ + "\341\237\377\377\377\377\376\377\377\377\375\220\377\377\377\1\376\376" \ + "\376\203\377\377\377\1\376\376\376\203\377\377\377\10\301\301\301::<" \ + ";;=99;;;=::<99;\234\234\236\207\377\377\377\1\376\376\376\273\377\377" \ + "\377\1\316\316\316\205::<\1kkm\216\377\377\377\1\376\376\376\202\377" \ + "\377\377\1\376\376\376\204\377\377\377\3\376\376\376\377\377\377\315" \ + "\315\315\202;;=\203::<\6;;=\265\265\267\377\377\377\376\376\376\377\377" \ + "\377\376\376\376\225\377\377\377\2\376\376\376\317\317\317\203::<\4;" \ + ";=::<;;=\264\264\264\206\377\377\377\10\234\234\234;;=::<;;=99;;;=::" \ + "<\346\346\346\233\377\377\377\1\234\234\236\205::<\1\234\234\234\237" \ + "\377\377\377\1\376\376\376\204\377\377\377\1\204\204\206\202::<\6;;=" \ + "99;;;=::<\346\346\346\376\376\376\204\377\377\377\3\376\376\376\377\377" \ + "\377\376\376\376\204\377\377\377\1\234\234\234\205::<\1\234\234\236\266" \ + "\377\377\377\3\214\305@\214\306>\214\305@\207\214\306>\4\214\305@\215" \ + "\305>\214\306>\252\324p\251\377\377\377\215\214\306>\1\250\325p\216\377" \ + "\377\377\1\342\361\320\202\214\306>\1\214\305@\210\214\306>\22\215\307" \ + "\77\212\307>\216\306A\212\304<\215\307\77\215\305@\216\306\77\213\307" \ + "A\214\306>\214\305@\215\307\77\213\310=\212\307>\214\306>\214\306<\214" \ + "\306>\216\306\77\324\353\267\202\376\376\376\3\377\377\377\376\376\377" \ + "\376\377\375\207\377\377\377\213\214\306>\3\215\305>\214\306>\305\342" \ + "\240\215\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306" \ + ">\3\214\305@\214\306>\214\305@\232\377\377\377\4\252\324p\214\306>\215" \ + "\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\221\377\377" \ + "\377\3\376\377\377\377\377\377\376\377\375\202\377\377\377\7\377\376" \ + "\377\341\363\315\215\305@\214\305@\215\306A\215\305@\216\306\77\202\214" \ + "\306>\12\214\305B\212\307<\213\304A\213\310=\216\306A\211\306;\213\310" \ + "=\214\305@\212\307>\215\305>\210\214\306>\10\215\307\77\214\304=\212" \ + "\307>\243\322b\377\377\377\376\377\377\377\376\377\377\377\375\226\377" \ + "\377\377\4\376\376\376\377\377\377\204\204\206;;=\203::<\3""99;;;=\364" \ + "\364\364\205\377\377\377\1\376\376\376\275\377\377\377\1\316\316\316" \ + "\205::<\1kkm\217\377\377\377\202\376\376\376\202\377\377\377\1\376\376" \ + "\376\203\377\377\377\4\376\376\376xxz;;=99;\202;;=\4::<;;=\346\346\346" \ + "\376\376\376\204\377\377\377\1\376\376\376\224\377\377\377\1xxz\203:" \ + ":<\3;;=::\214\305" \ + "@\207\214\306>\4\214\305@\215\305>\214\306>\252\324p\251\377\377\377" \ + "\215\214\306>\1\250\325p\216\377\377\377\1\342\361\320\202\214\306>\1" \ + "\214\305@\210\214\306>\7\213\305=\214\306<\210\306\77\216\306\77\215" \ + "\307=\214\306>\215\307\77\202\214\306>\14\215\307\77\214\305B\214\306" \ + "<\212\307<\214\305@\216\306\77\215\305>\214\305@\224\313L\352\364\331" \ + "\374\377\377\377\376\377\211\377\377\377\213\214\306>\3\215\305>\214" \ + "\306>\305\342\240\215\377\377\377\4\252\324p\214\306>\215\305>\214\305" \ + "@\207\214\306>\3\214\305@\214\306>\214\305@\232\377\377\377\4\252\324" \ + "p\214\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305" \ + "@\222\377\377\377\1\376\377\377\202\377\377\377\24\376\376\374\376\377" \ + "\375\377\375\377\277\337\224\214\306>\212\307>\215\307\77\214\304=\215" \ + "\307=\213\304A\214\306<\212\307>\215\307\77\214\305@\213\304\77\215\307" \ + "\77\215\305@\214\304=\215\305<\215\306A\210\214\306>\1\212\307>\202\215" \ + "\306A\4\350\365\333\377\375\376\377\376\377\375\376\377\226\377\377\377" \ + "\1\376\376\376\202\377\377\377\3TTV::<99;\202;;=\4::<\203\203\203\377" \ + "\377\377\376\376\376\302\377\377\377\1\316\316\316\205::<\1kkm\222\377" \ + "\377\377\1\376\376\376\204\377\377\377\3\300\300\302;;=::<\202;;=\202" \ + "::<\2```\376\376\376\227\377\377\377\7\376\376\376\377\377\377\346\346" \ + "\346;;=99;::<;;=\202::<\3\251\251\251\377\377\377\376\376\376\206\377" \ + "\377\377\1\234\234\234\202::<\1;;=\202::<\2;;=\346\346\346\232\377\377" \ + "\377\1\234\234\236\205::<\1\234\234\234\235\377\377\377\1\376\376\376" \ + "\207\377\377\377\11SSU::<;;=99;<<>::\214\305@\207\214\306>\4\214\305@\215\305>\214\306>\252" \ + "\324p\251\377\377\377\215\214\306>\1\250\325p\216\377\377\377\1\342\361" \ + "\320\202\214\306>\1\214\305@\210\214\306>\25\213\307A\216\306A\232\315" \ + "W\215\306C\212\306@\214\305@\212\307;\216\306A\215\305>\215\307\77\214" \ + "\305@\215\307\77\214\306>\214\305@\212\306B\213\307C\214\306>\215\305" \ + "@\232\315V\372\374\367\376\376\376\202\377\377\375\1\376\376\376\206" \ + "\377\377\377\213\214\306>\3\215\305>\214\306>\305\342\240\215\377\377" \ + "\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3\214\305@\214" \ + "\306>\214\305@\232\377\377\377\4\252\324p\214\306>\215\305>\214\305@" \ + "\207\214\306>\3\214\305@\214\306>\214\305@\221\377\377\377\5\377\376" \ + "\377\376\377\377\377\375\376\377\376\377\376\377\377\202\377\377\377" \ + "\10\370\373\362\233\314V\213\307A\211\306=\215\307\77\212\307<\212\306" \ + "@\215\305<\202\214\306>\7\215\307=\215\306A\214\305@\212\307>\216\306" \ + "A\212\306@\215\307=\210\214\306>\10\212\307>\212\307<\313\347\254\376" \ + "\377\377\377\377\377\377\376\377\376\377\377\377\377\375\223\377\377" \ + "\377\1\376\376\376\203\377\377\377\1\332\332\332\202::<\1;;=\203::<\1" \ + "\302\302\302\203\377\377\377\5\376\376\376\377\377\377\376\376\376\377" \ + "\377\377\376\376\376\274\377\377\377\1\316\316\316\205::<\1kkm\217\377" \ + "\377\377\1\376\376\376\206\377\377\377\3\332\332\334FFH;;=\205::<\1\265" \ + "\265\265\202\377\377\377\1\376\376\376\224\377\377\377\1\376\376\376" \ + "\202\377\377\377\1\205\205\207\202::<\1;;=\202::<\2GGI\363\363\363\202" \ + "\377\377\377\1\376\376\376\205\377\377\377\1\363\363\363\202::<\1;;=" \ + "\202::<\2""99;\234\234\234\203\377\377\377\1\376\376\376\226\377\377" \ + "\377\1\234\234\236\205::<\1\234\234\234\234\377\377\377\1\376\376\376" \ + "\210\377\377\377\3\222\222\222::<99;\202;;=\5""99;GGI\376\376\376\377" \ + "\377\377\376\376\376\211\377\377\377\1\234\234\234\205::<\1\234\234\236" \ + "\266\377\377\377\3\214\305@\214\306>\214\305@\207\214\306>\4\214\305" \ + "@\215\305>\214\306>\252\324p\251\377\377\377\215\214\306>\1\250\325p" \ + "\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\210\214\306>\10" \ + "\213\307A\214\306>\331\356\303\232\315W\215\305>\215\306A\214\305B\214" \ + "\306>\202\214\305@\7\213\310=\214\306>\215\304B\215\306A\211\306;\213" \ + "\310\77\214\305@\202\215\307\77\2\257\326{\376\377\373\202\377\377\377" \ + "\1\377\377\375\206\377\377\377\213\214\306>\3\215\305>\214\306>\305\342" \ + "\240\215\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306" \ + ">\3\214\305@\214\306>\214\305@\232\377\377\377\4\252\324p\214\306>\215" \ + "\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\221\377\377" \ + "\377\6\377\377\373\377\377\375\377\377\377\376\376\377\377\376\377\373" \ + "\377\374\202\377\376\377\4\336\362\315\220\303@\213\310=\215\307\77\202" \ + "\212\306@\1\215\305@\202\214\306>\7\213\305=\214\306>\213\305=\214\305" \ + "@\213\310\77\212\306@\213\307A\210\214\306>\10\215\307\77\252\324p\377" \ + "\377\375\376\377\377\377\377\375\377\377\377\377\376\377\377\377\375" \ + "\220\377\377\377\1\376\376\376\203\377\377\377\1\376\376\376\202\377" \ + "\377\377\1\265\265\265\204::<\5;;=::<\363\363\363\377\377\377\376\376" \ + "\376\302\377\377\377\1\316\316\316\205::<\1kkm\225\377\377\377\2\317" \ + "\317\317FFH\206::<\1SSU\204\377\377\377\1\376\376\376\225\377\377\377" \ + "\2\346\346\346;;=\203::<\3;;=::<\234\234\236\202\377\377\377\1\376\376" \ + "\376\207\377\377\377\2\204\204\206;;=\204::<\2FFF\362\362\362\231\377" \ + "\377\377\1\234\234\236\205::<\1\234\234\234\245\377\377\377\1\301\301" \ + "\301\202::<\6;;=::<;;=::<\347\347\347\376\376\376\212\377\377\377\1\234" \ + "\234\234\205::<\1\234\234\236\266\377\377\377\3\214\305@\214\306>\214" \ + "\305@\207\214\306>\4\214\305@\215\305>\214\306>\252\324p\251\377\377" \ + "\377\215\214\306>\1\250\325p\216\377\377\377\1\342\361\320\202\214\306" \ + ">\1\214\305@\210\214\306>\27\214\305@\215\305<\342\362\315\353\365\334" \ + "\223\312K\215\305<\212\306@\215\305<\212\307>\215\306A\214\306>\212\307" \ + ">\215\307\77\215\304B\215\307\77\215\305@\214\306>\215\305>\214\305@" \ + "\215\305<\315\345\253\377\377\375\376\377\377\207\377\377\377\213\214" \ + "\306>\3\215\305>\214\306>\305\342\240\215\377\377\377\4\252\324p\214" \ + "\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\232" \ + "\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3\214" \ + "\305@\214\306>\214\305@\221\377\377\377\14\376\377\377\376\376\377\377" \ + "\377\377\377\377\373\376\377\375\377\376\377\376\377\377\377\377\377" \ + "\377\376\375\276\340\224\214\306<\215\305@\202\214\306>\12\215\305>\214" \ + "\305@\215\305@\214\305@\213\310\77\214\306>\216\306\77\211\305\77\215" \ + "\307=\214\305@\210\214\306>\4\223\312K\360\367\347\377\377\377\377\377" \ + "\375\232\377\377\377\2\376\376\376\234\234\236\204::<\2;;=___\234\377" \ + "\377\377\1\376\376\376\203\377\377\377\1\376\376\376\244\377\377\377" \ + "\1\316\316\316\205::<\1kkm\202\377\377\377\1\376\376\376\216\377\377" \ + "\377\4\376\376\376\377\377\377\347\347\347\204\204\204\203::<\6;;=::" \ + "<;;=::<;;=\301\301\303\226\377\377\377\1\376\376\376\203\377\377\377" \ + "\1\203\203\205\202;;=\5::<;;=::\214\305@\207\214\306>\4" \ + "\214\305@\215\305>\214\306>\252\324p\251\377\377\377\215\214\306>\1\250" \ + "\325p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\210\214\306" \ + ">\40\213\307A\215\305>\341\360\317\377\375\376\324\353\267\215\304B\214" \ + "\306>\215\307=\214\305@\212\307>\212\307<\215\305<\215\306A\214\306>" \ + "\214\306<\212\306@\214\305@\215\307\77\216\306=\212\306B\214\306>\352" \ + "\364\333\377\376\377\377\377\377\377\376\377\377\377\377\377\377\375" \ + "\376\377\373\375\376\377\377\376\377\214\306>\215\307\77\211\214\306" \ + ">\3\215\305>\214\306>\305\342\240\215\377\377\377\4\252\324p\214\306" \ + ">\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\232\377" \ + "\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3\214\305" \ + "@\214\306>\214\305@\232\377\377\377\7\374\377\375\242\321a\216\306A\212" \ + "\307>\214\306>\215\307\77\212\307<\210\214\306>\16\215\307\77\214\307" \ + ";\213\304\77\216\306A\214\305B\215\307\77\215\305>\212\307>\320\345\254" \ + "\374\377\377\377\376\377\377\377\375\377\376\377\375\377\372\223\377" \ + "\377\377\1\376\376\376\203\377\377\377\3\376\376\376\377\377\377kkm\203" \ + "::<\3<<>::<\221\221\221\305\377\377\377\1\316\316\316\204::<\2;;=jjl" \ + "\217\377\377\377\16\316\316\316\300\300\300\234\234\234__a::<;;=::<;" \ + ";=::<99;;;=::<;;=\204\204\206\232\377\377\377\1\362\362\362\202;;=\202" \ + "::<\3""99;::<\235\235\235\212\377\377\377\12\376\376\376\377\377\377" \ + "\205\205\20799;;;=::<;;=::\214\305" \ + "@\207\214\306>\4\214\305@\215\305>\214\306>\252\324p\251\377\377\377" \ + "\215\214\306>\1\250\325p\216\377\377\377\1\342\361\320\202\214\306>\1" \ + "\214\305@\210\214\306>\202\214\306<\32\342\361\322\377\377\377\377\377" \ + "\375\266\334\205\212\306B\215\307\77\212\306@\220\306=\214\306>\215\307" \ + "\77\214\305B\213\305=\216\306\77\215\307\77\215\305<\212\306B\215\306" \ + "A\215\305@\216\306=\232\315V\371\373\360\377\377\375\377\377\377\375" \ + "\376\377\377\375\377\376\376\377\202\377\377\377\2\214\305@\212\307>" \ + "\211\214\306>\3\215\305>\214\306>\305\342\240\215\377\377\377\4\252\324" \ + "p\214\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305" \ + "@\232\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>" \ + "\3\214\305@\214\306>\214\305@\233\377\377\377\5\347\365\334\211\306=" \ + "\215\305>\216\306=\214\305@\211\214\306>\2\215\304B\212\307>\202\214" \ + "\306>\14\215\306A\214\306<\215\305@\252\324p\374\377\377\377\377\377" \ + "\377\375\376\377\376\377\376\376\377\377\377\375\377\377\377\377\375" \ + "\377\222\377\377\377\1\376\376\376\203\377\377\377\4\376\376\376lln:" \ + ":<;;=\203::<\2\235\235\235\376\376\376\304\377\377\377\1\316\316\316" \ + "\205::<\202;;=\2::<;;=\202::<\1;;=\211::<\202;;=\204::<\1""99;\202::" \ + "<\5;;=::<;;=__a\376\376\376\224\377\377\377\1\376\376\376\205\377\377" \ + "\377\1\235\235\235\206::<\3\346\346\346\377\377\377\376\376\376\207\377" \ + "\377\377\5\376\376\376\377\377\377\376\376\376\346\346\350;;=\203::<" \ + "\3;;=::<\265\265\265\230\377\377\377\1\234\234\236\205::<\1\234\234\234" \ + "\246\377\377\377\1lln\202::<\4""99;;;=99;\234\234\234\213\377\377\377" \ + "\1\234\234\234\203::<\7;;=::<;;=::<;;=::<;;=\222::<\7;;=99;;;=::<;;=" \ + "::<\316\316\316\231\377\377\377\3\214\305@\214\306>\214\305@\207\214" \ + "\306>\4\214\305@\215\305>\214\306>\252\324p\251\377\377\377\215\214\306" \ + ">\1\250\325p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\210" \ + "\214\306>\13\216\306A\213\310\77\343\361\320\377\377\375\375\377\376" \ + "\371\374\361\242\320c\213\310\77\216\306\77\214\306>\215\306A\202\214" \ + "\305@\2\216\306A\213\305=\204\214\306>\11\213\307A\216\306A\212\307>" \ + "\260\331y\377\376\377\376\377\375\377\377\373\376\377\377\377\377\377" \ + "\202\377\376\377\2\212\311=\215\306A\211\214\306>\3\215\305>\214\306" \ + ">\305\342\240\215\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207" \ + "\214\306>\3\214\305@\214\306>\214\305@\232\377\377\377\4\252\324p\214" \ + "\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\231" \ + "\377\377\377\6\377\376\377\377\377\373\377\376\377\305\342\240\212\310" \ + "\77\214\304=\202\215\305@\210\214\306>\4\215\305>\213\305=\212\306@\215" \ + "\306A\202\214\306>\10\222\312M\370\373\362\377\376\377\377\375\376\377" \ + "\376\377\377\377\377\376\377\375\377\377\377\202\377\376\377\221\377" \ + "\377\377\1\376\376\376\205\377\377\377\2::<;;=\202::<\202;;=\3\300\300" \ + "\300\377\377\377\376\376\376\235\377\377\377\1\376\376\376\245\377\377" \ + "\377\1\316\316\316\207::<\5;;=::<;;=::<;;=\210::<\202;;=\2""99;;;=\202" \ + "::<\3;;=::<;;=\202::<\3;;=xxz\363\363\363\225\377\377\377\3\376\376\376" \ + "\377\377\377\376\376\376\202\377\377\377\3\363\363\363FFH::<\202;;=\202" \ + "::<\1\204\204\206\205\377\377\377\1\376\376\376\205\377\377\377\1\376" \ + "\376\376\202\377\377\377\1kkm\202::<\1;;=\202::<\1SSU\230\377\377\377" \ + "\1\234\234\236\205::<\1\234\234\234\244\377\377\377\3\376\376\376\377" \ + "\377\377xxz\202::<\1;;=\202::<\3xxx\377\377\377\376\376\376\211\377\377" \ + "\377\1\234\234\234\203::<\1;;=\202::<\1;;=\224::<\5;;=99;;;=::<;;=\202" \ + "::<\1\316\316\316\231\377\377\377\3\214\305@\214\306>\214\305@\207\214" \ + "\306>\4\214\305@\215\305>\214\306>\252\324p\251\377\377\377\215\214\306" \ + ">\1\250\325p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\210" \ + "\214\306>\3\214\305@\214\306<\343\361\316\202\377\377\377\26\377\376" \ + "\374\353\365\335\223\312K\211\305\77\215\307=\215\306C\211\306;\214\306" \ + ">\215\305@\215\307\77\214\305@\213\307A\214\306>\212\307<\216\306\77" \ + "\212\306B\215\305>\212\306@\304\341\236\377\376\377\375\377\376\377\377" \ + "\375\203\377\377\377\2\212\306@\214\306<\211\214\306>\3\215\305>\214" \ + "\306>\305\342\240\215\377\377\377\4\252\324p\214\306>\215\305>\214\305" \ + "@\207\214\306>\3\214\305@\214\306>\214\305@\232\377\377\377\4\252\324" \ + "p\214\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305" \ + "@\231\377\377\377\2\377\377\373\376\377\377\202\377\377\377\4\241\321" \ + "c\215\306A\215\305>\213\310\77\210\214\306>\20\215\305@\215\307=\213" \ + "\310\77\214\304;\216\306\77\213\310\77\333\355\303\377\375\376\377\377" \ + "\375\377\376\377\377\377\377\375\377\374\376\377\377\377\377\377\377" \ + "\377\375\376\376\376\222\377\377\377\1\376\376\376\204\377\377\377\206" \ + "::<\2\316\316\316\376\376\376\234\377\377\377\1\376\376\376\247\377\377" \ + "\377\1\316\316\316\204::<\1;;=\205::<\1;;=\212::<\4""99;;;=::<;;=\203" \ + "::<\1;;=\202::<\1\233\233\233\234\377\377\377\3\235\235\23799;;;=\203" \ + "::<\2;;=\346\346\346\203\377\377\377\1\376\376\376\204\377\377\377\3" \ + "\376\376\376\377\377\377\376\376\376\203\377\377\377\4\316\316\320;;" \ + "=::<;;=\202::<\2;;=\264\264\264\227\377\377\377\1\234\234\236\205::<" \ + "\1\234\234\234\246\377\377\377\2\234\234\236;;=\203::<\2;;=kkk\213\377" \ + "\377\377\1\234\234\234\204::<\3;;=::<;;=\225::<\2;;=99;\202::<\3;;=:" \ + "::\316\316\316\231\377\377\377\3\214\305@\214\306>\214\305@\207\214\306" \ + ">\4\214\305@\215\305>\214\306>\252\324p\251\377\377\377\215\214\306>" \ + "\1\250\325p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\210" \ + "\214\306>\14\215\307\77\215\305@\340\361\315\376\376\376\377\376\377" \ + "\377\377\375\377\377\377\323\353\267\212\307>\215\305@\214\305@\214\311" \ + "@\202\214\306>\22\212\307>\215\305@\214\306>\212\306@\214\305@\215\305" \ + ">\215\307=\214\306>\214\304=\215\307\77\341\362\316\377\376\377\377\377" \ + "\377\376\376\376\377\377\375\375\376\377\217\307@\212\306@\211\214\306" \ + ">\3\215\305>\214\306>\305\342\240\215\377\377\377\4\252\324p\214\306" \ + ">\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\232\377" \ + "\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3\214\305" \ + "@\214\306>\214\305@\232\377\377\377\7\377\376\377\376\377\377\377\377" \ + "\377\352\364\331\212\307<\215\307=\212\307>\211\214\306>\13\212\306@" \ + "\214\306<\216\306A\214\305@\252\322q\376\376\377\376\377\373\377\376" \ + "\377\376\376\377\377\377\375\376\377\377\203\377\377\377\1\376\377\375" \ + "\227\377\377\377\202::<\202;;=\3::<;;=\316\316\316\233\377\377\377\1" \ + "\375\375\375\251\377\377\377\1\316\316\316\211::<\1;;=\213::<\3;;=::" \ + "<;;=\204::<\3""99;\205\205\207\346\346\346\233\377\377\377\4\376\376" \ + "\376\364\364\364FFH;;=\202::<\202;;=\1\204\204\204\215\377\377\377\1" \ + "\376\376\376\202\377\377\377\7kkm::<99;::<;;=99;TTV\227\377\377\377\1" \ + "\234\234\236\205::<\1\234\234\234\246\377\377\377\1\234\234\236\202:" \ + ":<\202;;=\2::\214\305@\207\214\306>\4\214\305@\215\305>\214\306>\252\324p\251" \ + "\377\377\377\215\214\306>\1\250\325p\216\377\377\377\1\342\361\320\202" \ + "\214\306>\1\214\305@\210\214\306>\202\214\305@\15\341\362\316\377\377" \ + "\375\376\377\375\377\377\377\373\377\374\377\376\377\271\332\211\212" \ + "\307>\212\307<\214\305B\214\305@\216\306\77\212\307>\202\215\307\77\11" \ + "\214\305B\215\306A\212\311=\214\303A\214\306>\215\306A\212\307>\225\311" \ + "K\371\372\362\202\377\377\375\202\377\377\377\2\214\305@\215\306A\211" \ + "\214\306>\3\215\305>\214\306>\305\342\240\215\377\377\377\4\252\324p" \ + "\214\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305" \ + "@\232\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>" \ + "\3\214\305@\214\306>\214\305@\231\377\377\377\10\376\377\377\377\376" \ + "\377\377\377\375\377\375\376\331\356\303\214\306>\214\305B\215\307\77" \ + "\210\214\306>\12\215\305>\212\306B\215\304B\214\306>\215\307=\224\310" \ + "J\364\370\351\376\376\374\375\377\372\377\377\375\203\377\377\377\3\377" \ + "\376\377\377\377\377\376\377\375\221\377\377\377\3\376\376\376\377\377" \ + "\377\376\376\376\203\377\377\377\7::<;;=99;::<;;=::<\315\315\315\232" \ + "\377\377\377\1\376\376\376\203\377\377\377\1\376\376\376\246\377\377" \ + "\377\1\316\316\316\204::<\1;;=\202::<\1;;=\203::<\1;;=\210::<\1;;=\202" \ + "::<\1;;=\202::<\4``b\233\233\235\347\347\351\376\376\376\235\377\377" \ + "\377\2\265\265\265;;=\202::<\1;;=\202::<\1\332\332\332\216\377\377\377" \ + "\3\376\376\376\377\377\377\302\302\302\206::<\1\315\315\315\226\377\377" \ + "\377\1\234\234\236\205::<\1\234\234\234\245\377\377\377\2\376\376\376" \ + "\235\235\237\205::<\1jjj\203\377\377\377\3\376\376\376\377\377\377\376" \ + "\376\376\205\377\377\377\1\234\234\234\204::<\2;;=kkm\202\234\234\236" \ + "\1\233\233\235\223\234\234\234\202\235\235\235\1\233\233\233\203\234" \ + "\234\234\1\346\346\346\231\377\377\377\3\214\305@\214\306>\214\305@\207" \ + "\214\306>\4\214\305@\215\305>\214\306>\252\324p\251\377\377\377\215\214" \ + "\306>\1\250\325p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305" \ + "@\210\214\306>\17\212\307>\216\306A\342\360\315\376\377\377\376\376\374" \ + "\375\377\376\377\376\377\377\376\374\377\377\375\242\320d\215\307=\214" \ + "\306>\214\305@\215\305@\212\306@\202\214\305@\17\215\305@\212\307>\215" \ + "\307\77\214\306<\215\306A\213\304\77\215\306A\215\307\77\252\324n\377" \ + "\377\377\375\377\376\377\376\377\377\377\375\212\307<\215\305@\211\214" \ + "\306>\3\215\305>\214\306>\305\342\240\215\377\377\377\4\252\324p\214" \ + "\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\232" \ + "\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3\214" \ + "\305@\214\306>\214\305@\232\377\377\377\6\376\377\375\377\375\377\367" \ + "\375\363\223\312H\216\306\77\215\305>\212\214\306>\2\215\305@\214\306" \ + ">\202\212\307>\3\214\305@\247\324o\377\376\377\202\377\377\377\2\377" \ + "\376\377\377\377\375\233\377\377\377\2::<;;=\204::<\2\316\316\316\376" \ + "\376\376\236\377\377\377\3\316\316\316;;;:::\230::<\213\377\377\377\1" \ + "\316\316\316\224::<\6kkmlln\205\205\207\234\234\236\301\301\303\363\363" \ + "\363\202\377\377\377\1\376\376\376\202\377\377\377\3\376\376\376\377" \ + "\377\377\376\376\376\231\377\377\377\1SSS\204::<\2;;=lln\213\377\377" \ + "\377\1\376\376\376\205\377\377\377\2\376\376\376TTV\205::<\1lll\226\377" \ + "\377\377\1\234\234\236\205::<\1\234\234\234\246\377\377\377\2\233\233" \ + "\235;;=\204::<\2kkk\376\376\376\203\377\377\377\1\376\376\376\206\377" \ + "\377\377\1\234\234\234\205::<\1\234\234\236\266\377\377\377\3\214\305" \ + "@\214\306>\214\305@\207\214\306>\4\214\305@\215\305>\214\306>\252\324" \ + "p\251\377\377\377\215\214\306>\1\250\325p\216\377\377\377\1\342\361\320" \ + "\202\214\306>\1\214\305@\210\214\306>\3\212\307>\215\305>\342\362\315" \ + "\202\377\377\377\22\377\376\377\376\377\377\377\377\375\376\377\377\363" \ + "\367\346\225\311K\211\307@\216\306\77\212\307>\215\305@\214\306<\212" \ + "\307>\214\305@\214\306>\212\306@\215\306C\214\304\77\215\307\77\202\214" \ + "\306>\7\212\306@\307\341\240\377\376\377\376\377\372\377\377\377\212" \ + "\307>\215\305>\211\214\306>\3\215\305>\214\306>\305\342\240\215\377\377" \ + "\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3\214\305@\214" \ + "\306>\214\305@\232\377\377\377\4\252\324p\214\306>\215\305>\214\305@" \ + "\207\214\306>\3\214\305@\214\306>\214\305@\231\377\377\377\4\377\376" \ + "\377\376\377\375\376\377\377\257\330z\202\214\305@\1\215\307\77\211\214" \ + "\306>\14\212\307>\215\307\77\214\305@\215\305@\212\307>\215\307=\214" \ + "\305B\313\347\252\377\377\377\377\375\377\377\376\377\376\376\376\202" \ + "\376\377\375\231\377\377\377\4GGI;;=::<;;=\202::<\1\233\233\235\237\377" \ + "\377\377\3\316\316\316::<;;=\230::<\213\377\377\377\1\316\316\316\205" \ + "::<\1kkm\202\377\377\377\2\376\376\376\250\250\250\206::<\2FFH\346\346" \ + "\346\210\377\377\377\1\376\376\376\237\377\377\377\1\264\264\266\203" \ + ";;=\4::<;;=;;;\316\316\316\222\377\377\377\1\265\265\265\204::<\3;;=" \ + "::<\316\316\316\203\377\377\377\1\376\376\376\221\377\377\377\1\234\234" \ + "\236\205::<\1\234\234\234\245\377\377\377\2\376\376\376\235\235\237\205" \ + "::<\1lll\213\377\377\377\1\234\234\234\205::<\1\234\234\236\266\377\377" \ + "\377\3\214\305@\214\306>\214\305@\207\214\306>\4\214\305@\215\305>\214" \ + "\306>\252\324p\251\377\377\377\215\214\306>\1\250\325p\216\377\377\377" \ + "\1\342\361\320\202\214\306>\1\214\305@\211\214\306>\2\214\305@\343\361" \ + "\316\205\377\377\377\10\376\377\375\377\377\377\333\355\303\215\305@" \ + "\214\306>\214\306<\214\305@\215\305>\202\214\305@\207\214\306>\6\212" \ + "\306@\214\307;\330\355\304\377\376\377\377\377\377\215\305>\212\214\306" \ + ">\3\215\305>\214\306>\305\342\240\215\377\377\377\17\251\323q\214\306" \ + ">\215\307\77\214\305B\215\307\77\213\305=\215\307\77\214\305@\212\307" \ + ">\215\305@\213\310\77\214\305@\215\305<\214\306>\376\377\377\230\377" \ + "\377\377\6\376\377\377\253\323p\215\305@\213\307A\214\306<\212\306B\202" \ + "\214\306>\4\214\305@\214\306>\212\307>\214\305@\202\214\306>\2\214\305" \ + "@\376\377\375\220\377\377\377\1\377\377\375\202\377\377\377\16\376\377" \ + "\375\377\376\377\377\375\376\374\377\377\377\377\375\376\377\375\377" \ + "\377\377\336\355\304\214\306>\215\306A\214\306>\215\306A\212\306@\216" \ + "\306A\202\214\305@\4\215\307\77\214\306>\215\307\77\214\306>\202\214" \ + "\305@\16\214\306>\215\307\77\214\306>\215\307\77\214\305@\214\305B\222" \ + "\313H\361\370\346\376\377\377\377\377\377\377\376\377\377\377\377\374" \ + "\377\377\377\376\377\230\377\377\377\1kkm\202::<\1""99;\202::<\1\235" \ + "\235\237\233\377\377\377\1\376\376\376\203\377\377\377\1\316\316\316" \ + "\224::<\1;;=\205::<\213\377\377\377\1\316\316\316\205::<\1kkm\204\377" \ + "\377\377\3wwy::<;;=\202::<\4""99;;;=``b\363\363\363\206\377\377\377\1" \ + "\376\376\376\235\377\377\377\4\376\376\376\377\377\377\376\376\376TT" \ + "V\205::<\1lln\223\377\377\377\10\376\376\376SSU;;=::<;;=99;::\214\305@\207\214\306>\4\214\305@\215" \ + "\305>\214\306>\252\324p\251\377\377\377\215\214\306>\1\250\325p\216\377" \ + "\377\377\1\342\361\320\202\214\306>\1\214\305@\211\214\306>\2\214\305" \ + "@\343\361\316\205\377\377\377\7\377\375\377\377\377\375\376\377\377\276" \ + "\337\220\213\310\77\213\304A\216\306=\207\214\306>\3\215\307\77\214\306" \ + ">\212\307>\202\215\305>\5\223\312J\361\371\344\377\375\377\212\307<\214" \ + "\305@\211\214\306>\3\215\305>\214\306>\305\342\240\214\377\377\377\14" \ + "\376\376\374\252\324n\214\306>\213\305=\215\307\77\214\305@\215\306A" \ + "\214\306>\215\307\77\213\310\77\215\305@\212\307>\202\214\306>\1\214" \ + "\305@\232\377\377\377\3\247\324m\215\305>\214\305@\202\214\306>\1\215" \ + "\307=\202\214\305@\6\214\306<\215\307=\214\305B\215\307\77\214\306>\214" \ + "\305@\224\377\377\377\15\377\377\375\376\376\376\377\377\377\377\376" \ + "\377\376\377\375\377\377\375\372\373\366\222\312M\216\306A\215\305<\214" \ + "\306>\212\307>\215\305<\202\214\306>\2\215\307\77\213\305=\204\214\306" \ + ">\1\214\305@\203\214\306>\14\215\307\77\214\305@\213\304\77\214\305B" \ + "\253\324n\376\376\377\376\377\377\377\376\377\377\377\377\376\377\375" \ + "\377\377\375\376\377\375\227\377\377\377\3lln::<;;=\203::<\2kkm\376\376" \ + "\376\236\377\377\377\2\316\316\316;;=\226::<\3;;=::\214\305" \ + "@\207\214\306>\4\214\305@\215\305>\214\306>\252\324p\251\377\377\377" \ + "\215\214\306>\1\250\325p\216\377\377\377\1\342\361\320\202\214\306>\1" \ + "\214\305@\211\214\306>\2\214\305@\343\361\316\205\377\377\377\2\377\377" \ + "\375\377\375\377\202\377\377\377\1\242\322b\202\214\305@\2\214\305B\215" \ + "\307\77\205\214\306>\12\215\307\77\214\306>\215\306A\214\306>\212\306" \ + "@\215\307=\241\321c\377\377\377\215\304B\212\307>\211\214\306>\3\215" \ + "\305>\214\306>\305\342\240\214\377\377\377\5\376\377\375\251\323o\215" \ + "\307\77\214\306>\215\307\77\202\214\305@\2\214\306>\215\307\77\202\214" \ + "\306>\5\213\310\77\215\305>\214\305@\214\306>\377\376\377\230\377\377" \ + "\377\12\377\376\377\247\326p\213\304\77\215\307\77\214\305B\214\306<" \ + "\214\306>\215\307\77\214\305@\214\306>\202\215\307\77\3\214\306>\215" \ + "\306A\216\306\77\223\377\377\377\5\376\377\372\377\377\375\376\376\376" \ + "\377\377\377\377\377\375\202\377\376\377\4\250\325p\212\307<\214\305" \ + "@\215\307\77\202\214\305@\3\214\307;\215\307=\214\306>\202\214\305@\202" \ + "\214\306>\1\215\307\77\207\214\306>\202\214\305@\5\212\307>\307\341\240" \ + "\376\376\374\377\377\377\377\376\377\202\377\377\377\1\376\376\374\227" \ + "\377\377\377\7\234\234\236;;=99;<<>99;::<;;=\237\377\377\377\1\316\316" \ + "\316\223::<\7;;=99;;;=99;::<;;=kkm\213\377\377\377\1\316\316\316\205" \ + "::<\2mmo\376\376\377\204\377\377\377\12\332\332\332FFH;;=::<;;=99;<<" \ + ">::<\266\266\270\376\376\376\203\377\377\377\1\376\376\376\202\377\377" \ + "\377\1\376\376\376\230\377\377\377\3\376\376\376\377\377\377\376\376" \ + "\376\202\377\377\377\1kkm\205::<\202;;=\224::<\10;;=::<;;=::<;;=88:;" \ + ";=\205\205\205\224\377\377\377\1\234\234\236\205::<\1\234\234\234\246" \ + "\377\377\377\3SSU;;=::<\203;;=\1\234\234\234\206\377\377\377\1\376\376" \ + "\376\204\377\377\377\1\234\234\234\205::<\1\234\234\236\266\377\377\377" \ + "\3\214\305@\214\306>\214\305@\207\214\306>\4\214\305@\215\305>\214\306" \ + ">\252\324p\251\377\377\377\215\214\306>\1\250\325p\216\377\377\377\1" \ + "\342\361\320\202\214\306>\1\214\305@\211\214\306>\2\214\305@\343\361" \ + "\316\205\377\377\377\10\376\376\374\376\377\375\377\375\377\377\377\377" \ + "\367\372\357\224\313L\214\305B\215\305<\203\214\306>\202\215\307\77\204" \ + "\214\306>\6\215\306A\213\307A\214\306>\212\306@\277\337\223\215\305>" \ + "\212\214\306>\3\215\305>\214\306>\305\342\240\214\377\377\377\2\376\377" \ + "\377\251\322r\202\215\307\77\1\214\305B\202\214\306>\202\215\307\77\7" \ + "\214\306>\215\307\77\214\306>\214\304\77\212\306@\215\307\77\377\376" \ + "\377\230\377\377\377\7\377\377\375\215\305@\214\306>\214\305@\214\306" \ + ">\216\306\77\214\306<\203\214\305@\6\215\306C\215\307=\214\305@\215\306" \ + "A\233\314V\377\377\375\220\377\377\377\5\376\376\376\377\377\377\377" \ + "\376\377\377\375\377\377\377\375\202\376\377\377\21\377\376\377\314\346" \ + "\251\212\306B\215\307=\212\307>\216\306\77\215\306C\212\307>\215\306" \ + "C\214\305@\215\307\77\213\304\77\215\306A\214\306>\214\305@\215\307\77" \ + "\215\306A\203\214\306>\1\215\307\77\202\214\306>\202\215\307\77\10\214" \ + "\306>\214\305@\350\364\334\377\377\375\377\376\377\377\377\377\376\376" \ + "\376\377\376\377\222\377\377\377\1\376\376\376\204\377\377\377\1\301" \ + "\301\301\202::<\2""99;;;=\202::<\1\316\316\316\233\377\377\377\1\376" \ + "\376\376\202\377\377\377\2\316\316\316;;;\222::<\7""99;;;=::<;;=::<9" \ + "9;\204\204\206\213\377\377\377\1\316\316\316\205::<\1jjl\202\377\377" \ + "\377\202\376\376\376\202\377\377\377\1\265\265\267\202::<\202;;=\202" \ + "::<\2FFH\332\332\332\205\377\377\377\1\376\376\376\234\377\377\377\2" \ + "\376\376\376\317\317\317\202::<\1;;=\204::<\3;;=::<;;=\222::<\2""99;" \ + ";;=\202::<\1;;=\203::<\3\346\346\346\377\377\377\376\376\376\221\377" \ + "\377\377\1\234\234\236\205::<\1\234\234\234\246\377\377\377\1;;=\203" \ + "::<\4;;=::<\316\316\316\376\376\376\203\377\377\377\1\376\376\376\206" \ + "\377\377\377\1\234\234\234\205::<\1\234\234\236\266\377\377\377\3\214" \ + "\305@\214\306>\214\305@\207\214\306>\4\214\305@\215\305>\214\306>\252" \ + "\324p\251\377\377\377\215\214\306>\1\250\325p\216\377\377\377\1\342\361" \ + "\320\202\214\306>\1\214\305@\211\214\306>\2\214\305@\343\361\316\205" \ + "\377\377\377\203\376\377\377\202\377\376\377\2\341\361\315\214\305@\203" \ + "\215\307\77\202\214\306>\1\215\307\77\203\214\306>\10\214\305@\215\307" \ + "\77\214\306>\212\307>\216\306A\213\305;\214\305@\215\305<\211\214\306" \ + ">\3\215\305>\214\306>\305\342\240\214\377\377\377\2\376\377\377\252\324" \ + "p\202\214\306>\3\214\305B\214\306<\215\307\77\203\214\306>\6\214\306" \ + "<\214\307;\217\307@\212\307>\214\305@\376\377\377\231\377\377\377\10" \ + "\215\307=\214\305B\213\304A\216\310@\214\304\77\215\307=\214\305@\215" \ + "\307\77\203\214\306>\3\215\307\77\214\306>\247\324o\222\377\377\377\3" \ + "\377\377\375\377\377\377\377\375\376\203\377\377\377\20\360\371\346\223" \ + "\312K\216\306\77\213\304A\215\306A\213\305=\215\305@\212\307>\215\305" \ + "<\214\305B\214\305@\214\306>\214\306<\214\306>\215\307\77\213\305=\204" \ + "\214\306>\202\215\307\77\203\214\306>\10\215\306A\212\307<\243\321d\377" \ + "\377\373\375\377\376\377\376\377\377\377\377\376\376\374\223\377\377" \ + "\377\5\375\375\375\377\377\377\376\376\376\377\377\377\346\346\346\202" \ + "::<\1;;=\203::<\1\221\221\221\235\377\377\377\3\376\376\376\377\377\377" \ + "\376\376\376\222\377\377\377\1__a\204::<\2;;=\234\234\234\213\377\377" \ + "\377\1\316\316\316\205::<\3jjl\377\377\377\376\376\376\205\377\377\377" \ + "\2\204\204\206;;=\204::<\3;;=RRT\363\363\363\237\377\377\377\1\376\376" \ + "\376\202\377\377\377\2jjl;;=\206::<\4;;=::<99;;;=\223::<\1;;=\205::<" \ + "\1\204\204\206\203\377\377\377\1\376\376\376\217\377\377\377\1\234\234" \ + "\236\205::<\1\234\234\234\245\377\377\377\3\315\315\315;;=99;\202::<" \ + "\5""99;;;=\346\346\346\377\377\377\376\376\376\211\377\377\377\1\234" \ + "\234\234\205::<\1\234\234\236\266\377\377\377\3\214\305@\214\306>\214" \ + "\305@\207\214\306>\4\214\305@\215\305>\214\306>\252\324p\251\377\377" \ + "\377\215\214\306>\1\250\325p\216\377\377\377\1\342\361\320\202\214\306" \ + ">\1\214\305@\211\214\306>\2\214\305@\343\361\316\207\377\377\377\202" \ + "\377\377\375\4\376\377\377\377\377\375\303\342\237\212\306@\202\214\305" \ + "@\206\214\306>\7\216\306\77\213\305;\214\305@\216\306A\214\306>\215\307" \ + "\77\213\307A\212\214\306>\3\215\305>\214\306>\305\342\240\215\377\377" \ + "\377\17\252\323k\215\306A\214\306>\215\307\77\214\306>\215\307\77\214" \ + "\305@\214\306>\213\304A\215\306C\214\305@\213\304A\213\310=\214\306<" \ + "\342\357\321\230\377\377\377\6\360\371\346\214\305B\212\307<\215\307" \ + "=\213\305=\215\307\77\202\214\305@\7\215\306A\214\306>\214\306<\214\305" \ + "@\214\306>\214\305@\252\324p\222\377\377\377\11\377\376\377\376\377\377" \ + "\377\377\377\377\377\375\376\376\374\377\377\377\253\323p\215\307\77" \ + "\211\306;\202\215\306A\6\214\306>\214\306<\215\305>\216\305C\215\307" \ + "\77\213\304\77\202\215\307\77\2\215\307=\213\305;\202\215\307\77\2\214" \ + "\306>\215\307\77\205\214\306>\5\215\307\77\212\306@\214\306>\215\307" \ + "\77\304\341\236\202\377\377\377\2\376\376\377\374\377\377\230\377\377" \ + "\377\7SSU;;=99;::<;;=::\214\305@\207\214\306>\4\214\305@\215\305>\214\306" \ + ">\252\324p\251\377\377\377\215\214\306>\1\250\325p\216\377\377\377\1" \ + "\342\361\320\202\214\306>\1\214\305@\211\214\306>\2\214\305@\343\361" \ + "\316\206\377\377\377\13\377\376\377\377\377\377\376\377\375\377\377\377" \ + "\377\376\377\376\377\377\253\324l\214\305B\213\304\77\214\305@\215\307" \ + "\77\203\214\306>\11\214\305@\214\306<\216\306=\214\306>\212\306@\215" \ + "\306C\214\304;\212\307>\214\305@\211\214\306>\3\215\305>\214\306>\305" \ + "\342\240\215\377\377\377\1\261\330\177\202\214\306>\2\214\306<\215\306" \ + "A\203\214\306>\7\215\307\77\214\306>\214\306<\215\307=\214\306>\215\306" \ + "C\323\353\267\230\377\377\377\4\340\361\315\215\305@\215\306A\214\305" \ + "@\202\214\306>\2\213\305=\215\306A\202\214\305@\5\214\306>\215\307\77" \ + "\214\306>\214\305@\260\330x\221\377\377\377\3\376\376\376\377\377\373" \ + "\375\377\376\202\377\377\377\25\376\377\377\314\345\253\214\305@\213" \ + "\304\77\216\306\77\212\307>\215\305@\214\306>\214\305@\215\305>\214\305" \ + "@\214\306>\214\306<\214\305@\215\306A\214\305@\215\306C\214\306>\214" \ + "\305@\214\306>\215\307\77\207\214\306>\7\212\306@\220\306=\215\306C\350" \ + "\364\336\376\377\373\377\377\375\376\377\377\230\377\377\377\1\221\221" \ + "\223\203::<\1;;=\202::<\1\265\265\265\230\377\377\377\1\376\376\376\227" \ + "\377\377\377\1\316\316\316\202::<\1;;=\203::<\1\363\363\363\213\377\377" \ + "\377\1\316\316\316\205::<\1kkm\204\377\377\377\1\376\376\376\203\377" \ + "\377\377\2\346\346\346FFH\206::<\2\234\234\236\376\376\376\237\377\377" \ + "\377\1\205\205\205\206::<\3;;=::<;;=\223::<\1;;=\203::<\202;;=\204::" \ + "<\2\234\234\234\376\376\376\221\377\377\377\1\234\234\236\205::<\1\234" \ + "\234\234\245\377\377\377\1RRR\204::<\2""99;yy{\203\377\377\377\1\376" \ + "\376\376\202\377\377\377\202\376\376\376\204\377\377\377\1\234\234\234" \ + "\205::<\1\234\234\236\266\377\377\377\3\214\305@\214\306>\214\305@\207" \ + "\214\306>\4\214\305@\215\305>\214\306>\252\324p\251\377\377\377\215\214" \ + "\306>\1\250\325p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305" \ + "@\211\214\306>\2\214\305@\343\361\316\205\377\377\377\30\377\377\375" \ + "\377\377\377\375\377\376\377\377\377\377\376\377\377\377\377\376\377" \ + "\377\371\372\365\222\313H\214\305B\214\305@\215\307\77\214\306>\215\307" \ + "\77\214\306>\214\305@\212\306B\214\305@\212\307>\216\306\77\212\307>" \ + "\215\307\77\214\306<\214\305@\211\214\306>\3\215\305>\214\306>\305\342" \ + "\240\214\377\377\377\20\377\376\377\301\345\237\215\305>\215\306A\213" \ + "\304\77\215\306C\214\306>\214\306<\216\306\77\214\306>\214\305B\215\307" \ + "\77\214\306>\215\307\77\214\305@\271\332\211\230\377\377\377\10\307\341" \ + "\240\215\305>\214\305@\214\306>\215\305<\212\307>\214\305B\214\306<\202" \ + "\214\306>\5\215\305<\214\305B\215\307\77\214\306>\303\344\235\222\377" \ + "\377\377\6\376\376\377\377\377\375\376\377\377\377\376\377\352\364\333" \ + "\215\305@\202\215\307\77\16\214\306>\215\307\77\214\306>\215\307\77\214" \ + "\306<\216\306A\213\310\77\214\305D\215\3108\214\305@\215\305>\223\312" \ + "K\236\323a\215\307\77\207\214\306>\202\214\305@\10\214\306>\215\307\77" \ + "\212\307>\212\307<\241\321c\377\376\377\377\375\376\377\375\377\230\377" \ + "\377\377\3\332\332\332:::;;=\204::<\1SSU\203\377\377\377\1\376\376\376" \ + "\247\377\377\377\1\376\376\376\204\377\377\377\1\221\221\221\202::<\1" \ + ";:\77\202::<\1RRT\214\377\377\377\1\316\316\316\205::<\1kkm\211\377\377" \ + "\377\2\316\316\316;;=\202::<\5;;=::<;;=::<\316\316\316\210\377\377\377" \ + "\1\376\376\376\215\377\377\377\1\376\376\376\207\377\377\377\2\346\346" \ + "\350::<\202;;=\202::<\2:::xxx\230\234\234\234\3\235\235\235\234\234\234" \ + "kkm\203::<\4;;=::\214\305@\204\214\306>\2\213\307A\213\310\77\204\214\306>\1\252\324" \ + "p\232\377\377\377\1\377\377\375\216\377\377\377\215\214\306>\1\250\325" \ + "p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\211\214\306>" \ + "\2\214\305@\343\361\316\215\377\377\377\10\352\363\336\214\306>\212\306" \ + "B\215\307\77\212\307<\215\305>\214\305@\215\307\77\221\214\306>\3\215" \ + "\305>\214\306>\305\342\240\214\377\377\377\30\377\376\377\313\347\254" \ + "\215\307\77\214\304=\215\307\77\212\306@\215\307\77\215\306A\214\305" \ + "@\214\306>\215\307\77\214\306>\215\307\77\214\305@\214\305B\222\313H" \ + "\377\376\377\377\375\376\377\376\377\377\377\377\377\376\377\377\377" \ + "\373\376\377\377\377\376\377\211\377\377\377\26\377\377\375\377\376\377" \ + "\377\377\377\376\377\377\377\377\375\376\377\375\377\377\377\241\323" \ + "b\215\304D\214\307;\215\307\77\214\305B\215\307\77\214\306<\215\306A" \ + "\212\307>\215\305@\214\306>\213\310=\215\305@\215\306A\323\352\264\221" \ + "\377\377\377\11\376\377\377\376\376\374\376\377\377\377\376\374\377\376" \ + "\377\242\320c\215\307\77\215\306A\214\306>\202\214\305@\203\214\306>" \ + "\25\214\305@\215\306A\214\305@\215\307\77\214\306>\215\307=\315\345\253" \ + "\361\370\346\215\307\77\214\306>\212\306@\216\306A\214\306>\215\305>" \ + "\215\305@\214\305@\212\307>\215\305@\212\306@\215\305<\215\305@\202\214" \ + "\306>\12\277\337\223\377\377\377\376\377\375\377\376\377\377\377\375" \ + "\376\377\377\377\377\377\376\376\376\377\377\377\377\377\375\222\377" \ + "\377\377\1___\202::<\202;;=\202::<\1\266\266\266\250\377\377\377\1\376" \ + "\376\376\202\377\377\377\1\376\376\376\203\377\377\377\1SSU\203::<\3" \ + ";;=::<\221\221\223\214\377\377\377\1\316\316\316\205::<\1kkm\210\377" \ + "\377\377\3\376\376\376\377\377\377\233\233\233\203::<\5;;=::<;;=FFH\364" \ + "\364\364\210\377\377\377\1\376\376\376\213\377\377\377\2\376\376\376" \ + "\377\377\377\202\376\376\376\205\377\377\377\1\204\204\206\202::<\1;" \ + ";=\202::<\3FFF\363\363\363\376\376\376\231\377\377\377\3\346\346\346" \ + "::<;;=\204::<\3\234\234\234\377\377\377\376\376\376\217\377\377\377\1" \ + "\234\234\236\205::<\1\234\234\234\234\377\377\377\1\376\376\376\207\377" \ + "\377\377\3\205\205\207::<;;=\204::<\1\346\346\350\214\377\377\377\1\234" \ + "\234\234\205::<\1\234\234\236\266\377\377\377\3\214\305@\214\306>\214" \ + "\305@\205\214\306>\7\214\306<\214\306>\215\307\77\214\305@\214\306>\252" \ + "\324p\376\377\375\230\377\377\377\203\377\376\377\203\377\377\377\1\376" \ + "\376\377\211\377\377\377\215\214\306>\1\250\325p\216\377\377\377\1\342" \ + "\361\320\202\214\306>\1\214\305@\211\214\306>\2\214\305@\343\361\316" \ + "\215\377\377\377\2\376\377\375\313\347\254\203\214\306>\3\214\305@\216" \ + "\306\77\211\306=\221\214\306>\3\215\305>\214\306>\305\342\240\214\377" \ + "\377\377\11\375\376\377\343\361\316\215\305>\215\307\77\213\304A\215" \ + "\307\77\215\305>\214\306<\214\305@\203\214\306>\14\215\307\77\214\305" \ + "@\213\304\77\214\305B\322\353\264\377\377\377\377\377\375\377\377\377" \ + "\377\376\377\376\377\377\377\377\377\376\377\377\210\377\377\377\13\377" \ + "\377\375\377\377\377\376\377\375\377\376\377\376\376\374\377\377\375" \ + "\377\377\377\350\364\334\215\304D\215\305>\215\307\77\202\214\305@\202" \ + "\214\306>\10\214\305@\215\306A\214\306<\215\306C\214\304=\215\307=\212" \ + "\307<\351\366\332\222\377\377\377\14\377\377\375\377\377\377\377\377" \ + "\375\304\343\237\214\306>\212\307>\217\307@\214\305@\215\307\77\214\306" \ + ">\214\305@\215\306A\202\214\306>\5\214\306<\215\305>\211\307>\216\306" \ + "=\251\323o\202\376\377\377\31\304\341\241\212\306@\215\306A\212\307>" \ + "\215\307\77\214\306<\216\305C\212\307<\216\306A\214\306<\215\307\77\215" \ + "\305>\212\307>\216\306A\214\305@\216\306A\341\361\315\377\376\377\377" \ + "\377\375\376\377\377\377\376\377\376\376\376\377\377\377\377\376\377" \ + "\376\377\375\222\377\377\377\1\265\265\265\202;;=\204::<\2SSU\364\364" \ + "\364\203\377\377\377\1\376\376\376\245\377\377\377\1\376\376\376\203" \ + "\377\377\377\1\316\316\316\203::<\1;;=\202::<\1\302\302\302\214\377\377" \ + "\377\1\316\316\316\205::<\1kkm\213\377\377\377\1lln\204::<\3;;=::<__" \ + "a\202\377\377\377\1\376\376\376\206\377\377\377\1\376\376\376\213\377" \ + "\377\377\1\376\376\376\202\377\377\377\1\376\376\376\203\377\377\377" \ + "\3\346\346\346::<;;=\204::<\1\234\234\234\234\377\377\377\1\204\204\206" \ + "\202;;=\202::<\2;;=SSU\221\377\377\377\1\234\234\236\205::<\1\234\234" \ + "\234\235\377\377\377\1\376\376\376\202\377\377\377\1\376\376\376\202" \ + "\377\377\377\2\346\346\346::<\202;;=\4""99;;;=::\214\305@\204\214\306>\10\214\305@\215\306A\215\305@\213\305=\214\306" \ + ">\215\307\77\252\324p\376\377\377\230\377\377\377\1\376\376\376\205\377" \ + "\377\377\2\376\377\377\376\377\375\210\377\377\377\215\214\306>\1\250" \ + "\325p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\211\214\306" \ + ">\2\214\305@\343\361\316\215\377\377\377\10\377\377\375\377\375\376\262" \ + "\331|\214\305@\215\306A\214\306>\214\305B\215\307\77\221\214\306>\3\215" \ + "\305>\214\306>\305\342\240\214\377\377\377\10\376\377\375\377\377\377" \ + "\214\304\77\212\307>\216\306A\214\306>\215\305@\215\307\77\206\214\306" \ + ">\202\214\305@\3\233\316X\376\376\377\376\377\373\202\377\377\377\3\377" \ + "\375\376\377\377\375\377\376\377\210\377\377\377\12\377\376\377\376\377" \ + "\375\377\375\376\376\376\374\377\377\377\377\377\375\377\377\377\257" \ + "\330x\214\307;\215\307\77\202\214\305@\2\215\307\77\213\305=\202\214" \ + "\306>\1\215\305>\202\214\306>\5\216\306\77\215\306A\215\305@\376\377" \ + "\375\377\376\377\220\377\377\377\11\377\377\375\377\377\377\376\377\377" \ + "\350\364\334\212\307>\213\310\77\216\306\77\212\307>\214\305@\202\214" \ + "\306>%\215\306A\214\306>\213\305=\214\306>\215\307\77\215\305@\211\307" \ + ">\223\311M\363\367\350\376\377\375\377\377\377\377\377\375\242\320d\212" \ + "\307<\215\306A\214\305@\212\306@\215\306A\214\306>\212\307>\215\307\77" \ + "\217\304@\211\310<\215\305>\213\310\77\212\307>\214\306>\234\315W\367" \ + "\372\363\376\377\377\377\376\377\377\377\375\377\377\377\376\376\376" \ + "\377\377\375\377\377\377\376\377\375\222\377\377\377\1RRR\202::<\203" \ + ";;=\2::<\234\234\236\204\377\377\377\1\376\376\376\246\377\377\377\3" \ + "\376\376\376\377\377\377kkk\202::<\4;;=99;;;=FFH\215\377\377\377\1\316" \ + "\316\316\205::<\1kkm\211\377\377\377\5\376\376\376\377\377\377\363\363" \ + "\363SSU;;=\202::<\202;;=\2""99;\222\222\222\207\377\377\377\3\376\376" \ + "\376\377\377\377\376\376\376\214\377\377\377\1\376\376\376\204\377\377" \ + "\377\3\204\204\204;;=99;\202;;=\3::\214\305@\204\214\306>\2\214\305@\214\306>\203\215\306A\2\215\307\77" \ + "\251\323q\231\377\377\377\203\377\377\375\202\377\377\377\1\377\375\376" \ + "\202\377\376\377\210\377\377\377\215\214\306>\1\250\325p\216\377\377" \ + "\377\1\342\361\320\202\214\306>\1\214\305@\211\214\306>\2\214\305@\343" \ + "\361\316\215\377\377\377\7\376\376\376\377\377\375\366\373\364\233\316" \ + "X\215\305@\215\307=\215\305>\222\214\306>\3\215\305>\214\306>\305\342" \ + "\240\216\377\377\377\6\243\322b\214\306>\215\305@\215\307\77\215\305" \ + "@\215\306A\203\214\306>\1\215\307\77\202\214\306>\202\215\307\77\2\214" \ + "\306>\315\346\254\202\377\377\377\4\377\376\375\376\377\375\376\376\377" \ + "\377\376\377\212\377\377\377\7\377\377\375\377\376\377\377\377\373\377" \ + "\377\375\327\356\304\214\306>\215\307\77\202\214\305@\203\214\306>\12" \ + "\215\307\77\214\306>\214\305@\216\306\77\214\306<\214\304\77\212\307" \ + ">\260\331{\376\377\375\377\376\377\220\377\377\377\13\376\377\377\377" \ + "\377\375\370\373\362\233\315Z\216\306A\214\305@\212\307>\215\306A\214" \ + "\306>\214\305@\215\306A\202\214\306>\6\215\307\77\214\305@\214\305B\214" \ + "\306>\215\307=\313\347\254\202\377\377\377\23\377\376\377\377\377\375" \ + "\350\364\334\212\307>\220\306=\214\305@\216\306=\214\306>\214\305@\214" \ + "\306>\212\306@\215\305>\212\306@\215\307\77\212\307>\215\307\77\214\305" \ + "@\212\306@\277\340\221\202\377\377\377\1\377\377\375\203\377\377\377" \ + "\2\377\376\377\377\377\375\220\377\377\377\4\376\376\376\377\377\377" \ + "\265\265\265::<\202;;=\5""99;::<;;=99;\317\317\317\250\377\377\377\1" \ + "\376\376\376\202\377\377\377\2\316\316\31699;\202::<\202;;=\2::<\221" \ + "\221\223\215\377\377\377\1\316\316\316\205::<\1kkm\207\377\377\377\1" \ + "\376\376\376\204\377\377\377\1\332\332\334\203::<\5;;=::<;;=99;\302\302" \ + "\302\202\377\377\377\1\376\376\376\216\377\377\377\1\376\376\376\202" \ + "\377\377\377\1\376\376\376\204\377\377\377\4\362\362\362FFH::<;;=\202" \ + "::<\2;;=\221\221\223\204\377\377\377\202\376\376\376\224\377\377\377" \ + "\1\376\376\376\203\377\377\377\1kkm\202;;=\203::<\1SSU\220\377\377\377" \ + "\1\234\234\236\205::<\1\234\234\234\240\377\377\377\3\376\376\376\377" \ + "\377\377\315\315\315\203::<\1;;=\202::<\1SSU\216\377\377\377\1\234\234" \ + "\234\205::<\1\234\234\236\266\377\377\377\3\214\305@\214\306>\214\305" \ + "@\204\214\306>\3\215\306A\214\306<\215\307=\202\214\305@\3\214\306>\253" \ + "\324n\377\377\375\230\377\377\377\2\375\376\377\376\376\376\203\377\377" \ + "\377\1\377\377\375\212\377\377\377\215\214\306>\1\250\325p\216\377\377" \ + "\377\1\342\361\320\202\214\306>\1\214\305@\211\214\306>\2\214\305@\343" \ + "\361\316\220\377\377\377\5\350\365\333\214\306>\214\305@\214\306>\215" \ + "\306A\221\214\306>\3\215\305>\214\306>\305\342\240\215\377\377\377\7" \ + "\377\377\375\277\337\224\212\306@\215\305@\212\307>\215\306A\215\307" \ + "\77\203\214\306>\202\215\307\77\203\214\306>\3\214\306<\214\306>\351" \ + "\363\330\202\377\377\377\3\376\376\376\374\377\377\376\377\377\211\377" \ + "\377\377\1\376\377\377\202\377\377\377\7\375\376\377\351\365\337\223" \ + "\311M\215\307=\214\305B\214\305@\215\307\77\202\214\306>\12\215\306A" \ + "\214\305@\214\306>\212\307>\215\306A\214\306>\215\307=\213\310\77\316" \ + "\345\255\376\377\377\221\377\377\377\7\376\377\377\377\377\375\300\337" \ + "\223\216\306A\213\305=\215\307=\215\305>\202\214\306>\1\215\307\77\203" \ + "\214\306>\202\214\305@\5\215\307\77\213\307A\251\322r\377\377\377\377" \ + "\377\375\202\377\377\377\14\377\376\377\377\377\377\305\342\237\212\307" \ + "<\220\305\77\214\306>\212\306@\215\306A\214\306<\214\305@\214\306<\216" \ + "\305C\202\214\306>\7\215\305<\214\306>\215\305>\214\305@\342\362\316" \ + "\377\377\377\377\377\375\202\377\377\377\3\376\377\377\377\376\377\376" \ + "\376\376\221\377\377\377\3\376\376\376\377\377\377___\205::<\4;;=FFH" \ + "\363\363\363\377\377\377\202\376\376\376\246\377\377\377\3\363\363\363" \ + "SSU;;=\204::<\4;;=\345\345\345\377\377\377\376\376\376\213\377\377\377" \ + "\1\316\316\316\205::<\1kkm\211\377\377\377\1\376\376\376\203\377\377" \ + "\377\4\264\264\266;;=99;::<\202;;=\3::\214\305@\204\214\306>\2\212\306@\213\310" \ + "\77\202\214\305@\3\215\307\77\214\306<\251\323o\231\377\377\377\4\377" \ + "\376\377\377\377\375\377\377\377\376\376\377\214\377\377\377\215\214" \ + "\306>\1\250\325p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305" \ + "@\211\214\306>\2\214\305@\343\361\316\215\377\377\377\1\377\377\375\203" \ + "\377\377\377\4\323\353\267\212\307<\214\306<\212\306B\221\214\306>\3" \ + "\215\305>\214\306>\305\342\240\214\377\377\377\7\376\377\377\377\376" \ + "\377\350\365\331\215\307\77\215\305>\214\306>\212\307>\202\214\306>\1" \ + "\215\307\77\205\214\306>\11\215\307\77\213\304A\212\307>\222\312M\343" \ + "\361\316\376\376\377\377\376\377\377\377\377\377\375\377\210\377\377" \ + "\377\1\377\376\377\202\377\377\375\12\377\376\377\350\364\334\220\313" \ + "K\216\306=\215\305<\215\307\77\214\306>\213\305=\214\306>\215\306A\202" \ + "\214\306>\1\214\305@\202\212\307>\6\214\305@\215\306C\215\305>\360\370" \ + "\351\377\377\373\376\377\377\221\377\377\377\7\345\360\322\215\305@\214" \ + "\305@\215\307=\214\304=\213\310=\215\305>\202\214\306>\2\213\305=\215" \ + "\307\77\202\214\305@\7\215\307\77\214\307;\214\305@\363\367\346\376\377" \ + "\377\377\377\373\377\376\377\202\377\377\377\30\376\377\375\377\376\377" \ + "\241\321a\216\306\77\212\306@\213\310=\215\305@\213\307A\217\304>\215" \ + "\305@\214\306<\216\306A\215\306A\212\307>\214\306<\214\306>\212\307<" \ + "\233\314W\366\373\365\377\377\375\377\377\377\377\376\377\373\377\377" \ + "\377\376\377\224\377\377\377\1\317\317\317\205::<\4;;=::<``b\362\362" \ + "\362\247\377\377\377\2\376\376\376\221\221\221\206::<\3\204\204\206\377" \ + "\377\377\376\376\376\214\377\377\377\1\316\316\316\205::<\1kkm\212\377" \ + "\377\377\6\376\376\376\377\377\377\376\376\376\377\377\377\203\203\203" \ + ";;=\205::<\3``b\363\363\363\376\376\376\216\377\377\377\1\376\376\376" \ + "\206\377\377\377\3\363\363\363FFH;;=\203::<\2;;=\203\203\203\203\377" \ + "\377\377\3\376\376\376\377\377\377\376\376\376\225\377\377\377\1\376" \ + "\376\376\204\377\377\377\3kkk::<<<>\202::<\2;;=kkm\217\377\377\377\1" \ + "\234\234\236\205::<\1\234\234\234\236\377\377\377\4\376\376\376\377\377" \ + "\377\376\376\376kkk\202::<\5;;=::<99;;;=TTV\202\377\377\377\1\376\376" \ + "\376\214\377\377\377\1\234\234\234\205::<\1\234\234\236\266\377\377\377" \ + "\3\214\305@\214\306>\214\305@\204\214\306>\10\214\306<\214\306>\214\305" \ + "@\214\306>\215\307\77\214\306>\252\324r\376\377\377\230\377\377\377\1" \ + "\377\377\375\202\377\377\377\2\377\377\375\376\376\374\203\377\376\377" \ + "\210\377\377\377\215\214\306>\1\250\325p\216\377\377\377\1\342\361\320" \ + "\202\214\306>\1\214\305@\211\214\306>\2\214\305@\343\361\316\215\377" \ + "\377\377\10\375\377\374\377\376\377\375\377\376\376\376\377\377\377\377" \ + "\270\333\207\214\305@\215\307\77\221\214\306>\3\215\305>\214\306>\305" \ + "\342\240\214\377\377\377\12\375\376\377\377\376\377\376\377\377\234\313" \ + "Y\215\306A\214\305@\212\307>\214\305@\214\306>\215\307\77\206\214\306" \ + ">\7\215\307\77\214\306>\215\305@\213\310\77\304\343\240\371\372\364\376" \ + "\377\377\212\377\377\377\10\376\377\377\377\376\377\315\345\251\223\311" \ + "M\214\306>\216\306\77\214\305B\214\306<\202\214\306>\15\215\306A\214" \ + "\305@\214\306>\215\307\77\214\305@\214\306<\214\305@\215\307\77\213\304" \ + "A\263\330{\377\377\377\376\376\376\377\377\375\220\377\377\377\7\370" \ + "\373\364\232\315V\216\306=\212\311=\214\306>\216\306A\213\307A\202\214" \ + "\305@\202\214\306>\202\214\305@\10\215\307\77\215\305>\215\304D\304\341" \ + "\237\376\377\377\377\376\377\376\376\377\377\377\375\202\377\376\377" \ + "\24\376\377\377\377\377\373\350\365\333\215\305>\214\306<\214\306>\212" \ + "\306@\215\307\77\213\305=\215\305@\215\307\77\214\306>\215\305>\215\306" \ + "A\211\305A\215\305@\214\305B\213\310=\262\327z\374\377\377\202\377\377" \ + "\377\2\377\377\375\373\377\376\225\377\377\377\1\221\221\223\203::<\6" \ + ";;=99;;;=::<``b\362\362\362\246\377\377\377\2\265\265\265:::\202::<\1" \ + ";;=\203::<\1\346\346\350\216\377\377\377\1\316\316\316\205::<\1kkm\216" \ + "\377\377\377\6\363\363\363__a::<;;=::<;;=\202::<\1\204\204\204\204\377" \ + "\377\377\1\376\376\376\221\377\377\377\1\234\234\234\204::<\3;;=::<\347" \ + "\347\347\202\377\377\377\1\376\376\376\205\377\377\377\1\376\376\376" \ + "\225\377\377\377\3\376\376\376\377\377\377\265\265\265\202::<\202;;=" \ + "\3::<;;=\316\316\316\216\377\377\377\1\234\234\236\205::<\1\234\234\234" \ + "\240\377\377\377\2\204\204\204:::\206::<\1\301\301\303\217\377\377\377" \ + "\1\234\234\234\205::<\1\234\234\236\266\377\377\377\3\214\305@\214\306" \ + ">\214\305@\205\214\306>\7\214\305@\216\306A\215\307=\213\304\77\213\307" \ + "A\242\321a\345\356\317\230\342\362\316\7\341\361\315\342\361\322\342" \ + "\361\320\343\361\315\345\360\322\365\373\357\376\377\377\211\377\377" \ + "\377\215\214\306>\1\250\325p\216\377\377\377\1\342\361\320\202\214\306" \ + ">\1\214\305@\211\214\306>\2\214\305@\343\361\316\216\377\377\377\7\376" \ + "\377\375\377\377\375\377\377\377\377\376\377\371\374\365\242\322d\215" \ + "\306A\221\214\306>\3\215\305>\214\306>\305\342\240\214\377\377\377\10" \ + "\377\377\375\377\377\377\377\377\373\312\346\253\215\307=\212\307>\214" \ + "\305B\216\306=\206\214\306>\202\214\305@\10\214\306>\212\307>\216\306" \ + "\77\214\306>\212\307>\233\316W\306\340\237\361\370\346\210\377\377\377" \ + "\12\361\370\350\314\345\253\233\314W\214\306>\213\310\77\215\305<\214" \ + "\305@\212\307<\215\306A\214\305@\203\214\306>\202\214\305@\202\214\306" \ + ">\4\216\306A\212\306@\213\310\77\333\356\301\202\377\377\377\1\377\377" \ + "\375\220\377\377\377\26\270\332\204\215\306A\212\306B\214\306>\213\307" \ + "A\215\305@\214\306<\214\306>\215\306A\214\306<\215\307\77\214\305B\215" \ + "\307\77\214\307;\215\304D\241\323b\377\377\375\376\377\377\377\377\377" \ + "\377\377\373\377\377\377\376\377\377\202\377\377\375\16\377\377\377\376" \ + "\377\377\277\337\224\214\305@\215\306A\214\306>\215\305>\212\310\77\214" \ + "\305@\215\307\77\212\307>\214\305B\216\306=\215\306A\202\214\306<\6\214" \ + "\306>\213\307C\331\356\305\377\376\377\377\377\373\376\376\376\227\377" \ + "\377\377\3__a::<;:\77\205::<\2__a\363\363\363\203\377\377\377\1\376\376" \ + "\376\213\377\377\377\1\376\376\376\203\377\377\377\3\376\376\376\377" \ + "\377\377\376\376\376\213\377\377\377\1\376\376\376\202\377\377\377\1" \ + "\265\265\267\205::<\3;;=:::\234\234\234\217\377\377\377\1\316\316\316" \ + "\205::<\1kkm\217\377\377\377\4\332\332\332GGI::<;;=\204::<\1\250\250" \ + "\252\225\377\377\377\1FFH\205::<\1\204\204\204\242\377\377\377\1TTV\205" \ + "::<\4lln\376\376\376\377\377\377\376\376\376\203\377\377\377\1\376\376" \ + "\376\207\377\377\377\1\234\234\236\205::<\1\235\235\237\221\377\377\377" \ + "\1\376\376\376\202\377\377\377\1\376\376\376\202\377\377\377\202\376" \ + "\376\376\205\377\377\377\3\363\363\365\204\204\206;;=\204::<\3;;=:::" \ + "xxx\220\377\377\377\1\234\234\234\203::<\3;;=::<\234\234\234\204\377" \ + "\377\377\1\376\376\376\261\377\377\377\3\214\305@\214\306>\214\305@\250" \ + "\214\306>\2\215\307\77\342\362\316\212\377\377\377\215\214\306>\1\250" \ + "\325p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\211\214\306" \ + ">\2\214\305@\343\361\316\216\377\377\377\11\375\376\377\377\376\377\377" \ + "\377\375\376\377\377\377\376\377\351\365\335\223\311M\212\307<\214\306" \ + ">\202\216\306A\4\212\307<\215\306A\215\305>\215\307\77\211\214\306>\3" \ + "\215\305>\214\306>\305\342\240\214\377\377\377\20\377\376\377\377\377" \ + "\375\377\376\377\365\374\364\223\312J\217\304>\215\307\77\212\307;\215" \ + "\306A\214\305B\214\305@\215\307\77\214\306<\213\310\77\214\305@\215\305" \ + ">\210\214\306>\10\234\315Z\257\327~\304\343\235\306\340\237\307\341\240" \ + "\304\343\237\257\327\177\241\321a\210\214\306>\20\217\304>\215\306A\212" \ + "\306@\212\307>\213\305;\216\306A\213\305=\215\306C\211\310<\216\306A" \ + "\214\306>\234\314V\377\377\377\375\377\374\376\377\377\377\376\377\211" \ + "\377\377\377\7\377\376\377\376\377\375\376\377\377\376\377\375\377\376" \ + "\377\377\377\377\333\355\303\210\214\306>\10\215\306A\214\305@\216\306" \ + "=\214\306>\215\307\77\214\305@\215\307\77\352\364\334\211\377\377\377" \ + "\6\377\376\377\367\375\363\232\315V\215\307\77\214\306>\214\305@\212" \ + "\214\306>\6\212\307>\223\311M\366\373\364\377\376\377\377\377\377\376" \ + "\377\373\221\377\377\377\1\376\376\376\204\377\377\377\2\346\346\346" \ + "FFH\203::<\1""99;\203::<\2__a\332\332\332\211\377\377\377\1\376\376\376" \ + "\203\377\377\377\1\376\376\376\205\377\377\377\1\376\376\376\206\377" \ + "\377\377\1\376\376\376\207\377\377\377\1\265\265\267\202::<\1;;=\204" \ + "::<\2```\376\376\376\217\377\377\377\1\316\316\316\205::<\1kkm\216\377" \ + "\377\377\4\376\376\376\377\377\377\301\301\301;;=\205::<\2;;=\331\331" \ + "\331\202\377\377\377\3\376\376\376\377\377\377\376\376\376\216\377\377" \ + "\377\1\265\265\267\205::<\3;;=\332\332\332\376\376\376\241\377\377\377" \ + "\1\266\266\270\205::<\2""99;\316\316\320\215\377\377\377\1\234\234\236" \ + "\203::<\5;;=::<\234\234\234\377\377\377\376\376\376\220\377\377\377\1" \ + "\376\376\376\206\377\377\377\1\376\376\376\203\377\377\377\2\346\346" \ + "\346``b\202::<\2""99;;;=\203::<\4FFF\363\363\363\377\377\377\376\376" \ + "\376\216\377\377\377\1\234\234\234\204::<\3;;=\234\234\234\376\376\376" \ + "\265\377\377\377\3\214\305@\214\306>\214\305@\250\214\306>\2\215\307" \ + "\77\342\362\316\212\377\377\377\215\214\306>\1\250\325p\216\377\377\377" \ + "\1\342\361\320\202\214\306>\1\214\305@\211\214\306>\2\214\305@\343\361" \ + "\316\215\377\377\377\16\377\376\377\376\377\377\377\376\377\377\377\377" \ + "\376\377\377\377\376\377\375\377\374\323\353\267\215\305<\215\306C\215" \ + "\305<\213\306:\213\310\77\212\306@\202\214\305@\211\214\306>\3\215\305" \ + ">\214\306>\305\342\240\215\377\377\377\4\376\377\377\377\377\375\377" \ + "\376\377\305\342\242\202\214\305@\5\216\306A\214\306>\215\307=\215\307" \ + "\77\213\304A\202\214\305@\2\214\306>\212\306@\210\214\306>\7\214\306" \ + "<\215\307=\215\307\77\213\305=\214\306>\215\307\77\213\305=\211\214\306" \ + ">\11\215\306A\215\305>\212\307;\213\304\77\215\306A\211\306=\215\306" \ + "A\212\307<\216\306A\202\215\307\77\4\343\361\320\376\377\375\377\377" \ + "\375\376\376\377\212\377\377\377\1\377\376\377\202\377\377\377\4\377" \ + "\376\377\376\377\377\367\375\363\225\311J\210\214\306>\10\215\307=\213" \ + "\310\77\214\305@\216\306\77\214\305@\212\307>\307\341\240\376\377\375" \ + "\210\377\377\377\5\377\376\377\374\377\375\377\376\377\343\361\320\212" \ + "\306@\202\214\306>\1\213\310\77\210\214\306>\10\215\306A\215\305>\214" \ + "\305@\260\327z\377\376\374\374\377\377\377\377\377\377\376\377\226\377" \ + "\377\377\1\332\332\332\210::<\2GGI\250\250\250\223\377\377\377\3\376" \ + "\376\376\377\377\377\376\376\376\202\377\377\377\1\376\376\376\202\377" \ + "\377\377\1\376\376\376\204\377\377\377\2\250\250\252;;=\204::<\202;;" \ + "=\2EEG\331\331\331\220\377\377\377\1\316\316\316\205::<\1kkm\221\377" \ + "\377\377\5\222\222\224::<;;=::<;;=\202::<\5SSU\364\364\364\376\376\376" \ + "\377\377\377\376\376\376\216\377\377\377\2\376\376\376TTV\203::<\4;;" \ + "=99;lln\376\376\376\243\377\377\377\1TTV\204::<\5;;=\204\204\206\376" \ + "\376\376\377\377\377\376\376\376\212\377\377\377\1\234\234\236\202::" \ + "<\1;;=\202::<\1\234\234\234\215\377\377\377\1\376\376\376\202\377\377" \ + "\377\1\376\376\376\212\377\377\377\6\376\376\376\250\250\252FFH99;::" \ + "<;;=\205::<\1\316\316\316\221\377\377\377\1\234\234\234\203::<\3;;=:" \ + ":<\234\234\236\266\377\377\377\3\214\305@\214\306>\214\305@\250\214\306" \ + ">\2\215\307\77\342\362\316\212\377\377\377\215\214\306>\1\250\325p\216" \ + "\377\377\377\1\342\361\320\202\214\306>\1\214\305@\211\214\306>\2\214" \ + "\305@\343\361\316\215\377\377\377\3\377\376\377\376\377\375\376\377\377" \ + "\202\377\377\377\13\377\377\375\377\376\377\376\376\374\271\332\211\215" \ + "\306A\211\306;\216\306A\212\307>\213\307A\215\306A\212\307>\211\214\306" \ + ">\3\215\305>\214\306>\305\342\240\214\377\377\377\20\376\377\375\377" \ + "\377\377\377\377\375\377\377\377\371\370\364\233\316U\214\306>\214\305" \ + "@\215\306A\214\306>\214\305@\215\307=\214\306>\215\305@\215\304B\213" \ + "\310=\210\214\306>\3\215\305@\214\306>\213\305=\202\213\310\77\3\214" \ + "\306>\215\307\77\215\305@\210\214\306>\20\212\306@\212\307;\216\306\77" \ + "\215\307\77\212\306@\214\306<\215\305>\215\307\77\220\305\77\211\307" \ + ">\263\330{\377\376\377\377\377\375\376\377\377\377\377\377\376\376\376" \ + "\211\377\377\377\7\377\377\373\377\377\377\377\375\376\377\377\377\377" \ + "\377\375\257\330|\213\310\77\211\214\306>\6\215\306C\211\306=\214\305" \ + "@\214\306>\242\322e\377\377\375\212\377\377\377\7\376\377\377\377\377" \ + "\375\377\375\376\277\337\224\216\307B\212\307>\214\305@\210\214\306>" \ + "\2\214\305@\216\306\77\202\212\307>\4\332\360\302\376\376\374\376\376" \ + "\376\377\376\377\227\377\377\377\1\266\266\266\202::<\1;;=\202::<\2;" \ + ";=::<\202;;=\2kkm\346\346\350\202\377\377\377\1\376\376\376\207\377\377" \ + "\377\1\376\376\376\203\377\377\377\5\376\376\376\377\377\377\376\376" \ + "\376\377\377\377\376\376\376\202\377\377\377\3\376\376\376\377\377\377" \ + "\376\376\376\204\377\377\377\2\364\364\364yy{\203::<\2;;=99;\203::<\3" \ + "\265\265\267\377\377\377\376\376\376\217\377\377\377\1\316\316\316\205" \ + "::<\1kkm\222\377\377\377\1kkm\203::<\1;;=\202::<\5kkm\377\377\377\376" \ + "\376\376\377\377\377\376\376\376\212\377\377\377\5\376\376\376\377\377" \ + "\377\376\376\376\265\265\267;;=\204::<\2;;=\315\315\315\244\377\377\377" \ + "\11\234\234\234::<99;;;=::<;;=::<\347\347\347\376\376\376\213\377\377" \ + "\377\1\234\234\236\204::<\2;;=\233\233\233\217\377\377\377\1\376\376" \ + "\376\206\377\377\377\6\376\376\376\377\377\377\376\376\376\377\377\377" \ + "\265\265\265TTT\202::<\202;;=\203::<\3;;=::<\266\266\270\202\377\377" \ + "\377\1\376\376\376\217\377\377\377\1\234\234\234\204::<\4;;=\235\235" \ + "\237\377\377\377\376\376\376\224\377\377\377\1\376\376\376\203\377\377" \ + "\377\1\376\376\376\233\377\377\377\3\214\305@\214\306>\214\305@\250\214" \ + "\306>\2\215\307\77\342\362\316\212\377\377\377\215\214\306>\1\250\325" \ + "p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\211\214\306>" \ + "\2\214\305@\343\361\316\215\377\377\377\202\377\377\375\16\377\377\377" \ + "\377\377\375\377\377\377\376\377\375\376\376\374\377\376\377\375\377" \ + "\376\241\322_\215\306A\212\306B\215\305>\215\307\77\214\306<\214\305" \ + "B\211\214\306>\3\215\305>\214\306>\305\342\240\214\377\377\377\1\377" \ + "\376\377\202\377\377\375\15\376\377\377\377\375\376\340\361\317\214\306" \ + ">\212\307>\214\306>\215\307\77\214\306>\212\307<\215\307\77\215\305>" \ + "\216\306=\213\305=\210\214\306>\1\212\307>\202\214\305@\202\214\306>" \ + "\3\214\305@\215\306A\212\307>\210\214\306>\20\212\307>\213\304\77\214" \ + "\306>\211\310<\214\306>\216\306A\212\306@\215\305@\214\306>\223\313N" \ + "\367\372\363\376\377\377\377\377\377\377\376\377\376\377\373\377\376" \ + "\377\212\377\377\377\202\376\377\377\3\377\375\376\324\353\265\215\306" \ + "A\211\214\306>\7\215\305>\213\305=\215\307\77\215\306A\212\307>\351\363" \ + "\333\377\377\375\211\377\377\377\10\377\376\377\375\377\376\376\377\377" \ + "\377\376\377\370\373\362\233\314W\215\307\77\215\305<\210\214\306>\1" \ + "\215\307\77\202\214\306>\4\214\306<\225\310O\360\366\350\377\376\377" \ + "\221\377\377\377\3\376\376\376\377\377\377\376\376\376\205\377\377\377" \ + "\1\266\266\266\202::<\4;;=99;::<;;=\202::<\4;;=::<\204\204\206\346\346" \ + "\350\207\377\377\377\1\376\376\376\206\377\377\377\202\376\376\376\202" \ + "\377\377\377\1\376\376\376\203\377\377\377\1\376\376\376\202\377\377" \ + "\377\3\251\251\251FFF99;\202::<\1""99;\202::<\5;;=::<\234\234\236\377" \ + "\377\377\376\376\376\220\377\377\377\1\316\316\316\205::<\1kkm\222\377" \ + "\377\377\11\363\363\363GGI99;::<99;;;=::<;;=\234\234\234\214\377\377" \ + "\377\1\376\376\376\203\377\377\377\1SSU\202::<\1;;=\202::<\1kkm\245\377" \ + "\377\377\5\362\362\362GGI;;=::<;;=\202::<\1\204\204\206\206\377\377\377" \ + "\1\376\376\376\205\377\377\377\1\234\234\236\203::<\3""99;::<\234\234" \ + "\234\223\377\377\377\1\376\376\376\203\377\377\377\3\331\331\331\222" \ + "\222\222SSU\203::<\2;;=::<\202;;=\4::<;;=::<\265\265\267\202\377\377" \ + "\377\1\376\376\376\203\377\377\377\1\376\376\376\214\377\377\377\1\234" \ + "\234\234\205::<\1\234\234\236\203\377\377\377\1\376\376\376\223\377\377" \ + "\377\1\376\376\376\236\377\377\377\3\214\305@\214\306>\214\305@\250\214" \ + "\306>\2\215\307\77\342\362\316\212\377\377\377\215\214\306>\1\250\325" \ + "p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\211\214\306>" \ + "\2\214\305@\343\361\316\216\377\377\377\17\377\376\377\377\377\377\376" \ + "\376\376\377\376\377\377\377\375\376\377\377\375\377\376\377\377\377" \ + "\363\367\350\222\312K\214\305@\213\310\77\214\304\77\215\307\77\216\306" \ + "A\211\214\306>\3\215\305>\214\306>\305\342\240\214\377\377\377\14\377" \ + "\376\377\376\377\375\376\377\377\377\376\377\376\377\377\376\377\375" \ + "\307\342\237\214\305@\214\306<\215\304D\214\306>\214\305D\202\212\307" \ + "<\2\212\307>\213\307A\210\214\306>\3\215\307\77\214\306>\215\307\77\202" \ + "\214\305@\213\214\306>\12\213\305;\215\306A\212\306@\214\306>\213\307" \ + "C\212\307>\215\305>\212\307>\215\305>\333\356\301\202\377\377\377\3\377" \ + "\377\375\377\377\377\377\376\377\211\377\377\377\10\376\377\375\377\377" \ + "\375\376\377\375\374\377\375\362\371\347\225\311M\215\307\77\215\305" \ + "<\210\214\306>\2\214\305@\216\306=\202\212\306@\2\305\342\237\377\375" \ + "\376\212\377\377\377\1\376\376\374\203\377\377\377\4\376\376\376\337" \ + "\363\316\215\306C\215\305<\211\214\306>\1\215\307\77\202\214\305@\4\214" \ + "\306<\253\324n\375\377\374\377\377\375\224\377\377\377\1\376\376\376" \ + "\204\377\377\377\2\301\301\301FFH\202::<\2;;=99;\202;;=\2::<;;=\202:" \ + ":<\2\204\204\206\316\316\320\207\377\377\377\1\376\376\376\203\377\377" \ + "\377\1\376\376\376\206\377\377\377\6\376\376\376\377\377\377\364\364" \ + "\364\265\265\267SSU::<\202;;=\202::<\5;;=::<;;=::<\204\204\204\223\377" \ + "\377\377\1\316\316\316\205::<\1kkm\223\377\377\377\11\315\315\315;;=" \ + "::<;;=::<;;=::<99;\302\302\302\216\377\377\377\5\301\301\303::<;;=::" \ + "<;;=\202::<\2\316\316\316\377\377\377\202\376\376\376\241\377\377\377" \ + "\14\376\376\376\377\377\377\234\234\234;;=::<;;=::<;;=::<\347\347\351" \ + "\377\377\377\376\376\376\211\377\377\377\1\234\234\236\203::<\3;;=::" \ + "<\234\234\236\216\377\377\377\202\376\376\376\1\377\377\377\202\316\316" \ + "\316\6\250\250\250\234\234\234jjjFFF;;=99;\202;;=\2::<;;=\202::<\5<<" \ + ">99;;;=::<\265\265\267\204\377\377\377\1\376\376\376\217\377\377\377" \ + "\1\234\234\234\204::<\2;;=\234\234\236\202\377\377\377\1\376\376\376" \ + "\223\377\377\377\1\376\376\376\202\377\377\377\1\376\376\376\234\377" \ + "\377\377\3\214\305@\214\306>\214\305@\250\214\306>\2\215\307\77\342\362" \ + "\316\212\377\377\377\215\214\306>\1\250\325p\216\377\377\377\1\342\361" \ + "\320\202\214\306>\1\214\305@\211\214\306>\2\214\305@\343\361\316\215" \ + "\377\377\377\202\377\376\377\16\377\377\375\376\377\377\377\377\377\377" \ + "\377\375\377\376\377\376\376\376\377\376\377\377\377\377\333\354\302" \ + "\212\307>\213\310\77\214\306<\213\310=\215\305@\211\214\306>\3\215\305" \ + ">\214\306>\305\342\240\214\377\377\377\1\377\376\377\202\376\377\377" \ + "\202\377\377\375\13\376\377\377\377\375\376\271\333\205\215\305>\214" \ + "\306>\212\307>\214\306>\215\306A\214\306>\212\306@\214\305@\210\214\306" \ + ">\3\214\305@\215\307\77\214\306>\202\212\307>\3\214\306>\215\307\77\215" \ + "\306A\210\214\306>\4\216\306A\211\306=\214\306<\216\306A\202\212\307" \ + ">\202\215\306A\10\322\352\270\377\377\375\376\376\374\377\377\377\376" \ + "\377\377\377\376\377\377\377\375\376\377\377\210\377\377\377\10\377\377" \ + "\375\377\377\377\377\376\377\374\376\373\250\325n\216\306\77\212\307" \ + ">\214\305B\210\214\306>\202\212\307>\6\214\305@\242\322d\376\376\374" \ + "\377\377\375\375\377\376\377\376\377\210\377\377\377\10\376\377\377\377" \ + "\377\375\377\375\376\377\377\375\375\376\377\376\377\375\270\333\207" \ + "\211\310<\210\214\306>\10\214\304=\216\307B\214\306>\212\307>\216\306" \ + "A\215\307\77\313\350\250\376\376\377\221\377\377\377\1\376\376\376\203" \ + "\377\377\377\1\376\376\376\204\377\377\377\7\332\332\332RRT;;=::<;;=" \ + "::<;;=\202::<\1;;=\203::<\3RRT\221\221\223\317\317\321\214\377\377\377" \ + "\11\376\376\376\377\377\377\364\364\364\301\301\301\204\204\206EEG;;" \ + "=99;;;=\204::<\1""99;\202::<\1\251\251\251\207\377\377\377\1\376\376" \ + "\376\214\377\377\377\1\316\316\316\205::<\1kkm\224\377\377\377\1\247" \ + "\247\247\203::<\5;;=::<;;=FFH\345\345\345\214\377\377\377\2\376\376\376" \ + "kkm\205::<\1SSU\202\377\377\377\1\376\376\376\244\377\377\377\2\363\363" \ + "\363FFH\204::<\2;;=\221\221\223\213\377\377\377\1\234\234\236\204::<" \ + "\4;;=SSUkkmlln\213kkm\5;;=::<;;=::<;;=\204::<\2;;=99;\202;;=\2::<;;=" \ + "\202::<\7;;=99;::\214\305@\250\214\306>\2\215" \ + "\307\77\342\362\316\212\377\377\377\215\214\306>\1\250\325p\216\377\377" \ + "\377\1\342\361\320\202\214\306>\1\214\305@\211\214\306>\2\214\305@\343" \ + "\361\316\215\377\377\377\1\377\376\377\202\377\377\375\202\377\377\377" \ + "\202\377\376\377\11\377\377\375\377\377\377\376\377\377\377\376\377\276" \ + "\336\223\214\306<\213\310\77\214\304=\215\306A\211\214\306>\3\215\305" \ + ">\214\306>\305\342\240\214\377\377\377\20\377\377\375\376\377\375\376" \ + "\376\376\377\376\377\375\377\376\377\375\377\376\377\377\376\377\375" \ + "\270\333\207\217\305<\212\307>\214\305@\216\306\77\213\305=\214\305@" \ + "\216\306=\211\214\306>\2\215\306A\215\305@\202\216\306\77\3\215\305@" \ + "\214\305@\215\307\77\210\214\306>\13\213\305=\215\306A\215\305>\212\306" \ + "@\215\305>\215\306A\220\305A\323\352\266\376\377\375\377\376\377\377" \ + "\377\375\202\377\377\377\3\376\377\377\377\375\377\376\377\375\213\377" \ + "\377\377\5\316\347\256\212\307>\213\305;\216\306A\212\307<\210\214\306" \ + ">\10\212\307>\216\306\77\215\305>\350\364\336\377\376\377\376\376\374" \ + "\377\377\377\377\376\377\210\377\377\377\1\377\376\377\202\377\377\377" \ + "\5\377\376\377\376\377\375\377\376\377\370\373\360\225\311K\210\214\306" \ + ">\10\216\306=\214\305@\215\310<\212\307>\214\306>\214\305@\223\312J\356" \ + "\371\350\231\377\377\377\4\376\376\376\377\377\377\363\363\363xxz\202" \ + "::<\1""99;\202::<\1;;=\203::<\202;;=\203::<\4__a\205\205\205\234\234" \ + "\234\250\250\250\205\316\316\316\4\250\250\250\234\234\234xxx___\202" \ + "::<\3""99;;;=99;\203::<\1;;=\203::<\2FFH\265\265\265\205\377\377\377" \ + "\1\376\376\376\217\377\377\377\1\316\316\316\205::<\1kkm\225\377\377" \ + "\377\3xxx::<;;=\204::<\1```\213\377\377\377\4\376\376\376\317\317\317" \ + "::<;;=\204::<\1\266\266\270\203\377\377\377\1\376\376\376\241\377\377" \ + "\377\1\377\377\375\202\377\377\377\1\204\204\206\202::<\1;;=\202::<\2" \ + "GGI\363\363\363\212\377\377\377\1\234\234\236\203::<\1;;=\202::<\1;;" \ + "=\221::<\1;;=\207::<\1;;=\202::<\1;;=\202::<\2``b\346\346\350\210\377" \ + "\377\377\1\376\376\376\215\377\377\377\1\234\234\234\207::<\3;;=::<;" \ + ";=\221::<\1;;=\203::<\1;;=\202::<\1\316\316\320\231\377\377\377\3\214" \ + "\305@\214\306>\214\305@\250\214\306>\2\215\307\77\342\362\316\212\377" \ + "\377\377\215\214\306>\1\250\325p\216\377\377\377\1\342\361\320\202\214" \ + "\306>\1\214\305@\211\214\306>\2\214\305@\343\361\316\215\377\377\377" \ + "\7\377\377\375\376\377\375\377\377\377\377\376\377\376\376\374\376\377" \ + "\377\377\377\377\202\376\377\377\202\377\377\375\4\377\377\377\242\320" \ + "d\211\306=\215\305@\212\214\306>\3\215\305>\214\306>\305\342\240\214" \ + "\377\377\377\6\377\376\377\377\377\377\377\377\375\377\375\377\376\377" \ + "\372\375\376\377\202\377\377\377\10\376\377\377\304\343\240\215\305@" \ + "\214\306>\216\306A\215\307\77\212\307>\215\307\77\212\214\306>\3\215" \ + "\307\77\214\306>\214\305@\202\215\307\77\211\214\306>\12\215\306C\212" \ + "\307<\215\307\77\215\305@\213\310\77\215\306A\323\352\266\377\376\377" \ + "\377\377\377\376\377\377\204\377\377\377\2\377\377\375\377\376\377\210" \ + "\377\377\377\10\376\377\377\377\376\377\361\370\346\225\311K\212\307" \ + ">\215\306A\214\305@\215\305>\210\214\306>\3\214\305@\214\306>\307\341" \ + "\240\203\376\377\377\2\377\377\375\376\377\377\210\377\377\377\5\376" \ + "\377\377\377\376\372\376\377\375\376\376\376\377\377\377\202\377\376" \ + "\377\1\334\355\301\210\214\306>\10\215\306A\213\310\77\215\305@\214\306" \ + ">\214\306<\215\306A\214\306>\254\322o\232\377\377\377\6\376\376\376\377" \ + "\377\377\376\376\376\302\302\302FFH;;=\206::<\1;;=\202::<\202;;=\203" \ + "::<\1;;=\204::<\3;;=::<;;=\202::<\1;;=\202::<\1;;=\203::<\2;;=::<\202" \ + ";;=\2__a\332\332\332\226\377\377\377\3\316\316\316::<;;=\203::<\1kkm" \ + "\222\377\377\377\7\376\376\376\377\377\377\376\376\376\363\363\363__" \ + "a::<;;=\204::<\1\203\203\203\202\377\377\377\2\376\376\376\377\377\377" \ + "\202\376\376\376\205\377\377\377\1kkm\202::<\1;;=\202::<\5TTV\377\377" \ + "\377\376\376\376\377\377\377\376\376\376\245\377\377\377\2\347\347\347" \ + "99;\202::<\1;;=\202::<\1\235\235\237\206\377\377\377\1\376\376\376\202" \ + "\377\377\377\2\376\376\376\234\234\234\224::<\1;;=\202::<\3""99;::<;" \ + ";=\204::<\1;;=\204::<\3;;=GGI\250\250\252\230\377\377\377\2\234\234\236" \ + ";;=\232::<\10;;=99;;;=::<;;=::<:::\316\316\316\230\377\377\377\10\377" \ + "\376\377\212\306@\214\305@\213\310=\214\306<\215\306A\214\307;\215\306" \ + "A\240\214\306>\10\214\305@\212\307<\214\306<\214\305@\212\306@\342\360" \ + "\315\376\377\377\377\376\377\210\377\377\377\212\214\306>\4\216\306\77" \ + "\212\306B\214\306>\250\325n\202\377\376\377\210\377\377\377\1\377\376" \ + "\377\202\377\377\377\5\376\377\375\342\362\316\214\305B\215\305@\214" \ + "\306<\210\214\306>\202\212\307>\5\343\361\320\377\377\377\377\377\375" \ + "\376\377\377\377\376\377\223\377\377\377\6\377\376\377\377\377\375\371" \ + "\372\364\223\312J\212\306@\215\305@\210\214\306>\10\214\305@\215\305" \ + ">\212\307>\304\343\240\377\377\375\377\377\377\377\377\375\377\376\377" \ + "\220\377\377\377\11\376\377\377\377\377\377\333\355\303\226\310K\213" \ + "\310\77\214\306>\215\305@\215\306A\214\305@\203\214\306>\7\215\305>\215" \ + "\305@\214\305@\212\307>\215\305>\215\307\77\215\306A\202\214\306<\5\215" \ + "\306A\213\305=\215\305@\215\307\77\213\305;\202\215\305@\13\215\307\77" \ + "\213\310\77\214\305@\215\307\77\212\307>\215\305>\214\306>\212\306@\235" \ + "\315U\347\365\334\377\376\377\220\377\377\377\15\376\376\376\377\377" \ + "\375\377\377\377\244\317c\213\307A\214\306<\213\307A\215\305>\215\305" \ + "<\215\307\77\214\306<\215\307\77\214\305@\202\215\307\77\12\214\305@" \ + "\215\306A\215\305@\234\315W\367\375\363\377\376\377\376\377\377\377\377" \ + "\375\376\377\377\377\376\377\220\377\377\377\10\260\331{\215\307=\212" \ + "\307>\213\307A\214\306>\215\305@\215\307\77\215\305>\210\214\306>\3\314" \ + "\345\253\377\377\377\376\377\375\202\377\376\377\2\377\377\377\376\377" \ + "\377\222\377\377\377\3\376\376\376\377\377\377\376\376\376\202\377\377" \ + "\377\3\364\364\364\220\220\220;;=\211::<\2;;=::<\202;;=\2::<;;=\202:" \ + ":<\4;;=::<;;=99;\203::<\2;;=99;\206::<\2GGI\247\247\251\203\377\377\377" \ + "\1\376\376\376\222\377\377\377\6\376\376\376\377\377\377\316\316\316" \ + ";;=99;;;=\202::<\2lln\376\376\376\202\377\377\377\1\376\376\376\221\377" \ + "\377\377\4\376\376\376\333\333\333FFH;;=\202::<\1;;=\202::<\1\265\265" \ + "\265\202\377\377\377\1\376\376\376\202\377\377\377\5\376\376\376\377" \ + "\377\377\376\376\376\377\377\377\316\316\320\202::<\2;;=99;\202;;=\1" \ + "\264\264\266\202\377\377\377\1\376\376\376\244\377\377\377\1\376\376" \ + "\376\202\377\377\377\1\205\205\207\204::<\3;;=FFH\363\363\363\206\377" \ + "\377\377\1\376\376\376\202\377\377\377\3\233\233\233::<;;=\220::<\3""9" \ + "9;;;=99;\202::<\1;;=\203::<\1;;=\204::<\7;;=::\215\307\77" \ + "\214\306>\215\306A\240\214\306>\7\214\306<\214\306>\216\306\77\214\306" \ + ">\214\305@\343\361\320\377\377\375\211\377\377\377\210\214\306>\10\213" \ + "\307A\212\306@\215\305@\212\307<\215\307\77\247\324o\375\377\376\376" \ + "\377\377\211\377\377\377\7\376\377\375\377\377\377\377\377\375\342\360" \ + "\315\214\305@\213\305=\215\307\77\210\214\306>\10\215\305>\215\307\77" \ + "\343\361\316\376\376\376\377\376\377\376\377\377\377\377\375\376\377" \ + "\372\220\377\377\377\10\376\377\377\377\376\377\377\377\375\377\376\374" \ + "\376\377\375\343\362\321\212\307>\214\307;\210\214\306>\4\215\307=\215" \ + "\304B\213\307A\305\342\240\203\377\377\377\1\376\377\377\222\377\377" \ + "\377\21\377\376\377\367\374\365\267\332\206\215\306A\212\306@\214\306" \ + "<\214\306>\215\306A\215\307\77\214\306>\214\305@\212\306B\212\306@\212" \ + "\307<\215\307\77\214\306>\214\305@\202\215\305@\5\214\305@\214\306>\214" \ + "\305@\212\307>\215\306A\202\214\305@\11\214\307;\214\306>\215\306A\214" \ + "\305@\215\305>\212\306@\222\311I\306\343\240\366\373\364\224\377\377" \ + "\377\6\303\342\237\217\304@\214\306<\214\306>\215\306C\212\306B\204\214" \ + "\305@\1\215\306A\202\214\305@\11\215\306A\214\306<\214\306>\341\361\314" \ + "\377\377\377\376\377\375\377\377\377\377\375\377\377\377\375\221\377" \ + "\377\377\10\370\373\364\224\307N\215\305@\215\305>\212\307<\215\306A" \ + "\212\307<\215\306A\210\214\306>\10\215\307=\346\364\332\376\377\375\376" \ + "\377\373\377\377\377\376\376\377\377\376\377\377\377\375\230\377\377" \ + "\377\5\346\346\350\204\204\206GGI::<;;=\202::<\5;;=::<;;=::<;;=\202:" \ + ":<\3;;=::<;;=\202::<\5;;=99;;;=::<;;=\207::<\3FFH\234\234\234\363\363" \ + "\363\203\377\377\377\1\376\376\376\222\377\377\377\1\376\376\376\202" \ + "\377\377\377\4\316\316\316::<;;=99;\202;;=\1kkm\202\377\377\377\1\376" \ + "\376\376\220\377\377\377\1\376\376\376\202\377\377\377\5\376\376\376" \ + "\266\266\26699;;;=::<\202;;=\3::\215\307\77\212\307>\216\306\77\241\214\306" \ + ">\1\215\306C\202\215\305@\5\212\306@\215\307=\343\361\320\377\377\377" \ + "\377\376\377\210\377\377\377\210\214\306>\10\215\305<\215\307\77\216" \ + "\306\77\214\306>\216\305C\252\324r\377\377\377\377\377\373\211\377\377" \ + "\377\7\375\377\376\377\377\377\377\375\376\343\361\316\215\307=\212\307" \ + ">\215\305>\210\214\306>\10\214\305@\215\305<\342\362\316\377\377\375" \ + "\377\376\377\375\377\374\376\376\377\376\377\377\222\377\377\377\1\375" \ + "\377\372\202\377\377\377\3\377\376\377\304\341\237\215\307\77\210\214" \ + "\306>\10\212\307;\215\307\77\213\305=\305\342\240\377\377\377\377\376" \ + "\374\377\377\375\376\377\377\221\377\377\377\22\377\376\377\377\377\375" \ + "\376\377\377\377\375\376\361\367\351\270\334\204\214\306>\215\307\77" \ + "\214\305@\212\306@\213\307A\212\306@\213\310\77\214\306>\215\304B\214" \ + "\306>\212\307<\214\306>\202\216\306A\6\214\306>\213\310\77\214\305@\215" \ + "\305<\215\305>\215\307=\202\213\310\77\10\215\306A\214\306>\215\306A" \ + "\222\311I\300\336\226\361\370\346\376\376\376\377\377\377\202\377\376" \ + "\377\1\376\377\373\217\377\377\377\10\377\377\375\347\365\333\214\307" \ + ";\211\305A\213\304\77\215\307\77\215\305<\213\310\77\202\214\306>\1\215" \ + "\307\77\203\214\306>\4\215\307\77\214\306>\215\306A\275\337\223\202\377" \ + "\377\377\5\377\376\377\377\377\377\376\377\375\377\376\377\376\377\377" \ + "\220\377\377\377\10\375\377\376\331\357\301\215\307\77\215\305>\216\305" \ + "C\211\306=\220\305A\211\307@\210\214\306>\10\214\305@\246\321e\377\377" \ + "\377\377\376\377\376\377\377\377\377\375\376\377\377\377\376\377\227" \ + "\377\377\377\1\376\376\376\202\377\377\377\3\363\363\363\266\266\270" \ + "__a\207::<\202;;=\203::<\2;;=99;\202;;=\2""99;::<\202;;=\1::<\203;;=" \ + "\3^^^\250\250\250\363\363\363\203\377\377\377\1\376\376\376\202\377\377" \ + "\377\1\376\376\376\224\377\377\377\4\316\316\316999::<;;=\202::<\1ll" \ + "l\205\377\377\377\1\376\376\376\217\377\377\377\6\376\376\376\377\377" \ + "\377\376\376\376\204\204\204::<;;=\203::<\3:::TTT\363\363\363\206\377" \ + "\377\377\10\347\347\347;;;99;::<;;=::<:::\234\234\236\253\377\377\377" \ + "\3\376\376\376lln;;=\202::<\3;;=999SSS\202\377\377\377\1\376\376\376" \ + "\203\377\377\377\4\376\376\376\377\377\377\376\376\376\234\234\234\223" \ + "::<\1""99;\202::<\1;;=\203::<\5kkmxxz\235\235\237\301\301\301\346\346" \ + "\346\207\377\377\377\1\376\376\376\202\377\377\377\1\376\376\376\221" \ + "\377\377\377\1\376\376\376\202\377\377\377\3\235\235\235::<;;=\232::" \ + "<\2;;=99;\202::<\3;;=::<\316\316\316\230\377\377\377\10\373\377\376\216" \ + "\306A\214\306<\213\304A\212\306@\214\305@\214\304\77\215\307\77\240\214" \ + "\306>\6\214\306<\215\306A\215\305@\216\310@\217\304@\341\361\314\212" \ + "\377\377\377\210\214\306>\7\215\307\77\213\310\77\213\305=\215\307\77" \ + "\214\304\77\253\323r\374\377\373\211\377\377\377\1\377\376\377\203\377" \ + "\377\377\3\342\362\315\215\305@\215\307=\211\214\306>\10\214\306<\215" \ + "\304B\341\363\313\374\377\375\376\376\377\377\377\377\377\375\376\377" \ + "\377\375\221\377\377\377\7\376\377\375\376\376\377\377\377\377\375\377" \ + "\374\377\377\377\377\377\375\253\323p\210\214\306>\5\215\307\77\215\305" \ + ">\217\304@\305\342\237\376\377\375\202\377\377\377\1\377\377\375\220" \ + "\377\377\377\1\376\377\377\202\377\376\377\202\376\377\375\202\377\377" \ + "\377\5\360\370\351\311\347\247\245\320e\215\305>\212\307>\202\214\306" \ + ">\5\215\306A\212\307>\215\305@\214\306>\214\306<\202\214\306>\2\214\306" \ + "<\214\306>\202\216\306A\14\214\306>\215\306A\215\305<\214\306>\213\305" \ + "=\255\331x\323\353\267\366\374\362\377\377\377\377\377\375\377\377\377" \ + "\376\377\377\217\377\377\377\2\376\376\376\377\377\377\202\377\377\375" \ + "\11\244\317d\214\306>\213\307A\214\306>\214\305@\214\306>\215\306A\214" \ + "\306<\215\307\77\202\214\306>\202\214\305@\13\215\305<\215\305@\230\316" \ + "V\370\373\360\376\377\375\377\377\377\377\376\377\376\376\376\377\377" \ + "\375\377\376\377\376\377\377\220\377\377\377\10\376\376\376\377\376\377" \ + "\262\327x\214\306>\216\306A\215\307=\215\305<\215\306A\211\214\306>\6" \ + "\215\306C\307\341\240\376\377\373\376\377\377\376\377\375\376\376\374" \ + "\236\377\377\377\4\346\346\350\266\266\270\204\204\206SSU\202::<\1;;" \ + "=\202::<\1;;=\202::<\202;;=\3""99;::<;;=\203::<\4GGIxxz\247\247\247\347" \ + "\347\347\212\377\377\377\1\376\376\376\223\377\377\377\1\364\364\364" \ + "\205\316\316\316\1\332\332\332\203\377\377\377\202\376\376\376\221\377" \ + "\377\377\1\376\376\376\202\377\377\377\202\316\316\316\203\316\316\320" \ + "\3\316\316\316\317\317\317\346\346\346\206\377\377\377\5\346\346\346" \ + "\316\316\316\317\317\317\316\316\316\315\315\315\202\316\316\316\1\363" \ + "\363\363\250\377\377\377\1\376\376\376\203\377\377\377\3\346\346\346" \ + "\315\315\315\317\317\317\202\316\316\320\3\317\317\317\315\315\315\363" \ + "\363\363\202\377\377\377\202\376\376\376\204\377\377\377\3\346\346\346" \ + "\316\316\316\316\316\320\224\316\316\316\1\315\315\315\203\377\377\377" \ + "\1\376\376\376\215\377\377\377\1\376\376\376\225\377\377\377\2\346\346" \ + "\346\317\317\317\232\316\316\316\1\317\317\317\203\316\316\316\4\317" \ + "\317\317\315\315\315\316\316\316\363\363\363\231\377\377\377\3\340\361" \ + "\317\342\360\317\342\362\316\202\343\361\316\2\342\360\315\343\361\316" \ + "\240\342\361\320\10\342\362\316\342\361\320\343\363\317\341\360\317\342" \ + "\361\320\370\373\364\376\377\375\376\377\377\210\377\377\377\210\342" \ + "\361\320\7\341\360\317\342\362\316\343\361\316\342\360\314\342\361\320" \ + "\350\364\336\377\376\374\211\377\377\377\10\377\376\377\377\377\375\377" \ + "\377\377\377\377\375\370\373\362\341\360\321\340\357\316\342\362\316" \ + "\210\342\361\320\3\342\362\316\342\361\320\371\373\360\203\377\377\377" \ + "\202\377\376\377\220\377\377\377\4\377\377\375\376\376\376\377\376\377" \ + "\376\377\375\203\377\377\377\1\365\375\362\210\342\361\320\4\341\360" \ + "\321\342\361\322\343\363\317\360\367\345\224\377\377\377\7\376\377\377" \ + "\376\377\375\377\377\375\377\376\377\377\377\375\377\375\376\377\376" \ + "\377\202\377\377\377\30\376\376\377\364\370\351\333\354\277\277\337\224" \ + "\247\324k\224\313K\214\305@\214\306>\212\306@\214\306>\214\305B\215\306" \ + "C\215\307\77\212\306@\214\306>\215\307\77\241\321c\257\330|\304\342\242" \ + "\341\361\315\377\377\377\377\376\377\376\377\373\377\377\377\202\377" \ + "\377\375\1\377\376\377\203\377\377\377\1\376\377\377\212\377\377\377" \ + "\1\376\376\376\203\377\377\377\13\376\376\374\372\372\370\342\361\320" \ + "\343\361\316\342\362\316\341\360\317\342\361\320\341\360\317\342\362" \ + "\316\342\361\322\342\361\320\202\341\361\315\6\342\361\320\341\360\317" \ + "\343\361\315\343\361\320\356\371\350\377\376\377\203\377\377\377\1\376" \ + "\377\375\202\377\377\377\1\376\377\375\222\377\377\377\6\366\373\364" \ + "\342\361\320\342\362\316\342\360\317\341\362\316\343\361\320\210\342" \ + "\361\320\10\341\362\316\341\361\315\352\364\334\377\377\377\377\376\377" \ + "\377\377\377\376\377\377\376\377\375\222\377\377\377\202\376\376\376" \ + "\202\377\377\377\1\376\376\376\202\377\377\377\1\376\376\376\202\377" \ + "\377\377\3\376\376\376\377\377\377\375\375\375\202\377\377\377\5\363" \ + "\363\363\316\316\316\264\264\264\235\235\235\233\233\233\202kkk\202k" \ + "km\3llnkkmyy{\202\234\234\236\6\316\316\320\346\346\346\377\377\377\376" \ + "\376\376\377\377\377\376\376\376\204\377\377\377\1\376\376\376\204\377" \ + "\377\377\1\376\376\376\240\377\377\377\1\376\376\376\231\377\377\377" \ + "\1\375\375\375\203\377\377\377\1\376\376\376\214\377\377\377\1\376\376" \ + "\376\202\377\377\377\1\376\376\376\242\377\377\377\1\376\376\376\206" \ + "\377\377\377\3\376\376\376\377\377\377\376\376\376\204\377\377\377\1" \ + "\376\376\376\202\377\377\377\202\376\376\376\225\377\377\377\3\376\376" \ + "\376\377\377\377\376\376\376\202\377\377\377\3\376\376\376\377\377\377" \ + "\376\376\376\214\377\377\377\3\376\376\376\377\377\377\376\376\376\265" \ + "\377\377\377\1\375\375\375\234\377\377\377\7\376\377\377\377\376\377" \ + "\376\377\377\376\376\374\377\376\377\377\377\377\377\377\375\240\377" \ + "\377\377\1\377\377\375\202\377\377\377\5\377\376\377\376\376\376\377" \ + "\376\377\376\376\377\377\377\375\221\377\377\377\7\375\376\377\377\377" \ + "\377\377\376\377\377\377\375\376\377\377\377\377\373\377\376\377\210" \ + "\377\377\377\5\377\376\377\377\377\377\376\376\374\376\377\377\377\377" \ + "\377\202\377\377\375\1\376\377\377\210\377\377\377\6\376\377\377\375" \ + "\376\377\377\376\377\377\377\377\376\377\377\377\377\377\202\377\377" \ + "\375\224\377\377\377\202\377\376\377\2\374\377\377\377\376\377\210\377" \ + "\377\377\3\376\377\377\376\376\376\376\377\377\202\377\377\377\3\375" \ + "\377\376\377\377\377\377\376\377\220\377\377\377\202\377\376\377\2\376" \ + "\377\377\375\376\377\202\377\377\377\4\377\377\375\377\376\377\377\377" \ + "\377\377\377\375\202\376\377\377\7\377\377\377\377\376\377\377\377\377" \ + "\376\377\375\370\373\364\344\357\315\342\361\320\202\342\362\315\14\340" \ + "\357\316\345\360\316\376\377\373\376\376\376\377\377\377\377\375\376" \ + "\377\377\375\377\377\377\375\377\376\377\377\377\377\376\377\377\377" \ + "\375\202\376\377\375\5\376\377\377\377\377\377\377\377\375\376\376\376" \ + "\377\376\377\214\377\377\377\1\376\376\376\202\377\377\377\5\377\377" \ + "\375\376\375\377\377\377\377\376\376\377\377\377\375\204\377\377\377" \ + "\1\377\377\375\205\377\377\377\202\377\376\377\2\377\377\377\377\377" \ + "\375\202\377\377\377\202\376\377\377\222\377\377\377\5\377\377\375\377" \ + "\377\377\377\377\375\377\377\377\377\377\375\202\377\377\377\1\377\376" \ + "\372\212\377\377\377\1\377\375\377\202\377\377\377\3\377\376\377\377" \ + "\377\377\377\377\375\225\377\377\377\1\376\376\376\211\377\377\377\1" \ + "\376\376\376\204\377\377\377\1\376\376\376\205\377\377\377\1\376\376" \ + "\376\206\377\377\377\3\376\376\376\377\377\377\376\376\376\206\377\377" \ + "\377\1\376\376\376\233\377\377\377\1\376\376\376\203\377\377\377\5\376" \ + "\376\376\377\377\377\376\376\376\377\377\377\376\376\376\223\377\377" \ + "\377\3\376\376\376\377\377\377\376\376\376\205\377\377\377\3\376\376" \ + "\376\377\377\377\376\376\376\203\377\377\377\3\376\376\376\377\377\377" \ + "\376\376\376\203\377\377\377\1\376\376\376\205\377\377\377\1\376\376" \ + "\376\246\377\377\377\3\376\376\376\377\377\377\376\376\376\220\377\377" \ + "\377\1\376\376\376\246\377\377\377\1\376\376\376\225\377\377\377\1\376" \ + "\376\376\202\377\377\377\1\376\376\376\240\377\377\377\1\376\376\376" \ + "\230\377\377\377\6\377\377\375\377\377\377\377\376\377\376\377\375\374" \ + "\377\377\376\375\377\242\377\377\377\202\377\376\377\6\376\376\376\375" \ + "\376\377\377\377\377\377\377\375\377\377\377\376\377\375\220\377\377" \ + "\377\7\377\377\375\377\377\377\377\377\375\377\375\376\376\377\375\376" \ + "\377\377\376\376\376\212\377\377\377\4\377\376\377\377\377\375\377\377" \ + "\377\377\377\375\203\377\376\377\210\377\377\377\5\377\377\375\377\377" \ + "\377\377\375\376\377\376\377\377\377\375\202\377\377\377\1\376\377\377" \ + "\221\377\377\377\1\375\376\377\203\377\377\375\2\376\377\375\377\375" \ + "\376\211\377\377\377\204\377\376\377\4\377\377\377\376\377\375\377\377" \ + "\375\377\376\377\221\377\377\377\5\376\377\377\376\376\376\377\377\373" \ + "\376\376\377\376\377\377\202\377\377\377\2\377\376\377\377\377\375\202" \ + "\377\377\377\7\377\377\375\377\376\377\376\376\377\377\377\377\376\377" \ + "\377\376\377\375\376\377\377\202\377\377\377\203\376\377\377\2\377\377" \ + "\377\376\376\374\202\377\376\377\13\376\376\376\377\377\375\377\377\377" \ + "\377\375\376\376\377\377\377\377\377\376\376\377\377\376\377\376\376" \ + "\374\376\377\377\377\377\375\221\377\377\377\203\377\377\375\4\377\377" \ + "\377\377\377\375\377\376\377\376\376\376\210\377\377\377\1\377\377\373" \ + "\203\377\377\377\1\377\377\375\202\376\377\377\222\377\377\377\1\377" \ + "\377\375\202\377\376\377\3\377\377\377\377\376\377\377\376\374\202\376" \ + "\377\377\210\377\377\377\4\377\377\375\377\377\377\376\377\375\377\375" \ + "\377\202\376\377\377\1\377\376\375\227\377\377\377\1\376\376\376\207" \ + "\377\377\377\1\376\376\376\217\377\377\377\1\376\376\376\205\377\377" \ + "\377\1\376\376\376\204\377\377\377\1\376\376\376\233\377\377\377\1\376" \ + "\376\376\211\377\377\377\1\376\376\376\222\377\377\377\1\376\376\376" \ + "\206\377\377\377\1\376\376\376\207\377\377\377\1\376\376\376\262\377" \ + "\377\377\1\376\376\376\212\377\377\377\1\376\376\376\202\377\377\377" \ + "\1\376\376\376\202\377\377\377\1\376\376\376\225\377\377\377\1\376\376" \ + "\376\306\377\377\377\1\376\376\376\235\377\377\377\7\377\376\377\376" \ + "\377\377\377\377\377\377\377\375\376\375\377\377\377\375\377\376\377" \ + "\241\377\377\377\1\376\377\377\203\377\377\377\3\377\377\375\377\375" \ + "\376\377\376\377\221\377\377\377\202\376\377\377\5\377\377\377\377\377" \ + "\375\377\377\377\377\376\377\377\377\375\211\377\377\377\203\377\377" \ + "\375\202\377\377\377\202\376\377\377\1\377\377\375\212\377\377\377\202" \ + "\376\377\375\3\376\377\377\377\377\375\377\376\377\223\377\377\377\6" \ + "\377\377\375\377\376\377\374\377\377\377\377\377\377\376\377\376\377" \ + "\375\210\377\377\377\3\377\377\375\376\377\377\377\377\375\202\377\377" \ + "\377\1\377\377\375\223\377\377\377\4\376\376\376\377\377\375\376\376" \ + "\376\377\376\377\202\377\377\375\1\376\376\376\206\377\377\377\1\377" \ + "\377\375\215\377\377\377\1\377\377\375\202\377\377\377\5\376\377\377" \ + "\377\377\377\376\376\374\377\377\377\377\376\377\202\377\377\377\1\376" \ + "\376\376\221\377\377\377\7\376\377\375\377\375\377\377\377\377\376\377" \ + "\377\377\377\377\377\377\373\377\376\377\202\377\377\377\1\377\377\375" \ + "\202\377\377\377\1\377\377\375\204\377\377\377\6\376\376\377\377\377" \ + "\375\376\377\377\377\377\375\377\376\377\375\377\374\222\377\377\377" \ + "\3\376\377\375\377\377\377\376\377\375\203\376\377\377\1\377\376\377" \ + "\211\377\377\377\7\377\377\373\377\376\377\377\377\375\377\377\377\377" \ + "\376\377\376\376\376\376\377\377") + + diff --git a/meta-agl-profile-core/recipes-core/psplash/files/psplash-quit.service b/meta-agl-profile-core/recipes-core/psplash/files/psplash-quit.service new file mode 100644 index 000000000..14bd4994b --- /dev/null +++ b/meta-agl-profile-core/recipes-core/psplash/files/psplash-quit.service @@ -0,0 +1,11 @@ +[Unit] +Description=Terminate Psplash Boot Screen +After=psplash-start.service + +[Service] +Type=oneshot +ExecStart=/usr/bin/psplash-write QUIT +TimeoutSec=20 + +[Install] +WantedBy=multi-user.target diff --git a/meta-agl-profile-core/recipes-core/psplash/files/psplash-start.service b/meta-agl-profile-core/recipes-core/psplash/files/psplash-start.service new file mode 100644 index 000000000..d3b6940d0 --- /dev/null +++ b/meta-agl-profile-core/recipes-core/psplash/files/psplash-start.service @@ -0,0 +1,12 @@ +[Unit] +Description=Start Psplash Boot Screen +Wants=systemd-vconsole-setup.service +After=systemd-vconsole-setup.service systemd-udev-trigger.service systemd-udevd.service +DefaultDependencies=no + +[Service] +ExecStartPre=/bin/sh -c "if [ -e /sys/class/graphics/fbcon/cursor_blink ]; then echo 0 > /sys/class/graphics/fbcon/cursor_blink; fi" +ExecStart=/bin/bash -c "/usr/bin/psplash-anim -n -a 90" + +[Install] +WantedBy=sysinit.target diff --git a/meta-agl-profile-core/recipes-core/psplash/psplash_git.bbappend b/meta-agl-profile-core/recipes-core/psplash/psplash_git.bbappend new file mode 100644 index 000000000..bdc196b6f --- /dev/null +++ b/meta-agl-profile-core/recipes-core/psplash/psplash_git.bbappend @@ -0,0 +1,27 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +SRC_URI += "file://psplash-colors.h \ + file://psplash-start.service \ + file://psplash-quit.service \ + file://psplash-anim \ + " + +SPLASH_IMAGES="file://psplash-poky-img.h;outsuffix=default" + +inherit systemd + +SYSTEMD_PACKAGES = "${@bb.utils.contains('DISTRO_FEATURES', 'systemd', '${PN}', '', d)}" +SYSTEMD_SERVICE_${PN} = "${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'psplash-start.service psplash-quit.service', '', d)}" + +do_configure_append () { + cd ${S} + cp ../psplash-colors.h ./ +} + +do_install_append () { + if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)}; then + install -d ${D}${systemd_unitdir}/system + install -m 644 ${WORKDIR}/*.service ${D}/${systemd_unitdir}/system + fi + install -m 755 ${WORKDIR}/psplash-anim ${D}/${bindir} +} diff --git a/meta-agl-profile-core/recipes-core/systemd/.appends.core b/meta-agl-profile-core/recipes-core/systemd/.appends.core new file mode 100644 index 000000000..e69de29bb diff --git a/meta-agl-profile-core/recipes-core/systemd/systemd/0001-Switch-Smack-label-earlier.patch b/meta-agl-profile-core/recipes-core/systemd/systemd/0001-Switch-Smack-label-earlier.patch new file mode 100644 index 000000000..46445be73 --- /dev/null +++ b/meta-agl-profile-core/recipes-core/systemd/systemd/0001-Switch-Smack-label-earlier.patch @@ -0,0 +1,52 @@ +From 6cc74075797edb6f698cb7f312bb1c3d8cc6cb28 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jos=C3=A9=20Bollo?= +Date: Thu, 12 Oct 2017 17:17:56 +0200 +Subject: [PATCH] Switch Smack label earlier +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Switching label after removing capability isn't +possible. + +Change-Id: Ib7dac8f071f36119520ed3205d743c1e3df3cd5e +Signed-off-by: José Bollo +--- + src/core/execute.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/src/core/execute.c b/src/core/execute.c +index d72e5bf08..0abffd569 100644 +--- a/src/core/execute.c ++++ b/src/core/execute.c +@@ -2707,6 +2707,13 @@ static int exec_child( + } + } + ++ r = setup_smack(context, command); ++ if (r < 0) { ++ *exit_status = EXIT_SMACK_PROCESS_LABEL; ++ *error_message = strdup("Failed to set SMACK process label"); ++ return r; ++ } ++ + if (!cap_test_all(context->capability_bounding_set)) { + r = capability_bounding_set_drop(context->capability_bounding_set, false); + if (r < 0) { +@@ -2775,13 +2782,6 @@ static int exec_child( + } + #endif + +- r = setup_smack(context, command); +- if (r < 0) { +- *exit_status = EXIT_SMACK_PROCESS_LABEL; +- *error_message = strdup("Failed to set SMACK process label"); +- return r; +- } +- + #ifdef HAVE_APPARMOR + if (context->apparmor_profile && mac_apparmor_use()) { + r = aa_change_onexec(context->apparmor_profile); +-- +2.14.3 + diff --git a/meta-agl-profile-core/recipes-core/systemd/systemd/e2fsck.conf b/meta-agl-profile-core/recipes-core/systemd/systemd/e2fsck.conf new file mode 100644 index 000000000..b774f9ebf --- /dev/null +++ b/meta-agl-profile-core/recipes-core/systemd/systemd/e2fsck.conf @@ -0,0 +1,3 @@ +[options] +# This will prevent e2fsck from stopping boot just because the clock is wrong +broken_system_clock = 1 diff --git a/meta-agl-profile-core/recipes-core/systemd/systemd/wired.network b/meta-agl-profile-core/recipes-core/systemd/systemd/wired.network new file mode 100644 index 000000000..3559b0155 --- /dev/null +++ b/meta-agl-profile-core/recipes-core/systemd/systemd/wired.network @@ -0,0 +1,5 @@ +[Match] +Name=eth* en* + +[Network] +DHCP=yes diff --git a/meta-agl-profile-core/recipes-core/systemd/systemd_%.bbappend b/meta-agl-profile-core/recipes-core/systemd/systemd_%.bbappend new file mode 100644 index 000000000..f64ca8c8a --- /dev/null +++ b/meta-agl-profile-core/recipes-core/systemd/systemd_%.bbappend @@ -0,0 +1,26 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" + +SRC_URI += "\ + file://e2fsck.conf \ + ${@bb.utils.contains('VIRTUAL-RUNTIME_net_manager','systemd','file://wired.network','',d)} \ +" + +# enable networkd/resolved support +PACKAGECONFIG_append_pn-systemd = " \ + ${@bb.utils.contains('VIRTUAL-RUNTIME_net_manager','systemd','networkd resolved','',d)} \ +" + +do_install_append() { + # Install /etc/e2fsck.conf to avoid boot stuck by wrong clock time + install -m 644 -p -D ${WORKDIR}/e2fsck.conf ${D}${sysconfdir}/e2fsck.conf + + if ${@bb.utils.contains('VIRTUAL-RUNTIME_net_manager','systemd','true','false',d)}; then + # Install DHCP configuration for Ethernet adapters + install -m 644 ${WORKDIR}/wired.network ${D}${sysconfdir}/systemd/network + fi +} + +FILES_${PN} += "${sysconfdir}/e2fsck.conf " + +# SPEC-737: connmand also has a NTP client which races with systemd-timesyncd +PACKAGECONFIG_remove = "timesyncd" diff --git a/meta-agl-profile-core/recipes-core/systemd/systemd_234.bbappend b/meta-agl-profile-core/recipes-core/systemd/systemd_234.bbappend new file mode 100644 index 000000000..4df7684d0 --- /dev/null +++ b/meta-agl-profile-core/recipes-core/systemd/systemd_234.bbappend @@ -0,0 +1,6 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" + +SRC_URI += "\ + file://0001-Switch-Smack-label-earlier.patch \ +" + diff --git a/meta-agl-profile-core/recipes-devtools/gdb/gdb_%.bbappend b/meta-agl-profile-core/recipes-devtools/gdb/gdb_%.bbappend new file mode 100644 index 000000000..7cba933af --- /dev/null +++ b/meta-agl-profile-core/recipes-devtools/gdb/gdb_%.bbappend @@ -0,0 +1 @@ +PACKAGECONFIG_remove = "readline" diff --git a/meta-agl-profile-core/recipes-devtools/low-level-can-generator/low-level-can-generator_git.bb b/meta-agl-profile-core/recipes-devtools/low-level-can-generator/low-level-can-generator_git.bb new file mode 100644 index 000000000..d364939b5 --- /dev/null +++ b/meta-agl-profile-core/recipes-devtools/low-level-can-generator/low-level-can-generator_git.bb @@ -0,0 +1,16 @@ +SUMMARY = "Low level CAN generator" +DESCRIPTION = "Generator used to customize low level CAN service with customs signals" +SECTION = "devel" + +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10" + +inherit cmake pkgconfig +BBCLASSEXTEND = "nativesdk" + +SRC_URI = "gitsm://gerrit.automotivelinux.org/gerrit/src/low-level-can-generator;protocol=https;branch=${AGL_BRANCH}" +SRCREV = "92f95384ce4b4a198b1fea93272201421f7b9a39" + +PV = "4.0+git${SRCPV}" +S = "${WORKDIR}/git" + diff --git a/meta-agl-profile-core/recipes-devtools/packagegroups/nativesdk-packagegroup-sdk-host.bbappend b/meta-agl-profile-core/recipes-devtools/packagegroups/nativesdk-packagegroup-sdk-host.bbappend new file mode 100644 index 000000000..504a019b4 --- /dev/null +++ b/meta-agl-profile-core/recipes-devtools/packagegroups/nativesdk-packagegroup-sdk-host.bbappend @@ -0,0 +1 @@ +RDEPENDS_${PN} += "nativesdk-low-level-can-generator" diff --git a/meta-agl-profile-core/recipes-devtools/packagegroups/packagegroup-agl-devel.bb b/meta-agl-profile-core/recipes-devtools/packagegroups/packagegroup-agl-devel.bb new file mode 100644 index 000000000..ade8560ab --- /dev/null +++ b/meta-agl-profile-core/recipes-devtools/packagegroups/packagegroup-agl-devel.bb @@ -0,0 +1,24 @@ +SUMMARY = "Provides a set of tools for development for AGL DISTRO" +LICENSE = "MIT" + +inherit packagegroup + +RDEPENDS_${PN} = "\ + strace \ + ldd \ + less \ + vim \ + lsof \ + gdb \ + valgrind \ + perf \ + htop \ + powertop \ + latencytop \ + systemtap \ + screen \ + usbutils \ + rsync \ + tree \ + pstree \ + " diff --git a/meta-agl-profile-core/recipes-devtools/run-agl-postinsts/run-agl-postinsts/run-agl-postinsts b/meta-agl-profile-core/recipes-devtools/run-agl-postinsts/run-agl-postinsts/run-agl-postinsts new file mode 100755 index 000000000..1d1a5a059 --- /dev/null +++ b/meta-agl-profile-core/recipes-devtools/run-agl-postinsts/run-agl-postinsts/run-agl-postinsts @@ -0,0 +1,48 @@ +#!/bin/sh +# +# Copyright 2017 IoT.bzh. + +# Author: Ronan Le Martret +# + +# The following script will run all the scriptlets found in #SYSCONFDIR#/agl-postinsts. + +agl_pi_dir="#SYSCONFDIR#/agl-postinsts" + +POSTINST_LOGGING=1 +LOGFILE=/var/log/agl-postinstall.log + +[ -e $LOGFILE ] && mv ${LOGFILE} ${LOGFILE}.old.$(date +%F--%H%M.%S) + +append_log=">>$LOGFILE 2>&1" + +exec_postinst_scriptlets() { + for i in `ls $agl_pi_dir`; do + i=$agl_pi_dir/$i + echo "Running postinst $i..." + [ "$POSTINST_LOGGING" = "1" ] && eval echo "Running postinst $i..." $append_log + if [ -x $i ]; then + eval sh -c $i $append_log + if [ $? -eq 0 ]; then + rm $i + else + echo "ERROR: postinst $i failed." + [ "$POSTINST_LOGGING" = "1" ] && eval echo "ERROR: postinst $i failed." $append_log + remove_agl_pi_dir=0 + fi + else + echo "ERROR: postinst $i do not exists or do not have execute permission." + [ "$POSTINST_LOGGING" = "1" ] && eval echo "ERROR: postinst $i do not exists or do not have execute permission." $append_log + remove_agl_pi_dir=0 + fi + done +} + +remove_agl_pi_dir=1 +exec_postinst_scriptlets +systemctl daemon-reload + +# since all postinstalls executed successfully, remove the postinstalls directory +if [ $remove_agl_pi_dir = 1 ]; then + rm -rf $agl_pi_dir +fi diff --git a/meta-agl-profile-core/recipes-devtools/run-agl-postinsts/run-agl-postinsts/run-agl-postinsts.service b/meta-agl-profile-core/recipes-devtools/run-agl-postinsts/run-agl-postinsts/run-agl-postinsts.service new file mode 100644 index 000000000..8f8667db6 --- /dev/null +++ b/meta-agl-profile-core/recipes-devtools/run-agl-postinsts/run-agl-postinsts/run-agl-postinsts.service @@ -0,0 +1,17 @@ +[Unit] +Description=Run pending agl postinsts +DefaultDependencies=no +After=#SYSTEMD_SERVICE_AFTER# +Before=#SYSTEMD_SERVICE_BEFORE# +ConditionPathExists=#SYSCONFDIR#/agl-postinsts + +[Service] +Type=oneshot +StandardOutput=journal+console +ExecStart=#SBINDIR#/run-agl-postinsts +ExecStartPost=#BASE_BINDIR#/systemctl disable run-agl-postinsts.service +RemainAfterExit=No +TimeoutSec=0 + +[Install] +WantedBy=multi-user.target diff --git a/meta-agl-profile-core/recipes-devtools/run-agl-postinsts/run-agl-postinsts_1.0.bb b/meta-agl-profile-core/recipes-devtools/run-agl-postinsts/run-agl-postinsts_1.0.bb new file mode 100644 index 000000000..b1ecccf85 --- /dev/null +++ b/meta-agl-profile-core/recipes-devtools/run-agl-postinsts/run-agl-postinsts_1.0.bb @@ -0,0 +1,46 @@ +SUMMARY = "Runs AGL postinstall scripts on first boot of the target device" +SECTION = "devel" + +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" + +SRC_URI = "file://run-agl-postinsts \ + file://run-agl-postinsts.service" + +S = "${WORKDIR}" + +inherit allarch systemd + +SYSTEMD_SERVICE_${PN} = "run-agl-postinsts.service" + +SYSTEMD_SERVICE_AFTER ?= "dbus.service cynara.service" + +SYSTEMD_SERVICE_BEFORE ?= "systemd-user-sessions.service" + +do_configure() { + : +} + +do_compile () { + : +} + +do_install() { + install -d ${D}${sbindir} + install -m 0755 ${WORKDIR}/run-agl-postinsts ${D}${sbindir}/ + + install -d ${D}${systemd_unitdir}/system/ + install -m 0644 ${WORKDIR}/run-agl-postinsts.service ${D}${systemd_unitdir}/system/ + + sed -i -e 's:#SYSCONFDIR#:${sysconfdir}:g' \ + -e 's:#SBINDIR#:${sbindir}:g' \ + -e 's:#BASE_BINDIR#:${base_bindir}:g' \ + -e 's:#LOCALSTATEDIR#:${localstatedir}:g' \ + ${D}${sbindir}/run-agl-postinsts \ + ${D}${systemd_unitdir}/system/run-agl-postinsts.service + + sed -i -e 's:#SYSTEMD_SERVICE_AFTER#:${SYSTEMD_SERVICE_AFTER}:g' \ + -e 's:#SYSTEMD_SERVICE_BEFORE#:${SYSTEMD_SERVICE_BEFORE}:g' \ + ${D}${systemd_unitdir}/system/run-agl-postinsts.service +} + diff --git a/meta-agl-profile-core/recipes-devtools/run-postinsts/run-postinsts_%.bbappend b/meta-agl-profile-core/recipes-devtools/run-postinsts/run-postinsts_%.bbappend new file mode 100644 index 000000000..fc327b6ef --- /dev/null +++ b/meta-agl-profile-core/recipes-devtools/run-postinsts/run-postinsts_%.bbappend @@ -0,0 +1,5 @@ +do_configure_append() { + if ! grep -q StandardOutput= ${WORKDIR}/run-postinsts.service; then + sed -i '/ExecStart=/iStandardOutput=journal+console' ${WORKDIR}/run-postinsts.service + fi +} diff --git a/meta-agl-profile-core/recipes-ivi/images/agl-image-ivi-crosssdk.bb b/meta-agl-profile-core/recipes-ivi/images/agl-image-ivi-crosssdk.bb new file mode 100644 index 000000000..0303d051d --- /dev/null +++ b/meta-agl-profile-core/recipes-ivi/images/agl-image-ivi-crosssdk.bb @@ -0,0 +1,19 @@ +SUMMARY = "Cross SDK of AGL Distribution for IVI profile" + +DESCRIPTION = "Basic image for baseline of AGL Distribution for IVI profile. \ +It includes the full meta-toolchain, plus developement headers and libraries \ +to form a standalone cross SDK." + +require agl-image-ivi.bb + +LICENSE = "MIT" + +IMAGE_FEATURES += "dev-pkgs" +IMAGE_INSTALL += "kernel-dev" + +inherit populate_sdk + +# Task do_populate_sdk and do_rootfs can't be exec simultaneously. +# Both exec "createrepo" on the same directory, and so one of them +# can failed (randomly). +addtask do_populate_sdk after do_rootfs diff --git a/meta-agl-profile-core/recipes-ivi/images/agl-image-ivi-qa.bb b/meta-agl-profile-core/recipes-ivi/images/agl-image-ivi-qa.bb new file mode 100644 index 000000000..017439454 --- /dev/null +++ b/meta-agl-profile-core/recipes-ivi/images/agl-image-ivi-qa.bb @@ -0,0 +1,14 @@ +SUMMARY = "A basic system of AGL distribution of IVI profile for Quality Assurance(QA)" + +DESCRIPTION = "A basic set of AGL Distribution. This image also has additional \ +packages (e.g. commandline tools) for Quality Assurance(QA)." + +require agl-image-ivi.bb + +LICENSE = "MIT" + +IMAGE_INSTALL_append = " \ + packagegroup-agl-test \ + packagegroup-ivi-common-test \ + " + diff --git a/meta-agl-profile-core/recipes-ivi/images/agl-image-ivi.bb b/meta-agl-profile-core/recipes-ivi/images/agl-image-ivi.bb new file mode 100644 index 000000000..dd4f89b15 --- /dev/null +++ b/meta-agl-profile-core/recipes-ivi/images/agl-image-ivi.bb @@ -0,0 +1,17 @@ +SUMMARY = "A basic system of AGL distribution of IVI profile" + +DESCRIPTION = "Basic image for baseline of AGL Distribution for IVI profile." + +require agl-image-ivi.inc + +LICENSE = "MIT" + +IMAGE_INSTALL_append = "\ + packagegroup-agl-image-ivi \ + " + +DISTRO_FEATURES_append = " agl-core-image-profile" + +IMAGE_INSTALL += "\ + agl-desktop-config \ + " diff --git a/meta-agl-profile-core/recipes-ivi/images/agl-image-ivi.inc b/meta-agl-profile-core/recipes-ivi/images/agl-image-ivi.inc new file mode 100644 index 000000000..0b564840b --- /dev/null +++ b/meta-agl-profile-core/recipes-ivi/images/agl-image-ivi.inc @@ -0,0 +1,3 @@ +require recipes-core/images/agl-image-minimal.inc + +IMAGE_FEATURES += "splash package-management ssh-server-dropbear" diff --git a/meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-image-ivi.bb b/meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-image-ivi.bb new file mode 100644 index 000000000..075af913a --- /dev/null +++ b/meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-image-ivi.bb @@ -0,0 +1,31 @@ +SUMMARY = "The middlewares for AGL IVI profile" +DESCRIPTION = "The set of packages required for AGL Distribution" +LICENSE = "MIT" + +inherit packagegroup + +PACKAGES = "\ + packagegroup-agl-image-ivi \ + " + +ALLOW_EMPTY_${PN} = "1" + +RDEPENDS_${PN} += "\ + packagegroup-agl-image-minimal \ +" + +RDEPENDS_${PN} += "\ + packagegroup-agl-ivi-automotive \ + packagegroup-agl-ivi-connectivity \ + packagegroup-agl-ivi-graphics \ + packagegroup-agl-ivi-multimedia \ + packagegroup-agl-ivi-navi-lbs \ + packagegroup-agl-ivi-os-commonlibs \ + packagegroup-agl-ivi-speech-services \ + packagegroup-agl-ivi-security \ + packagegroup-agl-ivi-kernel \ + " + +RDEPENDS_${PN} += "\ + agl-login-manager \ + " diff --git a/meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-automotive.bb b/meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-automotive.bb new file mode 100644 index 000000000..f7221517f --- /dev/null +++ b/meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-automotive.bb @@ -0,0 +1,14 @@ +SUMMARY = "The middlewares for AGL IVI profile" +DESCRIPTION = "The set of packages required by Automotive Subsystem" +LICENSE = "MIT" + +inherit packagegroup + +PACKAGES = "\ + packagegroup-agl-ivi-automotive \ + " + +ALLOW_EMPTY_${PN} = "1" + +RDEPENDS_${PN} += "\ + " diff --git a/meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-connectivity.bb b/meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-connectivity.bb new file mode 100644 index 000000000..664180d55 --- /dev/null +++ b/meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-connectivity.bb @@ -0,0 +1,19 @@ +SUMMARY = "The middlewares for AGL IVI profile" +DESCRIPTION = "The set of packages required by Connectivity Subsystem" +LICENSE = "MIT" + +inherit packagegroup + +PACKAGES = "\ + packagegroup-agl-ivi-connectivity \ + " + +ALLOW_EMPTY_${PN} = "1" + +RDEPENDS_${PN} += "\ + ofono \ + rtl-sdr \ + rygel \ + rygel-plugin-media-export \ + rygel-plugin-lms \ + " diff --git a/meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-graphics.bb b/meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-graphics.bb new file mode 100644 index 000000000..d7650564b --- /dev/null +++ b/meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-graphics.bb @@ -0,0 +1,14 @@ +SUMMARY = "The middlewares for AGL IVI profile" +DESCRIPTION = "The set of packages required by Graphics Subsystem" +LICENSE = "MIT" + +inherit packagegroup + +PACKAGES = "\ + packagegroup-agl-ivi-graphics \ + " + +ALLOW_EMPTY_${PN} = "1" + +RDEPENDS_${PN} += "\ + " diff --git a/meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-kernel.bb b/meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-kernel.bb new file mode 100644 index 000000000..be51817b7 --- /dev/null +++ b/meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-kernel.bb @@ -0,0 +1,14 @@ +SUMMARY = "The middlewares for AGL IVI profile" +DESCRIPTION = "The set of packages required by Kernel Subsystem" +LICENSE = "MIT" + +inherit packagegroup + +PACKAGES = "\ + packagegroup-agl-ivi-kernel \ + " + +ALLOW_EMPTY_${PN} = "1" + +RDEPENDS_${PN} += "\ + " diff --git a/meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-multimedia.bb b/meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-multimedia.bb new file mode 100644 index 000000000..11536405e --- /dev/null +++ b/meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-multimedia.bb @@ -0,0 +1,17 @@ +SUMMARY = "The middlewares for AGL IVI profile" +DESCRIPTION = "The set of packages required by Multimedia Subsystem" +LICENSE = "MIT" + +inherit packagegroup + +PACKAGES = "\ + packagegroup-agl-ivi-multimedia \ + " + +ALLOW_EMPTY_${PN} = "1" + +RDEPENDS_${PN} += "\ + gstreamer1.0-plugins-base-meta \ + gstreamer1.0-plugins-good-meta \ + lightmediascanner-meta \ + " diff --git a/meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-navi-lbs.bb b/meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-navi-lbs.bb new file mode 100644 index 000000000..b7f47eecc --- /dev/null +++ b/meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-navi-lbs.bb @@ -0,0 +1,14 @@ +SUMMARY = "The packages of middlewares for AGL IVI profile" +DESCRIPTION = "The set of packages required by Navigation and Location Based Services Subsystem" +LICENSE = "MIT" + +inherit packagegroup + +PACKAGES = "\ + packagegroup-agl-ivi-navi-lbs \ + " + +RDEPENDS_${PN} += "\ + gpsd \ + geoclue \ + " diff --git a/meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-os-commonlibs.bb b/meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-os-commonlibs.bb new file mode 100644 index 000000000..0a9de8d5f --- /dev/null +++ b/meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-os-commonlibs.bb @@ -0,0 +1,14 @@ +SUMMARY = "The packages of middlewares for AGL IVI profile" +DESCRIPTION = "The set of packages required by Operating System and Common libraries Subsystem" +LICENSE = "MIT" + +inherit packagegroup + +PACKAGES = "\ + packagegroup-agl-ivi-os-commonlibs \ + " + +ALLOW_EMPTY_${PN} = "1" + +RDEPENDS_${PN} += "\ + " diff --git a/meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-security.bb b/meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-security.bb new file mode 100644 index 000000000..f651c50cd --- /dev/null +++ b/meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-security.bb @@ -0,0 +1,14 @@ +SUMMARY = "The packages of middlewares for AGL IVI profile" +DESCRIPTION = "The set of packages required by Security Subsystem" +LICENSE = "MIT" + +inherit packagegroup + +PACKAGES = "\ + packagegroup-agl-ivi-security \ + " + +ALLOW_EMPTY_${PN} = "1" + +RDEPENDS_${PN} += "\ + " diff --git a/meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-speech-services.bb b/meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-speech-services.bb new file mode 100644 index 000000000..eccebee9f --- /dev/null +++ b/meta-agl-profile-core/recipes-ivi/packagegroups/packagegroup-agl-ivi-speech-services.bb @@ -0,0 +1,14 @@ +SUMMARY = "The packages of middlewares for AGL IVI profile" +DESCRIPTION = "The set of packages required by Speech Services Subsystem" +LICENSE = "MIT" + +inherit packagegroup + +PACKAGES = "\ + packagegroup-agl-ivi-speech-services \ + " + +ALLOW_EMPTY_${PN} = "1" + +RDEPENDS_${PN} += "\ + " diff --git a/meta-agl-profile-core/recipes-multimedia/gstreamer1.0-plugins-good/gstreamer1.0-plugins-good_%.bbappend b/meta-agl-profile-core/recipes-multimedia/gstreamer1.0-plugins-good/gstreamer1.0-plugins-good_%.bbappend new file mode 100644 index 000000000..86a181fbb --- /dev/null +++ b/meta-agl-profile-core/recipes-multimedia/gstreamer1.0-plugins-good/gstreamer1.0-plugins-good_%.bbappend @@ -0,0 +1,2 @@ +# libv4l2 is useful for making more efficient use of cameras via v4l2src. +PACKAGECONFIG_append = " libv4l2" diff --git a/meta-agl-profile-core/recipes-multimedia/lightmediascanner/.appends.meta-efl b/meta-agl-profile-core/recipes-multimedia/lightmediascanner/.appends.meta-efl new file mode 100644 index 000000000..e69de29bb diff --git a/meta-agl-profile-core/recipes-multimedia/lightmediascanner/files/0001-Define-comparison_fn_t-for-non-glibc-systems.patch b/meta-agl-profile-core/recipes-multimedia/lightmediascanner/files/0001-Define-comparison_fn_t-for-non-glibc-systems.patch new file mode 100644 index 000000000..15d4b3f0e --- /dev/null +++ b/meta-agl-profile-core/recipes-multimedia/lightmediascanner/files/0001-Define-comparison_fn_t-for-non-glibc-systems.patch @@ -0,0 +1,33 @@ +From 5bc5b8c5dad3edec6736fd7e7ce61250c4ce3725 Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Wed, 12 Jul 2017 17:13:19 -0700 +Subject: [PATCH] Define comparison_fn_t for non-glibc systems + +lightmediascanner.c:324:12: error: 'comparison_fn_t' undeclared (first use in this function) + (comparison_fn_t)_plugin_sort); + ^~~~~~~~~~~~~~~ + +Signed-off-by: Khem Raj +--- + src/lib/lightmediascanner.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/src/lib/lightmediascanner.c b/src/lib/lightmediascanner.c +index 344b247..b866883 100644 +--- a/src/lib/lightmediascanner.c ++++ b/src/lib/lightmediascanner.c +@@ -37,6 +37,11 @@ + #define DEFAULT_SLAVE_TIMEOUT 1000 + #define DEFAULT_COMMIT_INTERVAL 100 + ++#if !defined(__GLIBC__) ++typedef int (*__compar_fn_t) (const void*, const void*); ++typedef __compar_fn_t comparison_fn_t; ++#endif ++ + #ifdef HAVE_MAGIC_H + static magic_t _magic_handle; + +-- +2.13.2 + diff --git a/meta-agl-profile-core/recipes-multimedia/lightmediascanner/files/dbus-lightmediascanner.conf b/meta-agl-profile-core/recipes-multimedia/lightmediascanner/files/dbus-lightmediascanner.conf new file mode 100644 index 000000000..9cb321ba9 --- /dev/null +++ b/meta-agl-profile-core/recipes-multimedia/lightmediascanner/files/dbus-lightmediascanner.conf @@ -0,0 +1,7 @@ + + + + + + + diff --git a/meta-agl-profile-core/recipes-multimedia/lightmediascanner/files/id3-plugin-support-out-of-tree-build.patch b/meta-agl-profile-core/recipes-multimedia/lightmediascanner/files/id3-plugin-support-out-of-tree-build.patch new file mode 100644 index 000000000..9528bec79 --- /dev/null +++ b/meta-agl-profile-core/recipes-multimedia/lightmediascanner/files/id3-plugin-support-out-of-tree-build.patch @@ -0,0 +1,11 @@ +--- a/src/plugins/Makefile.am 2015-10-25 16:12:29.331415823 +0000 ++++ b/src/plugins/Makefile.am 2015-10-25 16:14:37.593415808 +0000 +@@ -93,7 +93,7 @@ + id3_id3_la_SOURCES = id3/id3.c id3/id3v1_genres.c + id3_id3_la_LIBADD = $(PLUGINS_LIBADD) + +-id3/id3v1_genres.c: $(srcdir)/id3/id3v1_genres.def $(srcdir)/id3/id3v1_genres_gen.awk ++$(srcdir)/id3/id3v1_genres.c: $(srcdir)/id3/id3v1_genres.def $(srcdir)/id3/id3v1_genres_gen.awk + $(AWK) -f $(srcdir)/id3/id3v1_genres_gen.awk $(srcdir)/id3/id3v1_genres.def > $@ + + EXTRA_DIST += id3/id3v1_genres.def id3/id3v1_genres_gen.awk diff --git a/meta-agl-profile-core/recipes-multimedia/lightmediascanner/files/lightmediascanner.service b/meta-agl-profile-core/recipes-multimedia/lightmediascanner/files/lightmediascanner.service new file mode 100644 index 000000000..33cf27ed0 --- /dev/null +++ b/meta-agl-profile-core/recipes-multimedia/lightmediascanner/files/lightmediascanner.service @@ -0,0 +1,11 @@ +[Unit] +Description=Lightmediascanner (LMS) + +[Service] +Type=dbus +BusName=org.lightmediascanner +ExecStart=/usr/bin/lightmediascannerd --startup-scan --directory=/media --directory=${HOME}/Music --directory=${HOME}/Videos + +[Install] +WantedBy=default.target +Alias=dbus-org.lightmediascanner.service diff --git a/meta-agl-profile-core/recipes-multimedia/lightmediascanner/files/plugin-ogg-fix-chucksize-issue.patch b/meta-agl-profile-core/recipes-multimedia/lightmediascanner/files/plugin-ogg-fix-chucksize-issue.patch new file mode 100644 index 000000000..6a0b8ff93 --- /dev/null +++ b/meta-agl-profile-core/recipes-multimedia/lightmediascanner/files/plugin-ogg-fix-chucksize-issue.patch @@ -0,0 +1,53 @@ +From 3e66b97221440b17a184feb48692dce7e0561cac Mon Sep 17 00:00:00 2001 +From: Matt Ranostay +Date: Wed, 8 Mar 2017 16:30:01 -0800 +Subject: [PATCH] plugin: ogg: fix chucksize issue + +There are some OGG files that have metadata chucks that go over the +hardcoded 10 * 4096 size due to album art. This patchset just parses +each chuck and continues till it runs out of valid chunks. + +Signed-off-by: Matt Ranostay +--- + src/plugins/ogg/ogg.c | 11 ++--------- + 1 file changed, 2 insertions(+), 9 deletions(-) + +diff --git a/src/plugins/ogg/ogg.c b/src/plugins/ogg/ogg.c +index 1c0818e..c94dc38 100644 +--- a/src/plugins/ogg/ogg.c ++++ b/src/plugins/ogg/ogg.c +@@ -47,8 +47,6 @@ + int CHUNKSIZE = 4096; + #endif + +-#define MAX_CHUNKS_PER_PAGE 10 +- + struct stream { + struct lms_stream base; + int serial; +@@ -122,10 +120,8 @@ _set_lms_info(struct lms_string_size *info, const char *tag) + + static bool _ogg_read_page(FILE *fp, ogg_sync_state *osync, ogg_page *page) + { +- int i; +- +- for (i = 0; i < MAX_CHUNKS_PER_PAGE && ogg_sync_pageout(osync, page) != 1; +- i++) { ++ while(ogg_sync_pageout(osync, page) != 1) ++ { + lms_ogg_buffer_t buffer = lms_get_ogg_sync_buffer(osync, CHUNKSIZE); + int bytes = fread(buffer, 1, CHUNKSIZE, fp); + +@@ -136,9 +132,6 @@ static bool _ogg_read_page(FILE *fp, ogg_sync_state *osync, ogg_page *page) + ogg_sync_wrote(osync, bytes); + } + +- if (i > MAX_CHUNKS_PER_PAGE) +- return false; +- + return true; + } + +-- +2.7.4 + diff --git a/meta-agl-profile-core/recipes-multimedia/lightmediascanner/lightmediascanner_%.bbappend b/meta-agl-profile-core/recipes-multimedia/lightmediascanner/lightmediascanner_%.bbappend new file mode 100644 index 000000000..cf248d3fd --- /dev/null +++ b/meta-agl-profile-core/recipes-multimedia/lightmediascanner/lightmediascanner_%.bbappend @@ -0,0 +1,33 @@ +# Disable everything but the roygalty-free formats +PACKAGECONFIG = "ogg flac wave m3u pls jpeg png" + +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +SRC_URI += "file://lightmediascanner.service \ + file://plugin-ogg-fix-chucksize-issue.patch \ + file://dbus-lightmediascanner.conf \ + " + +CFLAGS_append = " -D_FILE_OFFSET_BITS=64" + +inherit systemd + +do_install_append() { + # Install LMS systemd service + if ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'true', 'false', d)}; then + install -m 644 -p -D ${WORKDIR}/lightmediascanner.service ${D}${systemd_user_unitdir}/lightmediascanner.service + + # Execute these manually on behalf of systemctl script (from systemd-systemctl-native.bb) + # because it does not support systemd's user mode. + mkdir -p ${D}/etc/systemd/user/default.target.wants/ + ln -sf ${systemd_user_unitdir}/lightmediascanner.service ${D}/etc/systemd/user/dbus-org.lightmediascanner.service + ln -sf ${systemd_user_unitdir}/lightmediascanner.service ${D}/etc/systemd/user/default.target.wants/lightmediascanner.service + fi + + install -d ${D}/etc/dbus-1/session.d + install -m 0644 ${WORKDIR}/dbus-lightmediascanner.conf ${D}/etc/dbus-1/session.d/lightmediascanner.conf +} + +FILES_${PN} += " \ + ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', '${systemd_user_unitdir}/lightmediascanner.service', '', d)} \ + " diff --git a/meta-agl-profile-core/recipes-multimedia/lightmediascanner/lightmediascanner_0.5.1.bb b/meta-agl-profile-core/recipes-multimedia/lightmediascanner/lightmediascanner_0.5.1.bb new file mode 100644 index 000000000..f2158760f --- /dev/null +++ b/meta-agl-profile-core/recipes-multimedia/lightmediascanner/lightmediascanner_0.5.1.bb @@ -0,0 +1,63 @@ +SUMMARY = "Lightweight media scanner" +DESCRIPTION = "Lightweight media scanner meant to be used in not-so-powerful devices, like embedded systems or old machines." +SECTION = "libs/multimedia" + +LICENSE = "LGPLv2.1+" +LIC_FILES_CHKSUM = "file://COPYING;md5=a6f89e2100d9b6cdffcea4f398e37343 \ + file://src/lib/lightmediascanner.c;endline=21;md5=6d8889bccb4c6c27e8b786342a3eb267" + +DEPENDS = "file gawk glib-2.0 sqlite3" + +PV = "0.5.1+git${SRCPV}" +SRCREV = "adfddb3486276a5ed2f5008c9e43a811e1271cc9" +SRC_URI = "git://github.com/profusion/lightmediascanner.git \ + file://id3-plugin-support-out-of-tree-build.patch \ + file://0001-Define-comparison_fn_t-for-non-glibc-systems.patch \ + " + +S = "${WORKDIR}/git" + +inherit autotools pkgconfig + +EXTRA_OECONF = "--enable-static --disable-mp4" + +PACKAGECONFIG ??= "ogg flac wave id3 m3u pls asf rm jpeg png" +PACKAGECONFIG[generic] = "--enable-generic,--disable-generic,libav" +PACKAGECONFIG[ogg] = "--enable-ogg,--disable-ogg,libogg libvorbis libtheora" +PACKAGECONFIG[flac] = "--enable-flac,--disable-flac,flac" +PACKAGECONFIG[wave] = "--enable-wave,--disable-wave" +PACKAGECONFIG[id3] = "--enable-id3,--disable-id3" +PACKAGECONFIG[m3u] = "--enable-m3u,--disable-m3u" +PACKAGECONFIG[pls] = "--enable-pls,--disable-pls" +PACKAGECONFIG[asf] = "--enable-asf,--disable-asf" +PACKAGECONFIG[rm] = "--enable-rm,--disable-rm" +PACKAGECONFIG[jpeg] = "--enable-jpeg,--disable-jpeg" +PACKAGECONFIG[png] = "--enable-png,--disable-png" + +do_install_append() { + # Install "test" binary for corresponding package + install -d ${D}/${bindir} + install -m 755 ${B}/src/bin/.libs/test ${D}/${bindir}/test-lms + # Remove .la files for loadable modules + rm -f ${D}/${libdir}/${PN}/plugins/*.la +} + +FILES_${PN} += "${datadir}/dbus-1" +FILES_${PN}-dbg += "${libdir}/${PN}/plugins/.debug" + +PACKAGES_prepend = "${PN}-test " +FILES_${PN}-test_prepend = "${bindir}/test-lms " + +PACKAGES += "${PN}-meta" +ALLOW_EMPTY_${PN}-meta = "1" + +PACKAGES_DYNAMIC = "${PN}-plugin-*" + +python populate_packages_prepend () { + lms_libdir = d.expand('${libdir}/${PN}') + pkgs = [] + + pkgs += do_split_packages(d, oe.path.join(lms_libdir, "plugins"), '^(.*)\.so$', d.expand('${PN}-plugin-%s'), 'LightMediaScanner plugin for %s', prepend=True, extra_depends=d.expand('${PN}')) + metapkg = d.getVar('PN') + '-meta' + d.setVar('RDEPENDS_' + metapkg, ' '.join(pkgs)) +} diff --git a/meta-agl-profile-core/recipes-multimedia/pulseaudio/agl-audio-plugin_0.1.bb b/meta-agl-profile-core/recipes-multimedia/pulseaudio/agl-audio-plugin_0.1.bb new file mode 100644 index 000000000..633a3e248 --- /dev/null +++ b/meta-agl-profile-core/recipes-multimedia/pulseaudio/agl-audio-plugin_0.1.bb @@ -0,0 +1,28 @@ +SUMMARY = "AGL Audio Policy Plugin" +DESCRIPTION = "AGL PulseAudio Routing plugin, forked from the Tizen IVI \ +PulseAudio Routing plugin, also known as module-murphy-ivi. This is a \ +stripped-down version of the former, not needing Murphy anymore and using \ +either a JSON configuration file or its own embedded configuration." +HOMEPAGE = "http://www.iot.bzh" + +LICENSE = "LGPL-2.1" +LIC_FILES_CHKSUM = "file://COPYING;md5=2d5025d4aa3495befef8f17206a5b0a1" + +DEPENDS = "json-c pulseaudio" +RDEPENDS_${PN} = "pulseaudio-server pulseaudio-module-null-sink pulseaudio-module-loopback" + +SRCREV = "952d404e87ca6001e546fe9105bdb6760c468760" +SRC_URI = "git://gerrit.automotivelinux.org/gerrit/staging/agl-audio-plugin;protocol=https;branch=${AGL_BRANCH}" + +S = "${WORKDIR}/git" + +inherit cmake pkgconfig + +FULL_OPTIMIZATION = "-O1 -pipe ${DEBUG_FLAGS}" + +PULSE_PV="9.0" + +EXTRA_OECMAKE_append = " -DPULSE_PV:STRING=${PULSE_PV}" + +FILES_${PN} += "${libdir}/pulse-${PULSE_PV}/modules/* ${sysconfdir}/pulse/*" +FILES_${PN}-dbg += "${libdir}/pulse-${PULSE_PV}/modules/.debug/*" diff --git a/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio-10.0/0001-install-files-for-a-module-development.patch b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio-10.0/0001-install-files-for-a-module-development.patch new file mode 100644 index 000000000..8c5f9efd4 --- /dev/null +++ b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio-10.0/0001-install-files-for-a-module-development.patch @@ -0,0 +1,78 @@ +From 53281e2d11f84e2dae0704e0167369710ee2cb30 Mon Sep 17 00:00:00 2001 +From: Yannick Gicquel +Date: Fri, 23 Sep 2016 14:26:03 +0200 +Subject: [PATCH 1/6] install files for a module development + +Signed-off-by: Yannick Gicquel +--- + Makefile.am | 14 +++++++++++++- + configure.ac | 1 + + pulseaudio-module-devel.pc.in | 12 ++++++++++++ + 3 files changed, 26 insertions(+), 1 deletion(-) + create mode 100644 pulseaudio-module-devel.pc.in + +diff --git a/Makefile.am b/Makefile.am +index 13bc469..f0d68a2 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -53,7 +53,16 @@ dist_vapi_DATA = \ + vala/libpulse-simple.deps vala/libpulse-simple.vapi + + pkgconfigdir = $(libdir)/pkgconfig +-pkgconfig_DATA = libpulse.pc libpulse-simple.pc ++pkgconfig_DATA = libpulse.pc libpulse-simple.pc pulseaudio-module-devel.pc ++ ++moduledev_DATA = pulsecore-config.h $(top_srcdir)/src/pulsecore/*.h ++moduledevdir = $(includedir)/pulsemodule/pulsecore ++ ++moduledevfilter_DATA = $(top_srcdir)/src/pulsecore/filter/*.h ++moduledevfilterdir = $(includedir)/pulsemodule/pulsecore/filter ++ ++moduledevinternal_DATA = src/pulse/internal.h src/pulse/client-conf.h src/pulse/fork-detect.h ++moduledevinternaldir = $(includedir)/pulsemodule/pulse + + if HAVE_GLIB20 + pkgconfig_DATA += \ +@@ -107,6 +116,9 @@ dist-hook: + check-daemon: + $(MAKE) -C src check-daemon + ++pulsecore-config.h: config.h ++ cp $< $@ ++ + .PHONY: homepage distcleancheck doxygen + + # see git-version-gen +diff --git a/configure.ac b/configure.ac +index 9250c05..f9201ee 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1502,6 +1502,7 @@ man/pulse-client.conf.5.xml + man/default.pa.5.xml + man/pulse-cli-syntax.5.xml + man/start-pulseaudio-x11.1.xml ++pulseaudio-module-devel.pc + ]) + + AC_CONFIG_FILES([src/esdcompat:src/daemon/esdcompat.in], [chmod +x src/esdcompat]) +diff --git a/pulseaudio-module-devel.pc.in b/pulseaudio-module-devel.pc.in +new file mode 100644 +index 0000000..85aadbc +--- /dev/null ++++ b/pulseaudio-module-devel.pc.in +@@ -0,0 +1,12 @@ ++prefix=@prefix@ ++exec_prefix=@exec_prefix@ ++libdir=@libdir@ ++includedir=@includedir@ ++modlibexecdir=@modlibexecdir@ ++ ++Name: pulseaudio-module-devel ++Description: PulseAudio Module Development Interface ++Version: @PACKAGE_VERSION@ ++Libs: -L${libdir} -L${libdir}/pulseaudio -L${modlibexecdir} -lpulsecommon-@PA_MAJORMINOR@ -lpulsecore-@PA_MAJORMINOR@ -lprotocol-native ++Libs.private: ++Cflags: -I${includedir}/pulsemodule -D_REENTRANT +-- +1.9.1 + diff --git a/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio-10.0/0002-volume-ramp-additions-to-the-low-level-infra.patch b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio-10.0/0002-volume-ramp-additions-to-the-low-level-infra.patch new file mode 100644 index 000000000..9cee6f5de --- /dev/null +++ b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio-10.0/0002-volume-ramp-additions-to-the-low-level-infra.patch @@ -0,0 +1,566 @@ +From 7757059ffc6e63ea20ba9013682d72d619e7aefc Mon Sep 17 00:00:00 2001 +From: Sangchul Lee +Date: Sat, 27 Aug 2016 21:33:16 +0900 +Subject: [PATCH 2/6] volume ramp: additions to the low level infra + +The original patch is + - https://review.tizen.org/git/?p=platform/upstream/pulseaudio.git;a=commit;h=df1c4275ed79e0b708c75b92f9d247e0492bc1f0 + - by Jaska Uimonen helsinki.fi> + +Signed-off-by: Sangchul Lee +--- + src/map-file | 4 + + src/pulse/def.h | 13 ++- + src/pulse/volume.c | 74 ++++++++++++- + src/pulse/volume.h | 33 ++++++ + src/pulsecore/mix.c | 310 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + src/pulsecore/mix.h | 27 +++++ + 6 files changed, 459 insertions(+), 2 deletions(-) + +diff --git a/src/map-file b/src/map-file +index 93a62b8..ef9b57d 100644 +--- a/src/map-file ++++ b/src/map-file +@@ -138,6 +138,10 @@ pa_cvolume_max_mask; + pa_cvolume_merge; + pa_cvolume_min; + pa_cvolume_min_mask; ++pa_cvolume_ramp_equal; ++pa_cvolume_ramp_init; ++pa_cvolume_ramp_set; ++pa_cvolume_ramp_channel_ramp_set; + pa_cvolume_remap; + pa_cvolume_scale; + pa_cvolume_scale_mask; +diff --git a/src/pulse/def.h b/src/pulse/def.h +index 680bdc9..bc3cedd 100644 +--- a/src/pulse/def.h ++++ b/src/pulse/def.h +@@ -347,11 +347,15 @@ typedef enum pa_stream_flags { + * consider absolute when the sink is in flat volume mode, + * relative otherwise. \since 0.9.20 */ + +- PA_STREAM_PASSTHROUGH = 0x80000U ++ PA_STREAM_PASSTHROUGH = 0x80000U, + /**< Used to tag content that will be rendered by passthrough sinks. + * The data will be left as is and not reformatted, resampled. + * \since 1.0 */ + ++ PA_STREAM_START_RAMP_MUTED = 0x100000U ++ /**< Used to tag content that the stream will be started ramp volume ++ * muted so that you can nicely fade it in */ ++ + } pa_stream_flags_t; + + /** \cond fulldocs */ +@@ -380,6 +384,7 @@ typedef enum pa_stream_flags { + #define PA_STREAM_FAIL_ON_SUSPEND PA_STREAM_FAIL_ON_SUSPEND + #define PA_STREAM_RELATIVE_VOLUME PA_STREAM_RELATIVE_VOLUME + #define PA_STREAM_PASSTHROUGH PA_STREAM_PASSTHROUGH ++#define PA_STREAM_START_RAMP_MUTED PA_STREAM_START_RAMP_MUTED + + /** \endcond */ + +@@ -1047,6 +1052,12 @@ typedef enum pa_port_available { + /** \endcond */ + #endif + ++/** \cond fulldocs */ ++#define PA_VOLUMER_RAMP_TYPE_LINEAR PA_VOLUMER_RAMP_TYPE_LINEAR ++#define PA_VOLUMER_RAMP_TYPE_LOGARITHMIC PA_VOLUMER_RAMP_TYPE_LOGARITHMIC ++#define PA_VOLUMER_RAMP_TYPE_CUBIC PA_VOLUMER_RAMP_TYPE_CUBIC ++/** \endcond */ ++ + PA_C_DECL_END + + #endif +diff --git a/src/pulse/volume.c b/src/pulse/volume.c +index 1667b94..85072c1 100644 +--- a/src/pulse/volume.c ++++ b/src/pulse/volume.c +@@ -445,7 +445,10 @@ int pa_cvolume_channels_equal_to(const pa_cvolume *a, pa_volume_t v) { + unsigned c; + pa_assert(a); + +- pa_return_val_if_fail(pa_cvolume_valid(a), 0); ++ if (pa_cvolume_valid(a) == 0) ++ abort(); ++ ++ /* pa_return_val_if_fail(pa_cvolume_valid(a), 0); */ + pa_return_val_if_fail(PA_VOLUME_IS_VALID(v), 0); + + for (c = 0; c < a->channels; c++) +@@ -977,3 +980,72 @@ pa_cvolume* pa_cvolume_dec(pa_cvolume *v, pa_volume_t dec) { + + return pa_cvolume_scale(v, m); + } ++ ++int pa_cvolume_ramp_equal(const pa_cvolume_ramp *a, const pa_cvolume_ramp *b) { ++ int i; ++ pa_assert(a); ++ pa_assert(b); ++ ++ if (PA_UNLIKELY(a == b)) ++ return 1; ++ ++ if (a->channels != b->channels) ++ return 0; ++ ++ for (i = 0; i < a->channels; i++) { ++ if (a->ramps[i].type != b->ramps[i].type || ++ a->ramps[i].length != b->ramps[i].length || ++ a->ramps[i].target != b->ramps[i].target) ++ return 0; ++ } ++ ++ return 1; ++} ++ ++pa_cvolume_ramp* pa_cvolume_ramp_init(pa_cvolume_ramp *ramp) { ++ unsigned c; ++ ++ pa_assert(ramp); ++ ++ ramp->channels = 0; ++ ++ for (c = 0; c < PA_CHANNELS_MAX; c++) { ++ ramp->ramps[c].type = PA_VOLUME_RAMP_TYPE_LINEAR; ++ ramp->ramps[c].length = 0; ++ ramp->ramps[c].target = PA_VOLUME_INVALID; ++ } ++ ++ return ramp; ++} ++ ++pa_cvolume_ramp* pa_cvolume_ramp_set(pa_cvolume_ramp *ramp, unsigned channels, pa_volume_ramp_type_t type, long time, pa_volume_t vol) { ++ int i; ++ ++ pa_assert(ramp); ++ pa_assert(channels > 0); ++ pa_assert(time >= 0); ++ pa_assert(channels <= PA_CHANNELS_MAX); ++ ++ ramp->channels = (uint8_t) channels; ++ ++ for (i = 0; i < ramp->channels; i++) { ++ ramp->ramps[i].type = type; ++ ramp->ramps[i].length = time; ++ ramp->ramps[i].target = PA_CLAMP_VOLUME(vol); ++ } ++ ++ return ramp; ++} ++ ++pa_cvolume_ramp* pa_cvolume_ramp_channel_ramp_set(pa_cvolume_ramp *ramp, unsigned channel, pa_volume_ramp_type_t type, long time, pa_volume_t vol) { ++ ++ pa_assert(ramp); ++ pa_assert(channel <= ramp->channels); ++ pa_assert(time >= 0); ++ ++ ramp->ramps[channel].type = type; ++ ramp->ramps[channel].length = time; ++ ramp->ramps[channel].target = PA_CLAMP_VOLUME(vol); ++ ++ return ramp; ++} +diff --git a/src/pulse/volume.h b/src/pulse/volume.h +index 8cf4fa4..2ae3451 100644 +--- a/src/pulse/volume.h ++++ b/src/pulse/volume.h +@@ -431,6 +431,39 @@ pa_cvolume* pa_cvolume_inc(pa_cvolume *v, pa_volume_t inc); + * the channels are kept. \since 0.9.16 */ + pa_cvolume* pa_cvolume_dec(pa_cvolume *v, pa_volume_t dec); + ++/** Volume ramp type ++*/ ++typedef enum pa_volume_ramp_type { ++ PA_VOLUME_RAMP_TYPE_LINEAR = 0, /**< linear */ ++ PA_VOLUME_RAMP_TYPE_LOGARITHMIC = 1, /**< logarithmic */ ++ PA_VOLUME_RAMP_TYPE_CUBIC = 2, ++} pa_volume_ramp_type_t; ++ ++/** A structure encapsulating a volume ramp */ ++typedef struct pa_volume_ramp_t { ++ pa_volume_ramp_type_t type; ++ long length; ++ pa_volume_t target; ++} pa_volume_ramp_t; ++ ++/** A structure encapsulating a multichannel volume ramp */ ++typedef struct pa_cvolume_ramp { ++ uint8_t channels; ++ pa_volume_ramp_t ramps[PA_CHANNELS_MAX]; ++} pa_cvolume_ramp; ++ ++/** Return non-zero when *a == *b */ ++int pa_cvolume_ramp_equal(const pa_cvolume_ramp *a, const pa_cvolume_ramp *b); ++ ++/** Init volume ramp struct */ ++pa_cvolume_ramp* pa_cvolume_ramp_init(pa_cvolume_ramp *ramp); ++ ++/** Set first n channels of ramp struct to certain value */ ++pa_cvolume_ramp* pa_cvolume_ramp_set(pa_cvolume_ramp *ramp, unsigned channel, pa_volume_ramp_type_t type, long time, pa_volume_t vol); ++ ++/** Set individual channel in the channel struct */ ++pa_cvolume_ramp* pa_cvolume_ramp_channel_ramp_set(pa_cvolume_ramp *ramp, unsigned channel, pa_volume_ramp_type_t type, long time, pa_volume_t vol); ++ + PA_C_DECL_END + + #endif +diff --git a/src/pulsecore/mix.c b/src/pulsecore/mix.c +index 59622d7..1e4cc1e 100644 +--- a/src/pulsecore/mix.c ++++ b/src/pulsecore/mix.c +@@ -724,3 +724,313 @@ void pa_volume_memchunk( + + pa_memblock_release(c->memblock); + } ++ ++static void calc_linear_integer_volume_no_mapping(int32_t linear[], float volume[], unsigned nchannels) { ++ unsigned channel, padding; ++ ++ pa_assert(linear); ++ pa_assert(volume); ++ ++ for (channel = 0; channel < nchannels; channel++) ++ linear[channel] = (int32_t) lrint(volume[channel] * 0x10000U); ++ ++ for (padding = 0; padding < VOLUME_PADDING; padding++, channel++) ++ linear[channel] = linear[padding]; ++} ++ ++static void calc_linear_float_volume_no_mapping(float linear[], float volume[], unsigned nchannels) { ++ unsigned channel, padding; ++ ++ pa_assert(linear); ++ pa_assert(volume); ++ ++ for (channel = 0; channel < nchannels; channel++) ++ linear[channel] = volume[channel]; ++ ++ for (padding = 0; padding < VOLUME_PADDING; padding++, channel++) ++ linear[channel] = linear[padding]; ++} ++ ++typedef void (*pa_calc_volume_no_mapping_func_t) (void *volumes, float *volume, int channels); ++ ++static const pa_calc_volume_no_mapping_func_t calc_volume_table_no_mapping[] = { ++ [PA_SAMPLE_U8] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, ++ [PA_SAMPLE_ALAW] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, ++ [PA_SAMPLE_ULAW] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, ++ [PA_SAMPLE_S16LE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, ++ [PA_SAMPLE_S16BE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, ++ [PA_SAMPLE_FLOAT32LE] = (pa_calc_volume_no_mapping_func_t) calc_linear_float_volume_no_mapping, ++ [PA_SAMPLE_FLOAT32BE] = (pa_calc_volume_no_mapping_func_t) calc_linear_float_volume_no_mapping, ++ [PA_SAMPLE_S32LE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, ++ [PA_SAMPLE_S32BE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, ++ [PA_SAMPLE_S24LE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, ++ [PA_SAMPLE_S24BE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, ++ [PA_SAMPLE_S24_32LE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, ++ [PA_SAMPLE_S24_32BE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping ++}; ++ ++static const unsigned format_sample_size_table[] = { ++ [PA_SAMPLE_U8] = 1, ++ [PA_SAMPLE_ALAW] = 1, ++ [PA_SAMPLE_ULAW] = 1, ++ [PA_SAMPLE_S16LE] = 2, ++ [PA_SAMPLE_S16BE] = 2, ++ [PA_SAMPLE_FLOAT32LE] = 4, ++ [PA_SAMPLE_FLOAT32BE] = 4, ++ [PA_SAMPLE_S32LE] = 4, ++ [PA_SAMPLE_S32BE] = 4, ++ [PA_SAMPLE_S24LE] = 3, ++ [PA_SAMPLE_S24BE] = 3, ++ [PA_SAMPLE_S24_32LE] = 4, ++ [PA_SAMPLE_S24_32BE] = 4 ++}; ++ ++static float calc_volume_ramp_linear(pa_volume_ramp_int_t *ramp) { ++ pa_assert(ramp); ++ pa_assert(ramp->length > 0); ++ ++ /* basic linear interpolation */ ++ return ramp->start + (ramp->length - ramp->left) * (ramp->end - ramp->start) / (float) ramp->length; ++} ++ ++static float calc_volume_ramp_logarithmic(pa_volume_ramp_int_t *ramp) { ++ float x_val, s, e; ++ long temp; ++ ++ pa_assert(ramp); ++ pa_assert(ramp->length > 0); ++ ++ if (ramp->end > ramp->start) { ++ temp = ramp->left; ++ s = ramp->end; ++ e = ramp->start; ++ } else { ++ temp = ramp->length - ramp->left; ++ s = ramp->start; ++ e = ramp->end; ++ } ++ ++ x_val = temp == 0 ? 0.0 : powf(temp, 10); ++ ++ /* base 10 logarithmic interpolation */ ++ return s + x_val * (e - s) / powf(ramp->length, 10); ++} ++ ++static float calc_volume_ramp_cubic(pa_volume_ramp_int_t *ramp) { ++ float x_val, s, e; ++ long temp; ++ ++ pa_assert(ramp); ++ pa_assert(ramp->length > 0); ++ ++ if (ramp->end > ramp->start) { ++ temp = ramp->left; ++ s = ramp->end; ++ e = ramp->start; ++ } else { ++ temp = ramp->length - ramp->left; ++ s = ramp->start; ++ e = ramp->end; ++ } ++ ++ x_val = temp == 0 ? 0.0 : cbrtf(temp); ++ ++ /* cubic interpolation */ ++ return s + x_val * (e - s) / cbrtf(ramp->length); ++} ++ ++typedef float (*pa_calc_volume_ramp_func_t) (pa_volume_ramp_int_t *); ++ ++static const pa_calc_volume_ramp_func_t calc_volume_ramp_table[] = { ++ [PA_VOLUME_RAMP_TYPE_LINEAR] = (pa_calc_volume_ramp_func_t) calc_volume_ramp_linear, ++ [PA_VOLUME_RAMP_TYPE_LOGARITHMIC] = (pa_calc_volume_ramp_func_t) calc_volume_ramp_logarithmic, ++ [PA_VOLUME_RAMP_TYPE_CUBIC] = (pa_calc_volume_ramp_func_t) calc_volume_ramp_cubic ++}; ++ ++static void calc_volume_ramps(pa_cvolume_ramp_int *ram, float *vol) ++{ ++ int i; ++ ++ for (i = 0; i < ram->channels; i++) { ++ if (ram->ramps[i].left <= 0) { ++ if (ram->ramps[i].target == PA_VOLUME_NORM) { ++ vol[i] = 1.0; ++ } ++ } else { ++ vol[i] = ram->ramps[i].curr = calc_volume_ramp_table[ram->ramps[i].type] (&ram->ramps[i]); ++ ram->ramps[i].left--; ++ } ++ } ++} ++ ++void pa_volume_ramp_memchunk( ++ pa_memchunk *c, ++ const pa_sample_spec *spec, ++ pa_cvolume_ramp_int *ramp) { ++ ++ void *ptr; ++ volume_val linear[PA_CHANNELS_MAX + VOLUME_PADDING]; ++ float vol[PA_CHANNELS_MAX + VOLUME_PADDING]; ++ pa_do_volume_func_t do_volume; ++ long length_in_frames; ++ int i; ++ ++ pa_assert(c); ++ pa_assert(spec); ++ pa_assert(pa_frame_aligned(c->length, spec)); ++ pa_assert(ramp); ++ ++ length_in_frames = c->length / format_sample_size_table[spec->format] / spec->channels; ++ ++ if (pa_memblock_is_silence(c->memblock)) { ++ for (i = 0; i < ramp->channels; i++) { ++ if (ramp->ramps[i].length > 0) ++ ramp->ramps[i].length -= length_in_frames; ++ } ++ return; ++ } ++ ++ if (spec->format < 0 || spec->format >= PA_SAMPLE_MAX) { ++ pa_log_warn("Unable to change volume of format"); ++ return; ++ } ++ ++ do_volume = pa_get_volume_func(spec->format); ++ pa_assert(do_volume); ++ ++ ptr = (uint8_t*) pa_memblock_acquire(c->memblock) + c->index; ++ ++ for (i = 0; i < length_in_frames; i++) { ++ calc_volume_ramps(ramp, vol); ++ calc_volume_table_no_mapping[spec->format] ((void *)linear, vol, spec->channels); ++ ++ /* we only process one frame per iteration */ ++ do_volume (ptr, (void *)linear, spec->channels, format_sample_size_table[spec->format] * spec->channels); ++ ++ /* pa_log_debug("1: %d 2: %d", linear[0], linear[1]); */ ++ ++ ptr = (uint8_t*)ptr + format_sample_size_table[spec->format] * spec->channels; ++ } ++ ++ pa_memblock_release(c->memblock); ++} ++ ++pa_cvolume_ramp_int* pa_cvolume_ramp_convert(const pa_cvolume_ramp *src, pa_cvolume_ramp_int *dst, int sample_rate) { ++ ++ int i, j, channels, remaining_channels; ++ float temp; ++ ++ if (dst->channels < src->channels) { ++ channels = dst->channels; ++ remaining_channels = 0; ++ } ++ else { ++ channels = src->channels; ++ remaining_channels = dst->channels; ++ } ++ ++ for (i = 0; i < channels; i++) { ++ dst->ramps[i].type = src->ramps[i].type; ++ /* ms to samples */ ++ dst->ramps[i].length = src->ramps[i].length * sample_rate / 1000; ++ dst->ramps[i].left = dst->ramps[i].length; ++ dst->ramps[i].start = dst->ramps[i].end; ++ dst->ramps[i].target = src->ramps[i].target; ++ /* scale to pulse internal mapping so that when ramp is over there's no glitch in volume */ ++ temp = src->ramps[i].target / (float)0x10000U; ++ dst->ramps[i].end = temp * temp * temp; ++ } ++ ++ j = i; ++ ++ for (i--; j < remaining_channels; j++) { ++ dst->ramps[j].type = dst->ramps[i].type; ++ dst->ramps[j].length = dst->ramps[i].length; ++ dst->ramps[j].left = dst->ramps[i].left; ++ dst->ramps[j].start = dst->ramps[i].start; ++ dst->ramps[j].target = dst->ramps[i].target; ++ dst->ramps[j].end = dst->ramps[i].end; ++ } ++ ++ return dst; ++} ++ ++bool pa_cvolume_ramp_active(pa_cvolume_ramp_int *ramp) { ++ int i; ++ ++ for (i = 0; i < ramp->channels; i++) { ++ if (ramp->ramps[i].left > 0) ++ return true; ++ } ++ ++ return false; ++} ++ ++bool pa_cvolume_ramp_target_active(pa_cvolume_ramp_int *ramp) { ++ int i; ++ ++ for (i = 0; i < ramp->channels; i++) { ++ if (ramp->ramps[i].target != PA_VOLUME_NORM) ++ return true; ++ } ++ ++ return false; ++} ++ ++pa_cvolume * pa_cvolume_ramp_get_targets(pa_cvolume_ramp_int *ramp, pa_cvolume *volume) { ++ int i = 0; ++ ++ volume->channels = ramp->channels; ++ ++ for (i = 0; i < ramp->channels; i++) ++ volume->values[i] = ramp->ramps[i].target; ++ ++ return volume; ++} ++ ++pa_cvolume_ramp_int* pa_cvolume_ramp_start_from(pa_cvolume_ramp_int *src, pa_cvolume_ramp_int *dst) { ++ int i; ++ ++ for (i = 0; i < src->channels; i++) { ++ /* if new vols are invalid, copy old ramp i.e. no effect */ ++ if (dst->ramps[i].target == PA_VOLUME_INVALID) ++ dst->ramps[i] = src->ramps[i]; ++ /* if there's some old ramp still left */ ++ else if (src->ramps[i].left > 0) ++ dst->ramps[i].start = src->ramps[i].curr; ++ } ++ ++ return dst; ++} ++ ++pa_cvolume_ramp_int* pa_cvolume_ramp_int_init(pa_cvolume_ramp_int *src, pa_volume_t vol, int channels) { ++ int i; ++ float temp; ++ ++ src->channels = channels; ++ ++ for (i = 0; i < channels; i++) { ++ src->ramps[i].type = PA_VOLUME_RAMP_TYPE_LINEAR; ++ src->ramps[i].length = 0; ++ src->ramps[i].left = 0; ++ if (vol == PA_VOLUME_NORM) { ++ src->ramps[i].start = 1.0; ++ src->ramps[i].end = 1.0; ++ src->ramps[i].curr = 1.0; ++ } ++ else if (vol == PA_VOLUME_MUTED) { ++ src->ramps[i].start = 0.0; ++ src->ramps[i].end = 0.0; ++ src->ramps[i].curr = 0.0; ++ } ++ else { ++ temp = vol / (float)0x10000U; ++ src->ramps[i].start = temp * temp * temp; ++ src->ramps[i].end = src->ramps[i].start; ++ src->ramps[i].curr = src->ramps[i].start; ++ } ++ src->ramps[i].target = vol; ++ } ++ ++ return src; ++} +diff --git a/src/pulsecore/mix.h b/src/pulsecore/mix.h +index 8102bcd..0f86b6f 100644 +--- a/src/pulsecore/mix.h ++++ b/src/pulsecore/mix.h +@@ -59,4 +59,31 @@ void pa_volume_memchunk( + const pa_sample_spec *spec, + const pa_cvolume *volume); + ++typedef struct pa_volume_ramp_int_t { ++ pa_volume_ramp_type_t type; ++ long length; ++ long left; ++ float start; ++ float end; ++ float curr; ++ pa_volume_t target; ++} pa_volume_ramp_int_t; ++ ++typedef struct pa_cvolume_ramp_int { ++ uint8_t channels; ++ pa_volume_ramp_int_t ramps[PA_CHANNELS_MAX]; ++} pa_cvolume_ramp_int; ++ ++pa_cvolume_ramp_int* pa_cvolume_ramp_convert(const pa_cvolume_ramp *src, pa_cvolume_ramp_int *dst, int sample_rate); ++bool pa_cvolume_ramp_active(pa_cvolume_ramp_int *ramp); ++bool pa_cvolume_ramp_target_active(pa_cvolume_ramp_int *ramp); ++pa_cvolume_ramp_int* pa_cvolume_ramp_start_from(pa_cvolume_ramp_int *src, pa_cvolume_ramp_int *dst); ++pa_cvolume_ramp_int* pa_cvolume_ramp_int_init(pa_cvolume_ramp_int *src, pa_volume_t vol, int channels); ++pa_cvolume * pa_cvolume_ramp_get_targets(pa_cvolume_ramp_int *ramp, pa_cvolume *volume); ++ ++void pa_volume_ramp_memchunk( ++ pa_memchunk *c, ++ const pa_sample_spec *spec, ++ pa_cvolume_ramp_int *ramp); ++ + #endif +-- +1.9.1 + diff --git a/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio-10.0/0003-volume-ramp-adding-volume-ramping-to-sink-input.patch b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio-10.0/0003-volume-ramp-adding-volume-ramping-to-sink-input.patch new file mode 100644 index 000000000..eb485ca7c --- /dev/null +++ b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio-10.0/0003-volume-ramp-adding-volume-ramping-to-sink-input.patch @@ -0,0 +1,189 @@ +From e4469df7c69316b49cad93dd288badc98fa1cad5 Mon Sep 17 00:00:00 2001 +From: Sangchul Lee +Date: Sat, 27 Aug 2016 21:33:17 +0900 +Subject: [PATCH 3/6] volume ramp: adding volume ramping to sink-input + +The original patch is + - https://review.tizen.org/git/?p=platform/upstream/pulseaudio.git;a=commit;h=98042248fd67ce0ab3807c5c472c0d5d8b0f99d3 + - by Jaska Uimonen helsinki.fi> + +Signed-off-by: Sangchul Lee +--- + src/pulsecore/sink-input.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++ + src/pulsecore/sink-input.h | 11 ++++++++- + 2 files changed, 71 insertions(+), 1 deletion(-) + +diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c +index 8ec63b5..cc8953f 100644 +--- a/src/pulsecore/sink-input.c ++++ b/src/pulsecore/sink-input.c +@@ -526,6 +526,11 @@ int pa_sink_input_new( + reset_callbacks(i); + i->userdata = NULL; + ++ if (data->flags & PA_SINK_INPUT_START_RAMP_MUTED) ++ pa_cvolume_ramp_int_init(&i->ramp, PA_VOLUME_MUTED, data->sample_spec.channels); ++ else ++ pa_cvolume_ramp_int_init(&i->ramp, PA_VOLUME_NORM, data->sample_spec.channels); ++ + i->thread_info.state = i->state; + i->thread_info.attached = false; + pa_atomic_store(&i->thread_info.drained, 1); +@@ -542,6 +547,8 @@ int pa_sink_input_new( + i->thread_info.playing_for = 0; + i->thread_info.direct_outputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); + ++ i->thread_info.ramp = i->ramp; ++ + pa_assert_se(pa_idxset_put(core->sink_inputs, i, &i->index) == 0); + pa_assert_se(pa_idxset_put(i->sink->inputs, pa_sink_input_ref(i), NULL) == 0); + +@@ -923,6 +930,8 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink bytes */, pa + while (tchunk.length > 0) { + pa_memchunk wchunk; + bool nvfs = need_volume_factor_sink; ++ pa_cvolume target; ++ pa_bool_t tmp; + + wchunk = tchunk; + pa_memblock_ref(wchunk.memblock); +@@ -959,6 +968,16 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink bytes */, pa + pa_volume_memchunk(&wchunk, &i->sink->sample_spec, &i->volume_factor_sink); + } + ++ /* check for possible volume ramp */ ++ if (pa_cvolume_ramp_active(&i->thread_info.ramp)) { ++ pa_memchunk_make_writable(&wchunk, 0); ++ pa_volume_ramp_memchunk(&wchunk, &i->sink->sample_spec, &(i->thread_info.ramp)); ++ } else if ((tmp = pa_cvolume_ramp_target_active(&(i->thread_info.ramp)))) { ++ pa_memchunk_make_writable(&wchunk, 0); ++ pa_cvolume_ramp_get_targets(&i->thread_info.ramp, &target); ++ pa_volume_memchunk(&wchunk, &i->sink->sample_spec, &target); ++ } ++ + pa_memblockq_push_align(i->thread_info.render_memblockq, &wchunk); + } else { + pa_memchunk rchunk; +@@ -975,6 +994,16 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink bytes */, pa + pa_volume_memchunk(&rchunk, &i->sink->sample_spec, &i->volume_factor_sink); + } + ++ /* check for possible volume ramp */ ++ if (pa_cvolume_ramp_active(&(i->thread_info.ramp))) { ++ pa_memchunk_make_writable(&rchunk, 0); ++ pa_volume_ramp_memchunk(&rchunk, &i->sink->sample_spec, &(i->thread_info.ramp)); ++ } else if (pa_cvolume_ramp_target_active(&(i->thread_info.ramp))) { ++ pa_memchunk_make_writable(&rchunk, 0); ++ pa_cvolume_ramp_get_targets(&i->thread_info.ramp, &target); ++ pa_volume_memchunk(&rchunk, &i->sink->sample_spec, &target); ++ } ++ + pa_memblockq_push_align(i->thread_info.render_memblockq, &rchunk); + pa_memblock_unref(rchunk.memblock); + } +@@ -1339,6 +1368,31 @@ int pa_sink_input_remove_volume_factor(pa_sink_input *i, const char *key) { + return 0; + } + ++/* Called from main thread */ ++void pa_sink_input_set_volume_ramp( ++ pa_sink_input *i, ++ const pa_cvolume_ramp *ramp, ++ pa_bool_t send_msg, ++ pa_bool_t save) { ++ ++ pa_sink_input_assert_ref(i); ++ pa_assert_ctl_context(); ++ pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); ++ pa_assert(ramp); ++ ++ pa_cvolume_ramp_convert(ramp, &i->ramp, i->sample_spec.rate); ++ ++ pa_log_debug("setting volume ramp with target vol:%d and length:%ld", ++ i->ramp.ramps[0].target, ++ i->ramp.ramps[0].length); ++ ++ ++ /* This tells the sink that volume ramp changed */ ++ if (send_msg) ++ pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP, ++ NULL, 0, NULL) == 0); ++} ++ + /* Called from main context */ + static void set_real_ratio(pa_sink_input *i, const pa_cvolume *v) { + pa_sink_input_assert_ref(i); +@@ -1932,6 +1986,13 @@ int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t + } + return 0; + ++ case PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP: ++ /* we have ongoing ramp where we take current start values */ ++ pa_cvolume_ramp_start_from(&i->thread_info.ramp, &i->ramp); ++ i->thread_info.ramp = i->ramp; ++ pa_sink_input_request_rewind(i, 0, true, false, false); ++ return 0; ++ + case PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE: + if (i->thread_info.muted != i->muted) { + i->thread_info.muted = i->muted; +diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h +index 86deab2..6e1b211 100644 +--- a/src/pulsecore/sink-input.h ++++ b/src/pulsecore/sink-input.h +@@ -32,6 +32,7 @@ + #include + #include + #include ++#include + + typedef enum pa_sink_input_state { + PA_SINK_INPUT_INIT, /*< The stream is not active yet, because pa_sink_input_put() has not been called yet */ +@@ -58,7 +59,8 @@ typedef enum pa_sink_input_flags { + PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND = 256, + PA_SINK_INPUT_NO_CREATE_ON_SUSPEND = 512, + PA_SINK_INPUT_KILL_ON_SUSPEND = 1024, +- PA_SINK_INPUT_PASSTHROUGH = 2048 ++ PA_SINK_INPUT_PASSTHROUGH = 2048, ++ PA_SINK_INPUT_START_RAMP_MUTED = 4096, + } pa_sink_input_flags_t; + + struct pa_sink_input { +@@ -121,6 +123,9 @@ struct pa_sink_input { + * this.*/ + bool save_sink:1, save_volume:1, save_muted:1; + ++ /* for volume ramps */ ++ pa_cvolume_ramp_int ramp; ++ + pa_resample_method_t requested_resample_method, actual_resample_method; + + /* Returns the chunk of audio data and drops it from the +@@ -249,6 +254,8 @@ struct pa_sink_input { + pa_usec_t requested_sink_latency; + + pa_hashmap *direct_outputs; ++ ++ pa_cvolume_ramp_int ramp; + } thread_info; + + void *userdata; +@@ -265,6 +272,7 @@ enum { + PA_SINK_INPUT_MESSAGE_SET_STATE, + PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY, + PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY, ++ PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP, + PA_SINK_INPUT_MESSAGE_MAX + }; + +@@ -370,6 +378,7 @@ void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, bool s + void pa_sink_input_add_volume_factor(pa_sink_input *i, const char *key, const pa_cvolume *volume_factor); + int pa_sink_input_remove_volume_factor(pa_sink_input *i, const char *key); + pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i, pa_cvolume *volume, bool absolute); ++void pa_sink_input_set_volume_ramp(pa_sink_input *i, const pa_cvolume_ramp *ramp, pa_bool_t send_msg, pa_bool_t save); + + void pa_sink_input_set_mute(pa_sink_input *i, bool mute, bool save); + +-- +1.9.1 + diff --git a/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio-10.0/0004-sink-input-Code-cleanup-regarding-volume-ramping.patch b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio-10.0/0004-sink-input-Code-cleanup-regarding-volume-ramping.patch new file mode 100644 index 000000000..64d7b141d --- /dev/null +++ b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio-10.0/0004-sink-input-Code-cleanup-regarding-volume-ramping.patch @@ -0,0 +1,62 @@ +From 49d8943b151a73be3dd726561a720c0f4bfdccac Mon Sep 17 00:00:00 2001 +From: Sangchul Lee +Date: Sat, 27 Aug 2016 21:33:18 +0900 +Subject: [PATCH 4/6] sink-input: Code cleanup regarding volume ramping + +Remove unused parameter of pa_sink_input_set_volume_ramp(). +Use bool instead of pa_bool_t. + +Signed-off-by: Sangchul Lee +--- + src/pulsecore/sink-input.c | 7 ++----- + src/pulsecore/sink-input.h | 2 +- + 2 files changed, 3 insertions(+), 6 deletions(-) + +diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c +index cc8953f..e1968e0 100644 +--- a/src/pulsecore/sink-input.c ++++ b/src/pulsecore/sink-input.c +@@ -931,7 +931,6 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink bytes */, pa + pa_memchunk wchunk; + bool nvfs = need_volume_factor_sink; + pa_cvolume target; +- pa_bool_t tmp; + + wchunk = tchunk; + pa_memblock_ref(wchunk.memblock); +@@ -972,7 +971,7 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink bytes */, pa + if (pa_cvolume_ramp_active(&i->thread_info.ramp)) { + pa_memchunk_make_writable(&wchunk, 0); + pa_volume_ramp_memchunk(&wchunk, &i->sink->sample_spec, &(i->thread_info.ramp)); +- } else if ((tmp = pa_cvolume_ramp_target_active(&(i->thread_info.ramp)))) { ++ } else if ((pa_cvolume_ramp_target_active(&(i->thread_info.ramp)))) { + pa_memchunk_make_writable(&wchunk, 0); + pa_cvolume_ramp_get_targets(&i->thread_info.ramp, &target); + pa_volume_memchunk(&wchunk, &i->sink->sample_spec, &target); +@@ -1372,9 +1371,7 @@ int pa_sink_input_remove_volume_factor(pa_sink_input *i, const char *key) { + void pa_sink_input_set_volume_ramp( + pa_sink_input *i, + const pa_cvolume_ramp *ramp, +- pa_bool_t send_msg, +- pa_bool_t save) { +- ++ bool send_msg) { + pa_sink_input_assert_ref(i); + pa_assert_ctl_context(); + pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); +diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h +index 6e1b211..92f61c3 100644 +--- a/src/pulsecore/sink-input.h ++++ b/src/pulsecore/sink-input.h +@@ -378,7 +378,7 @@ void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, bool s + void pa_sink_input_add_volume_factor(pa_sink_input *i, const char *key, const pa_cvolume *volume_factor); + int pa_sink_input_remove_volume_factor(pa_sink_input *i, const char *key); + pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i, pa_cvolume *volume, bool absolute); +-void pa_sink_input_set_volume_ramp(pa_sink_input *i, const pa_cvolume_ramp *ramp, pa_bool_t send_msg, pa_bool_t save); ++void pa_sink_input_set_volume_ramp(pa_sink_input *i, const pa_cvolume_ramp *ramp, bool send_msg); + + void pa_sink_input_set_mute(pa_sink_input *i, bool mute, bool save); + +-- +1.9.1 + diff --git a/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio-10.0/0005-sink-input-volume-Add-support-for-volume-ramp-factor.patch b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio-10.0/0005-sink-input-volume-Add-support-for-volume-ramp-factor.patch new file mode 100644 index 000000000..e371b7ec5 --- /dev/null +++ b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio-10.0/0005-sink-input-volume-Add-support-for-volume-ramp-factor.patch @@ -0,0 +1,299 @@ +From a98e78ccc4f12d6efad2832a09202651e2a8b6cd Mon Sep 17 00:00:00 2001 +From: Sangchul Lee +Date: Sat, 27 Aug 2016 21:33:19 +0900 +Subject: [PATCH 5/6] sink-input, volume: Add support for volume ramp factor + +Previously, using pa_sink_input_set_volume_ramp() is hard to manage +if there are several callers. These new volume ramp factor APIs make it +easy for caller to use and to set more than one volume ramp factor. +New volume ramp factor will be applied by the multiplication of the other +ramp factors that have been already set. + +APIs are added as below. + - pa_sink_input_add_volume_ramp_factor() + - pa_sink_input_remove_volume_ramp_factor() + - pa_cvolume_ramp_compatible() + - pa_sw_cvolume_ramp_multiply() + - pa_cvolume_ramp_valid() + +Signed-off-by: Sangchul Lee +--- + src/map-file | 3 ++ + src/pulse/volume.c | 44 ++++++++++++++++++ + src/pulse/volume.h | 9 ++++ + src/pulsecore/sink-input.c | 108 +++++++++++++++++++++++++++++++++++++++++++++ + src/pulsecore/sink-input.h | 5 +++ + 5 files changed, 169 insertions(+) + +diff --git a/src/map-file b/src/map-file +index ef9b57d..7577c14 100644 +--- a/src/map-file ++++ b/src/map-file +@@ -142,6 +142,8 @@ pa_cvolume_ramp_equal; + pa_cvolume_ramp_init; + pa_cvolume_ramp_set; + pa_cvolume_ramp_channel_ramp_set; ++pa_cvolume_ramp_compatible; ++pa_cvolume_ramp_valid; + pa_cvolume_remap; + pa_cvolume_scale; + pa_cvolume_scale_mask; +@@ -344,6 +346,7 @@ pa_sw_cvolume_divide_scalar; + pa_sw_cvolume_multiply; + pa_sw_cvolume_multiply_scalar; + pa_sw_cvolume_snprint_dB; ++pa_sw_cvolume_ramp_multiply; + pa_sw_volume_divide; + pa_sw_volume_from_dB; + pa_sw_volume_from_linear; +diff --git a/src/pulse/volume.c b/src/pulse/volume.c +index 85072c1..8d99150 100644 +--- a/src/pulse/volume.c ++++ b/src/pulse/volume.c +@@ -1049,3 +1049,47 @@ pa_cvolume_ramp* pa_cvolume_ramp_channel_ramp_set(pa_cvolume_ramp *ramp, unsigne + + return ramp; + } ++ ++int pa_cvolume_ramp_compatible(const pa_cvolume_ramp *ramp, const pa_sample_spec *ss) { ++ ++ pa_assert(ramp); ++ pa_assert(ss); ++ ++ pa_return_val_if_fail(pa_cvolume_ramp_valid(ramp), 0); ++ pa_return_val_if_fail(pa_sample_spec_valid(ss), 0); ++ ++ return ramp->channels == ss->channels; ++} ++ ++pa_cvolume_ramp *pa_sw_cvolume_ramp_multiply(pa_cvolume_ramp *dest, const pa_cvolume_ramp *a, const pa_cvolume_ramp *b) { ++ unsigned i; ++ ++ pa_assert(dest); ++ pa_assert(a); ++ pa_assert(b); ++ ++ pa_return_val_if_fail(pa_cvolume_ramp_valid(a), NULL); ++ pa_return_val_if_fail(pa_cvolume_ramp_valid(b), NULL); ++ ++ for (i = 0; i < a->channels && i < b->channels; i++) ++ dest->ramps[i].target = pa_sw_volume_multiply(a->ramps[i].target, b->ramps[i].target); ++ ++ dest->channels = (uint8_t) i; ++ ++ return dest; ++} ++ ++int pa_cvolume_ramp_valid(const pa_cvolume_ramp *ramp) { ++ unsigned c; ++ ++ pa_assert(ramp); ++ ++ if (!pa_channels_valid(ramp->channels)) ++ return 0; ++ ++ for (c = 0; c < ramp->channels; c++) ++ if (!PA_VOLUME_IS_VALID(ramp->ramps[c].target)) ++ return 0; ++ ++ return 1; ++} +diff --git a/src/pulse/volume.h b/src/pulse/volume.h +index 2ae3451..65fcb08 100644 +--- a/src/pulse/volume.h ++++ b/src/pulse/volume.h +@@ -458,12 +458,21 @@ int pa_cvolume_ramp_equal(const pa_cvolume_ramp *a, const pa_cvolume_ramp *b); + /** Init volume ramp struct */ + pa_cvolume_ramp* pa_cvolume_ramp_init(pa_cvolume_ramp *ramp); + ++/** Set the volume ramp of the first n channels to PA_VOLUME_NORM */ ++#define pa_cvolume_ramp_reset(a, n, t, l) pa_cvolume_ramp_set((a), (n), (t), (l), PA_VOLUME_NORM) ++ + /** Set first n channels of ramp struct to certain value */ + pa_cvolume_ramp* pa_cvolume_ramp_set(pa_cvolume_ramp *ramp, unsigned channel, pa_volume_ramp_type_t type, long time, pa_volume_t vol); + + /** Set individual channel in the channel struct */ + pa_cvolume_ramp* pa_cvolume_ramp_channel_ramp_set(pa_cvolume_ramp *ramp, unsigned channel, pa_volume_ramp_type_t type, long time, pa_volume_t vol); + ++int pa_cvolume_ramp_compatible(const pa_cvolume_ramp *ramp, const pa_sample_spec *ss); ++ ++int pa_cvolume_ramp_valid(const pa_cvolume_ramp *ramp); ++ ++pa_cvolume_ramp *pa_sw_cvolume_ramp_multiply(pa_cvolume_ramp *dest, const pa_cvolume_ramp *a, const pa_cvolume_ramp *b); ++ + PA_C_DECL_END + + #endif +diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c +index e1968e0..6f89aa1 100644 +--- a/src/pulsecore/sink-input.c ++++ b/src/pulsecore/sink-input.c +@@ -53,6 +53,11 @@ struct volume_factor_entry { + pa_cvolume volume; + }; + ++struct volume_ramp_factor_entry { ++ char *key; ++ pa_cvolume_ramp ramp; ++}; ++ + static struct volume_factor_entry *volume_factor_entry_new(const char *key, const pa_cvolume *volume) { + struct volume_factor_entry *entry; + +@@ -83,6 +88,37 @@ static void volume_factor_from_hashmap(pa_cvolume *v, pa_hashmap *items, uint8_t + pa_sw_cvolume_multiply(v, v, &entry->volume); + } + ++static struct volume_ramp_factor_entry *volume_ramp_factor_entry_new(const char *key, const pa_cvolume_ramp *ramp) { ++ struct volume_ramp_factor_entry *entry; ++ ++ pa_assert(key); ++ pa_assert(ramp); ++ ++ entry = pa_xnew(struct volume_ramp_factor_entry, 1); ++ entry->key = pa_xstrdup(key); ++ ++ entry->ramp = *ramp; ++ ++ return entry; ++} ++ ++static void volume_ramp_factor_entry_free(struct volume_ramp_factor_entry *ramp_entry) { ++ pa_assert(ramp_entry); ++ ++ pa_xfree(ramp_entry->key); ++ pa_xfree(ramp_entry); ++} ++ ++static void volume_ramp_factor_from_hashmap(pa_cvolume_ramp *r, pa_hashmap *items, uint8_t channels, pa_volume_ramp_type_t type, long length) { ++ struct volume_ramp_factor_entry *entry; ++ void *state = NULL; ++ ++ pa_cvolume_ramp_reset(r, channels, type, length); ++ PA_HASHMAP_FOREACH(entry, items, state) ++ pa_sw_cvolume_ramp_multiply(r, r, &entry->ramp); ++ ++} ++ + static void sink_input_free(pa_object *o); + static void set_real_ratio(pa_sink_input *i, const pa_cvolume *v); + +@@ -500,6 +536,8 @@ int pa_sink_input_new( + i->volume_factor_sink_items = data->volume_factor_sink_items; + data->volume_factor_sink_items = NULL; + volume_factor_from_hashmap(&i->volume_factor_sink, i->volume_factor_sink_items, i->sink->sample_spec.channels); ++ i->ramp_factor_items = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, ++ (pa_free_cb_t) volume_ramp_factor_entry_free); + + i->real_ratio = i->reference_ratio = data->volume; + pa_cvolume_reset(&i->soft_volume, i->sample_spec.channels); +@@ -764,6 +802,9 @@ static void sink_input_free(pa_object *o) { + if (i->volume_factor_sink_items) + pa_hashmap_free(i->volume_factor_sink_items); + ++ if (i->ramp_factor_items) ++ pa_hashmap_free(i->ramp_factor_items); ++ + pa_xfree(i->driver); + pa_xfree(i); + } +@@ -1367,6 +1408,73 @@ int pa_sink_input_remove_volume_factor(pa_sink_input *i, const char *key) { + return 0; + } + ++void pa_sink_input_add_volume_ramp_factor(pa_sink_input *i, const char *key, const pa_cvolume_ramp *ramp_factor, bool send_msg) { ++ struct volume_ramp_factor_entry *r; ++ ++ pa_sink_input_assert_ref(i); ++ pa_assert_ctl_context(); ++ pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); ++ pa_assert(ramp_factor); ++ pa_assert(key); ++ pa_assert(pa_cvolume_ramp_valid(ramp_factor)); ++ pa_assert(ramp_factor->channels == 1 || pa_cvolume_ramp_compatible(ramp_factor, &i->sample_spec)); ++ ++ r = volume_ramp_factor_entry_new(key, ramp_factor); ++ if (!pa_cvolume_ramp_compatible(ramp_factor, &i->sample_spec)) ++ pa_cvolume_ramp_set(&r->ramp, i->sample_spec.channels, ramp_factor->ramps[0].type, ramp_factor->ramps[0].length, ramp_factor->ramps[0].target); ++ ++ pa_assert_se(pa_hashmap_put(i->ramp_factor_items, r->key, r) >= 0); ++ if (pa_hashmap_size(i->ramp_factor_items) == 1) ++ pa_cvolume_ramp_set(&i->ramp_factor, i->sample_spec.channels, r->ramp.ramps[0].type, r->ramp.ramps[0].length, r->ramp.ramps[0].target); ++ else ++ pa_sw_cvolume_ramp_multiply(&i->ramp_factor, &i->ramp_factor, &r->ramp); ++ ++ pa_cvolume_ramp_convert(&i->ramp_factor, &i->ramp, i->sample_spec.rate); ++ ++ if (send_msg) ++ pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP, NULL, 0, NULL) == 0); ++ ++ return 0; ++} ++ ++/* Returns 0 if an entry was removed and -1 if no entry for the given key was ++ * found. */ ++int pa_sink_input_remove_volume_ramp_factor(pa_sink_input *i, const char *key, bool send_msg) { ++ struct volume_ramp_factor_entry *r; ++ ++ pa_sink_input_assert_ref(i); ++ pa_assert(key); ++ pa_assert_ctl_context(); ++ pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); ++ ++ r = pa_hashmap_remove(i->ramp_factor_items, key); ++ if (!r) ++ return -1; ++ ++ switch (pa_hashmap_size(i->ramp_factor_items)) { ++ case 0: ++ pa_cvolume_ramp_reset(&i->ramp_factor, i->sample_spec.channels, r->ramp.ramps[0].type, r->ramp.ramps[0].length); ++ break; ++ case 1: { ++ struct volume_ramp_factor_entry *rf; ++ rf = pa_hashmap_first(i->ramp_factor_items); ++ pa_cvolume_ramp_set(&i->ramp_factor, i->sample_spec.channels, r->ramp.ramps[0].type, r->ramp.ramps[0].length, rf->ramp.ramps[0].target); ++ break; ++ } ++ default: ++ volume_ramp_factor_from_hashmap(&i->ramp_factor, i->ramp_factor_items, i->ramp_factor.channels, i->ramp_factor.ramps[0].type, i->ramp_factor.ramps[0].length); ++ } ++ ++ volume_ramp_factor_entry_free(r); ++ ++ pa_cvolume_ramp_convert(&i->ramp_factor, &i->ramp, i->sample_spec.rate); ++ ++ if (send_msg) ++ pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP, NULL, 0, NULL) == 0); ++ ++ return 0; ++} ++ + /* Called from main thread */ + void pa_sink_input_set_volume_ramp( + pa_sink_input *i, +diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h +index 92f61c3..5430d53 100644 +--- a/src/pulsecore/sink-input.h ++++ b/src/pulsecore/sink-input.h +@@ -113,6 +113,9 @@ struct pa_sink_input { + pa_cvolume volume_factor_sink; /* A second volume factor in format of the sink this stream is connected to. */ + pa_hashmap *volume_factor_sink_items; + ++ pa_cvolume_ramp ramp_factor; ++ pa_hashmap *ramp_factor_items; ++ + bool volume_writable:1; + + bool muted:1; +@@ -379,6 +382,8 @@ void pa_sink_input_add_volume_factor(pa_sink_input *i, const char *key, const pa + int pa_sink_input_remove_volume_factor(pa_sink_input *i, const char *key); + pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i, pa_cvolume *volume, bool absolute); + void pa_sink_input_set_volume_ramp(pa_sink_input *i, const pa_cvolume_ramp *ramp, bool send_msg); ++void pa_sink_input_add_volume_ramp_factor(pa_sink_input *i, const char *key, const pa_cvolume_ramp *ramp_factor, bool send_msg); ++int pa_sink_input_remove_volume_ramp_factor(pa_sink_input *i, const char *key, bool send_msg); + + void pa_sink_input_set_mute(pa_sink_input *i, bool mute, bool save); + +-- +1.9.1 + diff --git a/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio-10.0/0006-sink-input-Remove-pa_sink_input_set_volume_ramp.patch b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio-10.0/0006-sink-input-Remove-pa_sink_input_set_volume_ramp.patch new file mode 100644 index 000000000..50110bd14 --- /dev/null +++ b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio-10.0/0006-sink-input-Remove-pa_sink_input_set_volume_ramp.patch @@ -0,0 +1,63 @@ +From ac9a99505fd768b66dd92e9091e80b576cabc00d Mon Sep 17 00:00:00 2001 +From: Sangchul Lee +Date: Sat, 27 Aug 2016 21:33:20 +0900 +Subject: [PATCH 6/6] sink-input: Remove pa_sink_input_set_volume_ramp() + +Please use pa_sink_input_add_volume_ramp_factor() or +pa_sink_input_remove_volume_ramp_factor() instead of it. + +Signed-off-by: Sangchul Lee +--- + src/pulsecore/sink-input.c | 23 ----------------------- + src/pulsecore/sink-input.h | 1 - + 2 files changed, 24 deletions(-) + +diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c +index 6f89aa1..4c7c568 100644 +--- a/src/pulsecore/sink-input.c ++++ b/src/pulsecore/sink-input.c +@@ -1475,29 +1475,6 @@ int pa_sink_input_remove_volume_ramp_factor(pa_sink_input *i, const char *key, b + return 0; + } + +-/* Called from main thread */ +-void pa_sink_input_set_volume_ramp( +- pa_sink_input *i, +- const pa_cvolume_ramp *ramp, +- bool send_msg) { +- pa_sink_input_assert_ref(i); +- pa_assert_ctl_context(); +- pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); +- pa_assert(ramp); +- +- pa_cvolume_ramp_convert(ramp, &i->ramp, i->sample_spec.rate); +- +- pa_log_debug("setting volume ramp with target vol:%d and length:%ld", +- i->ramp.ramps[0].target, +- i->ramp.ramps[0].length); +- +- +- /* This tells the sink that volume ramp changed */ +- if (send_msg) +- pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP, +- NULL, 0, NULL) == 0); +-} +- + /* Called from main context */ + static void set_real_ratio(pa_sink_input *i, const pa_cvolume *v) { + pa_sink_input_assert_ref(i); +diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h +index 5430d53..5fef3d5 100644 +--- a/src/pulsecore/sink-input.h ++++ b/src/pulsecore/sink-input.h +@@ -381,7 +381,6 @@ void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, bool s + void pa_sink_input_add_volume_factor(pa_sink_input *i, const char *key, const pa_cvolume *volume_factor); + int pa_sink_input_remove_volume_factor(pa_sink_input *i, const char *key); + pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i, pa_cvolume *volume, bool absolute); +-void pa_sink_input_set_volume_ramp(pa_sink_input *i, const pa_cvolume_ramp *ramp, bool send_msg); + void pa_sink_input_add_volume_ramp_factor(pa_sink_input *i, const char *key, const pa_cvolume_ramp *ramp_factor, bool send_msg); + int pa_sink_input_remove_volume_ramp_factor(pa_sink_input *i, const char *key, bool send_msg); + +-- +1.9.1 + diff --git a/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio-10.0/enable-ofono-hfp-backend.patch b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio-10.0/enable-ofono-hfp-backend.patch new file mode 100644 index 000000000..85b1ae03d --- /dev/null +++ b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio-10.0/enable-ofono-hfp-backend.patch @@ -0,0 +1,11 @@ +--- pulseaudio-9.0/src/daemon/default.pa.in.orig 2017-05-17 17:26:20.415369638 +0000 ++++ pulseaudio-9.0/src/daemon/default.pa.in 2017-05-17 17:26:49.995316383 +0000 +@@ -82,7 +82,7 @@ + .endif + + .ifexists module-bluetooth-discover@PA_SOEXT@ +-load-module module-bluetooth-discover ++load-module module-bluetooth-discover headset=ofono + .endif + ])dnl + diff --git a/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0008-install-files-for-a-module-development.patch b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0008-install-files-for-a-module-development.patch new file mode 100644 index 000000000..ac164d643 --- /dev/null +++ b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0008-install-files-for-a-module-development.patch @@ -0,0 +1,53 @@ +--- a/Makefile.am 2016-04-12 11:28:10.832997230 +0200 ++++ b/Makefile.am 2016-04-12 11:32:41.868996777 +0200 +@@ -49,7 +49,13 @@ + vala/libpulse-simple.deps vala/libpulse-simple.vapi + + pkgconfigdir = $(libdir)/pkgconfig +-pkgconfig_DATA = libpulse.pc libpulse-simple.pc ++pkgconfig_DATA = libpulse.pc libpulse-simple.pc pulseaudio-module-devel.pc ++ ++moduledev_DATA = pulsecore-config.h $(top_srcdir)/src/pulsecore/*.h ++moduledevdir = $(includedir)/pulsemodule/pulsecore ++ ++moduledevinternal_DATA = src/pulse/internal.h src/pulse/client-conf.h src/pulse/fork-detect.h ++moduledevinternaldir = $(includedir)/pulsemodule/pulse + + if HAVE_GLIB20 + pkgconfig_DATA += \ +@@ -103,6 +109,9 @@ + check-daemon: + $(MAKE) -C src check-daemon + ++pulsecore-config.h: config.h ++ cp $< $@ ++ + .PHONY: homepage distcleancheck doxygen + + # see git-version-gen +--- a/configure.ac 2016-04-12 11:34:10.605996629 +0200 ++++ b/configure.ac 2016-04-12 11:37:43.502996274 +0200 +@@ -1464,6 +1464,7 @@ + man/default.pa.5.xml + man/pulse-cli-syntax.5.xml + man/start-pulseaudio-x11.1.xml ++pulseaudio-module-devel.pc + ]) + + AC_CONFIG_FILES([src/esdcompat:src/daemon/esdcompat.in], [chmod +x src/esdcompat]) +--- /dev/null 2016-03-15 16:08:23.302999643 +0100 ++++ b/pulseaudio-module-devel.pc.in 2016-03-17 16:16:58.427977484 +0100 +@@ -0,0 +1,12 @@ ++prefix=@prefix@ ++exec_prefix=@exec_prefix@ ++libdir=@libdir@ ++includedir=@includedir@ ++modlibexecdir=@modlibexecdir@ ++ ++Name: pulseaudio-module-devel ++Description: PulseAudio Module Development Interface ++Version: @PACKAGE_VERSION@ ++Libs: -L${libdir} -L${libdir}/pulseaudio -L${modlibexecdir} -lpulsecommon-@PA_MAJORMINOR@ -lpulsecore-@PA_MAJORMINOR@ -lprotocol-native ++Libs.private: ++Cflags: -I${includedir}/pulsemodule -D_REENTRANT + diff --git a/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0010-volume-ramp-additions-to-the-low-level-infra.patch b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0010-volume-ramp-additions-to-the-low-level-infra.patch new file mode 100644 index 000000000..e249bc438 --- /dev/null +++ b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0010-volume-ramp-additions-to-the-low-level-infra.patch @@ -0,0 +1,503 @@ +--- a/src/map-file 2016-04-12 15:03:17.009975690 +0200 ++++ b/src/map-file 2016-04-12 15:03:52.389975631 +0200 +@@ -136,6 +136,9 @@ + pa_cvolume_merge; + pa_cvolume_min; + pa_cvolume_min_mask; ++pa_cvolume_ramp_init; ++pa_cvolume_ramp_set; ++pa_cvolume_ramp_channel_ramp_set; + pa_cvolume_remap; + pa_cvolume_scale; + pa_cvolume_scale_mask; +--- a/src/pulse/def.h 2016-04-12 15:05:58.245975421 +0200 ++++ b/src/pulse/def.h 2016-04-12 15:13:19.424974685 +0200 +@@ -347,11 +347,15 @@ + * consider absolute when the sink is in flat volume mode, + * relative otherwise. \since 0.9.20 */ + +- PA_STREAM_PASSTHROUGH = 0x80000U ++ PA_STREAM_PASSTHROUGH = 0x80000U, + /**< Used to tag content that will be rendered by passthrough sinks. + * The data will be left as is and not reformatted, resampled. + * \since 1.0 */ + ++ PA_STREAM_START_RAMP_MUTED = 0x100000U ++ /**< Used to tag content that the stream will be started ramp volume ++ * muted so that you can nicely fade it in */ ++ + } pa_stream_flags_t; + + /** \cond fulldocs */ +@@ -380,6 +384,7 @@ + #define PA_STREAM_FAIL_ON_SUSPEND PA_STREAM_FAIL_ON_SUSPEND + #define PA_STREAM_RELATIVE_VOLUME PA_STREAM_RELATIVE_VOLUME + #define PA_STREAM_PASSTHROUGH PA_STREAM_PASSTHROUGH ++#define PA_STREAM_START_RAMP_MUTED PA_STREAM_START_RAMP_MUTED + + /** \endcond */ + +@@ -1047,6 +1052,13 @@ + /** \endcond */ + #endif + ++/** \cond fulldocs */ ++#define PA_VOLUMER_RAMP_TYPE_LINEAR PA_VOLUMER_RAMP_TYPE_LINEAR ++#define PA_VOLUMER_RAMP_TYPE_LOGARITHMIC PA_VOLUMER_RAMP_TYPE_LOGARITHMIC ++#define PA_VOLUMER_RAMP_TYPE_CUBIC PA_VOLUMER_RAMP_TYPE_CUBIC ++ ++/** \endcond */ ++ + PA_C_DECL_END + + #endif +--- a/src/pulse/volume.c 2016-04-12 15:13:38.598974653 +0200 ++++ b/src/pulse/volume.c 2016-04-12 15:27:57.729973219 +0200 +@@ -445,7 +445,10 @@ + unsigned c; + pa_assert(a); + +- pa_return_val_if_fail(pa_cvolume_valid(a), 0); ++ if (pa_cvolume_valid(a) == 0) ++ abort(); ++ ++ /* pa_return_val_if_fail(pa_cvolume_valid(a), 0); */ + pa_return_val_if_fail(PA_VOLUME_IS_VALID(v), 0); + + for (c = 0; c < a->channels; c++) +@@ -986,3 +989,51 @@ + + return pa_cvolume_scale(v, m); + } ++ ++pa_cvolume_ramp* pa_cvolume_ramp_init(pa_cvolume_ramp *ramp) { ++ unsigned c; ++ ++ pa_assert(ramp); ++ ++ ramp->channels = 0; ++ ++ for (c = 0; c < PA_CHANNELS_MAX; c++) { ++ ramp->ramps[c].type = PA_VOLUME_RAMP_TYPE_LINEAR; ++ ramp->ramps[c].length = 0; ++ ramp->ramps[c].target = PA_VOLUME_INVALID; ++ } ++ ++ return ramp; ++} ++ ++pa_cvolume_ramp* pa_cvolume_ramp_set(pa_cvolume_ramp *ramp, unsigned channels, pa_volume_ramp_type_t type, long time, pa_volume_t vol) { ++ int i; ++ ++ pa_assert(ramp); ++ pa_assert(channels > 0); ++ pa_assert(time >= 0); ++ pa_assert(channels <= PA_CHANNELS_MAX); ++ ++ ramp->channels = (uint8_t) channels; ++ ++ for (i = 0; i < ramp->channels; i++) { ++ ramp->ramps[i].type = type; ++ ramp->ramps[i].length = time; ++ ramp->ramps[i].target = PA_CLAMP_VOLUME(vol); ++ } ++ ++ return ramp; ++} ++ ++pa_cvolume_ramp* pa_cvolume_ramp_channel_ramp_set(pa_cvolume_ramp *ramp, unsigned channel, pa_volume_ramp_type_t type, long time, pa_volume_t vol) { ++ ++ pa_assert(ramp); ++ pa_assert(channel <= ramp->channels); ++ pa_assert(time >= 0); ++ ++ ramp->ramps[channel].type = type; ++ ramp->ramps[channel].length = time; ++ ramp->ramps[channel].target = PA_CLAMP_VOLUME(vol); ++ ++ return ramp; ++} +--- a/src/pulse/volume.h 2016-04-12 15:40:34.989971955 +0200 ++++ b/src/pulse/volume.h 2016-04-12 15:38:50.708972129 +0200 +@@ -413,6 +413,36 @@ + * the channels are kept. \since 0.9.16 */ + pa_cvolume* pa_cvolume_dec(pa_cvolume *v, pa_volume_t dec); + ++/** Volume ramp type ++*/ ++typedef enum pa_volume_ramp_type { ++ PA_VOLUME_RAMP_TYPE_LINEAR = 0, /**< linear */ ++ PA_VOLUME_RAMP_TYPE_LOGARITHMIC = 1, /**< logarithmic */ ++ PA_VOLUME_RAMP_TYPE_CUBIC = 2, ++} pa_volume_ramp_type_t; ++ ++/** A structure encapsulating a volume ramp */ ++typedef struct pa_volume_ramp_t { ++ pa_volume_ramp_type_t type; ++ long length; ++ pa_volume_t target; ++} pa_volume_ramp_t; ++ ++/** A structure encapsulating a multichannel volume ramp */ ++typedef struct pam_cvolume_ramp { ++ uint8_t channels; ++ pa_volume_ramp_t ramps[PA_CHANNELS_MAX]; ++} pa_cvolume_ramp; ++ ++/** Init volume ramp struct */ ++pa_cvolume_ramp* pa_cvolume_ramp_init(pa_cvolume_ramp *ramp); ++ ++/** Set first n channels of ramp struct to certain value */ ++pa_cvolume_ramp* pa_cvolume_ramp_set(pa_cvolume_ramp *ramp, unsigned channel, pa_volume_ramp_type_t type, long time, pa_volume_t vol); ++ ++/** Set individual channel in the channel struct */ ++pa_cvolume_ramp* pa_cvolume_ramp_channel_ramp_set(pa_cvolume_ramp *ramp, unsigned channel, pa_volume_ramp_type_t type, long time, pa_volume_t vol); ++ + PA_C_DECL_END + + #endif +--- a/src/pulsecore/sample-util.c 2016-04-12 15:41:51.812971827 +0200 ++++ b/src/pulsecore/sample-util.c 2016-04-12 16:31:56.795966812 +0200 +@@ -41,6 +41,13 @@ + + #define PA_SILENCE_MAX (PA_PAGE_SIZE*16) + ++#define VOLUME_PADDING 32 ++ ++typedef union { ++ float f; ++ uint32_t i; ++} volume_val; ++ + pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec) { + void *data; + +@@ -403,3 +410,292 @@ + usec = pa_bytes_to_usec_round_up(size, from); + return pa_usec_to_bytes_round_up(usec, to); + } ++ ++static void calc_linear_integer_volume_no_mapping(int32_t linear[], float volume[], unsigned nchannels) { ++ unsigned channel, padding; ++ ++ pa_assert(linear); ++ pa_assert(volume); ++ ++ for (channel = 0; channel < nchannels; channel++) ++ linear[channel] = (int32_t) lrint(volume[channel] * 0x10000U); ++ ++ for (padding = 0; padding < VOLUME_PADDING; padding++, channel++) ++ linear[channel] = linear[padding]; ++} ++ ++static void calc_linear_float_volume_no_mapping(float linear[], float volume[], unsigned nchannels) { ++ unsigned channel, padding; ++ ++ pa_assert(linear); ++ pa_assert(volume); ++ ++ for (channel = 0; channel < nchannels; channel++) ++ linear[channel] = volume[channel]; ++ ++ for (padding = 0; padding < VOLUME_PADDING; padding++, channel++) ++ linear[channel] = linear[padding]; ++} ++ ++typedef void (*pa_calc_volume_no_mapping_func_t) (void *volumes, float *volume, int channels); ++ ++static const pa_calc_volume_no_mapping_func_t calc_volume_table_no_mapping[] = { ++ [PA_SAMPLE_U8] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, ++ [PA_SAMPLE_ALAW] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, ++ [PA_SAMPLE_ULAW] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, ++ [PA_SAMPLE_S16LE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, ++ [PA_SAMPLE_S16BE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, ++ [PA_SAMPLE_FLOAT32LE] = (pa_calc_volume_no_mapping_func_t) calc_linear_float_volume_no_mapping, ++ [PA_SAMPLE_FLOAT32BE] = (pa_calc_volume_no_mapping_func_t) calc_linear_float_volume_no_mapping, ++ [PA_SAMPLE_S32LE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, ++ [PA_SAMPLE_S32BE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, ++ [PA_SAMPLE_S24LE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, ++ [PA_SAMPLE_S24BE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, ++ [PA_SAMPLE_S24_32LE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, ++ [PA_SAMPLE_S24_32BE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping ++}; ++ ++static const unsigned format_sample_size_table[] = { ++ [PA_SAMPLE_U8] = 1, ++ [PA_SAMPLE_ALAW] = 1, ++ [PA_SAMPLE_ULAW] = 1, ++ [PA_SAMPLE_S16LE] = 2, ++ [PA_SAMPLE_S16BE] = 2, ++ [PA_SAMPLE_FLOAT32LE] = 4, ++ [PA_SAMPLE_FLOAT32BE] = 4, ++ [PA_SAMPLE_S32LE] = 4, ++ [PA_SAMPLE_S32BE] = 4, ++ [PA_SAMPLE_S24LE] = 3, ++ [PA_SAMPLE_S24BE] = 3, ++ [PA_SAMPLE_S24_32LE] = 4, ++ [PA_SAMPLE_S24_32BE] = 4 ++}; ++ ++static float calc_volume_ramp_linear(pa_volume_ramp_int_t *ramp) { ++ pa_assert(ramp); ++ pa_assert(ramp->length > 0); ++ ++ /* basic linear interpolation */ ++ return ramp->start + (ramp->length - ramp->left) * (ramp->end - ramp->start) / (float) ramp->length; ++} ++ ++static float calc_volume_ramp_logarithmic(pa_volume_ramp_int_t *ramp) { ++ float x_val, s, e; ++ long temp; ++ ++ pa_assert(ramp); ++ pa_assert(ramp->length > 0); ++ ++ if (ramp->end > ramp->start) { ++ temp = ramp->left; ++ s = ramp->end; ++ e = ramp->start; ++ } else { ++ temp = ramp->length - ramp->left; ++ s = ramp->start; ++ e = ramp->end; ++ } ++ ++ x_val = temp == 0 ? 0.0 : powf(temp, 10); ++ ++ /* base 10 logarithmic interpolation */ ++ return s + x_val * (e - s) / powf(ramp->length, 10); ++} ++ ++static float calc_volume_ramp_cubic(pa_volume_ramp_int_t *ramp) { ++ float x_val, s, e; ++ long temp; ++ ++ pa_assert(ramp); ++ pa_assert(ramp->length > 0); ++ ++ if (ramp->end > ramp->start) { ++ temp = ramp->left; ++ s = ramp->end; ++ e = ramp->start; ++ } else { ++ temp = ramp->length - ramp->left; ++ s = ramp->start; ++ e = ramp->end; ++ } ++ ++ x_val = temp == 0 ? 0.0 : cbrtf(temp); ++ ++ /* cubic interpolation */ ++ return s + x_val * (e - s) / cbrtf(ramp->length); ++} ++ ++typedef float (*pa_calc_volume_ramp_func_t) (pa_volume_ramp_int_t *); ++ ++static const pa_calc_volume_ramp_func_t calc_volume_ramp_table[] = { ++ [PA_VOLUME_RAMP_TYPE_LINEAR] = (pa_calc_volume_ramp_func_t) calc_volume_ramp_linear, ++ [PA_VOLUME_RAMP_TYPE_LOGARITHMIC] = (pa_calc_volume_ramp_func_t) calc_volume_ramp_logarithmic, ++ [PA_VOLUME_RAMP_TYPE_CUBIC] = (pa_calc_volume_ramp_func_t) calc_volume_ramp_cubic ++}; ++ ++static void calc_volume_ramps(pa_cvolume_ramp_int *ram, float *vol) ++{ ++ int i; ++ ++ for (i = 0; i < ram->channels; i++) { ++ if (ram->ramps[i].left <= 0) { ++ if (ram->ramps[i].target == PA_VOLUME_NORM) { ++ vol[i] = 1.0; ++ } ++ } else { ++ vol[i] = ram->ramps[i].curr = calc_volume_ramp_table[ram->ramps[i].type] (&ram->ramps[i]); ++ ram->ramps[i].left--; ++ } ++ } ++} ++ ++void pa_volume_ramp_memchunk( ++ pa_memchunk *c, ++ const pa_sample_spec *spec, ++ pa_cvolume_ramp_int *ramp) { ++ ++ void *ptr; ++ volume_val linear[PA_CHANNELS_MAX + VOLUME_PADDING]; ++ float vol[PA_CHANNELS_MAX + VOLUME_PADDING]; ++ pa_do_volume_func_t do_volume; ++ long length_in_frames; ++ int i; ++ ++ pa_assert(c); ++ pa_assert(spec); ++ pa_assert(pa_frame_aligned(c->length, spec)); ++ pa_assert(ramp); ++ ++ length_in_frames = c->length / format_sample_size_table[spec->format] / spec->channels; ++ ++ if (pa_memblock_is_silence(c->memblock)) { ++ for (i = 0; i < ramp->channels; i++) { ++ if (ramp->ramps[i].length > 0) ++ ramp->ramps[i].length -= length_in_frames; ++ } ++ return; ++ } ++ ++ if (spec->format < 0 || spec->format >= PA_SAMPLE_MAX) { ++ pa_log_warn("Unable to change volume of format"); ++ return; ++ } ++ ++ do_volume = pa_get_volume_func(spec->format); ++ pa_assert(do_volume); ++ ++ ptr = (uint8_t*) pa_memblock_acquire(c->memblock) + c->index; ++ ++ for (i = 0; i < length_in_frames; i++) { ++ calc_volume_ramps(ramp, vol); ++ calc_volume_table_no_mapping[spec->format] ((void *)linear, vol, spec->channels); ++ ++ /* we only process one frame per iteration */ ++ do_volume (ptr, (void *)linear, spec->channels, format_sample_size_table[spec->format] * spec->channels); ++ ++ /* pa_log_debug("1: %d 2: %d", linear[0], linear[1]); */ ++ ++ ptr = (uint8_t*)ptr + format_sample_size_table[spec->format] * spec->channels; ++ } ++ ++ pa_memblock_release(c->memblock); ++} ++ ++pa_cvolume_ramp_int* pa_cvolume_ramp_convert(const pa_cvolume_ramp *src, pa_cvolume_ramp_int *dst, int sample_rate) { ++ int i; ++ float temp; ++ ++ for (i = 0; i < dst->channels; i++) { ++ dst->ramps[i].type = src->ramps[i].type; ++ /* ms to samples */ ++ dst->ramps[i].length = src->ramps[i].length * sample_rate / 1000; ++ dst->ramps[i].left = dst->ramps[i].length; ++ dst->ramps[i].start = dst->ramps[i].end; ++ dst->ramps[i].target = src->ramps[i].target; ++ /* scale to pulse internal mapping so that when ramp is over there's no glitch in volume */ ++ temp = src->ramps[i].target / (float)0x10000U; ++ dst->ramps[i].end = temp * temp * temp; ++ } ++ ++ return dst; ++} ++ ++bool pa_cvolume_ramp_active(pa_cvolume_ramp_int *ramp) { ++ int i; ++ ++ for (i = 0; i < ramp->channels; i++) { ++ if (ramp->ramps[i].left > 0) ++ return true; ++ } ++ ++ return false; ++} ++ ++bool pa_cvolume_ramp_target_active(pa_cvolume_ramp_int *ramp) { ++ int i; ++ ++ for (i = 0; i < ramp->channels; i++) { ++ if (ramp->ramps[i].target != PA_VOLUME_NORM) ++ return true; ++ } ++ ++ return false; ++} ++ ++pa_cvolume * pa_cvolume_ramp_get_targets(pa_cvolume_ramp_int *ramp, pa_cvolume *volume) { ++ int i = 0; ++ ++ volume->channels = ramp->channels; ++ ++ for (i = 0; i < ramp->channels; i++) ++ volume->values[i] = ramp->ramps[i].target; ++ ++ return volume; ++} ++ ++pa_cvolume_ramp_int* pa_cvolume_ramp_start_from(pa_cvolume_ramp_int *src, pa_cvolume_ramp_int *dst) { ++ int i; ++ ++ for (i = 0; i < src->channels; i++) { ++ /* if new vols are invalid, copy old ramp i.e. no effect */ ++ if (dst->ramps[i].target == PA_VOLUME_INVALID) ++ dst->ramps[i] = src->ramps[i]; ++ /* if there's some old ramp still left */ ++ else if (src->ramps[i].left > 0) ++ dst->ramps[i].start = src->ramps[i].curr; ++ } ++ ++ return dst; ++} ++ ++pa_cvolume_ramp_int* pa_cvolume_ramp_int_init(pa_cvolume_ramp_int *src, pa_volume_t vol, int channels) { ++ int i; ++ float temp; ++ ++ src->channels = channels; ++ ++ for (i = 0; i < channels; i++) { ++ src->ramps[i].type = PA_VOLUME_RAMP_TYPE_LINEAR; ++ src->ramps[i].length = 0; ++ src->ramps[i].left = 0; ++ if (vol == PA_VOLUME_NORM) { ++ src->ramps[i].start = 1.0; ++ src->ramps[i].end = 1.0; ++ src->ramps[i].curr = 1.0; ++ } ++ else if (vol == PA_VOLUME_MUTED) { ++ src->ramps[i].start = 0.0; ++ src->ramps[i].end = 0.0; ++ src->ramps[i].curr = 0.0; ++ } ++ else { ++ temp = vol / (float)0x10000U; ++ src->ramps[i].start = temp * temp * temp; ++ src->ramps[i].end = src->ramps[i].start; ++ src->ramps[i].curr = src->ramps[i].start; ++ } ++ src->ramps[i].target = vol; ++ } ++ ++ return src; ++} +--- a/src/pulsecore/sample-util.h 2016-04-12 15:53:06.327970701 +0200 ++++ b/src/pulsecore/sample-util.h 2016-04-12 16:24:16.356967580 +0200 +@@ -45,6 +45,33 @@ + + pa_memchunk* pa_silence_memchunk_get(pa_silence_cache *cache, pa_mempool *pool, pa_memchunk* ret, const pa_sample_spec *spec, size_t length); + ++typedef struct pa_volume_ramp_int_t { ++ pa_volume_ramp_type_t type; ++ long length; ++ long left; ++ float start; ++ float end; ++ float curr; ++ pa_volume_t target; ++} pa_volume_ramp_int_t; ++ ++typedef struct pa_cvolume_ramp_int { ++ uint8_t channels; ++ pa_volume_ramp_int_t ramps[PA_CHANNELS_MAX]; ++} pa_cvolume_ramp_int; ++ ++pa_cvolume_ramp_int* pa_cvolume_ramp_convert(const pa_cvolume_ramp *src, pa_cvolume_ramp_int *dst, int sample_rate); ++bool pa_cvolume_ramp_active(pa_cvolume_ramp_int *ramp); ++bool pa_cvolume_ramp_target_active(pa_cvolume_ramp_int *ramp); ++pa_cvolume_ramp_int* pa_cvolume_ramp_start_from(pa_cvolume_ramp_int *src, pa_cvolume_ramp_int *dst); ++pa_cvolume_ramp_int* pa_cvolume_ramp_int_init(pa_cvolume_ramp_int *src, pa_volume_t vol, int channels); ++pa_cvolume * pa_cvolume_ramp_get_targets(pa_cvolume_ramp_int *ramp, pa_cvolume *volume); ++ ++void pa_volume_ramp_memchunk( ++ pa_memchunk *c, ++ const pa_sample_spec *spec, ++ pa_cvolume_ramp_int *ramp); ++ + size_t pa_frame_align(size_t l, const pa_sample_spec *ss) PA_GCC_PURE; + + bool pa_frame_aligned(size_t l, const pa_sample_spec *ss) PA_GCC_PURE; diff --git a/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0011-volume-ramp-adding-volume-ramping-to-sink-input.patch b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0011-volume-ramp-adding-volume-ramping-to-sink-input.patch new file mode 100644 index 000000000..08fb79248 --- /dev/null +++ b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0011-volume-ramp-adding-volume-ramping-to-sink-input.patch @@ -0,0 +1,159 @@ +--- a/src/pulsecore/sink-input.c 2016-04-12 16:50:41.311964935 +0200 ++++ b/src/pulsecore/sink-input.c 2016-04-12 17:22:40.420961732 +0200 +@@ -525,6 +525,11 @@ + reset_callbacks(i); + i->userdata = NULL; + ++ if (data->flags & PA_SINK_INPUT_START_RAMP_MUTED) ++ pa_cvolume_ramp_int_init(&i->ramp, PA_VOLUME_MUTED, data->sample_spec.channels); ++ else ++ pa_cvolume_ramp_int_init(&i->ramp, PA_VOLUME_NORM, data->sample_spec.channels); ++ + i->thread_info.state = i->state; + i->thread_info.attached = false; + pa_atomic_store(&i->thread_info.drained, 1); +@@ -541,6 +546,8 @@ + i->thread_info.playing_for = 0; + i->thread_info.direct_outputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); + ++ i->thread_info.ramp = i->ramp; ++ + pa_assert_se(pa_idxset_put(core->sink_inputs, i, &i->index) == 0); + pa_assert_se(pa_idxset_put(i->sink->inputs, pa_sink_input_ref(i), NULL) == 0); + +@@ -922,6 +929,8 @@ + while (tchunk.length > 0) { + pa_memchunk wchunk; + bool nvfs = need_volume_factor_sink; ++ pa_cvolume target; ++ bool tmp; + + wchunk = tchunk; + pa_memblock_ref(wchunk.memblock); +@@ -958,6 +967,16 @@ + pa_volume_memchunk(&wchunk, &i->sink->sample_spec, &i->volume_factor_sink); + } + ++ /* check for possible volume ramp */ ++ if (pa_cvolume_ramp_active(&i->thread_info.ramp)) { ++ pa_memchunk_make_writable(&wchunk, 0); ++ pa_volume_ramp_memchunk(&wchunk, &i->sink->sample_spec, &(i->thread_info.ramp)); ++ } else if ((tmp = pa_cvolume_ramp_target_active(&(i->thread_info.ramp)))) { ++ pa_memchunk_make_writable(&wchunk, 0); ++ pa_cvolume_ramp_get_targets(&i->thread_info.ramp, &target); ++ pa_volume_memchunk(&wchunk, &i->sink->sample_spec, &target); ++ } ++ + pa_memblockq_push_align(i->thread_info.render_memblockq, &wchunk); + } else { + pa_memchunk rchunk; +@@ -974,6 +993,16 @@ + pa_volume_memchunk(&rchunk, &i->sink->sample_spec, &i->volume_factor_sink); + } + ++ /* check for possible volume ramp */ ++ if (pa_cvolume_ramp_active(&i->thread_info.ramp)) { ++ pa_memchunk_make_writable(&wchunk, 0); ++ pa_volume_ramp_memchunk(&wchunk, &i->sink->sample_spec, &(i->thread_info.ramp)); ++ } else if ((tmp = pa_cvolume_ramp_target_active(&(i->thread_info.ramp)))) { ++ pa_memchunk_make_writable(&wchunk, 0); ++ pa_cvolume_ramp_get_targets(&i->thread_info.ramp, &target); ++ pa_volume_memchunk(&wchunk, &i->sink->sample_spec, &target); ++ } ++ + pa_memblockq_push_align(i->thread_info.render_memblockq, &rchunk); + pa_memblock_unref(rchunk.memblock); + } +@@ -1338,6 +1367,31 @@ + return 0; + } + ++/* Called from main thread */ ++void pa_sink_input_set_volume_ramp( ++ pa_sink_input *i, ++ const pa_cvolume_ramp *ramp, ++ bool send_msg, ++ bool save) { ++ ++ pa_sink_input_assert_ref(i); ++ pa_assert_ctl_context(); ++ pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); ++ pa_assert(ramp); ++ ++ pa_cvolume_ramp_convert(ramp, &i->ramp, i->sample_spec.rate); ++ ++ pa_log_debug("setting volume ramp with target vol:%d and length:%ld", ++ i->ramp.ramps[0].target, ++ i->ramp.ramps[0].length); ++ ++ ++ /* This tells the sink that volume ramp changed */ ++ if (send_msg) ++ pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP, ++ NULL, 0, NULL) == 0); ++} ++ + /* Called from main context */ + static void set_real_ratio(pa_sink_input *i, const pa_cvolume *v) { + pa_sink_input_assert_ref(i); +@@ -1929,6 +1983,12 @@ + } + return 0; + ++ case PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP: ++ /* we have ongoing ramp where we take current start values */ ++ pa_cvolume_ramp_start_from(&i->thread_info.ramp, &i->ramp); ++ i->thread_info.ramp = i->ramp; ++ return 0; ++ + case PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE: + if (i->thread_info.muted != i->muted) { + i->thread_info.muted = i->muted; +--- a/src/pulsecore/sink-input.h 2016-04-12 16:50:46.712964926 +0200 ++++ b/src/pulsecore/sink-input.h 2016-04-12 17:30:24.289960958 +0200 +@@ -59,7 +59,8 @@ + PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND = 256, + PA_SINK_INPUT_NO_CREATE_ON_SUSPEND = 512, + PA_SINK_INPUT_KILL_ON_SUSPEND = 1024, +- PA_SINK_INPUT_PASSTHROUGH = 2048 ++ PA_SINK_INPUT_PASSTHROUGH = 2048, ++ PA_SINK_INPUT_START_RAMP_MUTED = 4096, + } pa_sink_input_flags_t; + + struct pa_sink_input { +@@ -122,6 +123,9 @@ + * this.*/ + bool save_sink:1, save_volume:1, save_muted:1; + ++ /* for volume ramps */ ++ pa_cvolume_ramp_int ramp; ++ + pa_resample_method_t requested_resample_method, actual_resample_method; + + /* Returns the chunk of audio data and drops it from the +@@ -250,6 +254,8 @@ + pa_usec_t requested_sink_latency; + + pa_hashmap *direct_outputs; ++ ++ pa_cvolume_ramp_int ramp; + } thread_info; + + void *userdata; +@@ -266,6 +272,7 @@ + PA_SINK_INPUT_MESSAGE_SET_STATE, + PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY, + PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY, ++ PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP, + PA_SINK_INPUT_MESSAGE_MAX + }; + +@@ -374,6 +381,8 @@ + + void pa_sink_input_set_mute(pa_sink_input *i, bool mute, bool save); + ++void pa_sink_input_set_volume_ramp(pa_sink_input *i, const pa_cvolume_ramp *ramp, bool send_msg, bool save); ++ + void pa_sink_input_update_proplist(pa_sink_input *i, pa_update_mode_t mode, pa_proplist *p); + + pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i); diff --git a/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0012-volume-ramp-add-volume-ramping-to-sink.patch b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0012-volume-ramp-add-volume-ramping-to-sink.patch new file mode 100644 index 000000000..43e8283ef --- /dev/null +++ b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0012-volume-ramp-add-volume-ramping-to-sink.patch @@ -0,0 +1,159 @@ +--- a/src/pulsecore/sink.c 2016-04-12 18:01:23.403957855 +0200 ++++ b/src/pulsecore/sink.c 2016-04-12 18:44:49.677953506 +0200 +@@ -324,6 +324,8 @@ + &s->sample_spec, + 0); + ++ pa_cvolume_ramp_int_init(&s->ramp, PA_VOLUME_NORM, data->sample_spec.channels); ++ + s->thread_info.rtpoll = NULL; + s->thread_info.inputs = pa_hashmap_new_full(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func, NULL, + (pa_free_cb_t) pa_sink_input_unref); +@@ -347,6 +349,8 @@ + s->thread_info.volume_change_extra_delay = core->deferred_volume_extra_delay_usec; + s->thread_info.latency_offset = s->latency_offset; + ++ s->thread_info.ramp = s->ramp; ++ + /* FIXME: This should probably be moved to pa_sink_put() */ + pa_assert_se(pa_idxset_put(core->sinks, s, &s->index) >= 0); + +@@ -1182,6 +1186,7 @@ + + } else if (n == 1) { + pa_cvolume volume; ++ pa_cvolume target; + + *result = info[0].chunk; + pa_memblock_ref(result->memblock); +@@ -1198,9 +1203,20 @@ + result, + &s->sample_spec, + result->length); +- } else if (!pa_cvolume_is_norm(&volume)) { ++ } else if (!pa_cvolume_is_norm(&volume) || pa_cvolume_ramp_target_active(&s->thread_info.ramp) || pa_cvolume_ramp_active(&s->thread_info.ramp)) { + pa_memchunk_make_writable(result, 0); +- pa_volume_memchunk(result, &s->sample_spec, &volume); ++ if (!pa_cvolume_ramp_active(&s->thread_info.ramp)) { ++ if (!pa_cvolume_is_norm(&volume)) ++ pa_volume_memchunk(result, &s->sample_spec, &volume); ++ pa_volume_ramp_memchunk(result, &s->sample_spec, &(s->thread_info.ramp)); ++ } ++ else { ++ if (pa_cvolume_ramp_target_active(&s->thread_info.ramp)) { ++ pa_cvolume_ramp_get_targets(&s->thread_info.ramp, &target); ++ pa_sw_cvolume_multiply(&volume, &volume, &target); ++ } ++ pa_volume_memchunk(result, &s->sample_spec, &volume); ++ } + } + } else { + void *ptr; +@@ -1290,6 +1306,7 @@ + + } else { + void *ptr; ++ pa_cvolume target_vol; + + ptr = pa_memblock_acquire(target->memblock); + +@@ -1299,6 +1316,15 @@ + &s->thread_info.soft_volume, + s->thread_info.soft_muted); + ++ if (pa_cvolume_ramp_target_active(&s->thread_info.ramp) || pa_cvolume_ramp_active(&s->thread_info.ramp)) { ++ if (pa_cvolume_ramp_active(&s->thread_info.ramp)) ++ pa_volume_ramp_memchunk(target, &s->sample_spec, &(s->thread_info.ramp)); ++ else { ++ pa_cvolume_ramp_get_targets(&s->thread_info.ramp, &target_vol); ++ pa_volume_memchunk(target, &s->sample_spec, &target_vol); ++ } ++ } ++ + pa_memblock_release(target->memblock); + } + +@@ -2058,6 +2084,32 @@ + pa_assert_se(pa_asyncmsgq_send(root_sink->asyncmsgq, PA_MSGOBJECT(root_sink), PA_SINK_MESSAGE_SET_SHARED_VOLUME, NULL, 0, NULL) == 0); + } + ++/* Called from main thread */ ++void pa_sink_set_volume_ramp( ++ pa_sink *s, ++ const pa_cvolume_ramp *ramp, ++ bool send_msg, ++ bool save) { ++ ++ pa_sink_assert_ref(s); ++ pa_assert_ctl_context(); ++ pa_assert(PA_SINK_IS_LINKED(s->state)); ++ pa_assert(ramp); ++ ++ /* make sure we don't change the volume when a PASSTHROUGH input is connected ... ++ * ... *except* if we're being invoked to reset the volume to ensure 0 dB gain */ ++ if (pa_sink_is_passthrough(s)) { ++ pa_log_warn("Cannot do volume ramp, Sink is connected to PASSTHROUGH input"); ++ return; ++ } ++ ++ pa_cvolume_ramp_convert(ramp, &s->ramp, s->sample_spec.rate); ++ ++ /* This tells the sink that volume ramp changed */ ++ if (send_msg) ++ pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_VOLUME_RAMP, NULL, 0, NULL) == 0); ++} ++ + /* Called from the io thread if sync volume is used, otherwise from the main thread. + * Only to be called by sink implementor */ + void pa_sink_set_soft_volume(pa_sink *s, const pa_cvolume *volume) { +@@ -2713,6 +2765,12 @@ + sync_input_volumes_within_thread(s); + return 0; + ++ case PA_SINK_MESSAGE_SET_VOLUME_RAMP: ++ /* if we have ongoing ramp where we take current start values */ ++ pa_cvolume_ramp_start_from(&s->thread_info.ramp, &s->ramp); ++ s->thread_info.ramp = s->ramp; ++ return 0; ++ + case PA_SINK_MESSAGE_GET_VOLUME: + + if ((s->flags & PA_SINK_DEFERRED_VOLUME) && s->get_volume) { +--- a/src/pulsecore/sink.h 2016-04-12 18:01:42.117957824 +0200 ++++ b/src/pulsecore/sink.h 2016-04-12 18:23:29.394955642 +0200 +@@ -105,6 +105,9 @@ + pa_cvolume saved_volume; + bool saved_save_volume:1; + ++ /* for volume ramps */ ++ pa_cvolume_ramp_int ramp; ++ + pa_asyncmsgq *asyncmsgq; + + pa_memchunk silence; +@@ -300,6 +303,8 @@ + uint32_t volume_change_safety_margin; + /* Usec delay added to all volume change events, may be negative. */ + int32_t volume_change_extra_delay; ++ ++ pa_cvolume_ramp_int ramp; + } thread_info; + + void *userdata; +@@ -333,6 +338,7 @@ + PA_SINK_MESSAGE_SET_MAX_REQUEST, + PA_SINK_MESSAGE_SET_PORT, + PA_SINK_MESSAGE_UPDATE_VOLUME_AND_MUTE, ++ PA_SINK_MESSAGE_SET_VOLUME_RAMP, + PA_SINK_MESSAGE_SET_LATENCY_OFFSET, + PA_SINK_MESSAGE_MAX + } pa_sink_message_t; +@@ -453,6 +459,8 @@ + void pa_sink_set_mute(pa_sink *sink, bool mute, bool save); + bool pa_sink_get_mute(pa_sink *sink, bool force_refresh); + ++void pa_sink_set_volume_ramp(pa_sink *s, const pa_cvolume_ramp *ramp, bool send_msg, bool save); ++ + bool pa_sink_update_proplist(pa_sink *s, pa_update_mode_t mode, pa_proplist *p); + + int pa_sink_set_port(pa_sink *s, const char *name, bool save); diff --git a/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0013-add-internal-corking-state-for-sink-input.patch b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0013-add-internal-corking-state-for-sink-input.patch new file mode 100644 index 000000000..cb68e26af --- /dev/null +++ b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0013-add-internal-corking-state-for-sink-input.patch @@ -0,0 +1,72 @@ +--- a/src/pulsecore/sink-input.c 2016-04-13 11:44:04.389999429 +0200 ++++ b/src/pulsecore/sink-input.c 2016-04-13 11:52:45.167998560 +0200 +@@ -786,6 +786,9 @@ + update_n_corked(i, state); + i->state = state; + ++ i->corked = false; ++ i->corked_internal = false; ++ + /* We might need to update the sink's volume if we are in flat volume mode. */ + if (pa_sink_flat_volume_enabled(i->sink)) + pa_sink_set_volume(i->sink, NULL, false, i->save_volume); +@@ -1493,13 +1496,38 @@ + } + } + ++static void pa_sink_input_cork_really(pa_sink_input *i, bool b) { ++ pa_sink_input_assert_ref(i); ++ pa_assert_ctl_context(); ++ pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); ++ ++ if (i->corked_internal == false && i->corked == false) ++ b = false; ++ else ++ b = true; ++ ++ sink_input_set_state(i, b ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING); ++} ++ + /* Called from main context */ + void pa_sink_input_cork(pa_sink_input *i, bool b) { + pa_sink_input_assert_ref(i); + pa_assert_ctl_context(); + pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); + +- sink_input_set_state(i, b ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING); ++ i->corked = b; ++ ++ pa_sink_input_cork_really(i, b); ++} ++ ++void pa_sink_input_cork_internal(pa_sink_input *i, bool b) { ++ pa_sink_input_assert_ref(i); ++ pa_assert_ctl_context(); ++ pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); ++ ++ i->corked_internal = b; ++ ++ pa_sink_input_cork_really(i, b); + } + + /* Called from main context */ +--- a/src/pulsecore/sink-input.h 2016-04-13 11:44:28.035999390 +0200 ++++ b/src/pulsecore/sink-input.h 2016-04-13 11:53:56.325998441 +0200 +@@ -126,6 +126,9 @@ + /* for volume ramps */ + pa_cvolume_ramp_int ramp; + ++ bool corked; ++ bool corked_internal; ++ + pa_resample_method_t requested_resample_method, actual_resample_method; + + /* Returns the chunk of audio data and drops it from the +@@ -357,6 +360,7 @@ + void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes, bool rewrite, bool flush, bool dont_rewind_render); + + void pa_sink_input_cork(pa_sink_input *i, bool b); ++void pa_sink_input_cork_internal(pa_sink_input *i, bool b); + + int pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate); + int pa_sink_input_update_rate(pa_sink_input *i); diff --git a/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0020-core-util-Add-pa_join.patch b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0020-core-util-Add-pa_join.patch new file mode 100644 index 000000000..891a5b83a --- /dev/null +++ b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0020-core-util-Add-pa_join.patch @@ -0,0 +1,37 @@ +--- a/src/pulsecore/core-util.c 2016-04-13 16:17:33.314016929 +0200 ++++ b/src/pulsecore/core-util.c 2016-04-13 16:18:31.186016833 +0200 +@@ -1104,6 +1104,24 @@ + return pa_xstrndup(current, l); + } + ++char *pa_join(const char * const *strings, unsigned n_strings, const char *delimiter) { ++ pa_strbuf *buf; ++ unsigned i; ++ ++ pa_assert(strings || n_strings == 0); ++ ++ buf = pa_strbuf_new(); ++ ++ for (i = 0; i < n_strings; i++) { ++ if (i > 0 && delimiter) ++ pa_strbuf_puts(buf, delimiter); ++ ++ pa_strbuf_puts(buf, strings[i]); ++ } ++ ++ return pa_strbuf_tostring_free(buf); ++} ++ + PA_STATIC_TLS_DECLARE(signame, pa_xfree); + + /* Return the name of an UNIX signal. Similar to Solaris sig2str() */ +--- a/src/pulsecore/core-util.h 2016-04-13 16:17:39.177016919 +0200 ++++ b/src/pulsecore/core-util.h 2016-04-13 16:19:09.141016769 +0200 +@@ -108,6 +108,7 @@ + char *pa_split(const char *c, const char*delimiters, const char **state); + const char *pa_split_in_place(const char *c, const char*delimiters, int *n, const char **state); + char *pa_split_spaces(const char *c, const char **state); ++char *pa_join(const char * const *strings, unsigned n_strings, const char *delimiter); + + char *pa_strip_nl(char *s); + char *pa_strip(char *s); diff --git a/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0021-dynarray-Add-pa_dynarray_get_raw_array.patch b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0021-dynarray-Add-pa_dynarray_get_raw_array.patch new file mode 100644 index 000000000..040913c8f --- /dev/null +++ b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0021-dynarray-Add-pa_dynarray_get_raw_array.patch @@ -0,0 +1,21 @@ +--- a/src/pulsecore/dynarray.c 2016-04-13 16:25:38.628016119 +0200 ++++ b/src/pulsecore/dynarray.c 2016-04-13 16:26:54.694015992 +0200 +@@ -91,3 +91,9 @@ + + return array->n_entries; + } ++ ++void * const *pa_dynarray_get_raw_array(pa_dynarray *array) { ++ pa_assert(array); ++ ++ return array->data; ++} +--- a/src/pulsecore/dynarray.h 2016-04-13 16:25:43.225016112 +0200 ++++ b/src/pulsecore/dynarray.h 2016-04-13 16:27:47.414015904 +0200 +@@ -52,5 +52,5 @@ + void *pa_dynarray_steal_last(pa_dynarray *array); + + unsigned pa_dynarray_size(pa_dynarray *array); +- ++void * const *pa_dynarray_get_raw_array(pa_dynarray *array); + #endif diff --git a/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0022-device-port-Add-pa_device_port.active.patch b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0022-device-port-Add-pa_device_port.active.patch new file mode 100644 index 000000000..4a8143f61 --- /dev/null +++ b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0022-device-port-Add-pa_device_port.active.patch @@ -0,0 +1,198 @@ +--- a/src/pulsecore/core.h 2016-04-13 16:38:56.392014788 +0200 ++++ b/src/pulsecore/core.h 2016-04-13 16:41:50.331014498 +0200 +@@ -125,6 +125,7 @@ + PA_CORE_HOOK_CARD_PROFILE_ADDED, + PA_CORE_HOOK_CARD_PROFILE_AVAILABLE_CHANGED, + PA_CORE_HOOK_PORT_AVAILABLE_CHANGED, ++ PA_CORE_HOOK_PORT_ACTIVE_CHANGED, + PA_CORE_HOOK_PORT_LATENCY_OFFSET_CHANGED, + PA_CORE_HOOK_MAX + } pa_core_hook_t; +--- a/src/pulsecore/device-port.c 2016-04-13 16:39:37.411014719 +0200 ++++ b/src/pulsecore/device-port.c 2016-04-13 17:06:47.393011999 +0200 +@@ -175,6 +175,21 @@ + pa_hook_fire(&core->hooks[PA_CORE_HOOK_PORT_LATENCY_OFFSET_CHANGED], p); + } + ++void pa_device_port_active_changed(pa_device_port *port, bool new_active) { ++ bool old_active; ++ ++ pa_assert(port); ++ ++ old_active = port->active; ++ ++ if (new_active == old_active) ++ return; ++ ++ port->active = new_active; ++ pa_log_debug("Port %s %s.", port->name, new_active ? "activated" : "deactivated"); ++ pa_hook_fire(&port->core->hooks[PA_CORE_HOOK_PORT_ACTIVE_CHANGED], port); ++} ++ + pa_device_port *pa_device_port_find_best(pa_hashmap *ports) + { + void *state; +--- a/src/pulsecore/device-port.h 2016-04-13 16:39:51.603014696 +0200 ++++ b/src/pulsecore/device-port.h 2016-04-13 17:07:12.649011957 +0200 +@@ -46,6 +46,7 @@ + + unsigned priority; + pa_available_t available; /* PA_AVAILABLE_UNKNOWN, PA_AVAILABLE_NO or PA_AVAILABLE_YES */ ++ bool active; + + pa_proplist *proplist; + pa_hashmap *profiles; /* Does not own the profiles */ +--- a/src/pulsecore/sink.c 2016-04-13 16:40:11.131014663 +0200 ++++ b/src/pulsecore/sink.c 2016-04-13 17:14:30.963011225 +0200 +@@ -658,6 +658,9 @@ + else + pa_assert_se(sink_set_state(s, PA_SINK_IDLE) == 0); + ++ if (s->active_port) ++ pa_device_port_active_changed(s->active_port, true); ++ + pa_source_put(s->monitor_source); + + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_NEW, s->index); +@@ -685,6 +688,9 @@ + if (linked) + pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK], s); + ++ if (s->active_port) ++ pa_device_port_active_changed(s->active_port, false); ++ + if (s->state != PA_SINK_UNLINKED) + pa_namereg_unregister(s->core, s->name); + pa_idxset_remove_by_data(s->core->sinks, s, NULL); +@@ -3297,6 +3303,7 @@ + /* Called from main context */ + int pa_sink_set_port(pa_sink *s, const char *name, bool save) { + pa_device_port *port; ++ pa_device_port *old_port; + int ret; + + pa_sink_assert_ref(s); +@@ -3313,11 +3320,15 @@ + if (!(port = pa_hashmap_get(s->ports, name))) + return -PA_ERR_NOENTITY; + +- if (s->active_port == port) { ++ old_port = s->active_port; ++ ++ if (port == old_port) { + s->save_port = s->save_port || save; + return 0; + } + ++ pa_device_port_active_changed(old_port, false); ++ + if (s->flags & PA_SINK_DEFERRED_VOLUME) { + struct sink_message_set_port msg = { .port = port, .ret = 0 }; + pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_PORT, &msg, 0, NULL) == 0); +@@ -3326,17 +3337,26 @@ + else + ret = s->set_port(s, port); + +- if (ret < 0) +- return -PA_ERR_NOENTITY; ++ if (ret < 0) { ++ pa_log("Failed to set the port of sink %s from %s to %s.", s->name, old_port->name, port->name); ++ ++ /* We don't know the real state of the device, but let's assume that ++ * the old port is still active, because s->active_port is left to ++ * point to the old port anyway. */ ++ pa_device_port_active_changed(old_port, true); ++ ++ return ret; ++ } + + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); + +- pa_log_info("Changed port of sink %u \"%s\" to %s", s->index, s->name, port->name); ++ pa_log_info("Changed port of sink %u \"%s\" from %s to %s", s->index, s->name, old_port->name, port->name); + + s->active_port = port; + s->save_port = save; + + pa_sink_set_latency_offset(s, s->active_port->latency_offset); ++ pa_device_port_active_changed(port, true); + + pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PORT_CHANGED], s); + +--- a/src/pulsecore/source.c 2016-04-13 16:40:25.290014640 +0200 ++++ b/src/pulsecore/source.c 2016-04-13 17:21:26.051010533 +0200 +@@ -603,6 +603,9 @@ + else + pa_assert_se(source_set_state(s, PA_SOURCE_IDLE) == 0); + ++ if (s->active_port) ++ pa_device_port_active_changed(s->active_port, true); ++ + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_NEW, s->index); + pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PUT], s); + } +@@ -623,6 +626,9 @@ + if (linked) + pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], s); + ++ if (s->active_port) ++ pa_device_port_active_changed(s->active_port, false); ++ + if (s->state != PA_SOURCE_UNLINKED) + pa_namereg_unregister(s->core, s->name); + pa_idxset_remove_by_data(s->core->sources, s, NULL); +@@ -2576,6 +2582,7 @@ + /* Called from main context */ + int pa_source_set_port(pa_source *s, const char *name, bool save) { + pa_device_port *port; ++ pa_device_port *old_port; + int ret; + + pa_source_assert_ref(s); +@@ -2592,11 +2599,15 @@ + if (!(port = pa_hashmap_get(s->ports, name))) + return -PA_ERR_NOENTITY; + +- if (s->active_port == port) { ++ old_port = s->active_port; ++ ++ if (port == old_port) { + s->save_port = s->save_port || save; + return 0; + } + ++ pa_device_port_active_changed(old_port, false); ++ + if (s->flags & PA_SOURCE_DEFERRED_VOLUME) { + struct source_message_set_port msg = { .port = port, .ret = 0 }; + pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_PORT, &msg, 0, NULL) == 0); +@@ -2605,16 +2616,26 @@ + else + ret = s->set_port(s, port); + +- if (ret < 0) +- return -PA_ERR_NOENTITY; ++ if (ret < 0) { ++ pa_log("Failed to set the port of sink %s from %s to %s.", s->name, old_port->name, port->name); ++ ++ /* We don't know the real state of the device, but let's assume that ++ * the old port is still active, because s->active_port is left to ++ * point to the old port anyway. */ ++ pa_device_port_active_changed(old_port, true); ++ ++ return ret; ++ } + + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); + +- pa_log_info("Changed port of source %u \"%s\" to %s", s->index, s->name, port->name); ++ pa_log_info("Changed port of source %u \"%s\" from %s to %s", s->index, s->name, old_port->name, port->name); + + s->active_port = port; + s->save_port = save; + ++ pa_device_port_active_changed(port, true); ++ + pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PORT_CHANGED], s); + + return 0; diff --git a/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0030-volume-api-Add-libvolume-api.patch b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0030-volume-api-Add-libvolume-api.patch new file mode 100644 index 000000000..b904ac315 --- /dev/null +++ b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0030-volume-api-Add-libvolume-api.patch @@ -0,0 +1,6118 @@ +From 0223ac3e092249c792bedcab2bf5dbaec443f960 Mon Sep 17 00:00:00 2001 +From: Tanu Kaskinen +Date: Wed, 21 May 2014 11:51:27 +0300 +Subject: [PATCH 1/1] volume-api: Add libvolume-api.so + +This library implements the "core" of the new volume system, which +will be used by several modules. + +Change-Id: Ib25ada1392e83237a3908e6064ee0ad6dff7afaf +Signed-off-by: Jaska Uimonen +--- + Makefile.am | 3 + + src/Makefile.am | 19 +- + src/map-file | 15 + + src/modules/volume-api/audio-group.c | 448 +++++++++++++ + src/modules/volume-api/audio-group.h | 85 +++ + src/modules/volume-api/binding.c | 386 +++++++++++ + src/modules/volume-api/binding.h | 128 ++++ + src/modules/volume-api/bvolume.h | 43 ++ + src/modules/volume-api/device-creator.c | 1108 +++++++++++++++++++++++++++++++ + src/modules/volume-api/device-creator.h | 32 + + src/modules/volume-api/device.c | 293 ++++++++ + src/modules/volume-api/device.h | 76 +++ + src/modules/volume-api/mute-control.c | 306 +++++++++ + src/modules/volume-api/mute-control.h | 102 +++ + src/modules/volume-api/sstream.c | 366 ++++++++++ + src/modules/volume-api/sstream.h | 108 +++ + src/modules/volume-api/stream-creator.c | 691 +++++++++++++++++++ + src/modules/volume-api/stream-creator.h | 32 + + src/modules/volume-api/volume-api.c | 647 ++++++++++++++++++ + src/modules/volume-api/volume-api.h | 163 +++++ + src/modules/volume-api/volume-control.c | 363 ++++++++++ + src/modules/volume-api/volume-control.h | 112 ++++ + src/pulse/ext-volume-api.c | 275 ++++++++ + src/pulse/ext-volume-api.h | 68 ++ + 24 files changed, 5868 insertions(+), 1 deletion(-) + create mode 100644 src/modules/volume-api/audio-group.c + create mode 100644 src/modules/volume-api/audio-group.h + create mode 100644 src/modules/volume-api/binding.c + create mode 100644 src/modules/volume-api/binding.h + create mode 100644 src/modules/volume-api/bvolume.h + create mode 100644 src/modules/volume-api/device-creator.c + create mode 100644 src/modules/volume-api/device-creator.h + create mode 100644 src/modules/volume-api/device.c + create mode 100644 src/modules/volume-api/device.h + create mode 100644 src/modules/volume-api/mute-control.c + create mode 100644 src/modules/volume-api/mute-control.h + create mode 100644 src/modules/volume-api/sstream.c + create mode 100644 src/modules/volume-api/sstream.h + create mode 100644 src/modules/volume-api/stream-creator.c + create mode 100644 src/modules/volume-api/stream-creator.h + create mode 100644 src/modules/volume-api/volume-api.c + create mode 100644 src/modules/volume-api/volume-api.h + create mode 100644 src/modules/volume-api/volume-control.c + create mode 100644 src/modules/volume-api/volume-control.h + create mode 100644 src/pulse/ext-volume-api.c + create mode 100644 src/pulse/ext-volume-api.h + +diff --git a/Makefile.am b/Makefile.am +index 9431d4a..cf4a648 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -57,6 +57,9 @@ + moduledevinternal_DATA = src/pulse/internal.h src/pulse/client-conf.h src/pulse/fork-detect.h + moduledevinternaldir = $(includedir)/pulsemodule/pulse + ++moduledevvolumeapi_DATA = $(top_srcdir)/src/modules/volume-api/*.h ++moduledevvolumeapidir = $(includedir)/pulsemodule/modules/volume-api ++ + if HAVE_GLIB20 + pkgconfig_DATA += \ + libpulse-mainloop-glib.pc +diff --git a/src/Makefile.am b/src/Makefile.am +index 22b9b81..bc41dca 100644 +--- a/src/Makefile.am 2016-04-13 15:51:34.439019531 +0200 ++++ b/src/Makefile.am 2016-04-13 15:53:03.721019382 +0200 +@@ -792,6 +792,7 @@ + pulse/ext-device-manager.h \ + pulse/ext-device-restore.h \ + pulse/ext-stream-restore.h \ ++ pulse/ext-volume-api.h \ + pulse/format.h \ + pulse/gccmacro.h \ + pulse/introspect.h \ +@@ -838,6 +839,7 @@ + pulse/ext-device-manager.c pulse/ext-device-manager.h \ + pulse/ext-device-restore.c pulse/ext-device-restore.h \ + pulse/ext-stream-restore.c pulse/ext-stream-restore.h \ ++ pulse/ext-volume-api.c pulse/ext-volume-api.h \ + pulse/format.c pulse/format.h \ + pulse/gccmacro.h \ + pulse/internal.h \ +@@ -1018,7 +1020,8 @@ modlibexec_LTLIBRARIES = \ + libprotocol-cli.la \ + libprotocol-simple.la \ + libprotocol-http.la \ +- libprotocol-native.la ++ libprotocol-native.la \ ++ libvolume-api.la + + if HAVE_WEBRTC + modlibexec_LTLIBRARIES += libwebrtc-util.la +@@ -1065,6 +1068,20 @@ libprotocol_native_la_CFLAGS += $(DBUS_CFLAGS) + libprotocol_native_la_LIBADD += $(DBUS_LIBS) + endif + ++libvolume_api_la_SOURCES = \ ++ modules/volume-api/audio-group.c modules/volume-api/audio-group.h \ ++ modules/volume-api/binding.c modules/volume-api/binding.h \ ++ modules/volume-api/bvolume.h \ ++ modules/volume-api/device.c modules/volume-api/device.h \ ++ modules/volume-api/device-creator.c modules/volume-api/device-creator.h \ ++ modules/volume-api/mute-control.c modules/volume-api/mute-control.h \ ++ modules/volume-api/sstream.c modules/volume-api/sstream.h \ ++ modules/volume-api/stream-creator.c modules/volume-api/stream-creator.h \ ++ modules/volume-api/volume-api.c modules/volume-api/volume-api.h \ ++ modules/volume-api/volume-control.c modules/volume-api/volume-control.h ++libvolume_api_la_LDFLAGS = $(AM_LDFLAGS) -avoid-version ++libvolume_api_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINOR@.la libpulsecommon-@PA_MAJORMINOR@.la libpulse.la ++ + if HAVE_ESOUND + libprotocol_esound_la_SOURCES = pulsecore/protocol-esound.c pulsecore/protocol-esound.h pulsecore/esound.h + libprotocol_esound_la_LDFLAGS = $(AM_LDFLAGS) -avoid-version +diff --git a/src/map-file b/src/map-file +index fbf3f22..1f64a2f 100644 +--- a/src/map-file ++++ b/src/map-file +@@ -172,6 +172,21 @@ + pa_ext_stream_restore_subscribe; + pa_ext_stream_restore_test; + pa_ext_stream_restore_write; ++pa_ext_volume_api_balance_valid; ++pa_ext_volume_api_bvolume_copy_balance; ++pa_ext_volume_api_bvolume_get_left_right_balance; ++pa_ext_volume_api_bvolume_get_rear_front_balance; ++pa_ext_volume_api_bvolume_equal; ++pa_ext_volume_api_bvolume_from_cvolume; ++pa_ext_volume_api_bvolume_init_invalid; ++pa_ext_volume_api_bvolume_init_mono; ++pa_ext_volume_api_bvolume_remap; ++pa_ext_volume_api_bvolume_reset_balance; ++pa_ext_volume_api_bvolume_set_left_right_balance; ++pa_ext_volume_api_bvolume_set_rear_front_balance; ++pa_ext_volume_api_bvolume_snprint_balance; ++pa_ext_volume_api_bvolume_to_cvolume; ++pa_ext_volume_api_bvolume_valid; + pa_format_info_copy; + pa_format_info_free; + pa_format_info_from_string; +diff --git a/src/modules/volume-api/audio-group.c b/src/modules/volume-api/audio-group.c +new file mode 100644 +index 0000000..76bfa69 +--- /dev/null ++++ b/src/modules/volume-api/audio-group.c +@@ -0,0 +1,448 @@ ++/*** ++ This file is part of PulseAudio. ++ ++ Copyright 2014 Intel Corporation ++ ++ PulseAudio is free software; you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as published ++ by the Free Software Foundation; either version 2.1 of the License, ++ or (at your option) any later version. ++ ++ PulseAudio 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 Lesser General Public License ++ along with PulseAudio; if not, write to the Free Software ++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ USA. ++***/ ++ ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ ++#include "audio-group.h" ++ ++#include ++ ++#include ++ ++int pa_audio_group_new(pa_volume_api *api, const char *name, const char *description, pa_audio_group **group) { ++ pa_audio_group *group_local; ++ int r; ++ ++ pa_assert(api); ++ pa_assert(name); ++ pa_assert(description); ++ pa_assert(group); ++ ++ group_local = pa_xnew0(pa_audio_group, 1); ++ group_local->volume_api = api; ++ group_local->index = pa_volume_api_allocate_audio_group_index(api); ++ ++ r = pa_volume_api_register_name(api, name, true, &group_local->name); ++ if (r < 0) ++ goto fail; ++ ++ group_local->description = pa_xstrdup(description); ++ group_local->proplist = pa_proplist_new(); ++ group_local->volume_streams = pa_hashmap_new(NULL, NULL); ++ group_local->mute_streams = pa_hashmap_new(NULL, NULL); ++ ++ *group = group_local; ++ ++ return 0; ++ ++fail: ++ pa_audio_group_free(group_local); ++ ++ return r; ++} ++ ++void pa_audio_group_put(pa_audio_group *group) { ++ const char *prop_key; ++ void *state = NULL; ++ ++ pa_assert(group); ++ ++ pa_volume_api_add_audio_group(group->volume_api, group); ++ ++ group->linked = true; ++ ++ pa_log_debug("Created audio group #%u.", group->index); ++ pa_log_debug(" Name: %s", group->name); ++ pa_log_debug(" Description: %s", group->description); ++ pa_log_debug(" Volume control: %s", group->volume_control ? group->volume_control->name : "(unset)"); ++ pa_log_debug(" Mute control: %s", group->mute_control ? group->mute_control->name : "(unset)"); ++ pa_log_debug(" Properties:"); ++ ++ while ((prop_key = pa_proplist_iterate(group->proplist, &state))) ++ pa_log_debug(" %s = %s", prop_key, pa_strnull(pa_proplist_gets(group->proplist, prop_key))); ++ ++ pa_hook_fire(&group->volume_api->hooks[PA_VOLUME_API_HOOK_AUDIO_GROUP_PUT], group); ++} ++ ++void pa_audio_group_unlink(pa_audio_group *group) { ++ pas_stream *stream; ++ ++ pa_assert(group); ++ ++ if (group->unlinked) { ++ pa_log_debug("Unlinking audio group %s (already unlinked, this is a no-op).", group->name); ++ return; ++ } ++ ++ group->unlinked = true; ++ ++ pa_log_debug("Unlinking audio group %s.", group->name); ++ ++ if (group->linked) ++ pa_hook_fire(&group->volume_api->hooks[PA_VOLUME_API_HOOK_AUDIO_GROUP_UNLINK], group); ++ ++ pa_volume_api_remove_audio_group(group->volume_api, group); ++ ++ while ((stream = pa_hashmap_first(group->mute_streams))) ++ pas_stream_set_audio_group_for_mute(stream, NULL); ++ ++ while ((stream = pa_hashmap_first(group->volume_streams))) ++ pas_stream_set_audio_group_for_volume(stream, NULL); ++ ++ if (group->mute_control_binding) { ++ pa_binding_free(group->mute_control_binding); ++ group->mute_control_binding = NULL; ++ } ++ ++ if (group->volume_control_binding) { ++ pa_binding_free(group->volume_control_binding); ++ group->volume_control_binding = NULL; ++ } ++ ++ pa_audio_group_set_have_own_mute_control(group, false); ++ pa_audio_group_set_have_own_volume_control(group, false); ++ ++ if (group->mute_control) { ++ pa_mute_control_remove_audio_group(group->mute_control, group); ++ group->mute_control = NULL; ++ } ++ ++ if (group->volume_control) { ++ pa_volume_control_remove_audio_group(group->volume_control, group); ++ group->volume_control = NULL; ++ } ++} ++ ++void pa_audio_group_free(pa_audio_group *group) { ++ pa_assert(group); ++ ++ if (!group->unlinked) ++ pa_audio_group_unlink(group); ++ ++ if (group->mute_streams) ++ pa_hashmap_free(group->mute_streams); ++ ++ if (group->volume_streams) ++ pa_hashmap_free(group->volume_streams); ++ ++ if (group->proplist) ++ pa_proplist_free(group->proplist); ++ ++ pa_xfree(group->description); ++ ++ if (group->name) ++ pa_volume_api_unregister_name(group->volume_api, group->name); ++ ++ pa_xfree(group); ++} ++ ++const char *pa_audio_group_get_name(pa_audio_group *group) { ++ pa_assert(group); ++ ++ return group->name; ++} ++ ++static int volume_control_set_volume_cb(pa_volume_control *control, const pa_bvolume *volume, bool set_volume, ++ bool set_balance) { ++ pa_audio_group *group; ++ pas_stream *stream; ++ void *state; ++ ++ pa_assert(control); ++ pa_assert(volume); ++ ++ group = control->userdata; ++ ++ PA_HASHMAP_FOREACH(stream, group->volume_streams, state) { ++ if (stream->own_volume_control) ++ pa_volume_control_set_volume(stream->own_volume_control, volume, set_volume, set_balance); ++ } ++ ++ return 0; ++} ++ ++static void volume_control_set_initial_volume_cb(pa_volume_control *control) { ++ pa_audio_group *group; ++ pas_stream *stream; ++ void *state; ++ ++ pa_assert(control); ++ ++ group = control->userdata; ++ ++ PA_HASHMAP_FOREACH(stream, group->volume_streams, state) { ++ if (stream->own_volume_control) ++ pa_volume_control_set_volume(stream->own_volume_control, &control->volume, true, true); ++ } ++} ++ ++void pa_audio_group_set_have_own_volume_control(pa_audio_group *group, bool have) { ++ pa_assert(group); ++ ++ if (have == group->have_own_volume_control) ++ return; ++ ++ if (have) { ++ pa_bvolume initial_volume; ++ ++ if (group->volume_api->core->flat_volumes) ++ /* Usually the initial volume should get overridden by some module ++ * that manages audio group volume levels, but if there's no such ++ * module, let's try to avoid too high volume in flat volume ++ * mode. */ ++ pa_bvolume_init_mono(&initial_volume, 0.3 * PA_VOLUME_NORM); ++ else ++ pa_bvolume_init_mono(&initial_volume, PA_VOLUME_NORM); ++ ++ pa_assert(!group->own_volume_control); ++ group->own_volume_control = pa_volume_control_new(group->volume_api, "audio-group-volume-control", ++ group->description, false, false); ++ pa_volume_control_set_owner_audio_group(group->own_volume_control, group); ++ group->own_volume_control->set_volume = volume_control_set_volume_cb; ++ group->own_volume_control->userdata = group; ++ pa_volume_control_put(group->own_volume_control, &initial_volume, volume_control_set_initial_volume_cb); ++ } else { ++ pa_volume_control_free(group->own_volume_control); ++ group->own_volume_control = NULL; ++ } ++ ++ group->have_own_volume_control = have; ++} ++ ++static int mute_control_set_mute_cb(pa_mute_control *control, bool mute) { ++ pa_audio_group *group; ++ pas_stream *stream; ++ void *state; ++ ++ pa_assert(control); ++ ++ group = control->userdata; ++ ++ PA_HASHMAP_FOREACH(stream, group->mute_streams, state) { ++ if (stream->own_mute_control) ++ pa_mute_control_set_mute(stream->own_mute_control, mute); ++ } ++ ++ return 0; ++} ++ ++static void mute_control_set_initial_mute_cb(pa_mute_control *control) { ++ pa_audio_group *group; ++ pas_stream *stream; ++ void *state; ++ ++ pa_assert(control); ++ ++ group = control->userdata; ++ ++ PA_HASHMAP_FOREACH(stream, group->mute_streams, state) { ++ if (stream->own_mute_control) ++ pa_mute_control_set_mute(stream->own_mute_control, control->mute); ++ } ++} ++ ++void pa_audio_group_set_have_own_mute_control(pa_audio_group *group, bool have) { ++ pa_assert(group); ++ ++ if (have == group->have_own_mute_control) ++ return; ++ ++ group->have_own_mute_control = have; ++ ++ if (have) { ++ pa_assert(!group->own_mute_control); ++ group->own_mute_control = pa_mute_control_new(group->volume_api, "audio-group-mute-control", group->description); ++ pa_mute_control_set_owner_audio_group(group->own_mute_control, group); ++ group->own_mute_control->set_mute = mute_control_set_mute_cb; ++ group->own_mute_control->userdata = group; ++ pa_mute_control_put(group->own_mute_control, false, true, mute_control_set_initial_mute_cb); ++ } else { ++ pa_mute_control_free(group->own_mute_control); ++ group->own_mute_control = NULL; ++ } ++} ++ ++static void set_volume_control_internal(pa_audio_group *group, pa_volume_control *control) { ++ pa_volume_control *old_control; ++ ++ pa_assert(group); ++ ++ old_control = group->volume_control; ++ ++ if (control == old_control) ++ return; ++ ++ if (old_control) ++ pa_volume_control_remove_audio_group(old_control, group); ++ ++ group->volume_control = control; ++ ++ if (control) ++ pa_volume_control_add_audio_group(control, group); ++ ++ if (!group->linked || group->unlinked) ++ return; ++ ++ pa_log_debug("The volume control of audio group %s changed from %s to %s.", group->name, ++ old_control ? old_control->name : "(unset)", control ? control->name : "(unset)"); ++ ++ pa_hook_fire(&group->volume_api->hooks[PA_VOLUME_API_HOOK_AUDIO_GROUP_VOLUME_CONTROL_CHANGED], group); ++} ++ ++void pa_audio_group_set_volume_control(pa_audio_group *group, pa_volume_control *control) { ++ pa_assert(group); ++ ++ if (group->volume_control_binding) { ++ pa_binding_free(group->volume_control_binding); ++ group->volume_control_binding = NULL; ++ } ++ ++ set_volume_control_internal(group, control); ++} ++ ++static void set_mute_control_internal(pa_audio_group *group, pa_mute_control *control) { ++ pa_mute_control *old_control; ++ ++ pa_assert(group); ++ ++ old_control = group->mute_control; ++ ++ if (control == old_control) ++ return; ++ ++ if (old_control) ++ pa_mute_control_remove_audio_group(old_control, group); ++ ++ group->mute_control = control; ++ ++ if (control) ++ pa_mute_control_add_audio_group(control, group); ++ ++ if (!group->linked || group->unlinked) ++ return; ++ ++ pa_log_debug("The mute control of audio group %s changed from %s to %s.", group->name, ++ old_control ? old_control->name : "(unset)", control ? control->name : "(unset)"); ++ ++ pa_hook_fire(&group->volume_api->hooks[PA_VOLUME_API_HOOK_AUDIO_GROUP_MUTE_CONTROL_CHANGED], group); ++} ++ ++void pa_audio_group_set_mute_control(pa_audio_group *group, pa_mute_control *control) { ++ pa_assert(group); ++ ++ if (group->mute_control_binding) { ++ pa_binding_free(group->mute_control_binding); ++ group->mute_control_binding = NULL; ++ } ++ ++ set_mute_control_internal(group, control); ++} ++ ++void pa_audio_group_bind_volume_control(pa_audio_group *group, pa_binding_target_info *target_info) { ++ pa_binding_owner_info owner_info = { ++ .userdata = group, ++ .set_value = (pa_binding_set_value_cb_t) set_volume_control_internal, ++ }; ++ ++ pa_assert(group); ++ pa_assert(target_info); ++ ++ if (group->volume_control_binding) ++ pa_binding_free(group->volume_control_binding); ++ ++ group->volume_control_binding = pa_binding_new(group->volume_api, &owner_info, target_info); ++} ++ ++void pa_audio_group_bind_mute_control(pa_audio_group *group, pa_binding_target_info *target_info) { ++ pa_binding_owner_info owner_info = { ++ .userdata = group, ++ .set_value = (pa_binding_set_value_cb_t) set_mute_control_internal, ++ }; ++ ++ pa_assert(group); ++ pa_assert(target_info); ++ ++ if (group->mute_control_binding) ++ pa_binding_free(group->mute_control_binding); ++ ++ group->mute_control_binding = pa_binding_new(group->volume_api, &owner_info, target_info); ++} ++ ++void pa_audio_group_add_volume_stream(pa_audio_group *group, pas_stream *stream) { ++ pa_assert(group); ++ pa_assert(stream); ++ ++ pa_assert_se(pa_hashmap_put(group->volume_streams, stream, stream) >= 0); ++ ++ if (stream->own_volume_control && group->own_volume_control) ++ pa_volume_control_set_volume(stream->own_volume_control, &group->own_volume_control->volume, true, true); ++ ++ pa_log_debug("Stream %s added to audio group %s (volume).", stream->name, group->name); ++} ++ ++void pa_audio_group_remove_volume_stream(pa_audio_group *group, pas_stream *stream) { ++ pa_assert(group); ++ pa_assert(stream); ++ ++ pa_assert_se(pa_hashmap_remove(group->volume_streams, stream)); ++ ++ pa_log_debug("Stream %s removed from audio group %s (volume).", stream->name, group->name); ++} ++ ++void pa_audio_group_add_mute_stream(pa_audio_group *group, pas_stream *stream) { ++ pa_assert(group); ++ pa_assert(stream); ++ ++ pa_assert_se(pa_hashmap_put(group->mute_streams, stream, stream) >= 0); ++ ++ if (stream->own_mute_control && group->own_mute_control) ++ pa_mute_control_set_mute(stream->own_mute_control, group->own_mute_control->mute); ++ ++ pa_log_debug("Stream %s added to audio group %s (mute).", stream->name, group->name); ++} ++ ++void pa_audio_group_remove_mute_stream(pa_audio_group *group, pas_stream *stream) { ++ pa_assert(group); ++ pa_assert(stream); ++ ++ pa_assert_se(pa_hashmap_remove(group->mute_streams, stream)); ++ ++ pa_log_debug("Stream %s removed from audio group %s (mute).", stream->name, group->name); ++} ++ ++pa_binding_target_type *pa_audio_group_create_binding_target_type(pa_volume_api *api) { ++ pa_binding_target_type *type; ++ ++ pa_assert(api); ++ ++ type = pa_binding_target_type_new(PA_AUDIO_GROUP_BINDING_TARGET_TYPE, api->audio_groups, ++ &api->hooks[PA_VOLUME_API_HOOK_AUDIO_GROUP_PUT], ++ &api->hooks[PA_VOLUME_API_HOOK_AUDIO_GROUP_UNLINK], ++ (pa_binding_target_type_get_name_cb_t) pa_audio_group_get_name); ++ pa_binding_target_type_add_field(type, PA_AUDIO_GROUP_BINDING_TARGET_FIELD_VOLUME_CONTROL, ++ PA_BINDING_CALCULATE_FIELD_OFFSET(pa_audio_group, volume_control)); ++ pa_binding_target_type_add_field(type, PA_AUDIO_GROUP_BINDING_TARGET_FIELD_MUTE_CONTROL, ++ PA_BINDING_CALCULATE_FIELD_OFFSET(pa_audio_group, mute_control)); ++ ++ return type; ++} +diff --git a/src/modules/volume-api/audio-group.h b/src/modules/volume-api/audio-group.h +new file mode 100644 +index 0000000..41591ba +--- /dev/null ++++ b/src/modules/volume-api/audio-group.h +@@ -0,0 +1,85 @@ ++#ifndef fooaudiogrouphfoo ++#define fooaudiogrouphfoo ++ ++/*** ++ This file is part of PulseAudio. ++ ++ Copyright 2014 Intel Corporation ++ ++ PulseAudio is free software; you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as published ++ by the Free Software Foundation; either version 2.1 of the License, ++ or (at your option) any later version. ++ ++ PulseAudio 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 Lesser General Public License ++ along with PulseAudio; if not, write to the Free Software ++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ USA. ++***/ ++ ++#include ++#include ++#include ++ ++#include ++ ++#include ++ ++typedef struct pa_audio_group pa_audio_group; ++ ++#define PA_AUDIO_GROUP_BINDING_TARGET_TYPE "AudioGroup" ++#define PA_AUDIO_GROUP_BINDING_TARGET_FIELD_VOLUME_CONTROL "volume_control" ++#define PA_AUDIO_GROUP_BINDING_TARGET_FIELD_MUTE_CONTROL "mute_control" ++ ++struct pa_audio_group { ++ pa_volume_api *volume_api; ++ uint32_t index; ++ const char *name; ++ char *description; ++ pa_proplist *proplist; ++ pa_volume_control *volume_control; ++ pa_mute_control *mute_control; ++ bool have_own_volume_control; ++ bool have_own_mute_control; ++ pa_volume_control *own_volume_control; ++ pa_mute_control *own_mute_control; ++ ++ pa_binding *volume_control_binding; ++ pa_binding *mute_control_binding; ++ pa_hashmap *volume_streams; /* pas_stream -> pas_stream (hashmap-as-a-set) */ ++ pa_hashmap *mute_streams; /* pas_stream -> pas_stream (hashmap-as-a-set) */ ++ ++ bool linked; ++ bool unlinked; ++}; ++ ++int pa_audio_group_new(pa_volume_api *api, const char *name, const char *description, pa_audio_group **group); ++void pa_audio_group_put(pa_audio_group *group); ++void pa_audio_group_unlink(pa_audio_group *group); ++void pa_audio_group_free(pa_audio_group *group); ++ ++const char *pa_audio_group_get_name(pa_audio_group *group); ++ ++/* Called by policy modules. */ ++void pa_audio_group_set_have_own_volume_control(pa_audio_group *group, bool have); ++void pa_audio_group_set_have_own_mute_control(pa_audio_group *group, bool have); ++void pa_audio_group_set_volume_control(pa_audio_group *group, pa_volume_control *control); ++void pa_audio_group_set_mute_control(pa_audio_group *group, pa_mute_control *control); ++void pa_audio_group_bind_volume_control(pa_audio_group *group, pa_binding_target_info *target_info); ++void pa_audio_group_bind_mute_control(pa_audio_group *group, pa_binding_target_info *target_info); ++ ++/* Called from sstream.c only. */ ++void pa_audio_group_add_volume_stream(pa_audio_group *group, pas_stream *stream); ++void pa_audio_group_remove_volume_stream(pa_audio_group *group, pas_stream *stream); ++void pa_audio_group_add_mute_stream(pa_audio_group *group, pas_stream *stream); ++void pa_audio_group_remove_mute_stream(pa_audio_group *group, pas_stream *stream); ++ ++/* Called from volume-api.c only. */ ++pa_binding_target_type *pa_audio_group_create_binding_target_type(pa_volume_api *api); ++ ++#endif +diff --git a/src/modules/volume-api/binding.c b/src/modules/volume-api/binding.c +new file mode 100644 +index 0000000..6e73119 +--- /dev/null ++++ b/src/modules/volume-api/binding.c +@@ -0,0 +1,386 @@ ++/*** ++ This file is part of PulseAudio. ++ ++ Copyright 2014 Intel Corporation ++ ++ PulseAudio is free software; you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as published ++ by the Free Software Foundation; either version 2.1 of the License, ++ or (at your option) any later version. ++ ++ PulseAudio 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 Lesser General Public License ++ along with PulseAudio; if not, write to the Free Software ++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ USA. ++***/ ++ ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ ++#include "binding.h" ++ ++#include ++#include ++ ++#include ++#include ++ ++struct field_entry { ++ char *name; ++ size_t offset; ++}; ++ ++static void set_target_type(pa_binding *binding, pa_binding_target_type *type); ++static void set_target_object(pa_binding *binding, void *object); ++ ++pa_binding_owner_info *pa_binding_owner_info_new(pa_binding_set_value_cb_t set_value, void *userdata) { ++ pa_binding_owner_info *info; ++ ++ pa_assert(set_value); ++ ++ info = pa_xnew0(pa_binding_owner_info, 1); ++ info->set_value = set_value; ++ info->userdata = userdata; ++ ++ return info; ++} ++ ++pa_binding_owner_info *pa_binding_owner_info_copy(const pa_binding_owner_info *info) { ++ pa_assert(info); ++ ++ return pa_binding_owner_info_new(info->set_value, info->userdata); ++} ++ ++void pa_binding_owner_info_free(pa_binding_owner_info *info) { ++ pa_assert(info); ++ ++ pa_xfree(info); ++} ++ ++pa_binding_target_info *pa_binding_target_info_new(const char *type, const char *name, const char *field) { ++ pa_binding_target_info *info; ++ ++ pa_assert(type); ++ pa_assert(name); ++ pa_assert(field); ++ ++ info = pa_xnew0(pa_binding_target_info, 1); ++ info->type = pa_xstrdup(type); ++ info->name = pa_xstrdup(name); ++ info->field = pa_xstrdup(field); ++ ++ return info; ++} ++ ++int pa_binding_target_info_new_from_string(const char *str, const char *field, pa_binding_target_info **info) { ++ const char *colon; ++ char *type = NULL; ++ char *name = NULL; ++ ++ pa_assert(str); ++ pa_assert(field); ++ pa_assert(info); ++ ++ if (!pa_startswith(str, "bind:")) ++ goto fail; ++ ++ colon = strchr(str + 5, ':'); ++ if (!colon) ++ goto fail; ++ ++ type = pa_xstrndup(str + 5, colon - (str + 5)); ++ ++ if (!*type) ++ goto fail; ++ ++ name = pa_xstrdup(colon + 1); ++ ++ if (!*name) ++ goto fail; ++ ++ *info = pa_binding_target_info_new(type, name, field); ++ pa_xfree(name); ++ pa_xfree(type); ++ ++ return 0; ++ ++fail: ++ pa_log("Invalid binding target: %s", str); ++ pa_xfree(name); ++ pa_xfree(type); ++ ++ return -PA_ERR_INVALID; ++} ++ ++pa_binding_target_info *pa_binding_target_info_copy(const pa_binding_target_info *info) { ++ pa_assert(info); ++ ++ return pa_binding_target_info_new(info->type, info->name, info->field); ++} ++ ++void pa_binding_target_info_free(pa_binding_target_info *info) { ++ pa_assert(info); ++ ++ pa_xfree(info->field); ++ pa_xfree(info->name); ++ pa_xfree(info->type); ++ pa_xfree(info); ++} ++ ++static void field_entry_free(struct field_entry *entry) { ++ pa_assert(entry); ++ ++ pa_xfree(entry->name); ++ pa_xfree(entry); ++} ++ ++pa_binding_target_type *pa_binding_target_type_new(const char *name, pa_hashmap *objects, pa_hook *put_hook, ++ pa_hook *unlink_hook, pa_binding_target_type_get_name_cb_t get_name) { ++ pa_binding_target_type *type; ++ ++ pa_assert(name); ++ pa_assert(objects); ++ pa_assert(put_hook); ++ pa_assert(unlink_hook); ++ pa_assert(get_name); ++ ++ type = pa_xnew0(pa_binding_target_type, 1); ++ type->name = pa_xstrdup(name); ++ type->objects = objects; ++ type->put_hook = put_hook; ++ type->unlink_hook = unlink_hook; ++ type->get_name = get_name; ++ type->fields = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, (pa_free_cb_t) field_entry_free); ++ ++ return type; ++} ++ ++void pa_binding_target_type_free(pa_binding_target_type *type) { ++ pa_assert(type); ++ ++ if (type->fields) ++ pa_hashmap_free(type->fields); ++ ++ pa_xfree(type->name); ++ pa_xfree(type); ++} ++ ++void pa_binding_target_type_add_field(pa_binding_target_type *type, const char *name, size_t offset) { ++ struct field_entry *entry; ++ ++ pa_assert(type); ++ pa_assert(name); ++ ++ entry = pa_xnew0(struct field_entry, 1); ++ entry->name = pa_xstrdup(name); ++ entry->offset = offset; ++ ++ pa_assert_se(pa_hashmap_put(type->fields, entry->name, entry) >= 0); ++} ++ ++int pa_binding_target_type_get_field_offset(pa_binding_target_type *type, const char *field, size_t *offset) { ++ struct field_entry *entry; ++ ++ pa_assert(type); ++ pa_assert(field); ++ pa_assert(offset); ++ ++ entry = pa_hashmap_get(type->fields, field); ++ if (!entry) ++ return -PA_ERR_NOENTITY; ++ ++ *offset = entry->offset; ++ ++ return 0; ++} ++ ++static pa_hook_result_t target_type_added_cb(void *hook_data, void *call_data, void *userdata) { ++ pa_binding_target_type *type = call_data; ++ pa_binding *binding = userdata; ++ ++ pa_assert(type); ++ pa_assert(binding); ++ ++ if (!pa_streq(type->name, binding->target_info->type)) ++ return PA_HOOK_OK; ++ ++ set_target_type(binding, type); ++ ++ return PA_HOOK_OK; ++} ++ ++static pa_hook_result_t target_type_removed_cb(void *hook_data, void *call_data, void *userdata) { ++ pa_binding_target_type *type = call_data; ++ pa_binding *binding = userdata; ++ ++ pa_assert(type); ++ pa_assert(binding); ++ ++ if (type != binding->target_type) ++ return PA_HOOK_OK; ++ ++ set_target_type(binding, NULL); ++ ++ return PA_HOOK_OK; ++} ++ ++static pa_hook_result_t target_put_cb(void *hook_data, void *call_data, void *userdata) { ++ pa_binding *binding = userdata; ++ ++ pa_assert(call_data); ++ pa_assert(binding); ++ ++ if (!pa_streq(binding->target_type->get_name(call_data), binding->target_info->name)) ++ return PA_HOOK_OK; ++ ++ set_target_object(binding, call_data); ++ ++ return PA_HOOK_OK; ++} ++ ++static pa_hook_result_t target_unlink_cb(void *hook_data, void *call_data, void *userdata) { ++ pa_binding *binding = userdata; ++ ++ pa_assert(call_data); ++ pa_assert(binding); ++ ++ if (call_data != binding->target_object) ++ return PA_HOOK_OK; ++ ++ set_target_object(binding, NULL); ++ ++ return PA_HOOK_OK; ++} ++ ++static void set_target_object(pa_binding *binding, void *object) { ++ pa_assert(binding); ++ ++ binding->target_object = object; ++ ++ if (object) { ++ if (binding->target_put_slot) { ++ pa_hook_slot_free(binding->target_put_slot); ++ binding->target_put_slot = NULL; ++ } ++ ++ if (!binding->target_unlink_slot) ++ binding->target_unlink_slot = pa_hook_connect(binding->target_type->unlink_hook, PA_HOOK_NORMAL, target_unlink_cb, ++ binding); ++ ++ if (binding->target_field_offset_valid) ++ binding->owner_info->set_value(binding->owner_info->userdata, ++ *((void **) (((uint8_t *) object) + binding->target_field_offset))); ++ else ++ binding->owner_info->set_value(binding->owner_info->userdata, NULL); ++ } else { ++ if (binding->target_unlink_slot) { ++ pa_hook_slot_free(binding->target_unlink_slot); ++ binding->target_unlink_slot = NULL; ++ } ++ ++ if (binding->target_type) { ++ if (!binding->target_put_slot) ++ binding->target_put_slot = pa_hook_connect(binding->target_type->put_hook, PA_HOOK_NORMAL, target_put_cb, binding); ++ } else { ++ if (binding->target_put_slot) { ++ pa_hook_slot_free(binding->target_put_slot); ++ binding->target_put_slot = NULL; ++ } ++ } ++ ++ binding->owner_info->set_value(binding->owner_info->userdata, NULL); ++ } ++} ++ ++static void set_target_type(pa_binding *binding, pa_binding_target_type *type) { ++ pa_assert(binding); ++ ++ binding->target_type = type; ++ ++ if (type) { ++ int r; ++ ++ if (binding->target_type_added_slot) { ++ pa_hook_slot_free(binding->target_type_added_slot); ++ binding->target_type_added_slot = NULL; ++ } ++ ++ if (!binding->target_type_removed_slot) ++ binding->target_type_removed_slot = ++ pa_hook_connect(&binding->volume_api->hooks[PA_VOLUME_API_HOOK_BINDING_TARGET_TYPE_REMOVED], ++ PA_HOOK_NORMAL, target_type_removed_cb, binding); ++ ++ r = pa_binding_target_type_get_field_offset(type, binding->target_info->field, &binding->target_field_offset); ++ if (r >= 0) ++ binding->target_field_offset_valid = true; ++ else { ++ pa_log_warn("Reference to non-existing field \"%s\" in binding target type \"%s\".", binding->target_info->field, ++ type->name); ++ binding->target_field_offset_valid = false; ++ } ++ ++ set_target_object(binding, pa_hashmap_get(type->objects, binding->target_info->name)); ++ } else { ++ if (binding->target_type_removed_slot) { ++ pa_hook_slot_free(binding->target_type_removed_slot); ++ binding->target_type_removed_slot = NULL; ++ } ++ ++ if (!binding->target_type_added_slot) ++ binding->target_type_added_slot = ++ pa_hook_connect(&binding->volume_api->hooks[PA_VOLUME_API_HOOK_BINDING_TARGET_TYPE_ADDED], ++ PA_HOOK_NORMAL, target_type_added_cb, binding); ++ ++ binding->target_field_offset_valid = false; ++ ++ set_target_object(binding, NULL); ++ } ++} ++ ++pa_binding *pa_binding_new(pa_volume_api *api, const pa_binding_owner_info *owner_info, ++ const pa_binding_target_info *target_info) { ++ pa_binding *binding; ++ ++ pa_assert(api); ++ pa_assert(owner_info); ++ pa_assert(target_info); ++ ++ binding = pa_xnew0(pa_binding, 1); ++ binding->volume_api = api; ++ binding->owner_info = pa_binding_owner_info_copy(owner_info); ++ binding->target_info = pa_binding_target_info_copy(target_info); ++ ++ set_target_type(binding, pa_hashmap_get(api->binding_target_types, target_info->type)); ++ ++ return binding; ++} ++ ++void pa_binding_free(pa_binding *binding) { ++ pa_assert(binding); ++ ++ if (binding->target_unlink_slot) ++ pa_hook_slot_free(binding->target_unlink_slot); ++ ++ if (binding->target_put_slot) ++ pa_hook_slot_free(binding->target_put_slot); ++ ++ if (binding->target_type_removed_slot) ++ pa_hook_slot_free(binding->target_type_removed_slot); ++ ++ if (binding->target_type_added_slot) ++ pa_hook_slot_free(binding->target_type_added_slot); ++ ++ if (binding->target_info) ++ pa_binding_target_info_free(binding->target_info); ++ ++ if (binding->owner_info) ++ pa_binding_owner_info_free(binding->owner_info); ++ ++ pa_xfree(binding); ++} +diff --git a/src/modules/volume-api/binding.h b/src/modules/volume-api/binding.h +new file mode 100644 +index 0000000..ba4dea8 +--- /dev/null ++++ b/src/modules/volume-api/binding.h +@@ -0,0 +1,128 @@ ++#ifndef foobindinghfoo ++#define foobindinghfoo ++ ++/*** ++ This file is part of PulseAudio. ++ ++ Copyright 2014 Intel Corporation ++ ++ PulseAudio is free software; you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as published ++ by the Free Software Foundation; either version 2.1 of the License, ++ or (at your option) any later version. ++ ++ PulseAudio 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 Lesser General Public License ++ along with PulseAudio; if not, write to the Free Software ++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ USA. ++***/ ++ ++#include ++ ++typedef struct pa_binding pa_binding; ++typedef struct pa_binding_owner_info pa_binding_owner_info; ++typedef struct pa_binding_target_info pa_binding_target_info; ++typedef struct pa_binding_target_type pa_binding_target_type; ++ ++typedef void (*pa_binding_set_value_cb_t)(void *userdata, void *value); ++ ++struct pa_binding_owner_info { ++ /* This is the object that has the variable that the binding is created ++ * for. */ ++ void *userdata; ++ ++ /* Called when the owner object's value needs to be updated. The userdata ++ * parameter of the callback is the same as the userdata field in this ++ * struct, and the value parameter is the new value for whatever variable ++ * the binding was created for. */ ++ pa_binding_set_value_cb_t set_value; ++}; ++ ++pa_binding_owner_info *pa_binding_owner_info_new(pa_binding_set_value_cb_t set_value, void *userdata); ++pa_binding_owner_info *pa_binding_owner_info_copy(const pa_binding_owner_info *info); ++void pa_binding_owner_info_free(pa_binding_owner_info *info); ++ ++struct pa_binding_target_info { ++ /* The target type name as registered with ++ * pa_binding_target_type_register(). */ ++ char *type; ++ ++ /* The target object name as returned by the get_name callback of ++ * pa_binding_target_type. */ ++ char *name; ++ ++ /* The target field of the target object. */ ++ char *field; ++}; ++ ++pa_binding_target_info *pa_binding_target_info_new(const char *type, const char *name, const char *field); ++ ++/* The string format is "bind:TYPE:NAME". */ ++int pa_binding_target_info_new_from_string(const char *str, const char *field, pa_binding_target_info **info); ++ ++pa_binding_target_info *pa_binding_target_info_copy(const pa_binding_target_info *info); ++void pa_binding_target_info_free(pa_binding_target_info *info); ++ ++typedef const char *(*pa_binding_target_type_get_name_cb_t)(void *object); ++ ++struct pa_binding_target_type { ++ /* Identifier for this target type. */ ++ char *name; ++ ++ /* name -> object. Points directly to some "master" object hashmap, so the ++ * hashmap is not owned by pa_binding_target_type. */ ++ pa_hashmap *objects; ++ ++ /* The hook that notifies of new objects if this target type. The call data ++ * of the hook must be a pointer to the new object (this should be true for ++ * all PUT hooks, so don't worry too much). */ ++ pa_hook *put_hook; ++ ++ /* The hook that notifies of unlinked objects of this target type. The call ++ * data of the hook must be a pointer to the removed object (this should be ++ * true for all UNLINK hooks, so don't worry too much). */ ++ pa_hook *unlink_hook; ++ ++ /* Function for getting the name of an object of this target type. */ ++ pa_binding_target_type_get_name_cb_t get_name; ++ ++ pa_hashmap *fields; ++}; ++ ++pa_binding_target_type *pa_binding_target_type_new(const char *name, pa_hashmap *objects, pa_hook *put_hook, ++ pa_hook *unlink_hook, pa_binding_target_type_get_name_cb_t get_name); ++void pa_binding_target_type_free(pa_binding_target_type *type); ++ ++/* Useful when calling pa_binding_target_type_add_field(). */ ++#define PA_BINDING_CALCULATE_FIELD_OFFSET(type, field) ((size_t) &(((type *) 0)->field)) ++ ++/* Called during the type initialization (right after ++ * pa_binding_target_type_new()). */ ++void pa_binding_target_type_add_field(pa_binding_target_type *type, const char *name, size_t offset); ++ ++int pa_binding_target_type_get_field_offset(pa_binding_target_type *type, const char *field, size_t *offset); ++ ++struct pa_binding { ++ pa_volume_api *volume_api; ++ pa_binding_owner_info *owner_info; ++ pa_binding_target_info *target_info; ++ pa_binding_target_type *target_type; ++ void *target_object; ++ size_t target_field_offset; ++ bool target_field_offset_valid; ++ pa_hook_slot *target_type_added_slot; ++ pa_hook_slot *target_type_removed_slot; ++ pa_hook_slot *target_put_slot; ++ pa_hook_slot *target_unlink_slot; ++}; ++ ++pa_binding *pa_binding_new(pa_volume_api *api, const pa_binding_owner_info *owner_info, ++ const pa_binding_target_info *target_info); ++void pa_binding_free(pa_binding *binding); ++ ++#endif +diff --git a/src/modules/volume-api/bvolume.h b/src/modules/volume-api/bvolume.h +new file mode 100644 +index 0000000..0317fb6 +--- /dev/null ++++ b/src/modules/volume-api/bvolume.h +@@ -0,0 +1,43 @@ ++#ifndef foobvolumehfoo ++#define foobvolumehfoo ++ ++/*** ++ This file is part of PulseAudio. ++ ++ Copyright 2014 Intel Corporation ++ ++ PulseAudio is free software; you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as published ++ by the Free Software Foundation; either version 2.1 of the License, ++ or (at your option) any later version. ++ ++ PulseAudio 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 Lesser General Public License ++ along with PulseAudio; if not, write to the Free Software ++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ USA. ++***/ ++ ++#include ++ ++typedef pa_ext_volume_api_bvolume pa_bvolume; ++ ++#define pa_balance_valid pa_ext_volume_api_balance_valid ++#define pa_bvolume_valid pa_ext_volume_api_bvolume_valid ++#define pa_bvolume_init_invalid pa_ext_volume_api_bvolume_init_invalid ++#define pa_bvolume_init_mono pa_ext_volume_api_bvolume_init_mono ++#define pa_bvolume_equal pa_ext_volume_api_bvolume_equal ++#define pa_bvolume_from_cvolume pa_ext_volume_api_bvolume_from_cvolume ++#define pa_bvolume_to_cvolume pa_ext_volume_api_bvolume_to_cvolume ++#define pa_bvolume_copy_balance pa_ext_volume_api_bvolume_copy_balance ++#define pa_bvolume_reset_balance pa_ext_volume_api_bvolume_reset_balance ++#define pa_bvolume_remap pa_ext_volume_api_bvolume_remap ++ ++#define PA_BVOLUME_SNPRINT_BALANCE_MAX PA_EXT_VOLUME_API_BVOLUME_SNPRINT_BALANCE_MAX ++#define pa_bvolume_snprint_balance pa_ext_volume_api_bvolume_snprint_balance ++ ++#endif +diff --git a/src/modules/volume-api/device-creator.c b/src/modules/volume-api/device-creator.c +new file mode 100644 +index 0000000..1d912ba +--- /dev/null ++++ b/src/modules/volume-api/device-creator.c +@@ -0,0 +1,1108 @@ ++/*** ++ This file is part of PulseAudio. ++ ++ Copyright 2014 Intel Corporation ++ ++ PulseAudio is free software; you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as published ++ by the Free Software Foundation; either version 2.1 of the License, ++ or (at your option) any later version. ++ ++ PulseAudio 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 Lesser General Public License ++ along with PulseAudio; if not, write to the Free Software ++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ USA. ++***/ ++ ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ ++#include "device-creator.h" ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++struct pa_device_creator { ++ pa_volume_api *volume_api; ++ pa_hashmap *devices; /* pa_device_port/pa_sink/pa_source -> struct device */ ++ pa_hook_slot *card_put_slot; ++ pa_hook_slot *card_unlink_slot; ++ pa_hook_slot *sink_put_slot; ++ pa_hook_slot *sink_unlink_slot; ++ pa_hook_slot *source_put_slot; ++ pa_hook_slot *source_unlink_slot; ++}; ++ ++enum device_type { ++ DEVICE_TYPE_PORT, ++ DEVICE_TYPE_PORT_MONITOR, ++ DEVICE_TYPE_SINK, ++ DEVICE_TYPE_SOURCE, ++}; ++ ++struct device_volume_control { ++ struct device *device; ++ pa_volume_control *volume_control; ++ ++ bool unlinked; ++ ++ pa_hook_slot *volume_changed_slot; ++}; ++ ++struct device_mute_control { ++ struct device *device; ++ pa_mute_control *mute_control; ++ ++ bool unlinked; ++ ++ pa_hook_slot *mute_changed_slot; ++}; ++ ++struct device { ++ pa_device_creator *creator; ++ enum device_type type; ++ pa_device_port *port; ++ pa_sink *sink; ++ pa_source *source; ++ pa_device *device; ++ struct device_volume_control *volume_control; ++ struct device_mute_control *mute_control; ++ ++ bool unlinked; ++ ++ pa_hook_slot *proplist_changed_slot; ++ pa_hook_slot *port_active_changed_slot; ++ struct device *monitor; ++}; ++ ++static const char *device_type_from_icon_name(const char *icon_name) { ++ if (!icon_name) ++ return NULL; ++ ++ if (pa_streq(icon_name, "audio-input-microphone")) ++ return "microphone"; ++ ++ if (pa_streq(icon_name, "audio-speakers")) ++ return "speakers"; ++ ++ if (pa_streq(icon_name, "audio-headphones")) ++ return "headphones"; ++ ++ return NULL; ++} ++ ++static const char *device_type_from_port_name(pa_device_port *port) { ++ pa_assert(port); ++ ++ if (strstr(port->name, "analog")) { ++ if (port->direction == PA_DIRECTION_INPUT) ++ return "analog-input"; ++ else ++ return "analog-output"; ++ } ++ ++ if (strstr(port->name, "hdmi")) { ++ if (port->direction == PA_DIRECTION_INPUT) ++ return "hdmi-input"; ++ else ++ return "hdmi-output"; ++ } ++ ++ if (strstr(port->name, "iec958")) { ++ if (port->direction == PA_DIRECTION_INPUT) ++ return "spdif-input"; ++ else ++ return "spdif-output"; ++ } ++ ++ return NULL; ++} ++ ++static const char *device_type_from_port(pa_device_port *port) { ++ const char *device_type; ++ ++ pa_assert(port); ++ ++ device_type = device_type_from_icon_name(pa_proplist_gets(port->proplist, PA_PROP_DEVICE_ICON_NAME)); ++ if (device_type) ++ return device_type; ++ ++ device_type = device_type_from_port_name(port); ++ if (device_type) ++ return device_type; ++ ++ return NULL; ++} ++ ++static const char *get_sink_description(pa_sink *sink) { ++ const char *description; ++ ++ pa_assert(sink); ++ ++ description = pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_DESCRIPTION); ++ if (description) ++ return description; ++ ++ return sink->name; ++} ++ ++static const char *get_source_description(pa_source *source) { ++ const char *description; ++ ++ pa_assert(source); ++ ++ description = pa_proplist_gets(source->proplist, PA_PROP_DEVICE_DESCRIPTION); ++ if (description) ++ return description; ++ ++ return source->name; ++} ++ ++static int volume_control_set_volume_cb(pa_volume_control *c, const pa_bvolume *volume, bool set_volume, bool set_balance) { ++ struct device_volume_control *control; ++ struct device *device; ++ pa_bvolume bvolume; ++ pa_cvolume cvolume; ++ ++ pa_assert(c); ++ pa_assert(volume); ++ ++ control = c->userdata; ++ device = control->device; ++ ++ switch (device->type) { ++ case DEVICE_TYPE_PORT: ++ if (device->port->direction == PA_DIRECTION_OUTPUT) ++ pa_bvolume_from_cvolume(&bvolume, &device->sink->reference_volume, &device->sink->channel_map); ++ else ++ pa_bvolume_from_cvolume(&bvolume, &device->source->reference_volume, &device->source->channel_map); ++ break; ++ ++ case DEVICE_TYPE_SINK: ++ pa_bvolume_from_cvolume(&bvolume, &device->sink->reference_volume, &device->sink->channel_map); ++ break; ++ ++ case DEVICE_TYPE_PORT_MONITOR: ++ case DEVICE_TYPE_SOURCE: ++ pa_bvolume_from_cvolume(&bvolume, &device->source->reference_volume, &device->source->channel_map); ++ break; ++ } ++ ++ if (set_volume) ++ bvolume.volume = volume->volume; ++ ++ if (set_balance) ++ pa_bvolume_copy_balance(&bvolume, volume); ++ ++ pa_bvolume_to_cvolume(&bvolume, &cvolume); ++ ++ switch (device->type) { ++ case DEVICE_TYPE_PORT: ++ if (device->port->direction == PA_DIRECTION_OUTPUT) ++ pa_sink_set_volume(device->sink, &cvolume, true, true); ++ else ++ pa_source_set_volume(device->source, &cvolume, true, true); ++ break; ++ ++ case DEVICE_TYPE_PORT_MONITOR: ++ case DEVICE_TYPE_SOURCE: ++ pa_source_set_volume(device->source, &cvolume, true, true); ++ break; ++ ++ case DEVICE_TYPE_SINK: ++ pa_sink_set_volume(device->sink, &cvolume, true, true); ++ break; ++ } ++ ++ return 0; ++} ++ ++static struct device_volume_control *device_volume_control_new(struct device *device) { ++ struct device_volume_control *control; ++ const char *name = NULL; ++ bool convertible_to_dB = false; ++ bool channel_map_is_writable; ++ ++ pa_assert(device); ++ ++ control = pa_xnew0(struct device_volume_control, 1); ++ control->device = device; ++ ++ switch (device->type) { ++ case DEVICE_TYPE_PORT: ++ name = "port-volume-control"; ++ ++ if (device->port->direction == PA_DIRECTION_OUTPUT) ++ convertible_to_dB = device->sink->flags & PA_SINK_DECIBEL_VOLUME; ++ else ++ convertible_to_dB = device->source->flags & PA_SOURCE_DECIBEL_VOLUME; ++ ++ break; ++ ++ case DEVICE_TYPE_PORT_MONITOR: ++ name = "port-monitor-volume-control"; ++ convertible_to_dB = device->source->flags & PA_SOURCE_DECIBEL_VOLUME; ++ break; ++ ++ case DEVICE_TYPE_SINK: ++ name = "sink-volume-control"; ++ convertible_to_dB = device->sink->flags & PA_SINK_DECIBEL_VOLUME; ++ break; ++ ++ case DEVICE_TYPE_SOURCE: ++ name = "source-volume-control"; ++ convertible_to_dB = device->source->flags & PA_SOURCE_DECIBEL_VOLUME; ++ break; ++ } ++ ++ channel_map_is_writable = false; ++ control->volume_control = pa_volume_control_new(device->creator->volume_api, name, device->device->description, ++ convertible_to_dB, channel_map_is_writable); ++ control->volume_control->set_volume = volume_control_set_volume_cb; ++ control->volume_control->userdata = control; ++ ++ return control; ++} ++ ++static pa_hook_result_t sink_or_source_volume_changed_cb(void *hook_data, void *call_data, void *userdata) { ++ struct device_volume_control *control = userdata; ++ struct device *device; ++ pa_sink *sink = NULL; ++ pa_source *source = NULL; ++ pa_bvolume bvolume; ++ ++ pa_assert(control); ++ pa_assert(call_data); ++ ++ device = control->device; ++ ++ switch (device->type) { ++ case DEVICE_TYPE_PORT: ++ if (device->port->direction == PA_DIRECTION_OUTPUT) ++ sink = call_data; ++ else ++ source = call_data; ++ break; ++ ++ case DEVICE_TYPE_PORT_MONITOR: ++ case DEVICE_TYPE_SOURCE: ++ source = call_data; ++ break; ++ ++ case DEVICE_TYPE_SINK: ++ sink = call_data; ++ break; ++ } ++ ++ if ((sink && sink != device->sink) || (source && source != device->source)) ++ return PA_HOOK_OK; ++ ++ if (sink) ++ pa_bvolume_from_cvolume(&bvolume, &sink->reference_volume, &sink->channel_map); ++ else ++ pa_bvolume_from_cvolume(&bvolume, &source->reference_volume, &source->channel_map); ++ ++ pa_volume_control_volume_changed(control->volume_control, &bvolume, true, true); ++ ++ return PA_HOOK_OK; ++} ++ ++static void volume_control_set_initial_volume_cb(pa_volume_control *c) { ++ struct device_volume_control *control; ++ struct device *device; ++ pa_cvolume cvolume; ++ ++ pa_assert(c); ++ ++ control = c->userdata; ++ device = control->device; ++ pa_bvolume_to_cvolume(&control->volume_control->volume, &cvolume); ++ ++ switch (device->type) { ++ case DEVICE_TYPE_PORT: ++ if (device->port->direction == PA_DIRECTION_OUTPUT) ++ pa_sink_set_volume(device->sink, &cvolume, true, true); ++ else ++ pa_source_set_volume(device->source, &cvolume, true, true); ++ break; ++ ++ case DEVICE_TYPE_PORT_MONITOR: ++ case DEVICE_TYPE_SOURCE: ++ pa_source_set_volume(device->source, &cvolume, true, true); ++ break; ++ ++ case DEVICE_TYPE_SINK: ++ pa_sink_set_volume(device->sink, &cvolume, true, true); ++ break; ++ } ++} ++ ++static void device_volume_control_put(struct device_volume_control *control) { ++ struct device *device; ++ pa_bvolume volume; ++ ++ pa_assert(control); ++ ++ device = control->device; ++ ++ switch (device->type) { ++ case DEVICE_TYPE_PORT: ++ if (device->port->direction == PA_DIRECTION_OUTPUT) { ++ control->volume_changed_slot = pa_hook_connect(&device->port->core->hooks[PA_CORE_HOOK_SINK_VOLUME_CHANGED], ++ PA_HOOK_NORMAL, sink_or_source_volume_changed_cb, control); ++ pa_bvolume_from_cvolume(&volume, &device->sink->reference_volume, &device->sink->channel_map); ++ } else { ++ control->volume_changed_slot = pa_hook_connect(&device->port->core->hooks[PA_CORE_HOOK_SOURCE_VOLUME_CHANGED], ++ PA_HOOK_NORMAL, sink_or_source_volume_changed_cb, control); ++ pa_bvolume_from_cvolume(&volume, &device->source->reference_volume, &device->source->channel_map); ++ } ++ break; ++ ++ case DEVICE_TYPE_PORT_MONITOR: ++ case DEVICE_TYPE_SOURCE: ++ control->volume_changed_slot = pa_hook_connect(&device->source->core->hooks[PA_CORE_HOOK_SOURCE_VOLUME_CHANGED], ++ PA_HOOK_NORMAL, sink_or_source_volume_changed_cb, control); ++ pa_bvolume_from_cvolume(&volume, &device->source->reference_volume, &device->source->channel_map); ++ break; ++ ++ case DEVICE_TYPE_SINK: ++ control->volume_changed_slot = pa_hook_connect(&device->sink->core->hooks[PA_CORE_HOOK_SINK_VOLUME_CHANGED], ++ PA_HOOK_NORMAL, sink_or_source_volume_changed_cb, control); ++ pa_bvolume_from_cvolume(&volume, &device->sink->reference_volume, &device->sink->channel_map); ++ break; ++ } ++ ++ pa_volume_control_put(control->volume_control, &volume, volume_control_set_initial_volume_cb); ++} ++ ++static void device_volume_control_unlink(struct device_volume_control *control) { ++ pa_assert(control); ++ ++ if (control->unlinked) ++ return; ++ ++ control->unlinked = true; ++ ++ if (control->volume_control) ++ pa_volume_control_unlink(control->volume_control); ++ ++ if (control->volume_changed_slot) { ++ pa_hook_slot_free(control->volume_changed_slot); ++ control->volume_changed_slot = NULL; ++ } ++} ++ ++static void device_volume_control_free(struct device_volume_control *control) { ++ pa_assert(control); ++ ++ if (!control->unlinked) ++ device_volume_control_unlink(control); ++ ++ if (control->volume_control) ++ pa_volume_control_free(control->volume_control); ++ ++ pa_xfree(control); ++} ++ ++static int mute_control_set_mute_cb(pa_mute_control *c, bool mute) { ++ struct device_mute_control *control; ++ struct device *device; ++ ++ pa_assert(c); ++ ++ control = c->userdata; ++ device = control->device; ++ ++ switch (device->type) { ++ case DEVICE_TYPE_PORT: ++ if (device->port->direction == PA_DIRECTION_OUTPUT) ++ pa_sink_set_mute(device->sink, mute, true); ++ else ++ pa_source_set_mute(device->source, mute, true); ++ break; ++ ++ case DEVICE_TYPE_PORT_MONITOR: ++ case DEVICE_TYPE_SOURCE: ++ pa_source_set_mute(device->source, mute, true); ++ break; ++ ++ case DEVICE_TYPE_SINK: ++ pa_sink_set_mute(device->sink, mute, true); ++ break; ++ } ++ ++ return 0; ++} ++ ++static struct device_mute_control *device_mute_control_new(struct device *device) { ++ struct device_mute_control *control; ++ const char *name = NULL; ++ ++ pa_assert(device); ++ ++ control = pa_xnew0(struct device_mute_control, 1); ++ control->device = device; ++ ++ switch (device->type) { ++ case DEVICE_TYPE_PORT: ++ name = "port-mute-control"; ++ break; ++ ++ case DEVICE_TYPE_PORT_MONITOR: ++ name = "port-monitor-mute-control"; ++ break; ++ ++ case DEVICE_TYPE_SINK: ++ name = "sink-mute-control"; ++ break; ++ ++ case DEVICE_TYPE_SOURCE: ++ name = "source-mute-control"; ++ break; ++ } ++ ++ control->mute_control = pa_mute_control_new(device->creator->volume_api, name, device->device->description); ++ control->mute_control->set_mute = mute_control_set_mute_cb; ++ control->mute_control->userdata = control; ++ ++ return control; ++} ++ ++static pa_hook_result_t sink_or_source_mute_changed_cb(void *hook_data, void *call_data, void *userdata) { ++ struct device_mute_control *control = userdata; ++ struct device *device; ++ pa_sink *sink = NULL; ++ pa_source *source = NULL; ++ bool mute; ++ ++ pa_assert(control); ++ pa_assert(call_data); ++ ++ device = control->device; ++ ++ switch (device->type) { ++ case DEVICE_TYPE_PORT: ++ if (device->port->direction == PA_DIRECTION_OUTPUT) ++ sink = call_data; ++ else ++ source = call_data; ++ break; ++ ++ case DEVICE_TYPE_PORT_MONITOR: ++ case DEVICE_TYPE_SOURCE: ++ source = call_data; ++ break; ++ ++ case DEVICE_TYPE_SINK: ++ sink = call_data; ++ break; ++ } ++ ++ if ((sink && sink != device->sink) || (source && source != device->source)) ++ return PA_HOOK_OK; ++ ++ if (sink) ++ mute = sink->muted; ++ else ++ mute = source->muted; ++ ++ pa_mute_control_mute_changed(control->mute_control, mute); ++ ++ return PA_HOOK_OK; ++} ++ ++static void mute_control_set_initial_mute_cb(pa_mute_control *c) { ++ struct device_volume_control *control; ++ struct device *device; ++ ++ pa_assert(c); ++ ++ control = c->userdata; ++ device = control->device; ++ ++ switch (device->type) { ++ case DEVICE_TYPE_PORT: ++ if (device->port->direction == PA_DIRECTION_OUTPUT) ++ pa_sink_set_mute(device->sink, c->mute, true); ++ else ++ pa_source_set_mute(device->source, c->mute, true); ++ break; ++ ++ case DEVICE_TYPE_PORT_MONITOR: ++ case DEVICE_TYPE_SOURCE: ++ pa_source_set_mute(device->source, c->mute, true); ++ break; ++ ++ case DEVICE_TYPE_SINK: ++ pa_sink_set_mute(device->sink, c->mute, true); ++ break; ++ } ++} ++ ++static void device_mute_control_put(struct device_mute_control *control) { ++ struct device *device; ++ bool mute = false; ++ ++ pa_assert(control); ++ ++ device = control->device; ++ ++ switch (device->type) { ++ case DEVICE_TYPE_PORT: ++ if (device->port->direction == PA_DIRECTION_OUTPUT) { ++ control->mute_changed_slot = pa_hook_connect(&device->port->core->hooks[PA_CORE_HOOK_SINK_MUTE_CHANGED], ++ PA_HOOK_NORMAL, sink_or_source_mute_changed_cb, control); ++ mute = device->sink->muted; ++ } else { ++ control->mute_changed_slot = pa_hook_connect(&device->port->core->hooks[PA_CORE_HOOK_SOURCE_MUTE_CHANGED], ++ PA_HOOK_NORMAL, sink_or_source_mute_changed_cb, control); ++ mute = device->source->muted; ++ } ++ break; ++ ++ case DEVICE_TYPE_PORT_MONITOR: ++ case DEVICE_TYPE_SOURCE: ++ control->mute_changed_slot = pa_hook_connect(&device->source->core->hooks[PA_CORE_HOOK_SOURCE_MUTE_CHANGED], ++ PA_HOOK_NORMAL, sink_or_source_mute_changed_cb, control); ++ mute = device->source->muted; ++ break; ++ ++ case DEVICE_TYPE_SINK: ++ control->mute_changed_slot = pa_hook_connect(&device->sink->core->hooks[PA_CORE_HOOK_SINK_MUTE_CHANGED], ++ PA_HOOK_NORMAL, sink_or_source_mute_changed_cb, control); ++ mute = device->sink->muted; ++ break; ++ } ++ ++ pa_mute_control_put(control->mute_control, mute, true, mute_control_set_initial_mute_cb); ++} ++ ++static void device_mute_control_unlink(struct device_mute_control *control) { ++ pa_assert(control); ++ ++ if (control->unlinked) ++ return; ++ ++ control->unlinked = true; ++ ++ if (control->mute_control) ++ pa_mute_control_unlink(control->mute_control); ++ ++ if (control->mute_changed_slot) { ++ pa_hook_slot_free(control->mute_changed_slot); ++ control->mute_changed_slot = NULL; ++ } ++} ++ ++static void device_mute_control_free(struct device_mute_control *control) { ++ pa_assert(control); ++ ++ if (!control->unlinked) ++ device_mute_control_unlink(control); ++ ++ if (control->mute_control) ++ pa_mute_control_free(control->mute_control); ++ ++ pa_xfree(control); ++} ++ ++static void device_set_sink_and_source_from_port(struct device *device) { ++ pa_sink *sink; ++ pa_source *source; ++ uint32_t idx; ++ ++ pa_assert(device); ++ ++ device->sink = NULL; ++ device->source = NULL; ++ ++ if (!device->port->active) ++ return; ++ ++ switch (device->type) { ++ case DEVICE_TYPE_PORT: ++ if (device->port->direction == PA_DIRECTION_OUTPUT) { ++ PA_IDXSET_FOREACH(sink, device->port->card->sinks, idx) { ++ if (sink->active_port == device->port) { ++ device->sink = sink; ++ break; ++ } ++ } ++ ++ pa_assert(device->sink); ++ } else { ++ PA_IDXSET_FOREACH(source, device->port->card->sources, idx) { ++ if (source->active_port == device->port) { ++ device->source = source; ++ break; ++ } ++ } ++ ++ pa_assert(device->source); ++ } ++ break; ++ ++ case DEVICE_TYPE_PORT_MONITOR: { ++ PA_IDXSET_FOREACH(sink, device->port->card->sinks, idx) { ++ if (sink->active_port == device->port) { ++ device->sink = sink; ++ device->source = sink->monitor_source; ++ break; ++ } ++ } ++ ++ pa_assert(device->sink); ++ break; ++ } ++ ++ case DEVICE_TYPE_SINK: ++ case DEVICE_TYPE_SOURCE: ++ pa_assert_not_reached(); ++ } ++} ++ ++static pa_hook_result_t sink_or_source_proplist_changed_cb(void *hook_data, void *call_data, void *userdata) { ++ struct device *device = userdata; ++ pa_sink *sink = NULL; ++ pa_source *source = NULL; ++ const char *description = NULL; ++ ++ pa_assert(device); ++ pa_assert(call_data); ++ ++ switch (device->type) { ++ case DEVICE_TYPE_PORT: ++ case DEVICE_TYPE_PORT_MONITOR: ++ pa_assert_not_reached(); ++ ++ case DEVICE_TYPE_SINK: ++ sink = call_data; ++ ++ if (sink != device->sink) ++ return PA_HOOK_OK; ++ ++ description = get_sink_description(sink); ++ break; ++ ++ case DEVICE_TYPE_SOURCE: ++ source = call_data; ++ ++ if (source != device->source) ++ return PA_HOOK_OK; ++ ++ description = get_source_description(source); ++ break; ++ } ++ ++ pa_device_description_changed(device->device, description); ++ pa_volume_control_description_changed(device->volume_control->volume_control, description); ++ pa_mute_control_description_changed(device->mute_control->mute_control, description); ++ ++ return PA_HOOK_OK; ++} ++ ++static struct device *device_new(pa_device_creator *creator, enum device_type type, void *core_device) { ++ struct device *device = NULL; ++ const char *name = NULL; ++ char *description = NULL; ++ pa_direction_t direction = PA_DIRECTION_OUTPUT; ++ const char *device_type = NULL; ++ bool create_volume_and_mute_controls = true; ++ ++ pa_assert(creator); ++ pa_assert(core_device); ++ ++ device = pa_xnew0(struct device, 1); ++ device->creator = creator; ++ device->type = type; ++ ++ switch (type) { ++ case DEVICE_TYPE_PORT: ++ device->port = core_device; ++ device_set_sink_and_source_from_port(device); ++ name = "port-device"; ++ description = pa_xstrdup(device->port->description); ++ direction = device->port->direction; ++ device_type = device_type_from_port(device->port); ++ ++ if (!device->sink && !device->source) ++ create_volume_and_mute_controls = false; ++ break; ++ ++ case DEVICE_TYPE_PORT_MONITOR: ++ device->port = core_device; ++ device_set_sink_and_source_from_port(device); ++ name = "port-monitor-device"; ++ description = pa_sprintf_malloc(_("Monitor of %s"), device->port->description); ++ direction = PA_DIRECTION_INPUT; ++ ++ if (!device->source) ++ create_volume_and_mute_controls = false; ++ break; ++ ++ case DEVICE_TYPE_SINK: ++ device->sink = core_device; ++ name = "sink-device"; ++ description = pa_xstrdup(get_sink_description(device->sink)); ++ direction = PA_DIRECTION_OUTPUT; ++ break; ++ ++ case DEVICE_TYPE_SOURCE: ++ device->source = core_device; ++ name = "source-device"; ++ description = pa_xstrdup(get_source_description(device->source)); ++ direction = PA_DIRECTION_INPUT; ++ break; ++ } ++ ++ device->device = pa_device_new(creator->volume_api, name, description, direction, &device_type, device_type ? 1 : 0); ++ pa_xfree(description); ++ ++ if (create_volume_and_mute_controls) { ++ device->volume_control = device_volume_control_new(device); ++ device->mute_control = device_mute_control_new(device); ++ } ++ ++ switch (type) { ++ case DEVICE_TYPE_PORT: ++ if (device->port->direction == PA_DIRECTION_OUTPUT) ++ device->monitor = device_new(creator, DEVICE_TYPE_PORT_MONITOR, device->port); ++ break; ++ ++ case DEVICE_TYPE_PORT_MONITOR: ++ break; ++ ++ case DEVICE_TYPE_SINK: ++ device->proplist_changed_slot = pa_hook_connect(&device->sink->core->hooks[PA_CORE_HOOK_SINK_PROPLIST_CHANGED], ++ PA_HOOK_NORMAL, sink_or_source_proplist_changed_cb, device); ++ break; ++ ++ case DEVICE_TYPE_SOURCE: ++ device->proplist_changed_slot = pa_hook_connect(&device->source->core->hooks[PA_CORE_HOOK_SOURCE_PROPLIST_CHANGED], ++ PA_HOOK_NORMAL, sink_or_source_proplist_changed_cb, device); ++ break; ++ } ++ ++ return device; ++} ++ ++static pa_hook_result_t port_active_changed_cb(void *hook_data, void *call_data, void *userdata) { ++ struct device *device = userdata; ++ pa_device_port *port = call_data; ++ bool should_have_volume_and_mute_controls = false; ++ ++ pa_assert(device); ++ pa_assert(port); ++ ++ if (port != device->port) ++ return PA_HOOK_OK; ++ ++ device_set_sink_and_source_from_port(device); ++ ++ switch (device->type) { ++ case DEVICE_TYPE_PORT: ++ should_have_volume_and_mute_controls = device->sink || device->source; ++ break; ++ ++ case DEVICE_TYPE_PORT_MONITOR: ++ should_have_volume_and_mute_controls = !!device->source; ++ break; ++ ++ case DEVICE_TYPE_SINK: ++ case DEVICE_TYPE_SOURCE: ++ pa_assert_not_reached(); ++ } ++ ++ if (should_have_volume_and_mute_controls && !device->volume_control) { ++ pa_assert(!device->mute_control); ++ ++ device->volume_control = device_volume_control_new(device); ++ device_volume_control_put(device->volume_control); ++ pa_device_set_default_volume_control(device->device, device->volume_control->volume_control); ++ ++ device->mute_control = device_mute_control_new(device); ++ device_mute_control_put(device->mute_control); ++ pa_device_set_default_mute_control(device->device, device->mute_control->mute_control); ++ } ++ ++ if (!should_have_volume_and_mute_controls && device->volume_control) { ++ pa_assert(device->mute_control); ++ ++ device_mute_control_free(device->mute_control); ++ device->mute_control = NULL; ++ device_volume_control_free(device->volume_control); ++ device->volume_control = NULL; ++ } ++ ++ return PA_HOOK_OK; ++} ++ ++static void device_put(struct device *device) { ++ pa_assert(device); ++ ++ switch (device->type) { ++ case DEVICE_TYPE_PORT: ++ case DEVICE_TYPE_PORT_MONITOR: ++ device->port_active_changed_slot = pa_hook_connect(&device->port->core->hooks[PA_CORE_HOOK_PORT_ACTIVE_CHANGED], ++ PA_HOOK_NORMAL, port_active_changed_cb, device); ++ ++ case DEVICE_TYPE_SINK: ++ case DEVICE_TYPE_SOURCE: ++ break; ++ } ++ ++ if (device->volume_control) ++ device_volume_control_put(device->volume_control); ++ ++ if (device->mute_control) ++ device_mute_control_put(device->mute_control); ++ ++ pa_device_put(device->device, device->volume_control ? device->volume_control->volume_control : NULL, ++ device->mute_control ? device->mute_control->mute_control : NULL); ++ ++ if (device->monitor) ++ device_put(device->monitor); ++} ++ ++static void device_unlink(struct device *device) { ++ pa_assert(device); ++ ++ if (device->unlinked) ++ return; ++ ++ device->unlinked = true; ++ ++ if (device->monitor) ++ device_unlink(device->monitor); ++ ++ if (device->device) ++ pa_device_unlink(device->device); ++ ++ if (device->mute_control) ++ device_mute_control_unlink(device->mute_control); ++ ++ if (device->volume_control) ++ device_volume_control_unlink(device->volume_control); ++ ++ if (device->port_active_changed_slot) { ++ pa_hook_slot_free(device->port_active_changed_slot); ++ device->port_active_changed_slot = NULL; ++ } ++} ++ ++static void device_free(struct device *device) { ++ pa_assert(device); ++ ++ if (!device->unlinked) ++ device_unlink(device); ++ ++ if (device->monitor) ++ device_free(device->monitor); ++ ++ if (device->proplist_changed_slot) ++ pa_hook_slot_free(device->proplist_changed_slot); ++ ++ if (device->mute_control) ++ device_mute_control_free(device->mute_control); ++ ++ if (device->volume_control) ++ device_volume_control_free(device->volume_control); ++ ++ if (device->device) ++ pa_device_free(device->device); ++ ++ pa_xfree(device); ++} ++ ++static void create_device(pa_device_creator *creator, enum device_type type, void *core_device) { ++ struct device *device; ++ ++ pa_assert(creator); ++ pa_assert(core_device); ++ ++ switch (type) { ++ case DEVICE_TYPE_PORT: ++ break; ++ ++ case DEVICE_TYPE_PORT_MONITOR: ++ pa_assert_not_reached(); ++ ++ case DEVICE_TYPE_SINK: ++ if (!pa_hashmap_isempty(((pa_sink *) core_device)->ports)) ++ return; ++ break; ++ ++ case DEVICE_TYPE_SOURCE: { ++ pa_source *source = core_device; ++ ++ if (source->monitor_of && !pa_hashmap_isempty(source->monitor_of->ports)) ++ return; ++ ++ if (!pa_hashmap_isempty(((pa_source *) core_device)->ports)) ++ return; ++ break; ++ } ++ } ++ ++ device = device_new(creator, type, core_device); ++ pa_hashmap_put(creator->devices, core_device, device); ++ device_put(device); ++} ++ ++static pa_hook_result_t card_put_cb(void *hook_data, void *call_data, void *userdata) { ++ pa_device_creator *creator = userdata; ++ pa_card *card = call_data; ++ pa_device_port *port; ++ void *state; ++ ++ pa_assert(creator); ++ pa_assert(card); ++ ++ PA_HASHMAP_FOREACH(port, card->ports, state) ++ create_device(creator, DEVICE_TYPE_PORT, port); ++ ++ return PA_HOOK_OK; ++} ++ ++static pa_hook_result_t card_unlink_cb(void *hook_data, void *call_data, void *userdata) { ++ pa_device_creator *creator = userdata; ++ pa_card *card = call_data; ++ pa_device_port *port; ++ void *state; ++ ++ pa_assert(creator); ++ pa_assert(card); ++ ++ PA_HASHMAP_FOREACH(port, card->ports, state) ++ pa_hashmap_remove_and_free(creator->devices, port); ++ ++ return PA_HOOK_OK; ++} ++ ++static pa_hook_result_t sink_put_cb(void *hook_data, void *call_data, void *userdata) { ++ pa_device_creator *creator = userdata; ++ pa_sink *sink = call_data; ++ ++ pa_assert(creator); ++ pa_assert(sink); ++ ++ create_device(creator, DEVICE_TYPE_SINK, sink); ++ ++ return PA_HOOK_OK; ++} ++ ++static pa_hook_result_t sink_unlink_cb(void *hook_data, void *call_data, void *userdata) { ++ pa_device_creator *creator = userdata; ++ pa_sink *sink = call_data; ++ ++ pa_assert(creator); ++ pa_assert(sink); ++ ++ pa_hashmap_remove_and_free(creator->devices, sink); ++ ++ return PA_HOOK_OK; ++} ++ ++static pa_hook_result_t source_put_cb(void *hook_data, void *call_data, void *userdata) { ++ pa_device_creator *creator = userdata; ++ pa_source *source = call_data; ++ ++ pa_assert(creator); ++ pa_assert(source); ++ ++ create_device(creator, DEVICE_TYPE_SOURCE, source); ++ ++ return PA_HOOK_OK; ++} ++ ++static pa_hook_result_t source_unlink_cb(void *hook_data, void *call_data, void *userdata) { ++ pa_device_creator *creator = userdata; ++ pa_source *source = call_data; ++ ++ pa_assert(creator); ++ pa_assert(source); ++ ++ pa_hashmap_remove_and_free(creator->devices, source); ++ ++ return PA_HOOK_OK; ++} ++ ++pa_device_creator *pa_device_creator_new(pa_volume_api *api) { ++ pa_device_creator *creator; ++ pa_card *card; ++ uint32_t idx; ++ pa_sink *sink; ++ pa_source *source; ++ ++ pa_assert(api); ++ ++ creator = pa_xnew0(pa_device_creator, 1); ++ creator->volume_api = api; ++ creator->devices = pa_hashmap_new_full(NULL, NULL, NULL, (pa_free_cb_t) device_free); ++ creator->card_put_slot = pa_hook_connect(&api->core->hooks[PA_CORE_HOOK_CARD_PUT], PA_HOOK_NORMAL, card_put_cb, creator); ++ creator->card_unlink_slot = pa_hook_connect(&api->core->hooks[PA_CORE_HOOK_CARD_UNLINK], PA_HOOK_NORMAL, card_unlink_cb, ++ creator); ++ creator->sink_put_slot = pa_hook_connect(&api->core->hooks[PA_CORE_HOOK_SINK_PUT], PA_HOOK_NORMAL, sink_put_cb, creator); ++ creator->sink_unlink_slot = pa_hook_connect(&api->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_NORMAL, sink_unlink_cb, ++ creator); ++ creator->source_put_slot = pa_hook_connect(&api->core->hooks[PA_CORE_HOOK_SOURCE_PUT], PA_HOOK_NORMAL, source_put_cb, ++ creator); ++ creator->source_unlink_slot = pa_hook_connect(&api->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_NORMAL, ++ source_unlink_cb, creator); ++ ++ PA_IDXSET_FOREACH(card, api->core->cards, idx) { ++ pa_device_port *port; ++ void *state; ++ ++ PA_HASHMAP_FOREACH(port, card->ports, state) ++ create_device(creator, DEVICE_TYPE_PORT, port); ++ } ++ ++ PA_IDXSET_FOREACH(sink, api->core->sinks, idx) ++ create_device(creator, DEVICE_TYPE_SINK, sink); ++ ++ PA_IDXSET_FOREACH(source, api->core->sources, idx) ++ create_device(creator, DEVICE_TYPE_SOURCE, source); ++ ++ return creator; ++} ++ ++void pa_device_creator_free(pa_device_creator *creator) { ++ pa_assert(creator); ++ ++ if (creator->devices) ++ pa_hashmap_remove_all(creator->devices); ++ ++ if (creator->source_unlink_slot) ++ pa_hook_slot_free(creator->source_unlink_slot); ++ ++ if (creator->source_put_slot) ++ pa_hook_slot_free(creator->source_put_slot); ++ ++ if (creator->sink_unlink_slot) ++ pa_hook_slot_free(creator->sink_unlink_slot); ++ ++ if (creator->sink_put_slot) ++ pa_hook_slot_free(creator->sink_put_slot); ++ ++ if (creator->card_unlink_slot) ++ pa_hook_slot_free(creator->card_unlink_slot); ++ ++ if (creator->card_put_slot) ++ pa_hook_slot_free(creator->card_put_slot); ++ ++ if (creator->devices) ++ pa_hashmap_free(creator->devices); ++ ++ pa_xfree(creator); ++} +diff --git a/src/modules/volume-api/device-creator.h b/src/modules/volume-api/device-creator.h +new file mode 100644 +index 0000000..bcec8d9 +--- /dev/null ++++ b/src/modules/volume-api/device-creator.h +@@ -0,0 +1,32 @@ ++#ifndef foodevicecreatorhfoo ++#define foodevicecreatorhfoo ++ ++/*** ++ This file is part of PulseAudio. ++ ++ Copyright 2014 Intel Corporation ++ ++ PulseAudio is free software; you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as published ++ by the Free Software Foundation; either version 2.1 of the License, ++ or (at your option) any later version. ++ ++ PulseAudio 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 Lesser General Public License ++ along with PulseAudio; if not, write to the Free Software ++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ USA. ++***/ ++ ++#include ++ ++typedef struct pa_device_creator pa_device_creator; ++ ++pa_device_creator *pa_device_creator_new(pa_volume_api *api); ++void pa_device_creator_free(pa_device_creator *creator); ++ ++#endif +diff --git a/src/modules/volume-api/device.c b/src/modules/volume-api/device.c +new file mode 100644 +index 0000000..ea496ba +--- /dev/null ++++ b/src/modules/volume-api/device.c +@@ -0,0 +1,293 @@ ++/*** ++ This file is part of PulseAudio. ++ ++ Copyright 2014 Intel Corporation ++ ++ PulseAudio is free software; you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as published ++ by the Free Software Foundation; either version 2.1 of the License, ++ or (at your option) any later version. ++ ++ PulseAudio 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 Lesser General Public License ++ along with PulseAudio; if not, write to the Free Software ++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ USA. ++***/ ++ ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ ++#include "device.h" ++ ++#include ++#include ++ ++#include ++ ++#include ++ ++pa_device *pa_device_new(pa_volume_api *api, const char *name, const char *description, pa_direction_t direction, ++ const char * const *device_types, unsigned n_device_types) { ++ pa_device *device; ++ unsigned i; ++ ++ pa_assert(api); ++ pa_assert(name); ++ pa_assert(description); ++ pa_assert(device_types || n_device_types == 0); ++ ++ device = pa_xnew0(pa_device, 1); ++ device->volume_api = api; ++ device->index = pa_volume_api_allocate_device_index(api); ++ pa_assert_se(pa_volume_api_register_name(api, name, false, &device->name) >= 0); ++ device->description = pa_xstrdup(description); ++ device->direction = direction; ++ device->device_types = pa_dynarray_new(pa_xfree); ++ ++ for (i = 0; i < n_device_types; i++) ++ pa_dynarray_append(device->device_types, pa_xstrdup(device_types[i])); ++ ++ device->proplist = pa_proplist_new(); ++ device->use_default_volume_control = true; ++ device->use_default_mute_control = true; ++ ++ return device; ++} ++ ++void pa_device_put(pa_device *device, pa_volume_control *default_volume_control, pa_mute_control *default_mute_control) { ++ char *device_types_str; ++ const char *prop_key; ++ void *state = NULL; ++ ++ pa_assert(device); ++ ++ if (default_volume_control) { ++ device->default_volume_control = default_volume_control; ++ pa_volume_control_add_default_for_device(default_volume_control, device); ++ ++ device->volume_control = default_volume_control; ++ pa_volume_control_add_device(default_volume_control, device); ++ } ++ ++ if (default_mute_control) { ++ device->default_mute_control = default_mute_control; ++ pa_mute_control_add_default_for_device(default_mute_control, device); ++ ++ device->mute_control = default_mute_control; ++ pa_mute_control_add_device(default_mute_control, device); ++ } ++ ++ pa_volume_api_add_device(device->volume_api, device); ++ ++ device->linked = true; ++ ++ device_types_str = pa_join((const char * const *) pa_dynarray_get_raw_array(device->device_types), ++ pa_dynarray_size(device->device_types), ", "); ++ ++ pa_log_debug("Created device #%u.", device->index); ++ pa_log_debug(" Name: %s", device->name); ++ pa_log_debug(" Description: %s", device->description); ++ pa_log_debug(" Direction: %s", pa_direction_to_string(device->direction)); ++ pa_log_debug(" Device Types: %s", *device_types_str ? device_types_str : "(none)"); ++ pa_log_debug(" Volume control: %s", device->volume_control ? device->volume_control->name : "(unset)"); ++ pa_log_debug(" Mute control: %s", device->mute_control ? device->mute_control->name : "(unset)"); ++ pa_log_debug(" Properties:"); ++ ++ while ((prop_key = pa_proplist_iterate(device->proplist, &state))) ++ pa_log_debug(" %s = %s", prop_key, pa_strnull(pa_proplist_gets(device->proplist, prop_key))); ++ ++ pa_xfree(device_types_str); ++ ++ pa_hook_fire(&device->volume_api->hooks[PA_VOLUME_API_HOOK_DEVICE_PUT], device); ++} ++ ++void pa_device_unlink(pa_device *device) { ++ pa_assert(device); ++ ++ if (device->unlinked) { ++ pa_log_debug("Unlinking device %s (already unlinked, this is a no-op).", device->name); ++ return; ++ } ++ ++ device->unlinked = true; ++ ++ pa_log_debug("Unlinking device %s.", device->name); ++ ++ if (device->linked) ++ pa_hook_fire(&device->volume_api->hooks[PA_VOLUME_API_HOOK_DEVICE_UNLINK], device); ++ ++ pa_volume_api_remove_device(device->volume_api, device); ++ ++ if (device->mute_control) { ++ pa_mute_control_remove_device(device->mute_control, device); ++ device->mute_control = NULL; ++ } ++ ++ if (device->default_mute_control) { ++ pa_mute_control_remove_default_for_device(device->default_mute_control, device); ++ device->default_mute_control = NULL; ++ } ++ ++ if (device->volume_control) { ++ pa_volume_control_remove_device(device->volume_control, device); ++ device->volume_control = NULL; ++ } ++ ++ if (device->default_volume_control) { ++ pa_volume_control_remove_default_for_device(device->default_volume_control, device); ++ device->default_volume_control = NULL; ++ } ++} ++ ++void pa_device_free(pa_device *device) { ++ pa_assert(device); ++ ++ if (!device->unlinked) ++ pa_device_unlink(device); ++ ++ if (device->proplist) ++ pa_proplist_free(device->proplist); ++ ++ if (device->device_types) ++ pa_dynarray_free(device->device_types); ++ ++ pa_xfree(device->description); ++ ++ if (device->name) ++ pa_volume_api_unregister_name(device->volume_api, device->name); ++ ++ pa_xfree(device); ++} ++ ++static void set_volume_control_internal(pa_device *device, pa_volume_control *control) { ++ pa_volume_control *old_control; ++ ++ pa_assert(device); ++ ++ old_control = device->volume_control; ++ ++ if (control == old_control) ++ return; ++ ++ if (old_control) ++ pa_volume_control_remove_device(old_control, device); ++ ++ device->volume_control = control; ++ ++ if (control) ++ pa_volume_control_add_device(control, device); ++ ++ if (!device->linked || device->unlinked) ++ return; ++ ++ pa_log_debug("The volume control of device %s changed from %s to %s.", device->name, ++ old_control ? old_control->name : "(unset)", control ? control->name : "(unset)"); ++ ++ pa_hook_fire(&device->volume_api->hooks[PA_VOLUME_API_HOOK_DEVICE_VOLUME_CONTROL_CHANGED], device); ++} ++ ++void pa_device_set_volume_control(pa_device *device, pa_volume_control *control) { ++ pa_assert(device); ++ ++ device->use_default_volume_control = false; ++ set_volume_control_internal(device, control); ++} ++ ++static void set_mute_control_internal(pa_device *device, pa_mute_control *control) { ++ pa_mute_control *old_control; ++ ++ pa_assert(device); ++ ++ old_control = device->mute_control; ++ ++ if (control == old_control) ++ return; ++ ++ if (old_control) ++ pa_mute_control_remove_device(old_control, device); ++ ++ device->mute_control = control; ++ ++ if (control) ++ pa_mute_control_add_device(control, device); ++ ++ pa_log_debug("The mute control of device %s changed from %s to %s.", device->name, ++ old_control ? old_control->name : "(unset)", control ? control->name : "(unset)"); ++ ++ pa_hook_fire(&device->volume_api->hooks[PA_VOLUME_API_HOOK_DEVICE_MUTE_CONTROL_CHANGED], device); ++} ++ ++void pa_device_set_mute_control(pa_device *device, pa_mute_control *control) { ++ pa_assert(device); ++ ++ device->use_default_mute_control = false; ++ set_mute_control_internal(device, control); ++} ++ ++void pa_device_description_changed(pa_device *device, const char *new_description) { ++ char *old_description; ++ ++ pa_assert(device); ++ pa_assert(new_description); ++ ++ old_description = device->description; ++ ++ if (pa_streq(new_description, old_description)) ++ return; ++ ++ device->description = pa_xstrdup(new_description); ++ pa_log_debug("The description of device %s changed from \"%s\" to \"%s\".", device->name, old_description, ++ new_description); ++ pa_xfree(old_description); ++ pa_hook_fire(&device->volume_api->hooks[PA_VOLUME_API_HOOK_DEVICE_DESCRIPTION_CHANGED], device); ++} ++ ++void pa_device_set_default_volume_control(pa_device *device, pa_volume_control *control) { ++ pa_volume_control *old_control; ++ ++ pa_assert(device); ++ ++ old_control = device->default_volume_control; ++ ++ if (control == old_control) ++ return; ++ ++ if (old_control) ++ pa_volume_control_remove_default_for_device(old_control, device); ++ ++ device->default_volume_control = control; ++ ++ if (control) ++ pa_volume_control_add_default_for_device(control, device); ++ ++ if (device->use_default_volume_control) ++ set_volume_control_internal(device, control); ++} ++ ++void pa_device_set_default_mute_control(pa_device *device, pa_mute_control *control) { ++ pa_mute_control *old_control; ++ ++ pa_assert(device); ++ ++ old_control = device->default_mute_control; ++ ++ if (control == old_control) ++ return; ++ ++ if (old_control) ++ pa_mute_control_remove_default_for_device(old_control, device); ++ ++ device->default_mute_control = control; ++ ++ if (control) ++ pa_mute_control_add_default_for_device(control, device); ++ ++ if (device->use_default_mute_control) ++ set_mute_control_internal(device, control); ++} +diff --git a/src/modules/volume-api/device.h b/src/modules/volume-api/device.h +new file mode 100644 +index 0000000..9eac7e9 +--- /dev/null ++++ b/src/modules/volume-api/device.h +@@ -0,0 +1,76 @@ ++#ifndef foodevicehfoo ++#define foodevicehfoo ++ ++/*** ++ This file is part of PulseAudio. ++ ++ Copyright 2014 Intel Corporation ++ ++ PulseAudio is free software; you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as published ++ by the Free Software Foundation; either version 2.1 of the License, ++ or (at your option) any later version. ++ ++ PulseAudio 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 Lesser General Public License ++ along with PulseAudio; if not, write to the Free Software ++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ USA. ++***/ ++ ++#include ++ ++#include ++ ++typedef struct pa_device pa_device; ++ ++struct pa_device { ++ pa_volume_api *volume_api; ++ uint32_t index; ++ const char *name; ++ char *description; ++ pa_direction_t direction; ++ pa_dynarray *device_types; ++ pa_proplist *proplist; ++ pa_volume_control *volume_control; ++ pa_mute_control *mute_control; ++ ++ /* The device implementation can provide default volume and mute controls, ++ * which are used in case there's no policy module that wants to override ++ * the defaults. */ ++ pa_volume_control *default_volume_control; ++ bool use_default_volume_control; ++ pa_mute_control *default_mute_control; ++ bool use_default_mute_control; ++ ++ bool linked; ++ bool unlinked; ++}; ++ ++pa_device *pa_device_new(pa_volume_api *api, const char *name, const char *description, pa_direction_t direction, ++ const char * const *device_types, unsigned n_device_types); ++void pa_device_put(pa_device *device, pa_volume_control *default_volume_control, pa_mute_control *default_mute_control); ++void pa_device_unlink(pa_device *device); ++void pa_device_free(pa_device *device); ++ ++/* Called by policy modules. */ ++void pa_device_set_volume_control(pa_device *device, pa_volume_control *control); ++void pa_device_set_mute_control(pa_device *device, pa_mute_control *control); ++ ++/* Called by policy modules. Note that pa_device_set_volume_control() and ++ * pa_device_set_mute_control() automatically disable the corresponding ++ * use_default flags, so these functions are mainly useful for re-enabling the ++ * flags. */ ++void pa_device_set_use_default_volume_control(pa_device *device, bool use); ++void pa_device_set_use_default_mute_control(pa_device *device, bool use); ++ ++/* Called by the device implementation. */ ++void pa_device_description_changed(pa_device *device, const char *new_description); ++void pa_device_set_default_volume_control(pa_device *device, pa_volume_control *control); ++void pa_device_set_default_mute_control(pa_device *device, pa_mute_control *control); ++ ++#endif +diff --git a/src/modules/volume-api/mute-control.c b/src/modules/volume-api/mute-control.c +new file mode 100644 +index 0000000..adc008e +--- /dev/null ++++ b/src/modules/volume-api/mute-control.c +@@ -0,0 +1,306 @@ ++/*** ++ This file is part of PulseAudio. ++ ++ Copyright 2014 Intel Corporation ++ ++ PulseAudio is free software; you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as published ++ by the Free Software Foundation; either version 2.1 of the License, ++ or (at your option) any later version. ++ ++ PulseAudio 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 Lesser General Public License ++ along with PulseAudio; if not, write to the Free Software ++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ USA. ++***/ ++ ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ ++#include "mute-control.h" ++ ++#include ++#include ++#include ++ ++#include ++ ++pa_mute_control *pa_mute_control_new(pa_volume_api *api, const char *name, const char *description) { ++ pa_mute_control *control; ++ ++ pa_assert(api); ++ pa_assert(name); ++ pa_assert(description); ++ ++ control = pa_xnew0(pa_mute_control, 1); ++ control->volume_api = api; ++ control->index = pa_volume_api_allocate_mute_control_index(api); ++ pa_assert_se(pa_volume_api_register_name(api, name, false, &control->name) >= 0); ++ control->description = pa_xstrdup(description); ++ control->proplist = pa_proplist_new(); ++ control->devices = pa_hashmap_new(NULL, NULL); ++ control->default_for_devices = pa_hashmap_new(NULL, NULL); ++ control->streams = pa_hashmap_new(NULL, NULL); ++ control->audio_groups = pa_hashmap_new(NULL, NULL); ++ ++ return control; ++} ++ ++void pa_mute_control_put(pa_mute_control *control, bool initial_mute, bool initial_mute_is_set, ++ pa_mute_control_set_initial_mute_cb_t set_initial_mute_cb) { ++ const char *prop_key; ++ void *state = NULL; ++ ++ pa_assert(control); ++ pa_assert(initial_mute_is_set || control->set_mute); ++ pa_assert(set_initial_mute_cb || !control->set_mute); ++ ++ if (initial_mute_is_set) ++ control->mute = initial_mute; ++ else ++ control->mute = false; ++ ++ if (set_initial_mute_cb) ++ set_initial_mute_cb(control); ++ ++ pa_volume_api_add_mute_control(control->volume_api, control); ++ ++ control->linked = true; ++ ++ pa_log_debug("Created mute control #%u.", control->index); ++ pa_log_debug(" Name: %s", control->name); ++ pa_log_debug(" Description: %s", control->description); ++ pa_log_debug(" Mute: %s", pa_yes_no(control->mute)); ++ pa_log_debug(" Properties:"); ++ ++ while ((prop_key = pa_proplist_iterate(control->proplist, &state))) ++ pa_log_debug(" %s = %s", prop_key, pa_strnull(pa_proplist_gets(control->proplist, prop_key))); ++ ++ pa_hook_fire(&control->volume_api->hooks[PA_VOLUME_API_HOOK_MUTE_CONTROL_PUT], control); ++} ++ ++void pa_mute_control_unlink(pa_mute_control *control) { ++ pa_audio_group *group; ++ pa_device *device; ++ pas_stream *stream; ++ ++ pa_assert(control); ++ ++ if (control->unlinked) { ++ pa_log_debug("Unlinking mute control %s (already unlinked, this is a no-op).", control->name); ++ return; ++ } ++ ++ control->unlinked = true; ++ ++ pa_log_debug("Unlinking mute control %s.", control->name); ++ ++ if (control->linked) ++ pa_hook_fire(&control->volume_api->hooks[PA_VOLUME_API_HOOK_MUTE_CONTROL_UNLINK], control); ++ ++ pa_volume_api_remove_mute_control(control->volume_api, control); ++ ++ while ((group = pa_hashmap_first(control->audio_groups))) ++ pa_audio_group_set_mute_control(group, NULL); ++ ++ while ((stream = pa_hashmap_first(control->streams))) ++ pas_stream_set_mute_control(stream, NULL); ++ ++ while ((device = pa_hashmap_first(control->default_for_devices))) ++ pa_device_set_default_mute_control(device, NULL); ++ ++ while ((device = pa_hashmap_first(control->devices))) { ++ /* Why do we have this assertion here? The concern is that if we call ++ * pa_device_set_mute_control() for some device that has the ++ * use_default_mute_control flag set, then that flag will be unset as ++ * a side effect, and we don't want that side effect. This assertion ++ * should be safe, because we just called ++ * pa_device_set_default_mute_control(NULL) for each device that this ++ * control was the default for, and that should ensure that we don't ++ * any more hold any references to devices that used to use this ++ * control as the default. */ ++ pa_assert(!device->use_default_mute_control); ++ pa_device_set_mute_control(device, NULL); ++ } ++} ++ ++void pa_mute_control_free(pa_mute_control *control) { ++ pa_assert(control); ++ ++ if (!control->unlinked) ++ pa_mute_control_unlink(control); ++ ++ if (control->audio_groups) { ++ pa_assert(pa_hashmap_isempty(control->audio_groups)); ++ pa_hashmap_free(control->audio_groups); ++ } ++ ++ if (control->streams) { ++ pa_assert(pa_hashmap_isempty(control->streams)); ++ pa_hashmap_free(control->streams); ++ } ++ ++ if (control->default_for_devices) { ++ pa_assert(pa_hashmap_isempty(control->default_for_devices)); ++ pa_hashmap_free(control->default_for_devices); ++ } ++ ++ if (control->devices) { ++ pa_assert(pa_hashmap_isempty(control->devices)); ++ pa_hashmap_free(control->devices); ++ } ++ ++ if (control->proplist) ++ pa_proplist_free(control->proplist); ++ ++ pa_xfree(control->description); ++ ++ if (control->name) ++ pa_volume_api_unregister_name(control->volume_api, control->name); ++ ++ pa_xfree(control); ++} ++ ++void pa_mute_control_set_owner_audio_group(pa_mute_control *control, pa_audio_group *group) { ++ pa_assert(control); ++ pa_assert(group); ++ ++ control->owner_audio_group = group; ++} ++ ++static void set_mute_internal(pa_mute_control *control, bool mute) { ++ bool old_mute; ++ ++ pa_assert(control); ++ ++ old_mute = control->mute; ++ ++ if (mute == old_mute) ++ return; ++ ++ control->mute = mute; ++ ++ if (!control->linked || control->unlinked) ++ return; ++ ++ pa_log_debug("The mute of mute control %s changed from %s to %s.", control->name, pa_yes_no(old_mute), ++ pa_yes_no(control->mute)); ++ ++ pa_hook_fire(&control->volume_api->hooks[PA_VOLUME_API_HOOK_MUTE_CONTROL_MUTE_CHANGED], control); ++} ++ ++int pa_mute_control_set_mute(pa_mute_control *control, bool mute) { ++ int r; ++ ++ pa_assert(control); ++ ++ if (!control->set_mute) { ++ pa_log_info("Tried to set the mute of mute control %s, but the mute control doesn't support the operation.", ++ control->name); ++ return -PA_ERR_NOTSUPPORTED; ++ } ++ ++ if (mute == control->mute) ++ return 0; ++ ++ control->set_mute_in_progress = true; ++ r = control->set_mute(control, mute); ++ control->set_mute_in_progress = false; ++ ++ if (r >= 0) ++ set_mute_internal(control, mute); ++ ++ return r; ++} ++ ++void pa_mute_control_description_changed(pa_mute_control *control, const char *new_description) { ++ char *old_description; ++ ++ pa_assert(control); ++ pa_assert(new_description); ++ ++ old_description = control->description; ++ ++ if (pa_streq(new_description, old_description)) ++ return; ++ ++ control->description = pa_xstrdup(new_description); ++ pa_log_debug("The description of mute control %s changed from \"%s\" to \"%s\".", control->name, old_description, ++ new_description); ++ pa_xfree(old_description); ++ pa_hook_fire(&control->volume_api->hooks[PA_VOLUME_API_HOOK_MUTE_CONTROL_DESCRIPTION_CHANGED], control); ++} ++ ++void pa_mute_control_mute_changed(pa_mute_control *control, bool new_mute) { ++ pa_assert(control); ++ ++ if (!control->linked) ++ return; ++ ++ if (control->set_mute_in_progress) ++ return; ++ ++ set_mute_internal(control, new_mute); ++} ++ ++void pa_mute_control_add_device(pa_mute_control *control, pa_device *device) { ++ pa_assert(control); ++ pa_assert(device); ++ ++ pa_assert_se(pa_hashmap_put(control->devices, device, device) >= 0); ++} ++ ++void pa_mute_control_remove_device(pa_mute_control *control, pa_device *device) { ++ pa_assert(control); ++ pa_assert(device); ++ ++ pa_assert_se(pa_hashmap_remove(control->devices, device)); ++} ++ ++void pa_mute_control_add_default_for_device(pa_mute_control *control, pa_device *device) { ++ pa_assert(control); ++ pa_assert(device); ++ ++ pa_assert_se(pa_hashmap_put(control->default_for_devices, device, device) >= 0); ++} ++ ++void pa_mute_control_remove_default_for_device(pa_mute_control *control, pa_device *device) { ++ pa_assert(control); ++ pa_assert(device); ++ ++ pa_assert_se(pa_hashmap_remove(control->default_for_devices, device)); ++} ++ ++void pa_mute_control_add_stream(pa_mute_control *control, pas_stream *stream) { ++ pa_assert(control); ++ pa_assert(stream); ++ ++ pa_assert_se(pa_hashmap_put(control->streams, stream, stream) >= 0); ++} ++ ++void pa_mute_control_remove_stream(pa_mute_control *control, pas_stream *stream) { ++ pa_assert(control); ++ pa_assert(stream); ++ ++ pa_assert_se(pa_hashmap_remove(control->streams, stream)); ++} ++ ++void pa_mute_control_add_audio_group(pa_mute_control *control, pa_audio_group *group) { ++ pa_assert(control); ++ pa_assert(group); ++ ++ pa_assert_se(pa_hashmap_put(control->audio_groups, group, group) >= 0); ++} ++ ++void pa_mute_control_remove_audio_group(pa_mute_control *control, pa_audio_group *group) { ++ pa_assert(control); ++ pa_assert(group); ++ ++ pa_assert_se(pa_hashmap_remove(control->audio_groups, group)); ++} +diff --git a/src/modules/volume-api/mute-control.h b/src/modules/volume-api/mute-control.h +new file mode 100644 +index 0000000..1f70a43 +--- /dev/null ++++ b/src/modules/volume-api/mute-control.h +@@ -0,0 +1,102 @@ ++#ifndef foomutecontrolhfoo ++#define foomutecontrolhfoo ++ ++/*** ++ This file is part of PulseAudio. ++ ++ Copyright 2014 Intel Corporation ++ ++ PulseAudio is free software; you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as published ++ by the Free Software Foundation; either version 2.1 of the License, ++ or (at your option) any later version. ++ ++ PulseAudio 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 Lesser General Public License ++ along with PulseAudio; if not, write to the Free Software ++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ USA. ++***/ ++ ++#include ++ ++typedef struct pa_mute_control pa_mute_control; ++ ++struct pa_mute_control { ++ pa_volume_api *volume_api; ++ uint32_t index; ++ const char *name; ++ char *description; ++ pa_proplist *proplist; ++ bool mute; ++ ++ /* If this mute control is the "own mute control" of an audio group, this ++ * is set to point to that group, otherwise this is NULL. */ ++ pa_audio_group *owner_audio_group; ++ ++ pa_hashmap *devices; /* pa_device -> pa_device (hashmap-as-a-set) */ ++ pa_hashmap *default_for_devices; /* pa_device -> pa_device (hashmap-as-a-set) */ ++ pa_hashmap *streams; /* pas_stream -> pas_stream (hashmap-as-a-set) */ ++ pa_hashmap *audio_groups; /* pa_audio_group -> pa_audio_group (hashmap-as-a-set) */ ++ ++ bool linked; ++ bool unlinked; ++ bool set_mute_in_progress; ++ ++ /* Called from pa_mute_control_set_mute(). The implementation is expected ++ * to return a negative error code on failure. May be NULL, if the mute ++ * control is read-only. */ ++ int (*set_mute)(pa_mute_control *control, bool mute); ++ ++ void *userdata; ++}; ++ ++pa_mute_control *pa_mute_control_new(pa_volume_api *api, const char *name, const char *description); ++ ++typedef void (*pa_mute_control_set_initial_mute_cb_t)(pa_mute_control *control); ++ ++/* initial_mute is the preferred initial mute of the mute control ++ * implementation. It may be unset, if the implementation doesn't care about ++ * the initial state of the mute control. Read-only mute controls, however, ++ * must always set initial_mute. ++ * ++ * The implementation's initial mute preference may be overridden by policy, if ++ * the mute control isn't read-only. When the final initial mute is known, the ++ * the implementation is notified via set_initial_mute_cb (the mute can be read ++ * from control->mute). set_initial_mute_cb may be NULL, if the mute control is ++ * read-only. */ ++void pa_mute_control_put(pa_mute_control *control, bool initial_mute, bool initial_mute_is_set, ++ pa_mute_control_set_initial_mute_cb_t set_initial_mute_cb); ++ ++void pa_mute_control_unlink(pa_mute_control *control); ++void pa_mute_control_free(pa_mute_control *control); ++ ++/* Called by audio-group.c only. */ ++void pa_mute_control_set_owner_audio_group(pa_mute_control *control, pa_audio_group *group); ++ ++/* Called by clients and policy modules. */ ++int pa_mute_control_set_mute(pa_mute_control *control, bool mute); ++ ++/* Called by the mute control implementation. */ ++void pa_mute_control_description_changed(pa_mute_control *control, const char *new_description); ++void pa_mute_control_mute_changed(pa_mute_control *control, bool new_mute); ++ ++/* Called from device.c only. */ ++void pa_mute_control_add_device(pa_mute_control *control, pa_device *device); ++void pa_mute_control_remove_device(pa_mute_control *control, pa_device *device); ++void pa_mute_control_add_default_for_device(pa_mute_control *control, pa_device *device); ++void pa_mute_control_remove_default_for_device(pa_mute_control *control, pa_device *device); ++ ++/* Called from sstream.c only. */ ++void pa_mute_control_add_stream(pa_mute_control *control, pas_stream *stream); ++void pa_mute_control_remove_stream(pa_mute_control *control, pas_stream *stream); ++ ++/* Called from audio-group.c only. */ ++void pa_mute_control_add_audio_group(pa_mute_control *control, pa_audio_group *group); ++void pa_mute_control_remove_audio_group(pa_mute_control *control, pa_audio_group *group); ++ ++#endif +diff --git a/src/modules/volume-api/sstream.c b/src/modules/volume-api/sstream.c +new file mode 100644 +index 0000000..e3531a8 +--- /dev/null ++++ b/src/modules/volume-api/sstream.c +@@ -0,0 +1,366 @@ ++/*** ++ This file is part of PulseAudio. ++ ++ Copyright 2014 Intel Corporation ++ ++ PulseAudio is free software; you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as published ++ by the Free Software Foundation; either version 2.1 of the License, ++ or (at your option) any later version. ++ ++ PulseAudio 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 Lesser General Public License ++ along with PulseAudio; if not, write to the Free Software ++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ USA. ++***/ ++ ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ ++#include "sstream.h" ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++ ++pas_stream *pas_stream_new(pa_volume_api *api, const char *name, const char *description, pa_direction_t direction) { ++ pas_stream *stream; ++ ++ pa_assert(api); ++ pa_assert(name); ++ pa_assert(description); ++ ++ stream = pa_xnew0(pas_stream, 1); ++ stream->volume_api = api; ++ stream->index = pa_volume_api_allocate_stream_index(api); ++ pa_assert_se(pa_volume_api_register_name(api, name, false, &stream->name) >= 0); ++ stream->description = pa_xstrdup(description); ++ stream->direction = direction; ++ stream->proplist = pa_proplist_new(); ++ stream->use_default_volume_control = true; ++ stream->use_default_mute_control = true; ++ ++ return stream; ++} ++ ++static void set_volume_control_internal(pas_stream *stream, pa_volume_control *control) { ++ pa_volume_control *old_control; ++ ++ pa_assert(stream); ++ ++ old_control = stream->volume_control; ++ ++ if (control == old_control) ++ return; ++ ++ if (old_control) { ++ /* If the old control pointed to the own volume control of an audio ++ * group, then the stream's audio group for volume needs to be ++ * updated. We set it to NULL here, and if it should be non-NULL, that ++ * will be fixed very soon (a few lines down). */ ++ pas_stream_set_audio_group_for_volume(stream, NULL); ++ ++ pa_volume_control_remove_stream(old_control, stream); ++ } ++ ++ stream->volume_control = control; ++ ++ if (control) { ++ pa_volume_control_add_stream(control, stream); ++ pas_stream_set_audio_group_for_volume(stream, control->owner_audio_group); ++ } ++ ++ if (!stream->linked || stream->unlinked) ++ return; ++ ++ pa_log_debug("The volume control of stream %s changed from %s to %s.", stream->name, ++ old_control ? old_control->name : "(unset)", control ? control->name : "(unset)"); ++ ++ pa_hook_fire(&stream->volume_api->hooks[PA_VOLUME_API_HOOK_STREAM_VOLUME_CONTROL_CHANGED], stream); ++} ++ ++static void set_mute_control_internal(pas_stream *stream, pa_mute_control *control) { ++ pa_mute_control *old_control; ++ ++ pa_assert(stream); ++ ++ old_control = stream->mute_control; ++ ++ if (control == old_control) ++ return; ++ ++ if (old_control) { ++ /* If the old control pointed to the own mute control of an audio ++ * group, then the stream's audio group for mute needs to be updated. ++ * We set it to NULL here, and if it should be non-NULL, that will be ++ * fixed very soon (a few lines down). */ ++ pas_stream_set_audio_group_for_mute(stream, NULL); ++ ++ pa_mute_control_remove_stream(old_control, stream); ++ } ++ ++ stream->mute_control = control; ++ ++ if (control) { ++ pa_mute_control_add_stream(control, stream); ++ pas_stream_set_audio_group_for_mute(stream, control->owner_audio_group); ++ } ++ ++ if (!stream->linked || stream->unlinked) ++ return; ++ ++ pa_log_debug("The mute control of stream %s changed from %s to %s.", stream->name, ++ old_control ? old_control->name : "(unset)", control ? control->name : "(unset)"); ++ ++ pa_hook_fire(&stream->volume_api->hooks[PA_VOLUME_API_HOOK_STREAM_MUTE_CONTROL_CHANGED], stream); ++} ++ ++void pas_stream_put(pas_stream *stream, pa_proplist *initial_properties) { ++ const char *prop_key; ++ void *state = NULL; ++ ++ pa_assert(stream); ++ pa_assert(!stream->create_own_volume_control || stream->delete_own_volume_control); ++ pa_assert(!stream->create_own_mute_control || stream->delete_own_mute_control); ++ ++ if (initial_properties) ++ pa_proplist_update(stream->proplist, PA_UPDATE_REPLACE, initial_properties); ++ ++ pa_hook_fire(&stream->volume_api->hooks[PA_VOLUME_API_HOOK_STREAM_SET_INITIAL_VOLUME_CONTROL], stream); ++ ++ if (stream->use_default_volume_control) ++ set_volume_control_internal(stream, stream->own_volume_control); ++ ++ pa_hook_fire(&stream->volume_api->hooks[PA_VOLUME_API_HOOK_STREAM_SET_INITIAL_MUTE_CONTROL], stream); ++ ++ if (stream->use_default_mute_control) ++ set_mute_control_internal(stream, stream->own_mute_control); ++ ++ pa_volume_api_add_stream(stream->volume_api, stream); ++ ++ stream->linked = true; ++ ++ pa_log_debug("Created stream #%u.", stream->index); ++ pa_log_debug(" Name: %s", stream->name); ++ pa_log_debug(" Description: %s", stream->description); ++ pa_log_debug(" Direction: %s", pa_direction_to_string(stream->direction)); ++ pa_log_debug(" Volume control: %s", stream->volume_control ? stream->volume_control->name : "(unset)"); ++ pa_log_debug(" Mute control: %s", stream->mute_control ? stream->mute_control->name : "(unset)"); ++ pa_log_debug(" Properties:"); ++ ++ while ((prop_key = pa_proplist_iterate(stream->proplist, &state))) ++ pa_log_debug(" %s = %s", prop_key, pa_strnull(pa_proplist_gets(stream->proplist, prop_key))); ++ ++ pa_hook_fire(&stream->volume_api->hooks[PA_VOLUME_API_HOOK_STREAM_PUT], stream); ++} ++ ++void pas_stream_unlink(pas_stream *stream) { ++ pa_assert(stream); ++ ++ if (stream->unlinked) { ++ pa_log_debug("Unlinking stream %s (already unlinked, this is a no-op).", stream->name); ++ return; ++ } ++ ++ stream->unlinked = true; ++ ++ pa_log_debug("Unlinking stream %s.", stream->name); ++ ++ if (stream->linked) ++ pa_hook_fire(&stream->volume_api->hooks[PA_VOLUME_API_HOOK_STREAM_UNLINK], stream); ++ ++ pa_volume_api_remove_stream(stream->volume_api, stream); ++ ++ pas_stream_set_audio_group_for_mute(stream, NULL); ++ pas_stream_set_audio_group_for_volume(stream, NULL); ++ pas_stream_set_mute_control(stream, NULL); ++ pas_stream_set_volume_control(stream, NULL); ++ pas_stream_set_have_own_mute_control(stream, false); ++ pas_stream_set_have_own_volume_control(stream, false); ++} ++ ++void pas_stream_free(pas_stream *stream) { ++ pa_assert(stream); ++ ++ if (!stream->unlinked) ++ pas_stream_unlink(stream); ++ ++ if (stream->proplist) ++ pa_proplist_free(stream->proplist); ++ ++ pa_xfree(stream->description); ++ ++ if (stream->name) ++ pa_volume_api_unregister_name(stream->volume_api, stream->name); ++ ++ pa_xfree(stream); ++} ++ ++int pas_stream_set_have_own_volume_control(pas_stream *stream, bool have) { ++ pa_assert(stream); ++ ++ if (have == stream->have_own_volume_control) ++ return 0; ++ ++ if (have) { ++ pa_assert(!stream->own_volume_control); ++ ++ if (!stream->create_own_volume_control) { ++ pa_log_debug("Stream %s doesn't support own volume control.", stream->name); ++ return -PA_ERR_NOTSUPPORTED; ++ } ++ ++ stream->own_volume_control = stream->create_own_volume_control(stream); ++ } else { ++ stream->delete_own_volume_control(stream); ++ stream->own_volume_control = NULL; ++ } ++ ++ stream->have_own_volume_control = have; ++ ++ return 0; ++} ++ ++int pas_stream_set_have_own_mute_control(pas_stream *stream, bool have) { ++ pa_assert(stream); ++ ++ if (have == stream->have_own_mute_control) ++ return 0; ++ ++ if (have) { ++ pa_assert(!stream->own_mute_control); ++ ++ if (!stream->create_own_mute_control) { ++ pa_log_debug("Stream %s doesn't support own mute control.", stream->name); ++ return -PA_ERR_NOTSUPPORTED; ++ } ++ ++ stream->own_mute_control = stream->create_own_mute_control(stream); ++ } else { ++ stream->delete_own_mute_control(stream); ++ stream->own_mute_control = NULL; ++ } ++ ++ stream->have_own_mute_control = have; ++ ++ return 0; ++} ++ ++void pas_stream_set_volume_control(pas_stream *stream, pa_volume_control *control) { ++ pa_assert(stream); ++ ++ stream->use_default_volume_control = false; ++ ++ if (stream->volume_control_binding) { ++ pa_binding_free(stream->volume_control_binding); ++ stream->volume_control_binding = NULL; ++ } ++ ++ set_volume_control_internal(stream, control); ++} ++ ++void pas_stream_set_mute_control(pas_stream *stream, pa_mute_control *control) { ++ pa_assert(stream); ++ ++ stream->use_default_mute_control = false; ++ ++ if (stream->mute_control_binding) { ++ pa_binding_free(stream->mute_control_binding); ++ stream->mute_control_binding = NULL; ++ } ++ ++ set_mute_control_internal(stream, control); ++} ++ ++void pas_stream_bind_volume_control(pas_stream *stream, pa_binding_target_info *target_info) { ++ pa_binding_owner_info owner_info = { ++ .userdata = stream, ++ .set_value = (pa_binding_set_value_cb_t) set_volume_control_internal, ++ }; ++ ++ pa_assert(stream); ++ pa_assert(target_info); ++ ++ stream->use_default_volume_control = false; ++ ++ if (stream->volume_control_binding) ++ pa_binding_free(stream->volume_control_binding); ++ ++ stream->volume_control_binding = pa_binding_new(stream->volume_api, &owner_info, target_info); ++} ++ ++void pas_stream_bind_mute_control(pas_stream *stream, pa_binding_target_info *target_info) { ++ pa_binding_owner_info owner_info = { ++ .userdata = stream, ++ .set_value = (pa_binding_set_value_cb_t) set_mute_control_internal, ++ }; ++ ++ pa_assert(stream); ++ pa_assert(target_info); ++ ++ stream->use_default_mute_control = false; ++ ++ if (stream->mute_control_binding) ++ pa_binding_free(stream->mute_control_binding); ++ ++ stream->mute_control_binding = pa_binding_new(stream->volume_api, &owner_info, target_info); ++} ++ ++void pas_stream_description_changed(pas_stream *stream, const char *new_description) { ++ char *old_description; ++ ++ pa_assert(stream); ++ pa_assert(new_description); ++ ++ old_description = stream->description; ++ ++ if (pa_streq(new_description, old_description)) ++ return; ++ ++ stream->description = pa_xstrdup(new_description); ++ pa_log_debug("The description of stream %s changed from \"%s\" to \"%s\".", stream->name, old_description, ++ new_description); ++ pa_xfree(old_description); ++ pa_hook_fire(&stream->volume_api->hooks[PA_VOLUME_API_HOOK_STREAM_DESCRIPTION_CHANGED], stream); ++} ++ ++void pas_stream_set_audio_group_for_volume(pas_stream *stream, pa_audio_group *group) { ++ pa_assert(stream); ++ ++ if (group == stream->audio_group_for_volume) ++ return; ++ ++ if (stream->audio_group_for_volume) ++ pa_audio_group_remove_volume_stream(stream->audio_group_for_volume, stream); ++ ++ stream->audio_group_for_volume = group; ++ ++ if (group) ++ pa_audio_group_add_volume_stream(group, stream); ++} ++ ++void pas_stream_set_audio_group_for_mute(pas_stream *stream, pa_audio_group *group) { ++ pa_assert(stream); ++ ++ if (group == stream->audio_group_for_mute) ++ return; ++ ++ if (stream->audio_group_for_mute) ++ pa_audio_group_remove_mute_stream(stream->audio_group_for_mute, stream); ++ ++ stream->audio_group_for_mute = group; ++ ++ if (group) ++ pa_audio_group_add_mute_stream(group, stream); ++} +diff --git a/src/modules/volume-api/sstream.h b/src/modules/volume-api/sstream.h +new file mode 100644 +index 0000000..a65b34c +--- /dev/null ++++ b/src/modules/volume-api/sstream.h +@@ -0,0 +1,108 @@ ++#ifndef foosstreamhfoo ++#define foosstreamhfoo ++ ++/*** ++ This file is part of PulseAudio. ++ ++ Copyright 2014 Intel Corporation ++ ++ PulseAudio is free software; you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as published ++ by the Free Software Foundation; either version 2.1 of the License, ++ or (at your option) any later version. ++ ++ PulseAudio 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 Lesser General Public License ++ along with PulseAudio; if not, write to the Free Software ++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ USA. ++***/ ++ ++#include ++ ++/* We use the "pas_" prefix in pas_stream, because there's already pa_stream in ++ * the client API, and there's no good alternative term for streams. The 's' in ++ * "pas" means "server", i.e. the point is that this stuff is for servers, ++ * while pa_stream is for clients. */ ++ ++typedef struct pas_stream pas_stream; ++ ++struct pas_stream { ++ pa_volume_api *volume_api; ++ uint32_t index; ++ const char *name; ++ char *description; ++ pa_direction_t direction; ++ pa_proplist *proplist; ++ pa_volume_control *volume_control; ++ pa_mute_control *mute_control; ++ bool use_default_volume_control; ++ bool use_default_mute_control; ++ bool have_own_volume_control; ++ bool have_own_mute_control; ++ pa_volume_control *own_volume_control; ++ pa_mute_control *own_mute_control; ++ ++ pa_binding *volume_control_binding; ++ pa_binding *mute_control_binding; ++ pa_audio_group *audio_group_for_volume; ++ pa_audio_group *audio_group_for_mute; ++ ++ bool linked; ++ bool unlinked; ++ ++ /* Called when the own volume control is enabled. The callback ++ * implementation should return a new linked volume control object. The ++ * callback may be NULL, in which case the own volume control can't be ++ * enabled. */ ++ pa_volume_control *(*create_own_volume_control)(pas_stream *stream); ++ ++ /* Called when the own volume control is disabled. The implementation ++ * should free stream->own_volume_control. The callback may be NULL only if ++ * create_own_volume_control is NULL also. */ ++ void (*delete_own_volume_control)(pas_stream *stream); ++ ++ /* Called when the own mute control is enabled. The callback implementation ++ * should return a new linked mute control object. The callback may be ++ * NULL, in which case the own mute control can't be enabled. */ ++ pa_mute_control *(*create_own_mute_control)(pas_stream *stream); ++ ++ /* Called when the own mute control is disabled. The implementation should ++ * free stream->own_mute_control. The callback may be NULL only if ++ * create_own_mute_control is NULL also. */ ++ void (*delete_own_mute_control)(pas_stream *stream); ++ ++ void *userdata; ++}; ++ ++pas_stream *pas_stream_new(pa_volume_api *api, const char *name, const char *description, pa_direction_t direction); ++void pas_stream_put(pas_stream *stream, pa_proplist *initial_properties); ++void pas_stream_unlink(pas_stream *stream); ++void pas_stream_free(pas_stream *stream); ++ ++/* Called by the stream implementation and possibly by policy modules. ++ * Enabling own controls may fail (the stream may not support own controls), ++ * disabling will never fail. */ ++int pas_stream_set_have_own_volume_control(pas_stream *stream, bool have); ++int pas_stream_set_have_own_mute_control(pas_stream *stream, bool have); ++ ++/* Called by policy modules. */ ++void pas_stream_set_volume_control(pas_stream *stream, pa_volume_control *control); ++void pas_stream_set_mute_control(pas_stream *stream, pa_mute_control *control); ++void pas_stream_bind_volume_control(pas_stream *stream, pa_binding_target_info *target_info); ++void pas_stream_bind_mute_control(pas_stream *stream, pa_binding_target_info *target_info); ++ ++/* Called by the stream implementation. */ ++void pas_stream_description_changed(pas_stream *stream, const char *new_description); ++ ++/* Called by audio-group.c only. Adding a stream to an audio group happens ++ * implicitly when the volume or mute control of a stream is set to point to ++ * the own control of an audio group. */ ++void pas_stream_set_audio_group_for_volume(pas_stream *stream, pa_audio_group *group); ++void pas_stream_set_audio_group_for_mute(pas_stream *stream, pa_audio_group *group); ++ ++#endif +diff --git a/src/modules/volume-api/stream-creator.c b/src/modules/volume-api/stream-creator.c +new file mode 100644 +index 0000000..2bd0053 +--- /dev/null ++++ b/src/modules/volume-api/stream-creator.c +@@ -0,0 +1,691 @@ ++/*** ++ This file is part of PulseAudio. ++ ++ Copyright 2014 Intel Corporation ++ ++ PulseAudio is free software; you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as published ++ by the Free Software Foundation; either version 2.1 of the License, ++ or (at your option) any later version. ++ ++ PulseAudio 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 Lesser General Public License ++ along with PulseAudio; if not, write to the Free Software ++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ USA. ++***/ ++ ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ ++#include "stream-creator.h" ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++struct pa_stream_creator { ++ pa_volume_api *volume_api; ++ pa_hashmap *streams; /* pa_sink_input/pa_source_output -> struct stream */ ++ pa_hook_slot *sink_input_put_slot; ++ pa_hook_slot *sink_input_unlink_slot; ++ pa_hook_slot *source_output_put_slot; ++ pa_hook_slot *source_output_unlink_slot; ++}; ++ ++enum stream_type { ++ STREAM_TYPE_SINK_INPUT, ++ STREAM_TYPE_SOURCE_OUTPUT, ++}; ++ ++struct stream { ++ pa_stream_creator *creator; ++ enum stream_type type; ++ pa_sink_input *sink_input; ++ pa_source_output *source_output; ++ pa_client *client; ++ pas_stream *stream; ++ ++ bool unlinked; ++ ++ pa_hook_slot *proplist_changed_slot; ++ pa_hook_slot *client_proplist_changed_slot; ++ pa_hook_slot *volume_changed_slot; ++ pa_hook_slot *mute_changed_slot; ++}; ++ ++static char *get_stream_volume_and_mute_control_description_malloc(struct stream *stream) { ++ const char *application_name = NULL; ++ char *description; ++ ++ pa_assert(stream); ++ ++ if (stream->client) ++ application_name = pa_proplist_gets(stream->client->proplist, PA_PROP_APPLICATION_NAME); ++ ++ if (application_name) ++ description = pa_sprintf_malloc("%s: %s", application_name, stream->stream->description); ++ else ++ description = pa_xstrdup(stream->stream->description); ++ ++ return description; ++} ++ ++static int volume_control_set_volume_cb(pa_volume_control *control, const pa_bvolume *volume, bool set_volume, bool set_balance) { ++ struct stream *stream; ++ pa_bvolume bvolume; ++ pa_cvolume cvolume; ++ ++ pa_assert(control); ++ pa_assert(volume); ++ ++ stream = control->userdata; ++ ++ switch (stream->type) { ++ case STREAM_TYPE_SINK_INPUT: ++ pa_bvolume_from_cvolume(&bvolume, &stream->sink_input->volume, &stream->sink_input->channel_map); ++ break; ++ ++ case STREAM_TYPE_SOURCE_OUTPUT: ++ pa_bvolume_from_cvolume(&bvolume, &stream->source_output->volume, &stream->source_output->channel_map); ++ break; ++ } ++ ++ if (set_volume) ++ bvolume.volume = volume->volume; ++ ++ if (set_balance) ++ pa_bvolume_copy_balance(&bvolume, volume); ++ ++ pa_bvolume_to_cvolume(&bvolume, &cvolume); ++ ++ switch (stream->type) { ++ case STREAM_TYPE_SINK_INPUT: ++ pa_sink_input_set_volume(stream->sink_input, &cvolume, true, true); ++ break; ++ ++ case STREAM_TYPE_SOURCE_OUTPUT: ++ pa_source_output_set_volume(stream->source_output, &cvolume, true, true); ++ break; ++ } ++ ++ return 0; ++} ++ ++static pa_hook_result_t sink_input_or_source_output_volume_changed_cb(void *hook_data, void *call_data, void *userdata) { ++ struct stream *stream = userdata; ++ pa_sink_input *input = NULL; ++ pa_source_output *output = NULL; ++ pa_bvolume bvolume; ++ ++ pa_assert(stream); ++ pa_assert(call_data); ++ ++ switch (stream->type) { ++ case STREAM_TYPE_SINK_INPUT: ++ input = call_data; ++ break; ++ ++ case STREAM_TYPE_SOURCE_OUTPUT: ++ output = call_data; ++ break; ++ } ++ ++ if ((input && input != stream->sink_input) || (output && output != stream->source_output)) ++ return PA_HOOK_OK; ++ ++ if (input) ++ pa_bvolume_from_cvolume(&bvolume, &input->volume, &input->channel_map); ++ else ++ pa_bvolume_from_cvolume(&bvolume, &output->volume, &output->channel_map); ++ ++ pa_volume_control_volume_changed(stream->stream->own_volume_control, &bvolume, true, true); ++ ++ return PA_HOOK_OK; ++} ++ ++static void volume_control_set_initial_volume_cb(pa_volume_control *control) { ++ struct stream *stream; ++ pa_cvolume cvolume; ++ ++ pa_assert(control); ++ ++ stream = control->userdata; ++ pa_bvolume_to_cvolume(&control->volume, &cvolume); ++ ++ switch (stream->type) { ++ case STREAM_TYPE_SINK_INPUT: ++ pa_sink_input_set_volume(stream->sink_input, &cvolume, true, true); ++ break; ++ ++ case STREAM_TYPE_SOURCE_OUTPUT: ++ pa_source_output_set_volume(stream->source_output, &cvolume, true, true); ++ break; ++ } ++} ++ ++static int mute_control_set_mute_cb(pa_mute_control *control, bool mute) { ++ struct stream *stream; ++ ++ pa_assert(control); ++ ++ stream = control->userdata; ++ ++ switch (stream->type) { ++ case STREAM_TYPE_SINK_INPUT: ++ pa_sink_input_set_mute(stream->sink_input, mute, true); ++ break; ++ ++ case STREAM_TYPE_SOURCE_OUTPUT: ++ pa_source_output_set_mute(stream->source_output, mute, true); ++ break; ++ } ++ ++ return 0; ++} ++ ++static pa_hook_result_t sink_input_or_source_output_mute_changed_cb(void *hook_data, void *call_data, void *userdata) { ++ struct stream *stream = userdata; ++ pa_sink_input *input = NULL; ++ pa_source_output *output = NULL; ++ bool mute; ++ ++ pa_assert(stream); ++ pa_assert(call_data); ++ ++ switch (stream->type) { ++ case STREAM_TYPE_SINK_INPUT: ++ input = call_data; ++ break; ++ ++ case STREAM_TYPE_SOURCE_OUTPUT: ++ output = call_data; ++ break; ++ } ++ ++ if ((input && input != stream->sink_input) || (output && output != stream->source_output)) ++ return PA_HOOK_OK; ++ ++ if (input) ++ mute = input->muted; ++ else ++ mute = output->muted; ++ ++ pa_mute_control_mute_changed(stream->stream->own_mute_control, mute); ++ ++ return PA_HOOK_OK; ++} ++ ++static void mute_control_set_initial_mute_cb(pa_mute_control *control) { ++ struct stream *stream; ++ ++ pa_assert(control); ++ ++ stream = control->userdata; ++ ++ switch (stream->type) { ++ case STREAM_TYPE_SINK_INPUT: ++ pa_sink_input_set_mute(stream->sink_input, control->mute, true); ++ break; ++ ++ case STREAM_TYPE_SOURCE_OUTPUT: ++ pa_source_output_set_mute(stream->source_output, control->mute, true); ++ break; ++ } ++} ++ ++static const char *get_sink_input_description(pa_sink_input *input) { ++ const char *description; ++ ++ pa_assert(input); ++ ++ description = pa_proplist_gets(input->proplist, PA_PROP_MEDIA_NAME); ++ if (description) ++ return description; ++ ++ return NULL; ++} ++ ++static const char *get_source_output_description(pa_source_output *output) { ++ const char *description; ++ ++ pa_assert(output); ++ ++ description = pa_proplist_gets(output->proplist, PA_PROP_MEDIA_NAME); ++ if (description) ++ return description; ++ ++ return NULL; ++} ++ ++static pa_volume_control *stream_create_own_volume_control_cb(pas_stream *s) { ++ struct stream *stream; ++ const char *name = NULL; ++ char *description; ++ pa_volume_control *control; ++ pa_bvolume volume; ++ ++ pa_assert(s); ++ ++ stream = s->userdata; ++ ++ switch (stream->type) { ++ case STREAM_TYPE_SINK_INPUT: ++ name = "sink-input-volume-control"; ++ break; ++ ++ case STREAM_TYPE_SOURCE_OUTPUT: ++ name = "source-output-volume-control"; ++ break; ++ } ++ ++ description = get_stream_volume_and_mute_control_description_malloc(stream); ++ control = pa_volume_control_new(stream->creator->volume_api, name, description, true, false); ++ pa_xfree(description); ++ control->set_volume = volume_control_set_volume_cb; ++ control->userdata = stream; ++ ++ pa_assert(!stream->volume_changed_slot); ++ ++ switch (stream->type) { ++ case STREAM_TYPE_SINK_INPUT: ++ stream->volume_changed_slot = ++ pa_hook_connect(&stream->sink_input->core->hooks[PA_CORE_HOOK_SINK_INPUT_VOLUME_CHANGED], PA_HOOK_NORMAL, ++ sink_input_or_source_output_volume_changed_cb, stream); ++ pa_bvolume_from_cvolume(&volume, &stream->sink_input->volume, &stream->sink_input->channel_map); ++ break; ++ ++ case STREAM_TYPE_SOURCE_OUTPUT: ++ stream->volume_changed_slot = ++ pa_hook_connect(&stream->source_output->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_VOLUME_CHANGED], ++ PA_HOOK_NORMAL, sink_input_or_source_output_volume_changed_cb, stream); ++ pa_bvolume_from_cvolume(&volume, &stream->source_output->volume, &stream->source_output->channel_map); ++ break; ++ } ++ ++ pa_volume_control_put(control, &volume, volume_control_set_initial_volume_cb); ++ ++ return control; ++} ++ ++static void stream_delete_own_volume_control_cb(pas_stream *s) { ++ struct stream *stream; ++ ++ pa_assert(s); ++ ++ stream = s->userdata; ++ pa_hook_slot_free(stream->volume_changed_slot); ++ stream->volume_changed_slot = NULL; ++ pa_volume_control_free(s->own_volume_control); ++} ++ ++static pa_mute_control *stream_create_own_mute_control_cb(pas_stream *s) { ++ struct stream *stream; ++ const char *name = NULL; ++ char *description; ++ pa_mute_control *control; ++ bool mute = false; ++ ++ pa_assert(s); ++ ++ stream = s->userdata; ++ ++ switch (stream->type) { ++ case STREAM_TYPE_SINK_INPUT: ++ name = "sink-input-mute-control"; ++ break; ++ ++ case STREAM_TYPE_SOURCE_OUTPUT: ++ name = "source-output-mute-control"; ++ break; ++ } ++ ++ description = get_stream_volume_and_mute_control_description_malloc(stream); ++ control = pa_mute_control_new(stream->creator->volume_api, name, description); ++ pa_xfree(description); ++ control->set_mute = mute_control_set_mute_cb; ++ control->userdata = stream; ++ ++ pa_assert(!stream->mute_changed_slot); ++ ++ switch (stream->type) { ++ case STREAM_TYPE_SINK_INPUT: ++ stream->mute_changed_slot = ++ pa_hook_connect(&stream->sink_input->core->hooks[PA_CORE_HOOK_SINK_INPUT_MUTE_CHANGED], PA_HOOK_NORMAL, ++ sink_input_or_source_output_mute_changed_cb, stream); ++ mute = stream->sink_input->muted; ++ break; ++ ++ case STREAM_TYPE_SOURCE_OUTPUT: ++ stream->mute_changed_slot = ++ pa_hook_connect(&stream->source_output->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MUTE_CHANGED], ++ PA_HOOK_NORMAL, sink_input_or_source_output_mute_changed_cb, stream); ++ mute = stream->source_output->muted; ++ break; ++ } ++ ++ pa_mute_control_put(control, mute, true, mute_control_set_initial_mute_cb); ++ ++ return control; ++} ++ ++static void stream_delete_own_mute_control_cb(pas_stream *s) { ++ struct stream *stream; ++ ++ pa_assert(s); ++ ++ stream = s->userdata; ++ pa_hook_slot_free(stream->mute_changed_slot); ++ stream->mute_changed_slot = NULL; ++ pa_mute_control_free(s->own_mute_control); ++} ++ ++static pa_hook_result_t sink_input_or_source_output_proplist_changed_cb(void *hook_data, void *call_data, void *userdata) { ++ struct stream *stream = userdata; ++ pa_sink_input *input = NULL; ++ pa_source_output *output = NULL; ++ const char *new_stream_description = NULL; ++ char *new_control_description; ++ ++ pa_assert(stream); ++ pa_assert(call_data); ++ ++ switch (stream->type) { ++ case STREAM_TYPE_SINK_INPUT: ++ input = call_data; ++ ++ if (input != stream->sink_input) ++ return PA_HOOK_OK; ++ ++ new_stream_description = get_sink_input_description(input); ++ if (!new_stream_description) ++ new_stream_description = stream->stream->name; ++ break; ++ ++ case STREAM_TYPE_SOURCE_OUTPUT: ++ output = call_data; ++ ++ if (output != stream->source_output) ++ return PA_HOOK_OK; ++ ++ new_stream_description = get_source_output_description(output); ++ if (!new_stream_description) ++ new_stream_description = stream->stream->name; ++ break; ++ } ++ ++ pas_stream_description_changed(stream->stream, new_stream_description); ++ ++ new_control_description = get_stream_volume_and_mute_control_description_malloc(stream); ++ ++ if (stream->stream->own_volume_control) ++ pa_volume_control_description_changed(stream->stream->own_volume_control, new_control_description); ++ ++ if (stream->stream->own_mute_control) ++ pa_mute_control_description_changed(stream->stream->own_mute_control, new_control_description); ++ ++ pa_xfree(new_control_description); ++ ++ return PA_HOOK_OK; ++} ++ ++static pa_hook_result_t client_proplist_changed_cb(void *hook_data, void *call_data, void *userdata) { ++ struct stream *stream = userdata; ++ pa_client *client = call_data; ++ char *description; ++ ++ pa_assert(stream); ++ pa_assert(client); ++ ++ if (client != stream->client) ++ return PA_HOOK_OK; ++ ++ description = get_stream_volume_and_mute_control_description_malloc(stream); ++ ++ if (stream->stream->own_volume_control) ++ pa_volume_control_description_changed(stream->stream->own_volume_control, description); ++ ++ if (stream->stream->own_mute_control) ++ pa_mute_control_description_changed(stream->stream->own_mute_control, description); ++ ++ pa_xfree(description); ++ ++ return PA_HOOK_OK; ++} ++ ++static struct stream *stream_new(pa_stream_creator *creator, enum stream_type type, void *core_stream) { ++ struct stream *stream; ++ const char *name = NULL; ++ const char *description = NULL; ++ pa_direction_t direction = PA_DIRECTION_OUTPUT; ++ ++ pa_assert(creator); ++ pa_assert(core_stream); ++ ++ stream = pa_xnew0(struct stream, 1); ++ stream->creator = creator; ++ stream->type = type; ++ ++ switch (type) { ++ case STREAM_TYPE_SINK_INPUT: ++ stream->sink_input = core_stream; ++ stream->client = stream->sink_input->client; ++ name = "sink-input-stream"; ++ ++ description = get_sink_input_description(stream->sink_input); ++ if (!description) ++ description = name; ++ ++ direction = PA_DIRECTION_OUTPUT; ++ break; ++ ++ case STREAM_TYPE_SOURCE_OUTPUT: ++ stream->source_output = core_stream; ++ stream->client = stream->source_output->client; ++ name = "source-output-stream"; ++ ++ description = get_source_output_description(stream->source_output); ++ if (!description) ++ description = name; ++ ++ direction = PA_DIRECTION_INPUT; ++ break; ++ } ++ ++ stream->stream = pas_stream_new(creator->volume_api, name, description, direction); ++ stream->stream->create_own_volume_control = stream_create_own_volume_control_cb; ++ stream->stream->delete_own_volume_control = stream_delete_own_volume_control_cb; ++ stream->stream->create_own_mute_control = stream_create_own_mute_control_cb; ++ stream->stream->delete_own_mute_control = stream_delete_own_mute_control_cb; ++ stream->stream->userdata = stream; ++ pas_stream_set_have_own_volume_control(stream->stream, true); ++ pas_stream_set_have_own_mute_control(stream->stream, true); ++ ++ switch (type) { ++ case STREAM_TYPE_SINK_INPUT: ++ stream->proplist_changed_slot = ++ pa_hook_connect(&stream->sink_input->core->hooks[PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED], PA_HOOK_NORMAL, ++ sink_input_or_source_output_proplist_changed_cb, stream); ++ break; ++ ++ case STREAM_TYPE_SOURCE_OUTPUT: ++ stream->proplist_changed_slot = ++ pa_hook_connect(&stream->source_output->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PROPLIST_CHANGED], ++ PA_HOOK_NORMAL, sink_input_or_source_output_proplist_changed_cb, stream); ++ break; ++ } ++ ++ stream->client_proplist_changed_slot = ++ pa_hook_connect(&stream->creator->volume_api->core->hooks[PA_CORE_HOOK_CLIENT_PROPLIST_CHANGED], ++ PA_HOOK_NORMAL, client_proplist_changed_cb, stream); ++ ++ return stream; ++} ++ ++static void stream_put(struct stream *stream) { ++ pa_proplist *proplist = NULL; ++ ++ pa_assert(stream); ++ ++ switch (stream->type) { ++ case STREAM_TYPE_SINK_INPUT: ++ proplist = stream->sink_input->proplist; ++ break; ++ ++ case STREAM_TYPE_SOURCE_OUTPUT: ++ proplist = stream->source_output->proplist; ++ break; ++ } ++ ++ pas_stream_put(stream->stream, proplist); ++} ++ ++static void stream_unlink(struct stream *stream) { ++ pa_assert(stream); ++ ++ if (stream->unlinked) ++ return; ++ ++ stream->unlinked = true; ++ ++ if (stream->stream) ++ pas_stream_unlink(stream->stream); ++} ++ ++static void stream_free(struct stream *stream) { ++ pa_assert(stream); ++ ++ if (!stream->unlinked) ++ stream_unlink(stream); ++ ++ if (stream->client_proplist_changed_slot) ++ pa_hook_slot_free(stream->client_proplist_changed_slot); ++ ++ if (stream->proplist_changed_slot) ++ pa_hook_slot_free(stream->proplist_changed_slot); ++ ++ if (stream->stream) ++ pas_stream_free(stream->stream); ++ ++ pa_xfree(stream); ++} ++ ++static void create_stream(pa_stream_creator *creator, enum stream_type type, void *core_stream) { ++ struct stream *stream; ++ ++ pa_assert(creator); ++ pa_assert(core_stream); ++ ++ stream = stream_new(creator, type, core_stream); ++ pa_hashmap_put(creator->streams, core_stream, stream); ++ stream_put(stream); ++} ++ ++static pa_hook_result_t sink_input_put_cb(void *hook_data, void *call_data, void *userdata) { ++ pa_stream_creator *creator = userdata; ++ pa_sink_input *input = call_data; ++ ++ pa_assert(creator); ++ pa_assert(input); ++ ++ create_stream(creator, STREAM_TYPE_SINK_INPUT, input); ++ ++ return PA_HOOK_OK; ++} ++ ++static pa_hook_result_t sink_input_unlink_cb(void *hook_data, void *call_data, void *userdata) { ++ pa_stream_creator *creator = userdata; ++ pa_sink_input *input = call_data; ++ ++ pa_assert(creator); ++ pa_assert(input); ++ ++ pa_hashmap_remove_and_free(creator->streams, input); ++ ++ return PA_HOOK_OK; ++} ++ ++static pa_hook_result_t source_output_put_cb(void *hook_data, void *call_data, void *userdata) { ++ pa_stream_creator *creator = userdata; ++ pa_source_output *output = call_data; ++ ++ pa_assert(creator); ++ pa_assert(output); ++ ++ create_stream(creator, STREAM_TYPE_SOURCE_OUTPUT, output); ++ ++ return PA_HOOK_OK; ++} ++ ++static pa_hook_result_t source_output_unlink_cb(void *hook_data, void *call_data, void *userdata) { ++ pa_stream_creator *creator = userdata; ++ pa_source_output *output = call_data; ++ ++ pa_assert(creator); ++ pa_assert(output); ++ ++ pa_hashmap_remove_and_free(creator->streams, output); ++ ++ return PA_HOOK_OK; ++} ++ ++pa_stream_creator *pa_stream_creator_new(pa_volume_api *api) { ++ pa_stream_creator *creator; ++ uint32_t idx; ++ pa_sink_input *input; ++ pa_source_output *output; ++ ++ pa_assert(api); ++ ++ creator = pa_xnew0(pa_stream_creator, 1); ++ creator->volume_api = api; ++ creator->streams = pa_hashmap_new_full(NULL, NULL, NULL, (pa_free_cb_t) stream_free); ++ creator->sink_input_put_slot = pa_hook_connect(&api->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT], PA_HOOK_NORMAL, ++ sink_input_put_cb, creator); ++ creator->sink_input_unlink_slot = pa_hook_connect(&api->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK], PA_HOOK_NORMAL, ++ sink_input_unlink_cb, creator); ++ creator->source_output_put_slot = pa_hook_connect(&api->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PUT], PA_HOOK_NORMAL, ++ source_output_put_cb, creator); ++ creator->source_output_unlink_slot = pa_hook_connect(&api->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK], PA_HOOK_NORMAL, ++ source_output_unlink_cb, creator); ++ ++ PA_IDXSET_FOREACH(input, api->core->sink_inputs, idx) ++ create_stream(creator, STREAM_TYPE_SINK_INPUT, input); ++ ++ PA_IDXSET_FOREACH(output, api->core->source_outputs, idx) ++ create_stream(creator, STREAM_TYPE_SOURCE_OUTPUT, output); ++ ++ return creator; ++} ++ ++void pa_stream_creator_free(pa_stream_creator *creator) { ++ pa_assert(creator); ++ ++ if (creator->streams) ++ pa_hashmap_remove_all(creator->streams); ++ ++ if (creator->source_output_unlink_slot) ++ pa_hook_slot_free(creator->source_output_unlink_slot); ++ ++ if (creator->source_output_put_slot) ++ pa_hook_slot_free(creator->source_output_put_slot); ++ ++ if (creator->sink_input_unlink_slot) ++ pa_hook_slot_free(creator->sink_input_unlink_slot); ++ ++ if (creator->sink_input_put_slot) ++ pa_hook_slot_free(creator->sink_input_put_slot); ++ ++ if (creator->streams) ++ pa_hashmap_free(creator->streams); ++ ++ pa_xfree(creator); ++} +diff --git a/src/modules/volume-api/stream-creator.h b/src/modules/volume-api/stream-creator.h +new file mode 100644 +index 0000000..97a03a4 +--- /dev/null ++++ b/src/modules/volume-api/stream-creator.h +@@ -0,0 +1,32 @@ ++#ifndef foostreamcreatorhfoo ++#define foostreamcreatorhfoo ++ ++/*** ++ This file is part of PulseAudio. ++ ++ Copyright 2014 Intel Corporation ++ ++ PulseAudio is free software; you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as published ++ by the Free Software Foundation; either version 2.1 of the License, ++ or (at your option) any later version. ++ ++ PulseAudio 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 Lesser General Public License ++ along with PulseAudio; if not, write to the Free Software ++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ USA. ++***/ ++ ++#include ++ ++typedef struct pa_stream_creator pa_stream_creator; ++ ++pa_stream_creator *pa_stream_creator_new(pa_volume_api *api); ++void pa_stream_creator_free(pa_stream_creator *creator); ++ ++#endif +diff --git a/src/modules/volume-api/volume-api.c b/src/modules/volume-api/volume-api.c +new file mode 100644 +index 0000000..9abea7e +--- /dev/null ++++ b/src/modules/volume-api/volume-api.c +@@ -0,0 +1,647 @@ ++/*** ++ This file is part of PulseAudio. ++ ++ Copyright 2014 Intel Corporation ++ ++ PulseAudio is free software; you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as published ++ by the Free Software Foundation; either version 2.1 of the License, ++ or (at your option) any later version. ++ ++ PulseAudio 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 Lesser General Public License ++ along with PulseAudio; if not, write to the Free Software ++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ USA. ++***/ ++ ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ ++#include "volume-api.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++static pa_volume_api *volume_api_new(pa_core *core); ++static void volume_api_free(pa_volume_api *api); ++ ++pa_volume_api *pa_volume_api_get(pa_core *core) { ++ pa_volume_api *api; ++ ++ pa_assert(core); ++ ++ api = pa_shared_get(core, "volume-api"); ++ ++ if (api) ++ pa_volume_api_ref(api); ++ else { ++ api = volume_api_new(core); ++ pa_assert_se(pa_shared_set(core, "volume-api", api) >= 0); ++ } ++ ++ return api; ++} ++ ++pa_volume_api *pa_volume_api_ref(pa_volume_api *api) { ++ pa_assert(api); ++ ++ api->refcnt++; ++ ++ return api; ++} ++ ++void pa_volume_api_unref(pa_volume_api *api) { ++ pa_assert(api); ++ pa_assert(api->refcnt > 0); ++ ++ api->refcnt--; ++ ++ if (api->refcnt == 0) { ++ pa_assert_se(pa_shared_remove(api->core, "volume-api") >= 0); ++ volume_api_free(api); ++ } ++} ++ ++void pa_volume_api_add_binding_target_type(pa_volume_api *api, pa_binding_target_type *type) { ++ pa_assert(api); ++ pa_assert(type); ++ ++ pa_assert_se(pa_hashmap_put(api->binding_target_types, type->name, type) >= 0); ++ ++ pa_log_debug("Added binding target type %s.", type->name); ++ ++ pa_hook_fire(&api->hooks[PA_VOLUME_API_HOOK_BINDING_TARGET_TYPE_ADDED], type); ++} ++ ++void pa_volume_api_remove_binding_target_type(pa_volume_api *api, pa_binding_target_type *type) { ++ pa_assert(api); ++ pa_assert(type); ++ ++ pa_log_debug("Removing binding target type %s.", type->name); ++ ++ pa_hook_fire(&api->hooks[PA_VOLUME_API_HOOK_BINDING_TARGET_TYPE_REMOVED], type); ++ ++ pa_assert_se(pa_hashmap_remove(api->binding_target_types, type->name)); ++} ++ ++static void create_builtin_binding_target_types(pa_volume_api *api) { ++ pa_binding_target_type *type; ++ ++ pa_assert(api); ++ ++ type = pa_audio_group_create_binding_target_type(api); ++ pa_volume_api_add_binding_target_type(api, type); ++} ++ ++static void delete_builtin_binding_target_types(pa_volume_api *api) { ++ pa_binding_target_type *type; ++ ++ pa_assert(api); ++ ++ type = pa_hashmap_get(api->binding_target_types, PA_AUDIO_GROUP_BINDING_TARGET_TYPE); ++ pa_volume_api_remove_binding_target_type(api, type); ++} ++ ++static void create_objects_defer_event_cb(pa_mainloop_api *mainloop_api, pa_defer_event *event, void *userdata) { ++ pa_volume_api *volume_api = userdata; ++ ++ pa_assert(volume_api); ++ pa_assert(event == volume_api->create_objects_defer_event); ++ ++ mainloop_api->defer_free(event); ++ volume_api->create_objects_defer_event = NULL; ++ ++ volume_api->device_creator = pa_device_creator_new(volume_api); ++ volume_api->stream_creator = pa_stream_creator_new(volume_api); ++} ++ ++static pa_volume_api *volume_api_new(pa_core *core) { ++ pa_volume_api *api; ++ unsigned i; ++ ++ pa_assert(core); ++ ++ api = pa_xnew0(pa_volume_api, 1); ++ api->core = core; ++ api->refcnt = 1; ++ api->binding_target_types = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); ++ api->names = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, pa_xfree); ++ api->volume_controls = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); ++ api->mute_controls = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); ++ api->devices = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); ++ api->streams = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); ++ api->audio_groups = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); ++ ++ for (i = 0; i < PA_VOLUME_API_HOOK_MAX; i++) ++ pa_hook_init(&api->hooks[i], api); ++ ++ create_builtin_binding_target_types(api); ++ ++ /* We delay the object creation to ensure that policy modules have a chance ++ * to affect the initialization of the objects. If we created the objects ++ * immediately, policy modules wouldn't have a chance of connecting to the ++ * object creation hooks before the objects are created. */ ++ api->create_objects_defer_event = core->mainloop->defer_new(core->mainloop, create_objects_defer_event_cb, api); ++ ++ pa_log_debug("Created a pa_volume_api object."); ++ ++ return api; ++} ++ ++static void volume_api_free(pa_volume_api *api) { ++ unsigned i; ++ ++ pa_assert(api); ++ pa_assert(api->refcnt == 0); ++ ++ pa_log_debug("Freeing the pa_volume_api object."); ++ ++ if (api->stream_creator) ++ pa_stream_creator_free(api->stream_creator); ++ ++ if (api->device_creator) ++ pa_device_creator_free(api->device_creator); ++ ++ if (api->create_objects_defer_event) ++ api->core->mainloop->defer_free(api->create_objects_defer_event); ++ ++ if (api->binding_target_types) ++ delete_builtin_binding_target_types(api); ++ ++ for (i = 0; i < PA_VOLUME_API_HOOK_MAX; i++) ++ pa_hook_done(&api->hooks[i]); ++ ++ if (api->audio_groups) { ++ pa_assert(pa_hashmap_isempty(api->audio_groups)); ++ pa_hashmap_free(api->audio_groups); ++ } ++ ++ if (api->streams) { ++ pa_assert(pa_hashmap_isempty(api->streams)); ++ pa_hashmap_free(api->streams); ++ } ++ ++ if (api->devices) { ++ pa_assert(pa_hashmap_isempty(api->devices)); ++ pa_hashmap_free(api->devices); ++ } ++ ++ if (api->mute_controls) { ++ pa_assert(pa_hashmap_isempty(api->mute_controls)); ++ pa_hashmap_free(api->mute_controls); ++ } ++ ++ if (api->volume_controls) { ++ pa_assert(pa_hashmap_isempty(api->volume_controls)); ++ pa_hashmap_free(api->volume_controls); ++ } ++ ++ if (api->names) { ++ pa_assert(pa_hashmap_isempty(api->names)); ++ pa_hashmap_free(api->names); ++ } ++ ++ if (api->binding_target_types) { ++ pa_assert(pa_hashmap_isempty(api->binding_target_types)); ++ pa_hashmap_free(api->binding_target_types); ++ } ++ ++ pa_xfree(api); ++} ++ ++int pa_volume_api_register_name(pa_volume_api *api, const char *requested_name, bool fail_if_already_registered, ++ const char **registered_name) { ++ char *n; ++ ++ pa_assert(api); ++ pa_assert(requested_name); ++ pa_assert(registered_name); ++ ++ n = pa_xstrdup(requested_name); ++ ++ if (pa_hashmap_put(api->names, n, n) < 0) { ++ unsigned i = 1; ++ ++ pa_xfree(n); ++ ++ if (fail_if_already_registered) { ++ pa_log("Name %s already registered.", requested_name); ++ return -PA_ERR_EXIST; ++ } ++ ++ do { ++ i++; ++ n = pa_sprintf_malloc("%s.%u", requested_name, i); ++ } while (pa_hashmap_put(api->names, n, n) < 0); ++ } ++ ++ *registered_name = n; ++ ++ return 0; ++} ++ ++void pa_volume_api_unregister_name(pa_volume_api *api, const char *name) { ++ pa_assert(api); ++ pa_assert(name); ++ ++ pa_assert_se(pa_hashmap_remove_and_free(api->names, name) >= 0); ++} ++ ++uint32_t pa_volume_api_allocate_volume_control_index(pa_volume_api *api) { ++ uint32_t idx; ++ ++ pa_assert(api); ++ ++ idx = api->next_volume_control_index++; ++ ++ return idx; ++} ++ ++static void set_main_output_volume_control_internal(pa_volume_api *api, pa_volume_control *control) { ++ pa_volume_control *old_control; ++ ++ pa_assert(api); ++ ++ old_control = api->main_output_volume_control; ++ ++ if (control == old_control) ++ return; ++ ++ api->main_output_volume_control = control; ++ pa_log_debug("Main output volume control changed from %s to %s.", old_control ? old_control->name : "(unset)", ++ control ? control->name : "(unset)"); ++ pa_hook_fire(&api->hooks[PA_VOLUME_API_HOOK_MAIN_OUTPUT_VOLUME_CONTROL_CHANGED], api); ++} ++ ++static void set_main_input_volume_control_internal(pa_volume_api *api, pa_volume_control *control) { ++ pa_volume_control *old_control; ++ ++ pa_assert(api); ++ ++ old_control = api->main_input_volume_control; ++ ++ if (control == old_control) ++ return; ++ ++ api->main_input_volume_control = control; ++ pa_log_debug("Main input volume control changed from %s to %s.", old_control ? old_control->name : "(unset)", ++ control ? control->name : "(unset)"); ++ pa_hook_fire(&api->hooks[PA_VOLUME_API_HOOK_MAIN_INPUT_VOLUME_CONTROL_CHANGED], api); ++} ++ ++void pa_volume_api_add_volume_control(pa_volume_api *api, pa_volume_control *control) { ++ pa_assert(api); ++ pa_assert(control); ++ ++ pa_assert_se(pa_hashmap_put(api->volume_controls, (void *) control->name, control) >= 0); ++} ++ ++int pa_volume_api_remove_volume_control(pa_volume_api *api, pa_volume_control *control) { ++ pa_assert(api); ++ pa_assert(control); ++ ++ if (!pa_hashmap_remove(api->volume_controls, control->name)) ++ return -1; ++ ++ if (control == api->main_output_volume_control) ++ set_main_output_volume_control_internal(api, NULL); ++ ++ if (control == api->main_input_volume_control) ++ set_main_input_volume_control_internal(api, NULL); ++ ++ return 0; ++} ++ ++pa_volume_control *pa_volume_api_get_volume_control_by_index(pa_volume_api *api, uint32_t idx) { ++ pa_volume_control *control; ++ void *state; ++ ++ pa_assert(api); ++ ++ PA_HASHMAP_FOREACH(control, api->volume_controls, state) { ++ if (control->index == idx) ++ return control; ++ } ++ ++ return NULL; ++} ++ ++uint32_t pa_volume_api_allocate_mute_control_index(pa_volume_api *api) { ++ uint32_t idx; ++ ++ pa_assert(api); ++ ++ idx = api->next_mute_control_index++; ++ ++ return idx; ++} ++ ++static void set_main_output_mute_control_internal(pa_volume_api *api, pa_mute_control *control) { ++ pa_mute_control *old_control; ++ ++ pa_assert(api); ++ ++ old_control = api->main_output_mute_control; ++ ++ if (control == old_control) ++ return; ++ ++ api->main_output_mute_control = control; ++ pa_log_debug("Main output mute control changed from %s to %s.", old_control ? old_control->name : "(unset)", ++ control ? control->name : "(unset)"); ++ pa_hook_fire(&api->hooks[PA_VOLUME_API_HOOK_MAIN_OUTPUT_MUTE_CONTROL_CHANGED], api); ++} ++ ++static void set_main_input_mute_control_internal(pa_volume_api *api, pa_mute_control *control) { ++ pa_mute_control *old_control; ++ ++ pa_assert(api); ++ ++ old_control = api->main_input_mute_control; ++ ++ if (control == old_control) ++ return; ++ ++ api->main_input_mute_control = control; ++ pa_log_debug("Main input mute control changed from %s to %s.", old_control ? old_control->name : "(unset)", ++ control ? control->name : "(unset)"); ++ pa_hook_fire(&api->hooks[PA_VOLUME_API_HOOK_MAIN_INPUT_MUTE_CONTROL_CHANGED], api); ++} ++ ++void pa_volume_api_add_mute_control(pa_volume_api *api, pa_mute_control *control) { ++ pa_assert(api); ++ pa_assert(control); ++ ++ pa_assert_se(pa_hashmap_put(api->mute_controls, (void *) control->name, control) >= 0); ++} ++ ++int pa_volume_api_remove_mute_control(pa_volume_api *api, pa_mute_control *control) { ++ pa_assert(api); ++ pa_assert(control); ++ ++ if (!pa_hashmap_remove(api->mute_controls, control->name)) ++ return -1; ++ ++ if (control == api->main_output_mute_control) ++ set_main_output_mute_control_internal(api, NULL); ++ ++ if (control == api->main_input_mute_control) ++ set_main_input_mute_control_internal(api, NULL); ++ ++ return 0; ++} ++ ++pa_mute_control *pa_volume_api_get_mute_control_by_index(pa_volume_api *api, uint32_t idx) { ++ pa_mute_control *control; ++ void *state; ++ ++ pa_assert(api); ++ ++ PA_HASHMAP_FOREACH(control, api->mute_controls, state) { ++ if (control->index == idx) ++ return control; ++ } ++ ++ return NULL; ++} ++ ++uint32_t pa_volume_api_allocate_device_index(pa_volume_api *api) { ++ uint32_t idx; ++ ++ pa_assert(api); ++ ++ idx = api->next_device_index++; ++ ++ return idx; ++} ++ ++void pa_volume_api_add_device(pa_volume_api *api, pa_device *device) { ++ pa_assert(api); ++ pa_assert(device); ++ ++ pa_assert_se(pa_hashmap_put(api->devices, (void *) device->name, device) >= 0); ++} ++ ++int pa_volume_api_remove_device(pa_volume_api *api, pa_device *device) { ++ pa_assert(api); ++ pa_assert(device); ++ ++ if (!pa_hashmap_remove(api->devices, device->name)) ++ return -1; ++ ++ return 0; ++} ++ ++pa_device *pa_volume_api_get_device_by_index(pa_volume_api *api, uint32_t idx) { ++ pa_device *device; ++ void *state; ++ ++ pa_assert(api); ++ ++ PA_HASHMAP_FOREACH(device, api->devices, state) { ++ if (device->index == idx) ++ return device; ++ } ++ ++ return NULL; ++} ++ ++uint32_t pa_volume_api_allocate_stream_index(pa_volume_api *api) { ++ uint32_t idx; ++ ++ pa_assert(api); ++ ++ idx = api->next_stream_index++; ++ ++ return idx; ++} ++ ++void pa_volume_api_add_stream(pa_volume_api *api, pas_stream *stream) { ++ pa_assert(api); ++ pa_assert(stream); ++ ++ pa_assert_se(pa_hashmap_put(api->streams, (void *) stream->name, stream) >= 0); ++} ++ ++int pa_volume_api_remove_stream(pa_volume_api *api, pas_stream *stream) { ++ pa_assert(api); ++ pa_assert(stream); ++ ++ if (!pa_hashmap_remove(api->streams, stream->name)) ++ return -1; ++ ++ return 0; ++} ++ ++pas_stream *pa_volume_api_get_stream_by_index(pa_volume_api *api, uint32_t idx) { ++ pas_stream *stream; ++ void *state; ++ ++ pa_assert(api); ++ ++ PA_HASHMAP_FOREACH(stream, api->streams, state) { ++ if (stream->index == idx) ++ return stream; ++ } ++ ++ return NULL; ++} ++ ++uint32_t pa_volume_api_allocate_audio_group_index(pa_volume_api *api) { ++ uint32_t idx; ++ ++ pa_assert(api); ++ ++ idx = api->next_audio_group_index++; ++ ++ return idx; ++} ++ ++void pa_volume_api_add_audio_group(pa_volume_api *api, pa_audio_group *group) { ++ pa_assert(api); ++ pa_assert(group); ++ ++ pa_assert_se(pa_hashmap_put(api->audio_groups, (void *) group->name, group) >= 0); ++} ++ ++int pa_volume_api_remove_audio_group(pa_volume_api *api, pa_audio_group *group) { ++ pa_assert(api); ++ pa_assert(group); ++ ++ if (!pa_hashmap_remove(api->audio_groups, group->name)) ++ return -1; ++ ++ return 0; ++} ++ ++pa_audio_group *pa_volume_api_get_audio_group_by_index(pa_volume_api *api, uint32_t idx) { ++ pa_audio_group *group; ++ void *state; ++ ++ pa_assert(api); ++ ++ PA_HASHMAP_FOREACH(group, api->audio_groups, state) { ++ if (group->index == idx) ++ return group; ++ } ++ ++ return NULL; ++} ++ ++void pa_volume_api_set_main_output_volume_control(pa_volume_api *api, pa_volume_control *control) { ++ pa_assert(api); ++ ++ if (api->main_output_volume_control_binding) { ++ pa_binding_free(api->main_output_volume_control_binding); ++ api->main_output_volume_control_binding = NULL; ++ } ++ ++ set_main_output_volume_control_internal(api, control); ++} ++ ++void pa_volume_api_set_main_input_volume_control(pa_volume_api *api, pa_volume_control *control) { ++ pa_assert(api); ++ ++ if (api->main_input_volume_control_binding) { ++ pa_binding_free(api->main_input_volume_control_binding); ++ api->main_input_volume_control_binding = NULL; ++ } ++ ++ set_main_input_volume_control_internal(api, control); ++} ++ ++void pa_volume_api_set_main_output_mute_control(pa_volume_api *api, pa_mute_control *control) { ++ pa_assert(api); ++ ++ if (api->main_output_mute_control_binding) { ++ pa_binding_free(api->main_output_mute_control_binding); ++ api->main_output_mute_control_binding = NULL; ++ } ++ ++ set_main_output_mute_control_internal(api, control); ++} ++ ++void pa_volume_api_set_main_input_mute_control(pa_volume_api *api, pa_mute_control *control) { ++ pa_assert(api); ++ ++ if (api->main_input_mute_control_binding) { ++ pa_binding_free(api->main_input_mute_control_binding); ++ api->main_input_mute_control_binding = NULL; ++ } ++ ++ set_main_input_mute_control_internal(api, control); ++} ++ ++void pa_volume_api_bind_main_output_volume_control(pa_volume_api *api, pa_binding_target_info *target_info) { ++ pa_binding_owner_info owner_info = { ++ .userdata = api, ++ .set_value = (pa_binding_set_value_cb_t) set_main_output_volume_control_internal, ++ }; ++ ++ pa_assert(api); ++ pa_assert(target_info); ++ ++ if (api->main_output_volume_control_binding) ++ pa_binding_free(api->main_output_volume_control_binding); ++ ++ api->main_output_volume_control_binding = pa_binding_new(api, &owner_info, target_info); ++} ++ ++void pa_volume_api_bind_main_input_volume_control(pa_volume_api *api, pa_binding_target_info *target_info) { ++ pa_binding_owner_info owner_info = { ++ .userdata = api, ++ .set_value = (pa_binding_set_value_cb_t) set_main_input_volume_control_internal, ++ }; ++ ++ pa_assert(api); ++ pa_assert(target_info); ++ ++ if (api->main_input_volume_control_binding) ++ pa_binding_free(api->main_input_volume_control_binding); ++ ++ api->main_input_volume_control_binding = pa_binding_new(api, &owner_info, target_info); ++} ++ ++void pa_volume_api_bind_main_output_mute_control(pa_volume_api *api, pa_binding_target_info *target_info) { ++ pa_binding_owner_info owner_info = { ++ .userdata = api, ++ .set_value = (pa_binding_set_value_cb_t) set_main_output_mute_control_internal, ++ }; ++ ++ pa_assert(api); ++ pa_assert(target_info); ++ ++ if (api->main_output_mute_control_binding) ++ pa_binding_free(api->main_output_mute_control_binding); ++ ++ api->main_output_mute_control_binding = pa_binding_new(api, &owner_info, target_info); ++} ++ ++void pa_volume_api_bind_main_input_mute_control(pa_volume_api *api, pa_binding_target_info *target_info) { ++ pa_binding_owner_info owner_info = { ++ .userdata = api, ++ .set_value = (pa_binding_set_value_cb_t) set_main_input_mute_control_internal, ++ }; ++ ++ pa_assert(api); ++ pa_assert(target_info); ++ ++ if (api->main_input_mute_control_binding) ++ pa_binding_free(api->main_input_mute_control_binding); ++ ++ api->main_input_mute_control_binding = pa_binding_new(api, &owner_info, target_info); ++} +diff --git a/src/modules/volume-api/volume-api.h b/src/modules/volume-api/volume-api.h +new file mode 100644 +index 0000000..73a1410 +--- /dev/null ++++ b/src/modules/volume-api/volume-api.h +@@ -0,0 +1,163 @@ ++#ifndef foovolumeapihfoo ++#define foovolumeapihfoo ++ ++/*** ++ This file is part of PulseAudio. ++ ++ Copyright 2014 Intel Corporation ++ ++ PulseAudio is free software; you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as published ++ by the Free Software Foundation; either version 2.1 of the License, ++ or (at your option) any later version. ++ ++ PulseAudio 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 Lesser General Public License ++ along with PulseAudio; if not, write to the Free Software ++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ USA. ++***/ ++ ++#include ++ ++typedef struct pa_volume_api pa_volume_api; ++ ++/* Avoid circular dependencies... */ ++typedef struct pa_audio_group pa_audio_group; ++typedef struct pa_binding pa_binding; ++typedef struct pa_binding_target_info pa_binding_target_info; ++typedef struct pa_binding_target_type pa_binding_target_type; ++typedef struct pa_device pa_device; ++typedef struct pa_device_creator pa_device_creator; ++typedef struct pa_mute_control pa_mute_control; ++typedef struct pas_stream pas_stream; ++typedef struct pa_stream_creator pa_stream_creator; ++typedef struct pa_volume_control pa_volume_control; ++ ++enum { ++ PA_VOLUME_API_HOOK_BINDING_TARGET_TYPE_ADDED, ++ PA_VOLUME_API_HOOK_BINDING_TARGET_TYPE_REMOVED, ++ PA_VOLUME_API_HOOK_VOLUME_CONTROL_PUT, ++ PA_VOLUME_API_HOOK_VOLUME_CONTROL_UNLINK, ++ PA_VOLUME_API_HOOK_VOLUME_CONTROL_DESCRIPTION_CHANGED, ++ PA_VOLUME_API_HOOK_VOLUME_CONTROL_VOLUME_CHANGED, ++ PA_VOLUME_API_HOOK_MUTE_CONTROL_PUT, ++ PA_VOLUME_API_HOOK_MUTE_CONTROL_UNLINK, ++ PA_VOLUME_API_HOOK_MUTE_CONTROL_DESCRIPTION_CHANGED, ++ PA_VOLUME_API_HOOK_MUTE_CONTROL_MUTE_CHANGED, ++ PA_VOLUME_API_HOOK_DEVICE_PUT, ++ PA_VOLUME_API_HOOK_DEVICE_UNLINK, ++ PA_VOLUME_API_HOOK_DEVICE_DESCRIPTION_CHANGED, ++ PA_VOLUME_API_HOOK_DEVICE_VOLUME_CONTROL_CHANGED, ++ PA_VOLUME_API_HOOK_DEVICE_MUTE_CONTROL_CHANGED, ++ ++ /* Policy modules can use this to set the initial volume control for a ++ * stream. The hook callback should use pas_stream_set_volume_control() to ++ * set the volume control. The hook callback should not do anything if ++ * stream->volume_control is already non-NULL. */ ++ PA_VOLUME_API_HOOK_STREAM_SET_INITIAL_VOLUME_CONTROL, ++ ++ /* Policy modules can use this to set the initial mute control for a ++ * stream. The hook callback should use pas_stream_set_mute_control() to ++ * set the mute control. The hook callback should not do anything if ++ * stream->mute_control is already non-NULL. */ ++ PA_VOLUME_API_HOOK_STREAM_SET_INITIAL_MUTE_CONTROL, ++ ++ PA_VOLUME_API_HOOK_STREAM_PUT, ++ PA_VOLUME_API_HOOK_STREAM_UNLINK, ++ PA_VOLUME_API_HOOK_STREAM_DESCRIPTION_CHANGED, ++ PA_VOLUME_API_HOOK_STREAM_VOLUME_CONTROL_CHANGED, ++ PA_VOLUME_API_HOOK_STREAM_MUTE_CONTROL_CHANGED, ++ PA_VOLUME_API_HOOK_AUDIO_GROUP_PUT, ++ PA_VOLUME_API_HOOK_AUDIO_GROUP_UNLINK, ++ PA_VOLUME_API_HOOK_AUDIO_GROUP_VOLUME_CONTROL_CHANGED, ++ PA_VOLUME_API_HOOK_AUDIO_GROUP_MUTE_CONTROL_CHANGED, ++ PA_VOLUME_API_HOOK_MAIN_OUTPUT_VOLUME_CONTROL_CHANGED, ++ PA_VOLUME_API_HOOK_MAIN_INPUT_VOLUME_CONTROL_CHANGED, ++ PA_VOLUME_API_HOOK_MAIN_OUTPUT_MUTE_CONTROL_CHANGED, ++ PA_VOLUME_API_HOOK_MAIN_INPUT_MUTE_CONTROL_CHANGED, ++ PA_VOLUME_API_HOOK_MAX ++}; ++ ++struct pa_volume_api { ++ pa_core *core; ++ unsigned refcnt; ++ pa_hashmap *binding_target_types; /* name -> pa_binding_target_type */ ++ pa_hashmap *names; /* object name -> object name (hashmap-as-a-set) */ ++ pa_hashmap *volume_controls; /* name -> pa_volume_control */ ++ pa_hashmap *mute_controls; /* name -> pa_mute_control */ ++ pa_hashmap *devices; /* name -> pa_device */ ++ pa_hashmap *streams; /* name -> pas_stream */ ++ pa_hashmap *audio_groups; /* name -> pa_audio_group */ ++ pa_volume_control *main_output_volume_control; ++ pa_volume_control *main_input_volume_control; ++ pa_mute_control *main_output_mute_control; ++ pa_mute_control *main_input_mute_control; ++ ++ uint32_t next_volume_control_index; ++ uint32_t next_mute_control_index; ++ uint32_t next_device_index; ++ uint32_t next_stream_index; ++ uint32_t next_audio_group_index; ++ pa_binding *main_output_volume_control_binding; ++ pa_binding *main_input_volume_control_binding; ++ pa_binding *main_output_mute_control_binding; ++ pa_binding *main_input_mute_control_binding; ++ pa_hook hooks[PA_VOLUME_API_HOOK_MAX]; ++ pa_defer_event *create_objects_defer_event; ++ pa_device_creator *device_creator; ++ pa_stream_creator *stream_creator; ++}; ++ ++pa_volume_api *pa_volume_api_get(pa_core *core); ++pa_volume_api *pa_volume_api_ref(pa_volume_api *api); ++void pa_volume_api_unref(pa_volume_api *api); ++ ++void pa_volume_api_add_binding_target_type(pa_volume_api *api, pa_binding_target_type *type); ++void pa_volume_api_remove_binding_target_type(pa_volume_api *api, pa_binding_target_type *type); ++ ++/* If fail_if_already_registered is false, this function never fails. */ ++int pa_volume_api_register_name(pa_volume_api *api, const char *requested_name, bool fail_if_already_registered, ++ const char **registered_name); ++ ++void pa_volume_api_unregister_name(pa_volume_api *api, const char *name); ++ ++uint32_t pa_volume_api_allocate_volume_control_index(pa_volume_api *api); ++void pa_volume_api_add_volume_control(pa_volume_api *api, pa_volume_control *control); ++int pa_volume_api_remove_volume_control(pa_volume_api *api, pa_volume_control *control); ++pa_volume_control *pa_volume_api_get_volume_control_by_index(pa_volume_api *api, uint32_t idx); ++ ++uint32_t pa_volume_api_allocate_mute_control_index(pa_volume_api *api); ++void pa_volume_api_add_mute_control(pa_volume_api *api, pa_mute_control *control); ++int pa_volume_api_remove_mute_control(pa_volume_api *api, pa_mute_control *control); ++pa_mute_control *pa_volume_api_get_mute_control_by_index(pa_volume_api *api, uint32_t idx); ++ ++uint32_t pa_volume_api_allocate_device_index(pa_volume_api *api); ++void pa_volume_api_add_device(pa_volume_api *api, pa_device *device); ++int pa_volume_api_remove_device(pa_volume_api *api, pa_device *device); ++pa_device *pa_volume_api_get_device_by_index(pa_volume_api *api, uint32_t idx); ++ ++uint32_t pa_volume_api_allocate_stream_index(pa_volume_api *api); ++void pa_volume_api_add_stream(pa_volume_api *api, pas_stream *stream); ++int pa_volume_api_remove_stream(pa_volume_api *api, pas_stream *stream); ++pas_stream *pa_volume_api_get_stream_by_index(pa_volume_api *api, uint32_t idx); ++ ++uint32_t pa_volume_api_allocate_audio_group_index(pa_volume_api *api); ++void pa_volume_api_add_audio_group(pa_volume_api *api, pa_audio_group *group); ++int pa_volume_api_remove_audio_group(pa_volume_api *api, pa_audio_group *group); ++pa_audio_group *pa_volume_api_get_audio_group_by_index(pa_volume_api *api, uint32_t idx); ++ ++void pa_volume_api_set_main_output_volume_control(pa_volume_api *api, pa_volume_control *control); ++void pa_volume_api_set_main_input_volume_control(pa_volume_api *api, pa_volume_control *control); ++void pa_volume_api_set_main_output_mute_control(pa_volume_api *api, pa_mute_control *control); ++void pa_volume_api_set_main_input_mute_control(pa_volume_api *api, pa_mute_control *control); ++void pa_volume_api_bind_main_output_volume_control(pa_volume_api *api, pa_binding_target_info *target_info); ++void pa_volume_api_bind_main_input_volume_control(pa_volume_api *api, pa_binding_target_info *target_info); ++void pa_volume_api_bind_main_output_mute_control(pa_volume_api *api, pa_binding_target_info *target_info); ++void pa_volume_api_bind_main_input_mute_control(pa_volume_api *api, pa_binding_target_info *target_info); ++ ++#endif +diff --git a/src/modules/volume-api/volume-control.c b/src/modules/volume-api/volume-control.c +new file mode 100644 +index 0000000..c7f5dbb +--- /dev/null ++++ b/src/modules/volume-api/volume-control.c +@@ -0,0 +1,363 @@ ++/*** ++ This file is part of PulseAudio. ++ ++ Copyright 2014 Intel Corporation ++ ++ PulseAudio is free software; you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as published ++ by the Free Software Foundation; either version 2.1 of the License, ++ or (at your option) any later version. ++ ++ PulseAudio 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 Lesser General Public License ++ along with PulseAudio; if not, write to the Free Software ++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ USA. ++***/ ++ ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ ++#include "volume-control.h" ++ ++#include ++#include ++#include ++ ++#include ++ ++pa_volume_control *pa_volume_control_new(pa_volume_api *api, const char *name, const char *description, bool convertible_to_dB, ++ bool channel_map_is_writable) { ++ pa_volume_control *control; ++ ++ pa_assert(api); ++ pa_assert(name); ++ pa_assert(description); ++ ++ control = pa_xnew0(pa_volume_control, 1); ++ control->volume_api = api; ++ control->index = pa_volume_api_allocate_volume_control_index(api); ++ pa_assert_se(pa_volume_api_register_name(api, name, false, &control->name) >= 0); ++ control->description = pa_xstrdup(description); ++ control->proplist = pa_proplist_new(); ++ pa_bvolume_init_invalid(&control->volume); ++ control->convertible_to_dB = convertible_to_dB; ++ control->channel_map_is_writable = channel_map_is_writable; ++ control->devices = pa_hashmap_new(NULL, NULL); ++ control->default_for_devices = pa_hashmap_new(NULL, NULL); ++ control->streams = pa_hashmap_new(NULL, NULL); ++ control->audio_groups = pa_hashmap_new(NULL, NULL); ++ ++ return control; ++} ++ ++void pa_volume_control_put(pa_volume_control *control, const pa_bvolume *initial_volume, ++ pa_volume_control_set_initial_volume_cb_t set_initial_volume_cb) { ++ const char *prop_key; ++ void *state = NULL; ++ char volume_str[PA_VOLUME_SNPRINT_VERBOSE_MAX]; ++ char balance_str[PA_BVOLUME_SNPRINT_BALANCE_MAX]; ++ ++ pa_assert(control); ++ pa_assert((initial_volume && pa_bvolume_valid(initial_volume, true, true)) || control->set_volume); ++ pa_assert((initial_volume && pa_channel_map_valid(&initial_volume->channel_map)) || control->channel_map_is_writable); ++ pa_assert(set_initial_volume_cb || !control->set_volume); ++ ++ if (initial_volume && pa_bvolume_valid(initial_volume, true, false)) ++ control->volume.volume = initial_volume->volume; ++ else ++ control->volume.volume = PA_VOLUME_NORM / 3; ++ ++ if (initial_volume && pa_bvolume_valid(initial_volume, false, true)) ++ pa_bvolume_copy_balance(&control->volume, initial_volume); ++ else if (initial_volume && pa_channel_map_valid(&initial_volume->channel_map)) ++ pa_bvolume_reset_balance(&control->volume, &initial_volume->channel_map); ++ else { ++ pa_channel_map_init_mono(&control->volume.channel_map); ++ pa_bvolume_reset_balance(&control->volume, &control->volume.channel_map); ++ } ++ ++ if (set_initial_volume_cb) ++ set_initial_volume_cb(control); ++ ++ pa_volume_api_add_volume_control(control->volume_api, control); ++ ++ control->linked = true; ++ ++ pa_log_debug("Created volume control #%u.", control->index); ++ pa_log_debug(" Name: %s", control->name); ++ pa_log_debug(" Description: %s", control->description); ++ pa_log_debug(" Properties:"); ++ ++ while ((prop_key = pa_proplist_iterate(control->proplist, &state))) ++ pa_log_debug(" %s = %s", prop_key, pa_strnull(pa_proplist_gets(control->proplist, prop_key))); ++ ++ pa_log_debug(" Volume: %s", pa_volume_snprint_verbose(volume_str, sizeof(volume_str), control->volume.volume, ++ control->convertible_to_dB)); ++ pa_log_debug(" Balance: %s", pa_bvolume_snprint_balance(balance_str, sizeof(balance_str), &control->volume)); ++ pa_log_debug(" Channel map is writable: %s", pa_yes_no(control->channel_map_is_writable)); ++ ++ pa_hook_fire(&control->volume_api->hooks[PA_VOLUME_API_HOOK_VOLUME_CONTROL_PUT], control); ++} ++ ++void pa_volume_control_unlink(pa_volume_control *control) { ++ pa_audio_group *group; ++ pa_device *device; ++ pas_stream *stream; ++ ++ pa_assert(control); ++ ++ if (control->unlinked) { ++ pa_log_debug("Unlinking volume control %s (already unlinked, this is a no-op).", control->name); ++ return; ++ } ++ ++ control->unlinked = true; ++ ++ pa_log_debug("Unlinking volume control %s.", control->name); ++ ++ if (control->linked) ++ pa_hook_fire(&control->volume_api->hooks[PA_VOLUME_API_HOOK_VOLUME_CONTROL_UNLINK], control); ++ ++ pa_volume_api_remove_volume_control(control->volume_api, control); ++ ++ while ((group = pa_hashmap_first(control->audio_groups))) ++ pa_audio_group_set_volume_control(group, NULL); ++ ++ while ((stream = pa_hashmap_first(control->streams))) ++ pas_stream_set_volume_control(stream, NULL); ++ ++ while ((device = pa_hashmap_first(control->default_for_devices))) ++ pa_device_set_default_volume_control(device, NULL); ++ ++ while ((device = pa_hashmap_first(control->devices))) { ++ /* Why do we have this assertion here? The concern is that if we call ++ * pa_device_set_volume_control() for some device that has the ++ * use_default_volume_control flag set, then that flag will be unset as ++ * a side effect, and we don't want that side effect. This assertion ++ * should be safe, because we just called ++ * pa_device_set_default_volume_control(NULL) for each device that this ++ * control was the default for, and that should ensure that we don't ++ * any more hold any references to devices that used to use this ++ * control as the default. */ ++ pa_assert(!device->use_default_volume_control); ++ pa_device_set_volume_control(device, NULL); ++ } ++} ++ ++void pa_volume_control_free(pa_volume_control *control) { ++ pa_assert(control); ++ ++ if (!control->unlinked) ++ pa_volume_control_unlink(control); ++ ++ if (control->audio_groups) { ++ pa_assert(pa_hashmap_isempty(control->audio_groups)); ++ pa_hashmap_free(control->audio_groups); ++ } ++ ++ if (control->streams) { ++ pa_assert(pa_hashmap_isempty(control->streams)); ++ pa_hashmap_free(control->streams); ++ } ++ ++ if (control->default_for_devices) { ++ pa_assert(pa_hashmap_isempty(control->default_for_devices)); ++ pa_hashmap_free(control->default_for_devices); ++ } ++ ++ if (control->devices) { ++ pa_assert(pa_hashmap_isempty(control->devices)); ++ pa_hashmap_free(control->devices); ++ } ++ ++ if (control->proplist) ++ pa_proplist_free(control->proplist); ++ ++ pa_xfree(control->description); ++ ++ if (control->name) ++ pa_volume_api_unregister_name(control->volume_api, control->name); ++ ++ pa_xfree(control); ++} ++ ++void pa_volume_control_set_owner_audio_group(pa_volume_control *control, pa_audio_group *group) { ++ pa_assert(control); ++ pa_assert(group); ++ ++ control->owner_audio_group = group; ++} ++ ++static void set_volume_internal(pa_volume_control *control, const pa_bvolume *volume, bool set_volume, bool set_balance) { ++ pa_bvolume old_volume; ++ bool volume_changed; ++ bool balance_changed; ++ ++ pa_assert(control); ++ pa_assert(volume); ++ ++ old_volume = control->volume; ++ volume_changed = !pa_bvolume_equal(volume, &old_volume, set_volume, false); ++ balance_changed = !pa_bvolume_equal(volume, &old_volume, false, set_balance); ++ ++ if (!volume_changed && !balance_changed) ++ return; ++ ++ if (volume_changed) ++ control->volume.volume = volume->volume; ++ ++ if (balance_changed) ++ pa_bvolume_copy_balance(&control->volume, volume); ++ ++ if (!control->linked || control->unlinked) ++ return; ++ ++ if (volume_changed) { ++ char old_volume_str[PA_VOLUME_SNPRINT_VERBOSE_MAX]; ++ char new_volume_str[PA_VOLUME_SNPRINT_VERBOSE_MAX]; ++ ++ pa_log_debug("The volume of volume control %s changed from %s to %s.", control->name, ++ pa_volume_snprint_verbose(old_volume_str, sizeof(old_volume_str), old_volume.volume, ++ control->convertible_to_dB), ++ pa_volume_snprint_verbose(new_volume_str, sizeof(new_volume_str), control->volume.volume, ++ control->convertible_to_dB)); ++ } ++ ++ if (balance_changed) { ++ char old_balance_str[PA_BVOLUME_SNPRINT_BALANCE_MAX]; ++ char new_balance_str[PA_BVOLUME_SNPRINT_BALANCE_MAX]; ++ ++ pa_log_debug("The balance of volume control %s changed from %s to %s.", control->name, ++ pa_bvolume_snprint_balance(old_balance_str, sizeof(old_balance_str), &control->volume), ++ pa_bvolume_snprint_balance(new_balance_str, sizeof(new_balance_str), &control->volume)); ++ } ++ ++ pa_hook_fire(&control->volume_api->hooks[PA_VOLUME_API_HOOK_VOLUME_CONTROL_VOLUME_CHANGED], control); ++} ++ ++int pa_volume_control_set_volume(pa_volume_control *control, const pa_bvolume *volume, bool set_volume, bool set_balance) { ++ pa_bvolume volume_local; ++ int r; ++ ++ pa_assert(control); ++ pa_assert(volume); ++ ++ volume_local = *volume; ++ ++ if (!control->set_volume) { ++ pa_log_info("Tried to set the volume of volume control %s, but the volume control doesn't support the operation.", ++ control->name); ++ return -PA_ERR_NOTSUPPORTED; ++ } ++ ++ if (set_balance ++ && !control->channel_map_is_writable ++ && !pa_channel_map_equal(&volume_local.channel_map, &control->volume.channel_map)) ++ pa_bvolume_remap(&volume_local, &control->volume.channel_map); ++ ++ if (pa_bvolume_equal(&volume_local, &control->volume, set_volume, set_balance)) ++ return 0; ++ ++ control->set_volume_in_progress = true; ++ r = control->set_volume(control, &volume_local, set_volume, set_balance); ++ control->set_volume_in_progress = false; ++ ++ if (r >= 0) ++ set_volume_internal(control, &volume_local, set_volume, set_balance); ++ ++ return r; ++} ++ ++void pa_volume_control_description_changed(pa_volume_control *control, const char *new_description) { ++ char *old_description; ++ ++ pa_assert(control); ++ pa_assert(new_description); ++ ++ old_description = control->description; ++ ++ if (pa_streq(new_description, old_description)) ++ return; ++ ++ control->description = pa_xstrdup(new_description); ++ pa_log_debug("The description of volume control %s changed from \"%s\" to \"%s\".", control->name, old_description, ++ new_description); ++ pa_xfree(old_description); ++ pa_hook_fire(&control->volume_api->hooks[PA_VOLUME_API_HOOK_VOLUME_CONTROL_DESCRIPTION_CHANGED], control); ++} ++ ++void pa_volume_control_volume_changed(pa_volume_control *control, const pa_bvolume *new_volume, bool volume_changed, ++ bool balance_changed) { ++ pa_assert(control); ++ pa_assert(new_volume); ++ ++ if (!control->linked) ++ return; ++ ++ if (control->set_volume_in_progress) ++ return; ++ ++ set_volume_internal(control, new_volume, volume_changed, balance_changed); ++} ++ ++void pa_volume_control_add_device(pa_volume_control *control, pa_device *device) { ++ pa_assert(control); ++ pa_assert(device); ++ ++ pa_assert_se(pa_hashmap_put(control->devices, device, device) >= 0); ++} ++ ++void pa_volume_control_remove_device(pa_volume_control *control, pa_device *device) { ++ pa_assert(control); ++ pa_assert(device); ++ ++ pa_assert_se(pa_hashmap_remove(control->devices, device)); ++} ++ ++void pa_volume_control_add_default_for_device(pa_volume_control *control, pa_device *device) { ++ pa_assert(control); ++ pa_assert(device); ++ ++ pa_assert_se(pa_hashmap_put(control->default_for_devices, device, device) >= 0); ++} ++ ++void pa_volume_control_remove_default_for_device(pa_volume_control *control, pa_device *device) { ++ pa_assert(control); ++ pa_assert(device); ++ ++ pa_assert_se(pa_hashmap_remove(control->default_for_devices, device)); ++} ++ ++void pa_volume_control_add_stream(pa_volume_control *control, pas_stream *stream) { ++ pa_assert(control); ++ pa_assert(stream); ++ ++ pa_assert_se(pa_hashmap_put(control->streams, stream, stream) >= 0); ++} ++ ++void pa_volume_control_remove_stream(pa_volume_control *control, pas_stream *stream) { ++ pa_assert(control); ++ pa_assert(stream); ++ ++ pa_assert_se(pa_hashmap_remove(control->streams, stream)); ++} ++ ++void pa_volume_control_add_audio_group(pa_volume_control *control, pa_audio_group *group) { ++ pa_assert(control); ++ pa_assert(group); ++ ++ pa_assert_se(pa_hashmap_put(control->audio_groups, group, group) >= 0); ++} ++ ++void pa_volume_control_remove_audio_group(pa_volume_control *control, pa_audio_group *group) { ++ pa_assert(control); ++ pa_assert(group); ++ ++ pa_assert_se(pa_hashmap_remove(control->audio_groups, group)); ++} +diff --git a/src/modules/volume-api/volume-control.h b/src/modules/volume-api/volume-control.h +new file mode 100644 +index 0000000..aaba758 +--- /dev/null ++++ b/src/modules/volume-api/volume-control.h +@@ -0,0 +1,112 @@ ++#ifndef foovolumecontrolhfoo ++#define foovolumecontrolhfoo ++ ++/*** ++ This file is part of PulseAudio. ++ ++ Copyright 2014 Intel Corporation ++ ++ PulseAudio is free software; you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as published ++ by the Free Software Foundation; either version 2.1 of the License, ++ or (at your option) any later version. ++ ++ PulseAudio 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 Lesser General Public License ++ along with PulseAudio; if not, write to the Free Software ++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ USA. ++***/ ++ ++#include ++#include ++ ++typedef struct pa_volume_control pa_volume_control; ++ ++struct pa_volume_control { ++ pa_volume_api *volume_api; ++ uint32_t index; ++ const char *name; ++ char *description; ++ pa_proplist *proplist; ++ pa_bvolume volume; ++ bool convertible_to_dB; ++ bool channel_map_is_writable; ++ ++ /* If this volume control is the "own volume control" of an audio group, ++ * this is set to point to that group, otherwise this is NULL. */ ++ pa_audio_group *owner_audio_group; ++ ++ pa_hashmap *devices; /* pa_device -> pa_device (hashmap-as-a-set) */ ++ pa_hashmap *default_for_devices; /* pa_device -> pa_device (hashmap-as-a-set) */ ++ pa_hashmap *streams; /* pas_stream -> pas_stream (hashmap-as-a-set) */ ++ pa_hashmap *audio_groups; /* pa_audio_group -> pa_audio_group (hashmap-as-a-set) */ ++ ++ bool linked; ++ bool unlinked; ++ bool set_volume_in_progress; ++ ++ /* Called from pa_volume_control_set_volume(). The implementation is ++ * expected to return a negative error code on failure. May be NULL, if the ++ * volume control is read-only. */ ++ int (*set_volume)(pa_volume_control *control, const pa_bvolume *volume, bool set_volume, bool set_balance); ++ ++ void *userdata; ++}; ++ ++pa_volume_control *pa_volume_control_new(pa_volume_api *api, const char *name, const char *description, bool convertible_to_dB, ++ bool channel_map_is_writable); ++ ++typedef void (*pa_volume_control_set_initial_volume_cb_t)(pa_volume_control *control); ++ ++/* initial_volume is the preferred initial volume of the volume control ++ * implementation. It may be NULL or partially invalid, if the implementation ++ * doesn't care about the initial state of the volume control, as long as these ++ * two rules are followed: ++ * ++ * 1) Read-only volume controls must always specify fully valid initial ++ * volume. ++ * 2) Volume controls with read-only channel map must always specify a valid ++ * channel map in initial_volume. ++ * ++ * The implementation's initial volume preference may be overridden by policy, ++ * if the volume control isn't read-only. When the final initial volume is ++ * known, the implementation is notified via set_initial_volume_cb (the volume ++ * can be read from control->volume). set_initial_volume_cb may be NULL, if the ++ * volume control is read-only. */ ++void pa_volume_control_put(pa_volume_control *control, const pa_bvolume *initial_volume, ++ pa_volume_control_set_initial_volume_cb_t set_initial_volume_cb); ++ ++void pa_volume_control_unlink(pa_volume_control *control); ++void pa_volume_control_free(pa_volume_control *control); ++ ++/* Called by audio-group.c only. */ ++void pa_volume_control_set_owner_audio_group(pa_volume_control *control, pa_audio_group *group); ++ ++/* Called by clients and policy modules. */ ++int pa_volume_control_set_volume(pa_volume_control *control, const pa_bvolume *volume, bool set_volume, bool set_balance); ++ ++/* Called by the volume control implementation. */ ++void pa_volume_control_description_changed(pa_volume_control *control, const char *new_description); ++void pa_volume_control_volume_changed(pa_volume_control *control, const pa_bvolume *new_volume, bool volume_changed, ++ bool balance_changed); ++ ++/* Called from device.c only. */ ++void pa_volume_control_add_device(pa_volume_control *control, pa_device *device); ++void pa_volume_control_remove_device(pa_volume_control *control, pa_device *device); ++void pa_volume_control_add_default_for_device(pa_volume_control *control, pa_device *device); ++void pa_volume_control_remove_default_for_device(pa_volume_control *control, pa_device *device); ++ ++/* Called from sstream.c only. */ ++void pa_volume_control_add_stream(pa_volume_control *control, pas_stream *stream); ++void pa_volume_control_remove_stream(pa_volume_control *control, pas_stream *stream); ++ ++/* Called from audio-group.c only. */ ++void pa_volume_control_add_audio_group(pa_volume_control *control, pa_audio_group *group); ++void pa_volume_control_remove_audio_group(pa_volume_control *control, pa_audio_group *group); ++ ++#endif +diff --git a/src/pulse/ext-volume-api.c b/src/pulse/ext-volume-api.c +new file mode 100644 +index 0000000..8e93bce +--- /dev/null ++++ b/src/pulse/ext-volume-api.c +@@ -0,0 +1,275 @@ ++/*** ++ This file is part of PulseAudio. ++ ++ Copyright 2014 Intel Corporation ++ ++ PulseAudio is free software; you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as published ++ by the Free Software Foundation; either version 2.1 of the License, ++ or (at your option) any later version. ++ ++ PulseAudio 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 Lesser General Public License ++ along with PulseAudio; if not, write to the Free Software ++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ USA. ++***/ ++ ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ ++#include "ext-volume-api.h" ++ ++#include ++#include ++#include ++ ++#include ++ ++int pa_ext_volume_api_balance_valid(double balance) { ++ return balance >= 0.0 && balance <= 1.0; ++} ++ ++int pa_ext_volume_api_bvolume_valid(const pa_ext_volume_api_bvolume *volume, int check_volume, int check_balance) { ++ unsigned channel; ++ ++ pa_assert(volume); ++ ++ if (check_volume && !PA_VOLUME_IS_VALID(volume->volume)) ++ return 0; ++ ++ if (!check_balance) ++ return 1; ++ ++ if (!pa_channel_map_valid(&volume->channel_map)) ++ return 0; ++ ++ for (channel = 0; channel < volume->channel_map.channels; channel++) { ++ if (!pa_ext_volume_api_balance_valid(volume->balance[channel])) ++ return 0; ++ } ++ ++ return 1; ++} ++ ++void pa_ext_volume_api_bvolume_init_invalid(pa_ext_volume_api_bvolume *volume) { ++ unsigned i; ++ ++ pa_assert(volume); ++ ++ volume->volume = PA_VOLUME_INVALID; ++ ++ for (i = 0; i < PA_CHANNELS_MAX; i++) ++ volume->balance[i] = -1.0; ++ ++ pa_channel_map_init(&volume->channel_map); ++} ++ ++void pa_ext_volume_api_bvolume_init_mono(pa_ext_volume_api_bvolume *bvolume, pa_volume_t volume) { ++ pa_assert(bvolume); ++ pa_assert(PA_VOLUME_IS_VALID(volume)); ++ ++ bvolume->volume = volume; ++ bvolume->balance[0] = 1.0; ++ pa_channel_map_init_mono(&bvolume->channel_map); ++} ++ ++int pa_ext_volume_api_bvolume_equal(const pa_ext_volume_api_bvolume *a, const pa_ext_volume_api_bvolume *b, ++ int check_volume, int check_balance) { ++ unsigned i; ++ ++ pa_assert(a); ++ pa_assert(b); ++ ++ if (check_volume && a->volume != b->volume) ++ return 0; ++ ++ if (!check_balance) ++ return 1; ++ ++ if (!pa_channel_map_equal(&a->channel_map, &b->channel_map)) ++ return 0; ++ ++ for (i = 0; i < a->channel_map.channels; i++) { ++ if (fabs(a->balance[i] - b->balance[i]) > 0.00001) ++ return 0; ++ } ++ ++ return 1; ++} ++ ++void pa_ext_volume_api_bvolume_from_cvolume(pa_ext_volume_api_bvolume *bvolume, const pa_cvolume *cvolume, ++ const pa_channel_map *map) { ++ unsigned i; ++ ++ pa_assert(bvolume); ++ pa_assert(cvolume); ++ pa_assert(map); ++ pa_assert(cvolume->channels == map->channels); ++ ++ bvolume->volume = pa_cvolume_max(cvolume); ++ bvolume->channel_map = *map; ++ ++ for (i = 0; i < map->channels; i++) { ++ if (bvolume->volume != PA_VOLUME_MUTED) ++ bvolume->balance[i] = ((double) cvolume->values[i]) / ((double) bvolume->volume); ++ else ++ bvolume->balance[i] = 1.0; ++ } ++} ++ ++void pa_ext_volume_api_bvolume_to_cvolume(const pa_ext_volume_api_bvolume *bvolume, pa_cvolume *cvolume) { ++ unsigned i; ++ ++ pa_assert(bvolume); ++ pa_assert(cvolume); ++ pa_assert(pa_ext_volume_api_bvolume_valid(bvolume, true, true)); ++ ++ cvolume->channels = bvolume->channel_map.channels; ++ ++ for (i = 0; i < bvolume->channel_map.channels; i++) ++ cvolume->values[i] = bvolume->volume * bvolume->balance[i]; ++} ++ ++void pa_ext_volume_api_bvolume_copy_balance(pa_ext_volume_api_bvolume *to, ++ const pa_ext_volume_api_bvolume *from) { ++ pa_assert(to); ++ pa_assert(from); ++ ++ memcpy(to->balance, from->balance, sizeof(from->balance)); ++ to->channel_map = from->channel_map; ++} ++ ++void pa_ext_volume_api_bvolume_reset_balance(pa_ext_volume_api_bvolume *volume, const pa_channel_map *map) { ++ unsigned i; ++ ++ pa_assert(volume); ++ pa_assert(map); ++ pa_assert(pa_channel_map_valid(map)); ++ ++ for (i = 0; i < map->channels; i++) ++ volume->balance[i] = 1.0; ++ ++ volume->channel_map = *map; ++} ++ ++void pa_ext_volume_api_bvolume_remap(pa_ext_volume_api_bvolume *volume, const pa_channel_map *to) { ++ unsigned i; ++ pa_cvolume cvolume; ++ ++ pa_assert(volume); ++ pa_assert(to); ++ pa_assert(pa_ext_volume_api_bvolume_valid(volume, false, true)); ++ pa_assert(pa_channel_map_valid(to)); ++ ++ cvolume.channels = volume->channel_map.channels; ++ ++ for (i = 0; i < cvolume.channels; i++) ++ cvolume.values[i] = volume->balance[i] * (double) PA_VOLUME_NORM; ++ ++ pa_cvolume_remap(&cvolume, &volume->channel_map, to); ++ ++ for (i = 0; i < to->channels; i++) ++ volume->balance[i] = (double) cvolume.values[i] / (double) PA_VOLUME_NORM; ++ ++ volume->channel_map = *to; ++} ++ ++double pa_ext_volume_api_bvolume_get_left_right_balance(const pa_ext_volume_api_bvolume *volume) { ++ pa_ext_volume_api_bvolume bvolume; ++ pa_cvolume cvolume; ++ double ret; ++ ++ pa_assert(volume); ++ ++ bvolume.volume = PA_VOLUME_NORM; ++ pa_ext_volume_api_bvolume_copy_balance(&bvolume, volume); ++ pa_ext_volume_api_bvolume_to_cvolume(&bvolume, &cvolume); ++ ret = pa_cvolume_get_balance(&cvolume, &volume->channel_map); ++ ++ return ret; ++} ++ ++void pa_ext_volume_api_bvolume_set_left_right_balance(pa_ext_volume_api_bvolume *volume, double balance) { ++ pa_cvolume cvolume; ++ pa_volume_t old_volume; ++ ++ pa_assert(volume); ++ ++ if (!pa_channel_map_can_balance(&volume->channel_map)) ++ return; ++ ++ pa_cvolume_reset(&cvolume, volume->channel_map.channels); ++ pa_cvolume_set_balance(&cvolume, &volume->channel_map, balance); ++ old_volume = volume->volume; ++ pa_ext_volume_api_bvolume_from_cvolume(volume, &cvolume, &volume->channel_map); ++ volume->volume = old_volume; ++} ++ ++double pa_ext_volume_api_bvolume_get_rear_front_balance(const pa_ext_volume_api_bvolume *volume) { ++ pa_ext_volume_api_bvolume bvolume; ++ pa_cvolume cvolume; ++ double ret; ++ ++ pa_assert(volume); ++ ++ bvolume.volume = PA_VOLUME_NORM; ++ pa_ext_volume_api_bvolume_copy_balance(&bvolume, volume); ++ pa_ext_volume_api_bvolume_to_cvolume(&bvolume, &cvolume); ++ ret = pa_cvolume_get_fade(&cvolume, &volume->channel_map); ++ ++ return ret; ++} ++ ++void pa_ext_volume_api_bvolume_set_rear_front_balance(pa_ext_volume_api_bvolume *volume, double balance) { ++ pa_cvolume cvolume; ++ pa_volume_t old_volume; ++ ++ pa_assert(volume); ++ ++ if (!pa_channel_map_can_fade(&volume->channel_map)) ++ return; ++ ++ pa_cvolume_reset(&cvolume, volume->channel_map.channels); ++ pa_cvolume_set_fade(&cvolume, &volume->channel_map, balance); ++ old_volume = volume->volume; ++ pa_ext_volume_api_bvolume_from_cvolume(volume, &cvolume, &volume->channel_map); ++ volume->volume = old_volume; ++} ++ ++char *pa_ext_volume_api_bvolume_snprint_balance(char *buf, size_t buf_len, ++ const pa_ext_volume_api_bvolume *volume) { ++ char *e; ++ unsigned channel; ++ bool first = true; ++ ++ pa_assert(buf); ++ pa_assert(buf_len > 0); ++ pa_assert(volume); ++ ++ pa_init_i18n(); ++ ++ if (!pa_ext_volume_api_bvolume_valid(volume, true, true)) { ++ pa_snprintf(buf, buf_len, _("(invalid)")); ++ return buf; ++ } ++ ++ *(e = buf) = 0; ++ ++ for (channel = 0; channel < volume->channel_map.channels && buf_len > 1; channel++) { ++ buf_len -= pa_snprintf(e, buf_len, "%s%s: %u%%", ++ first ? "" : ", ", ++ pa_channel_position_to_string(volume->channel_map.map[channel]), ++ (unsigned) (volume->balance[channel] * 100 + 0.5)); ++ ++ e = strchr(e, 0); ++ first = false; ++ } ++ ++ return buf; ++} +diff --git a/src/pulse/ext-volume-api.h b/src/pulse/ext-volume-api.h +new file mode 100644 +index 0000000..36b7748 +--- /dev/null ++++ b/src/pulse/ext-volume-api.h +@@ -0,0 +1,68 @@ ++#ifndef fooextvolumeapihfoo ++#define fooextvolumeapihfoo ++ ++/*** ++ This file is part of PulseAudio. ++ ++ Copyright 2014 Intel Corporation ++ ++ PulseAudio is free software; you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as published ++ by the Free Software Foundation; either version 2.1 of the License, ++ or (at your option) any later version. ++ ++ PulseAudio 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 Lesser General Public License ++ along with PulseAudio; if not, write to the Free Software ++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ USA. ++***/ ++ ++#include ++#include ++#include ++ ++/* This API is temporary, and has no stability guarantees whatsoever. Think ++ * twice before making anything that relies on this API. This is undocumented ++ * for a reason. */ ++ ++PA_C_DECL_BEGIN ++ ++typedef struct pa_ext_volume_api_bvolume pa_ext_volume_api_bvolume; ++ ++struct pa_ext_volume_api_bvolume { ++ pa_volume_t volume; ++ double balance[PA_CHANNELS_MAX]; ++ pa_channel_map channel_map; ++}; ++ ++int pa_ext_volume_api_balance_valid(double balance) PA_GCC_CONST; ++int pa_ext_volume_api_bvolume_valid(const pa_ext_volume_api_bvolume *volume, int check_volume, int check_balance) ++ PA_GCC_PURE; ++void pa_ext_volume_api_bvolume_init_invalid(pa_ext_volume_api_bvolume *volume); ++void pa_ext_volume_api_bvolume_init_mono(pa_ext_volume_api_bvolume *bvolume, pa_volume_t volume); ++int pa_ext_volume_api_bvolume_equal(const pa_ext_volume_api_bvolume *a, const pa_ext_volume_api_bvolume *b, ++ int check_volume, int check_balance) PA_GCC_PURE; ++void pa_ext_volume_api_bvolume_from_cvolume(pa_ext_volume_api_bvolume *bvolume, const pa_cvolume *cvolume, ++ const pa_channel_map *map); ++void pa_ext_volume_api_bvolume_to_cvolume(const pa_ext_volume_api_bvolume *bvolume, pa_cvolume *cvolume); ++void pa_ext_volume_api_bvolume_copy_balance(pa_ext_volume_api_bvolume *to, ++ const pa_ext_volume_api_bvolume *from); ++void pa_ext_volume_api_bvolume_reset_balance(pa_ext_volume_api_bvolume *volume, const pa_channel_map *map); ++void pa_ext_volume_api_bvolume_remap(pa_ext_volume_api_bvolume *volume, const pa_channel_map *to); ++double pa_ext_volume_api_bvolume_get_left_right_balance(const pa_ext_volume_api_bvolume *volume) PA_GCC_PURE; ++void pa_ext_volume_api_bvolume_set_left_right_balance(pa_ext_volume_api_bvolume *volume, double balance); ++double pa_ext_volume_api_bvolume_get_rear_front_balance(const pa_ext_volume_api_bvolume *volume) PA_GCC_PURE; ++void pa_ext_volume_api_bvolume_set_rear_front_balance(pa_ext_volume_api_bvolume *volume, double balance); ++ ++#define PA_EXT_VOLUME_API_BVOLUME_SNPRINT_BALANCE_MAX 500 ++char *pa_ext_volume_api_bvolume_snprint_balance(char *buf, size_t buf_size, ++ const pa_ext_volume_api_bvolume *volume); ++ ++PA_C_DECL_END ++ ++#endif +-- +2.1.4 + +--- a/po/POTFILES.in 2016-04-13 17:40:00.818008672 +0200 ++++ b/po/POTFILES.in 2016-04-13 17:40:30.885008622 +0200 +@@ -198,3 +198,5 @@ + src/utils/padsp.c + src/utils/pasuspender.c + src/utils/pax11publish.c ++src/modules/volume-api/device-creator.c ++src/pulse/ext-volume-api.c diff --git a/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0031-Add-module-main-volume-policy.patch b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0031-Add-module-main-volume-policy.patch new file mode 100644 index 000000000..216ed21e9 --- /dev/null +++ b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0031-Add-module-main-volume-policy.patch @@ -0,0 +1,1418 @@ +From cfb39f18569679f59c9b6283c47e8d90ddd9763d Mon Sep 17 00:00:00 2001 +From: Tanu Kaskinen +Date: Wed, 21 May 2014 14:13:41 +0300 +Subject: [PATCH] Add module-main-volume-policy + +Change-Id: I787141b43cafb652aa752c64ae28b6b7aa052d8e +Signed-off-by: Jaska Uimonen +--- + Makefile.am | 3 + + src/Makefile.am | 15 + + src/daemon/default.pa.in | 4 + + .../main-volume-policy/main-volume-context.c | 325 ++++++++++++ + .../main-volume-policy/main-volume-context.h | 75 +++ + .../main-volume-policy/main-volume-policy.c | 213 ++++++++ + .../main-volume-policy.conf.example | 20 + + .../main-volume-policy/main-volume-policy.h | 72 +++ + .../main-volume-policy/module-main-volume-policy.c | 556 +++++++++++++++++++++ + 9 files changed, 1283 insertions(+) + create mode 100644 src/modules/main-volume-policy/main-volume-context.c + create mode 100644 src/modules/main-volume-policy/main-volume-context.h + create mode 100644 src/modules/main-volume-policy/main-volume-policy.c + create mode 100644 src/modules/main-volume-policy/main-volume-policy.conf.example + create mode 100644 src/modules/main-volume-policy/main-volume-policy.h + create mode 100644 src/modules/main-volume-policy/module-main-volume-policy.c + +diff --git a/Makefile.am b/Makefile.am +index cf4a648..646b7fc 100644 +--- a/Makefile.am 2016-04-13 15:14:28.942023245 +0200 ++++ b/Makefile.am 2016-04-13 15:16:32.691023039 +0200 +@@ -60,6 +60,9 @@ + moduledevvolumeapi_DATA = src/modules/volume-api/*.h + moduledevvolumeapidir = $(includedir)/pulsemodule/modules/volume-api + ++moduledevmainvolumepolicy_DATA = $(top_srcdir)/src/modules/main-volume-policy/*.h ++moduledevmainvolumepolicydir = $(includedir)/pulsemodule/modules/main-volume-policy ++ + if HAVE_GLIB20 + pkgconfig_DATA += \ + libpulse-mainloop-glib.pc + libpulse-mainloop-glib.pc +diff --git a/src/Makefile.am b/src/Makefile.am +index a6bb319..8fa60ec 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -1050,7 +1050,8 @@ + libprotocol-simple.la \ + libprotocol-http.la \ + libprotocol-native.la \ +- libvolume-api.la ++ libvolume-api.la \ ++ libmain-volume-policy.la + + if HAVE_WEBRTC + modlibexec_LTLIBRARIES += libwebrtc-util.la +@@ -1051,6 +1052,12 @@ libcli_la_SOURCES = pulsecore/cli.c pulsecore/cli.h + libcli_la_LDFLAGS = $(AM_LDFLAGS) -avoid-version + libcli_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINOR@.la libpulsecommon-@PA_MAJORMINOR@.la libpulse.la + ++libmain_volume_policy_la_SOURCES = \ ++ modules/main-volume-policy/main-volume-context.c modules/main-volume-policy/main-volume-context.h \ ++ modules/main-volume-policy/main-volume-policy.c modules/main-volume-policy/main-volume-policy.h ++libmain_volume_policy_la_LDFLAGS = $(AM_LDFLAGS) -avoid-version ++libmain_volume_policy_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINOR@.la libpulsecommon-@PA_MAJORMINOR@.la libpulse.la libvolume-api.la ++ + libprotocol_cli_la_SOURCES = pulsecore/protocol-cli.c pulsecore/protocol-cli.h + libprotocol_cli_la_LDFLAGS = $(AM_LDFLAGS) -avoid-version + libprotocol_cli_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINOR@.la libpulsecommon-@PA_MAJORMINOR@.la libpulse.la libcli.la +@@ -1136,6 +1136,7 @@ endif + modlibexec_LTLIBRARIES += \ + module-cli.la \ + module-cli-protocol-tcp.la \ ++ module-main-volume-policy.la \ + module-simple-protocol-tcp.la \ + module-null-sink.la \ + module-null-source.la \ +@@ -1426,6 +1434,7 @@ SYMDEF_FILES = \ + module-cli-symdef.h \ + module-cli-protocol-tcp-symdef.h \ + module-cli-protocol-unix-symdef.h \ ++ module-main-volume-policy-symdef.h \ + module-pipe-sink-symdef.h \ + module-pipe-source-symdef.h \ + module-simple-protocol-tcp-symdef.h \ +@@ -1575,6 +1584,12 @@ module_cli_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_CLI $(AM_ + module_cli_protocol_unix_la_LDFLAGS = $(MODULE_LDFLAGS) + module_cli_protocol_unix_la_LIBADD = $(MODULE_LIBADD) libprotocol-cli.la + ++# Main volume and mute policy ++ ++module_main_volume_policy_la_SOURCES = modules/main-volume-policy/module-main-volume-policy.c ++module_main_volume_policy_la_LDFLAGS = $(MODULE_LDFLAGS) ++module_main_volume_policy_la_LIBADD = $(MODULE_LIBADD) libmain-volume-policy.la libvolume-api.la ++ + # HTTP protocol + + module_http_protocol_tcp_la_SOURCES = modules/module-protocol-stub.c +diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in +index 7cf52a4..f70804c 100755 +--- a/src/daemon/default.pa.in ++++ b/src/daemon/default.pa.in +@@ -188,6 +188,10 @@ + #.endif + ])dnl + ++.ifexists module-main-volume-policy ++load-module module-main-volume-policy ++.endif ++ + ### Make some devices default + #set-default-sink output + #set-default-source input +diff --git a/src/modules/main-volume-policy/main-volume-context.c b/src/modules/main-volume-policy/main-volume-context.c +new file mode 100644 +index 0000000..7ac35c6 +--- /dev/null ++++ b/src/modules/main-volume-policy/main-volume-context.c +@@ -0,0 +1,325 @@ ++/*** ++ This file is part of PulseAudio. ++ ++ Copyright 2014 Intel Corporation ++ ++ PulseAudio is free software; you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as published ++ by the Free Software Foundation; either version 2.1 of the License, ++ or (at your option) any later version. ++ ++ PulseAudio 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 Lesser General Public License ++ along with PulseAudio; if not, write to the Free Software ++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ USA. ++***/ ++ ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ ++#include "main-volume-context.h" ++ ++#include ++#include ++ ++int pa_main_volume_context_new(pa_main_volume_policy *policy, const char *name, const char *description, ++ pa_main_volume_context **context) { ++ pa_main_volume_context *context_local; ++ int r; ++ ++ pa_assert(policy); ++ pa_assert(name); ++ pa_assert(description); ++ pa_assert(context); ++ ++ context_local = pa_xnew0(struct pa_main_volume_context, 1); ++ context_local->main_volume_policy = policy; ++ context_local->index = pa_main_volume_policy_allocate_main_volume_context_index(policy); ++ ++ r = pa_main_volume_policy_register_name(policy, name, true, &context_local->name); ++ if (r < 0) ++ goto fail; ++ ++ context_local->description = pa_xstrdup(description); ++ ++ *context = context_local; ++ ++ return 0; ++ ++fail: ++ pa_main_volume_context_free(context_local); ++ ++ return r; ++} ++ ++void pa_main_volume_context_put(pa_main_volume_context *context) { ++ pa_assert(context); ++ ++ pa_main_volume_policy_add_main_volume_context(context->main_volume_policy, context); ++ ++ context->linked = true; ++ ++ pa_log_debug("Created main volume context #%u.", context->index); ++ pa_log_debug(" Name: %s", context->name); ++ pa_log_debug(" Description: %s", context->description); ++ pa_log_debug(" Main output volume control: %s", ++ context->main_output_volume_control ? context->main_output_volume_control->name : "(unset)"); ++ pa_log_debug(" Main input volume control: %s", ++ context->main_input_volume_control ? context->main_input_volume_control->name : "(unset)"); ++ pa_log_debug(" Main output mute control: %s", ++ context->main_output_mute_control ? context->main_output_mute_control->name : "(unset)"); ++ pa_log_debug(" Main input mute control: %s", ++ context->main_input_mute_control ? context->main_input_mute_control->name : "(unset)"); ++ ++ pa_hook_fire(&context->main_volume_policy->hooks[PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_PUT], context); ++} ++ ++void pa_main_volume_context_unlink(pa_main_volume_context *context) { ++ pa_assert(context); ++ ++ if (context->unlinked) { ++ pa_log_debug("Unlinking main volume context %s (already unlinked, this is a no-op).", context->name); ++ return; ++ } ++ ++ context->unlinked = true; ++ ++ pa_log_debug("Unlinking main volume context %s.", context->name); ++ ++ if (context->linked) ++ pa_hook_fire(&context->main_volume_policy->hooks[PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_UNLINK], context); ++ ++ if (context->main_input_mute_control_binding) { ++ pa_binding_free(context->main_input_mute_control_binding); ++ context->main_input_mute_control_binding = NULL; ++ } ++ ++ if (context->main_output_mute_control_binding) { ++ pa_binding_free(context->main_output_mute_control_binding); ++ context->main_output_mute_control_binding = NULL; ++ } ++ ++ if (context->main_input_volume_control_binding) { ++ pa_binding_free(context->main_input_volume_control_binding); ++ context->main_input_volume_control_binding = NULL; ++ } ++ ++ if (context->main_output_volume_control_binding) { ++ pa_binding_free(context->main_output_volume_control_binding); ++ context->main_output_volume_control_binding = NULL; ++ } ++ ++ context->main_input_mute_control = NULL; ++ context->main_output_mute_control = NULL; ++ context->main_input_volume_control = NULL; ++ context->main_output_volume_control = NULL; ++ ++ pa_main_volume_policy_remove_main_volume_context(context->main_volume_policy, context); ++} ++ ++void pa_main_volume_context_free(pa_main_volume_context *context) { ++ pa_assert(context); ++ ++ if (!context->unlinked) ++ pa_main_volume_context_unlink(context); ++ ++ pa_xfree(context->description); ++ ++ if (context->name) ++ pa_main_volume_policy_unregister_name(context->main_volume_policy, context->name); ++ ++ pa_xfree(context); ++} ++ ++const char *pa_main_volume_context_get_name(pa_main_volume_context *context) { ++ pa_assert(context); ++ ++ return context->name; ++} ++ ++static void set_main_output_volume_control_internal(pa_main_volume_context *context, pa_volume_control *control) { ++ pa_volume_control *old_control; ++ ++ pa_assert(context); ++ ++ old_control = context->main_output_volume_control; ++ ++ if (control == old_control) ++ return; ++ ++ context->main_output_volume_control = control; ++ ++ if (!context->linked || context->unlinked) ++ return; ++ ++ pa_log_debug("The main output volume control of main volume context %s changed from %s to %s.", context->name, ++ old_control ? old_control->name : "(unset)", control ? control->name : "(unset)"); ++ ++ pa_hook_fire(&context->main_volume_policy->hooks ++ [PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_MAIN_OUTPUT_VOLUME_CONTROL_CHANGED], ++ context); ++} ++ ++void pa_main_volume_context_bind_main_output_volume_control(pa_main_volume_context *context, ++ pa_binding_target_info *target_info) { ++ pa_binding_owner_info owner_info = { ++ .userdata = context, ++ .set_value = (pa_binding_set_value_cb_t) set_main_output_volume_control_internal, ++ }; ++ ++ pa_assert(context); ++ pa_assert(target_info); ++ ++ if (context->main_output_volume_control_binding) ++ pa_binding_free(context->main_output_volume_control_binding); ++ ++ context->main_output_volume_control_binding = pa_binding_new(context->main_volume_policy->volume_api, &owner_info, ++ target_info); ++} ++ ++static void set_main_input_volume_control_internal(pa_main_volume_context *context, pa_volume_control *control) { ++ pa_volume_control *old_control; ++ ++ pa_assert(context); ++ ++ old_control = context->main_input_volume_control; ++ ++ if (control == old_control) ++ return; ++ ++ context->main_input_volume_control = control; ++ ++ if (!context->linked || context->unlinked) ++ return; ++ ++ pa_log_debug("The main input volume control of main volume context %s changed from %s to %s.", context->name, ++ old_control ? old_control->name : "(unset)", control ? control->name : "(unset)"); ++ ++ pa_hook_fire(&context->main_volume_policy->hooks ++ [PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_MAIN_INPUT_VOLUME_CONTROL_CHANGED], ++ context); ++} ++ ++void pa_main_volume_context_bind_main_input_volume_control(pa_main_volume_context *context, ++ pa_binding_target_info *target_info) { ++ pa_binding_owner_info owner_info = { ++ .userdata = context, ++ .set_value = (pa_binding_set_value_cb_t) set_main_input_volume_control_internal, ++ }; ++ ++ pa_assert(context); ++ pa_assert(target_info); ++ ++ if (context->main_input_volume_control_binding) ++ pa_binding_free(context->main_input_volume_control_binding); ++ ++ context->main_input_volume_control_binding = pa_binding_new(context->main_volume_policy->volume_api, &owner_info, ++ target_info); ++} ++ ++static void set_main_output_mute_control_internal(pa_main_volume_context *context, pa_mute_control *control) { ++ pa_mute_control *old_control; ++ ++ pa_assert(context); ++ ++ old_control = context->main_output_mute_control; ++ ++ if (control == old_control) ++ return; ++ ++ context->main_output_mute_control = control; ++ ++ if (!context->linked || context->unlinked) ++ return; ++ ++ pa_log_debug("The main output mute control of main volume context %s changed from %s to %s.", context->name, ++ old_control ? old_control->name : "(unset)", control ? control->name : "(unset)"); ++ ++ pa_hook_fire(&context->main_volume_policy->hooks ++ [PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_MAIN_OUTPUT_MUTE_CONTROL_CHANGED], ++ context); ++} ++ ++void pa_main_volume_context_bind_main_output_mute_control(pa_main_volume_context *context, ++ pa_binding_target_info *target_info) { ++ pa_binding_owner_info owner_info = { ++ .userdata = context, ++ .set_value = (pa_binding_set_value_cb_t) set_main_output_mute_control_internal, ++ }; ++ ++ pa_assert(context); ++ pa_assert(target_info); ++ ++ if (context->main_output_mute_control_binding) ++ pa_binding_free(context->main_output_mute_control_binding); ++ ++ context->main_output_mute_control_binding = pa_binding_new(context->main_volume_policy->volume_api, &owner_info, ++ target_info); ++} ++ ++static void set_main_input_mute_control_internal(pa_main_volume_context *context, pa_mute_control *control) { ++ pa_mute_control *old_control; ++ ++ pa_assert(context); ++ ++ old_control = context->main_input_mute_control; ++ ++ if (control == old_control) ++ return; ++ ++ context->main_input_mute_control = control; ++ ++ if (!context->linked || context->unlinked) ++ return; ++ ++ pa_log_debug("The main input mute control of main volume context %s changed from %s to %s.", context->name, ++ old_control ? old_control->name : "(unset)", control ? control->name : "(unset)"); ++ ++ pa_hook_fire(&context->main_volume_policy->hooks ++ [PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_MAIN_INPUT_MUTE_CONTROL_CHANGED], ++ context); ++} ++ ++void pa_main_volume_context_bind_main_input_mute_control(pa_main_volume_context *context, ++ pa_binding_target_info *target_info) { ++ pa_binding_owner_info owner_info = { ++ .userdata = context, ++ .set_value = (pa_binding_set_value_cb_t) set_main_input_mute_control_internal, ++ }; ++ ++ pa_assert(context); ++ pa_assert(target_info); ++ ++ if (context->main_input_mute_control_binding) ++ pa_binding_free(context->main_input_mute_control_binding); ++ ++ context->main_input_mute_control_binding = pa_binding_new(context->main_volume_policy->volume_api, &owner_info, ++ target_info); ++} ++ ++pa_binding_target_type *pa_main_volume_context_create_binding_target_type(pa_main_volume_policy *policy) { ++ pa_binding_target_type *type; ++ ++ pa_assert(policy); ++ ++ type = pa_binding_target_type_new(PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_TYPE, policy->main_volume_contexts, ++ &policy->hooks[PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_PUT], ++ &policy->hooks[PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_UNLINK], ++ (pa_binding_target_type_get_name_cb_t) pa_main_volume_context_get_name); ++ pa_binding_target_type_add_field(type, PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_OUTPUT_VOLUME_CONTROL, ++ PA_BINDING_CALCULATE_FIELD_OFFSET(pa_main_volume_context, main_output_volume_control)); ++ pa_binding_target_type_add_field(type, PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_INPUT_VOLUME_CONTROL, ++ PA_BINDING_CALCULATE_FIELD_OFFSET(pa_main_volume_context, main_input_volume_control)); ++ pa_binding_target_type_add_field(type, PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_OUTPUT_MUTE_CONTROL, ++ PA_BINDING_CALCULATE_FIELD_OFFSET(pa_main_volume_context, main_output_mute_control)); ++ pa_binding_target_type_add_field(type, PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_INPUT_MUTE_CONTROL, ++ PA_BINDING_CALCULATE_FIELD_OFFSET(pa_main_volume_context, main_input_mute_control)); ++ ++ return type; ++} +diff --git a/src/modules/main-volume-policy/main-volume-context.h b/src/modules/main-volume-policy/main-volume-context.h +new file mode 100644 +index 0000000..4a0a6f7 +--- /dev/null ++++ b/src/modules/main-volume-policy/main-volume-context.h +@@ -0,0 +1,75 @@ ++#ifndef foomainvolumecontexthfoo ++#define foomainvolumecontexthfoo ++ ++/*** ++ This file is part of PulseAudio. ++ ++ Copyright 2014 Intel Corporation ++ ++ PulseAudio is free software; you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as published ++ by the Free Software Foundation; either version 2.1 of the License, ++ or (at your option) any later version. ++ ++ PulseAudio 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 Lesser General Public License ++ along with PulseAudio; if not, write to the Free Software ++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ USA. ++***/ ++ ++#include ++ ++#include ++ ++typedef struct pa_main_volume_context pa_main_volume_context; ++ ++#define PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_TYPE "MainVolumeContext" ++#define PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_OUTPUT_VOLUME_CONTROL "main_output_volume_control" ++#define PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_INPUT_VOLUME_CONTROL "main_input_volume_control" ++#define PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_OUTPUT_MUTE_CONTROL "main_output_mute_control" ++#define PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_INPUT_MUTE_CONTROL "main_input_mute_control" ++ ++struct pa_main_volume_context { ++ pa_main_volume_policy *main_volume_policy; ++ uint32_t index; ++ const char *name; ++ char *description; ++ pa_volume_control *main_output_volume_control; ++ pa_volume_control *main_input_volume_control; ++ pa_mute_control *main_output_mute_control; ++ pa_mute_control *main_input_mute_control; ++ ++ pa_binding *main_output_volume_control_binding; ++ pa_binding *main_input_volume_control_binding; ++ pa_binding *main_output_mute_control_binding; ++ pa_binding *main_input_mute_control_binding; ++ ++ bool linked; ++ bool unlinked; ++}; ++ ++int pa_main_volume_context_new(pa_main_volume_policy *policy, const char *name, const char *description, ++ pa_main_volume_context **context); ++void pa_main_volume_context_put(pa_main_volume_context *context); ++void pa_main_volume_context_unlink(pa_main_volume_context *context); ++void pa_main_volume_context_free(pa_main_volume_context *context); ++ ++const char *pa_main_volume_context_get_name(pa_main_volume_context *context); ++ ++void pa_main_volume_context_bind_main_output_volume_control(pa_main_volume_context *context, ++ pa_binding_target_info *target_info); ++void pa_main_volume_context_bind_main_input_volume_control(pa_main_volume_context *context, ++ pa_binding_target_info *target_info); ++void pa_main_volume_context_bind_main_output_mute_control(pa_main_volume_context *context, ++ pa_binding_target_info *target_info); ++void pa_main_volume_context_bind_main_input_mute_control(pa_main_volume_context *context, pa_binding_target_info *target_info); ++ ++/* Called from main-volume-policy.c only. */ ++pa_binding_target_type *pa_main_volume_context_create_binding_target_type(pa_main_volume_policy *policy); ++ ++#endif +diff --git a/src/modules/main-volume-policy/main-volume-policy.c b/src/modules/main-volume-policy/main-volume-policy.c +new file mode 100644 +index 0000000..b0b4ede +--- /dev/null ++++ b/src/modules/main-volume-policy/main-volume-policy.c +@@ -0,0 +1,213 @@ ++/*** ++ This file is part of PulseAudio. ++ ++ Copyright 2014 Intel Corporation ++ ++ PulseAudio is free software; you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as published ++ by the Free Software Foundation; either version 2.1 of the License, ++ or (at your option) any later version. ++ ++ PulseAudio 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 Lesser General Public License ++ along with PulseAudio; if not, write to the Free Software ++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ USA. ++***/ ++ ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ ++#include "main-volume-policy.h" ++ ++#include ++ ++#include ++#include ++ ++static pa_main_volume_policy *main_volume_policy_new(pa_core *core); ++static void main_volume_policy_free(pa_main_volume_policy *policy); ++ ++pa_main_volume_policy *pa_main_volume_policy_get(pa_core *core) { ++ pa_main_volume_policy *policy; ++ ++ pa_assert(core); ++ ++ policy = pa_shared_get(core, "main-volume-policy"); ++ ++ if (policy) ++ pa_main_volume_policy_ref(policy); ++ else { ++ policy = main_volume_policy_new(core); ++ pa_assert_se(pa_shared_set(core, "main-volume-policy", policy) >= 0); ++ } ++ ++ return policy; ++} ++ ++pa_main_volume_policy *pa_main_volume_policy_ref(pa_main_volume_policy *policy) { ++ pa_assert(policy); ++ ++ policy->refcnt++; ++ ++ return policy; ++} ++ ++void pa_main_volume_policy_unref(pa_main_volume_policy *policy) { ++ pa_assert(policy); ++ pa_assert(policy->refcnt > 0); ++ ++ policy->refcnt--; ++ ++ if (policy->refcnt == 0) { ++ pa_assert_se(pa_shared_remove(policy->core, "main-volume-policy") >= 0); ++ main_volume_policy_free(policy); ++ } ++} ++ ++static pa_main_volume_policy *main_volume_policy_new(pa_core *core) { ++ pa_main_volume_policy *policy; ++ unsigned i; ++ ++ pa_assert(core); ++ ++ policy = pa_xnew0(pa_main_volume_policy, 1); ++ policy->core = core; ++ policy->refcnt = 1; ++ policy->volume_api = pa_volume_api_get(core); ++ policy->names = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, pa_xfree); ++ policy->main_volume_contexts = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); ++ ++ for (i = 0; i < PA_MAIN_VOLUME_POLICY_HOOK_MAX; i++) ++ pa_hook_init(&policy->hooks[i], policy); ++ ++ policy->main_volume_context_binding_target_type = pa_main_volume_context_create_binding_target_type(policy); ++ pa_volume_api_add_binding_target_type(policy->volume_api, policy->main_volume_context_binding_target_type); ++ ++ pa_log_debug("Created a pa_main_volume_policy object."); ++ ++ return policy; ++} ++ ++static void main_volume_policy_free(pa_main_volume_policy *policy) { ++ unsigned i; ++ ++ pa_assert(policy); ++ pa_assert(policy->refcnt == 0); ++ ++ pa_log_debug("Freeing the pa_main_volume_policy object."); ++ ++ if (policy->main_volume_context_binding_target_type) { ++ pa_volume_api_remove_binding_target_type(policy->volume_api, policy->main_volume_context_binding_target_type); ++ pa_binding_target_type_free(policy->main_volume_context_binding_target_type); ++ } ++ ++ for (i = 0; i < PA_MAIN_VOLUME_POLICY_HOOK_MAX; i++) ++ pa_hook_done(&policy->hooks[i]); ++ ++ if (policy->main_volume_contexts) { ++ pa_assert(pa_hashmap_isempty(policy->main_volume_contexts)); ++ pa_hashmap_free(policy->main_volume_contexts); ++ } ++ ++ if (policy->names) { ++ pa_assert(pa_hashmap_isempty(policy->names)); ++ pa_hashmap_free(policy->names); ++ } ++ ++ if (policy->volume_api) ++ pa_volume_api_unref(policy->volume_api); ++ ++ pa_xfree(policy); ++} ++ ++int pa_main_volume_policy_register_name(pa_main_volume_policy *policy, const char *requested_name, ++ bool fail_if_already_registered, const char **registered_name) { ++ char *n; ++ ++ pa_assert(policy); ++ pa_assert(requested_name); ++ pa_assert(registered_name); ++ ++ n = pa_xstrdup(requested_name); ++ ++ if (pa_hashmap_put(policy->names, n, n) < 0) { ++ unsigned i = 1; ++ ++ pa_xfree(n); ++ ++ if (fail_if_already_registered) { ++ pa_log("Name %s already registered.", requested_name); ++ return -PA_ERR_EXIST; ++ } ++ ++ do { ++ i++; ++ n = pa_sprintf_malloc("%s.%u", requested_name, i); ++ } while (pa_hashmap_put(policy->names, n, n) < 0); ++ } ++ ++ *registered_name = n; ++ ++ return 0; ++} ++ ++void pa_main_volume_policy_unregister_name(pa_main_volume_policy *policy, const char *name) { ++ pa_assert(policy); ++ pa_assert(name); ++ ++ pa_assert_se(pa_hashmap_remove_and_free(policy->names, name) >= 0); ++} ++ ++uint32_t pa_main_volume_policy_allocate_main_volume_context_index(pa_main_volume_policy *policy) { ++ uint32_t idx; ++ ++ pa_assert(policy); ++ ++ idx = policy->next_main_volume_context_index++; ++ ++ return idx; ++} ++ ++void pa_main_volume_policy_add_main_volume_context(pa_main_volume_policy *policy, pa_main_volume_context *context) { ++ pa_assert(policy); ++ pa_assert(context); ++ ++ pa_assert_se(pa_hashmap_put(policy->main_volume_contexts, (void *) context->name, context) >= 0); ++} ++ ++int pa_main_volume_policy_remove_main_volume_context(pa_main_volume_policy *policy, pa_main_volume_context *context) { ++ pa_assert(policy); ++ pa_assert(context); ++ ++ if (!pa_hashmap_remove(policy->main_volume_contexts, context->name)) ++ return -1; ++ ++ if (context == policy->active_main_volume_context) ++ pa_main_volume_policy_set_active_main_volume_context(policy, NULL); ++ ++ return 0; ++} ++ ++void pa_main_volume_policy_set_active_main_volume_context(pa_main_volume_policy *policy, pa_main_volume_context *context) { ++ pa_main_volume_context *old_context; ++ ++ pa_assert(policy); ++ ++ old_context = policy->active_main_volume_context; ++ ++ if (context == old_context) ++ return; ++ ++ policy->active_main_volume_context = context; ++ ++ pa_log_debug("The active main volume context changed from %s to %s.", old_context ? old_context->name : "(unset)", ++ context ? context->name : "(unset)"); ++ ++ pa_hook_fire(&policy->hooks[PA_MAIN_VOLUME_POLICY_HOOK_ACTIVE_MAIN_VOLUME_CONTEXT_CHANGED], NULL); ++} +diff --git a/src/modules/main-volume-policy/main-volume-policy.conf.example b/src/modules/main-volume-policy/main-volume-policy.conf.example +new file mode 100644 +index 0000000..a4a35d3 +--- /dev/null ++++ b/src/modules/main-volume-policy/main-volume-policy.conf.example +@@ -0,0 +1,20 @@ ++[General] ++output-volume-model = by-active-main-volume-context ++input-volume-model = by-active-main-volume-context ++output-mute-model = none ++input-mute-model = none ++main-volume-contexts = x-example-call-main-volume-context x-example-default-main-volume-context ++ ++[MainVolumeContext x-example-call-main-volume-context] ++description = Call main volume context ++main-output-volume-control = bind:AudioGroup:x-example-call-downlink-audio-group ++main-input-volume-control = bind:AudioGroup:x-example-call-uplink-audio-group ++main-output-mute-control = none ++main-input-mute-control = none ++ ++[MainVolumeContext x-example-default-main-volume-context] ++description = Default main volume context ++main-output-volume-control = bind:AudioGroup:x-example-default-output-audio-group ++main-input-volume-control = bind:AudioGroup:x-example-default-input-audio-group ++main-output-mute-control = none ++main-input-mute-control = none +diff --git a/src/modules/main-volume-policy/main-volume-policy.h b/src/modules/main-volume-policy/main-volume-policy.h +new file mode 100644 +index 0000000..5cd669e +--- /dev/null ++++ b/src/modules/main-volume-policy/main-volume-policy.h +@@ -0,0 +1,72 @@ ++#ifndef foomainvolumepolicyhfoo ++#define foomainvolumepolicyhfoo ++ ++/*** ++ This file is part of PulseAudio. ++ ++ Copyright 2014 Intel Corporation ++ ++ PulseAudio is free software; you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as published ++ by the Free Software Foundation; either version 2.1 of the License, ++ or (at your option) any later version. ++ ++ PulseAudio 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 Lesser General Public License ++ along with PulseAudio; if not, write to the Free Software ++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ USA. ++***/ ++ ++#include ++#include ++ ++#include ++ ++typedef struct pa_main_volume_policy pa_main_volume_policy; ++ ++/* Avoid circular dependencies... */ ++typedef struct pa_main_volume_context pa_main_volume_context; ++ ++enum { ++ PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_PUT, ++ PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_UNLINK, ++ PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_MAIN_OUTPUT_VOLUME_CONTROL_CHANGED, ++ PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_MAIN_INPUT_VOLUME_CONTROL_CHANGED, ++ PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_MAIN_OUTPUT_MUTE_CONTROL_CHANGED, ++ PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_MAIN_INPUT_MUTE_CONTROL_CHANGED, ++ PA_MAIN_VOLUME_POLICY_HOOK_ACTIVE_MAIN_VOLUME_CONTEXT_CHANGED, ++ PA_MAIN_VOLUME_POLICY_HOOK_MAX, ++}; ++ ++struct pa_main_volume_policy { ++ pa_core *core; ++ unsigned refcnt; ++ pa_volume_api *volume_api; ++ pa_hashmap *names; /* object name -> object name (hashmap-as-a-set) */ ++ pa_hashmap *main_volume_contexts; /* name -> pa_main_volume_context */ ++ pa_main_volume_context *active_main_volume_context; ++ ++ uint32_t next_main_volume_context_index; ++ pa_hook hooks[PA_MAIN_VOLUME_POLICY_HOOK_MAX]; ++ pa_binding_target_type *main_volume_context_binding_target_type; ++}; ++ ++pa_main_volume_policy *pa_main_volume_policy_get(pa_core *core); ++pa_main_volume_policy *pa_main_volume_policy_ref(pa_main_volume_policy *policy); ++void pa_main_volume_policy_unref(pa_main_volume_policy *policy); ++ ++int pa_main_volume_policy_register_name(pa_main_volume_policy *policy, const char *requested_name, ++ bool fail_if_already_registered, const char **registered_name); ++void pa_main_volume_policy_unregister_name(pa_main_volume_policy *policy, const char *name); ++ ++uint32_t pa_main_volume_policy_allocate_main_volume_context_index(pa_main_volume_policy *policy); ++void pa_main_volume_policy_add_main_volume_context(pa_main_volume_policy *policy, pa_main_volume_context *context); ++int pa_main_volume_policy_remove_main_volume_context(pa_main_volume_policy *policy, pa_main_volume_context *context); ++void pa_main_volume_policy_set_active_main_volume_context(pa_main_volume_policy *policy, pa_main_volume_context *context); ++ ++#endif +diff --git a/src/modules/main-volume-policy/module-main-volume-policy.c b/src/modules/main-volume-policy/module-main-volume-policy.c +new file mode 100644 +index 0000000..a14699d +--- /dev/null ++++ b/src/modules/main-volume-policy/module-main-volume-policy.c +@@ -0,0 +1,556 @@ ++/*** ++ This file is part of PulseAudio. ++ ++ Copyright 2014 Intel Corporation ++ ++ PulseAudio is free software; you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as published ++ by the Free Software Foundation; either version 2.1 of the License, ++ or (at your option) any later version. ++ ++ PulseAudio 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 Lesser General Public License ++ along with PulseAudio; if not, write to the Free Software ++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ USA. ++***/ ++ ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ ++#include "module-main-volume-policy-symdef.h" ++ ++#include ++ ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++ ++PA_MODULE_AUTHOR("Tanu Kaskinen"); ++PA_MODULE_DESCRIPTION(_("Main volume and mute policy")); ++PA_MODULE_VERSION(PACKAGE_VERSION); ++PA_MODULE_LOAD_ONCE(true); ++ ++enum control_type { ++ CONTROL_TYPE_VOLUME, ++ CONTROL_TYPE_MUTE, ++}; ++ ++enum model { ++ MODEL_NONE, ++ MODEL_BY_ACTIVE_MAIN_VOLUME_CONTEXT, ++}; ++ ++struct userdata { ++ pa_main_volume_policy *main_volume_policy; ++ enum model output_volume_model; ++ enum model input_volume_model; ++ enum model output_mute_model; ++ enum model input_mute_model; ++ pa_hashmap *contexts; /* name -> struct context */ ++ ++ pa_hook_slot *active_main_volume_context_changed_slot; ++ ++ /* The following fields are only used during initialization. */ ++ pa_hashmap *context_names; /* name -> name (hashmap-as-a-set) */ ++ pa_hashmap *unused_contexts; /* name -> struct context */ ++}; ++ ++struct context { ++ struct userdata *userdata; ++ char *name; ++ char *description; ++ pa_binding_target_info *main_output_volume_control_target_info; ++ pa_binding_target_info *main_input_volume_control_target_info; ++ pa_binding_target_info *main_output_mute_control_target_info; ++ pa_binding_target_info *main_input_mute_control_target_info; ++ pa_main_volume_context *main_volume_context; ++ ++ bool unlinked; ++}; ++ ++static void context_unlink(struct context *context); ++ ++static const char *model_to_string(enum model model) { ++ switch (model) { ++ case MODEL_NONE: ++ return "none"; ++ ++ case MODEL_BY_ACTIVE_MAIN_VOLUME_CONTEXT: ++ return "by-active-main-volume-context"; ++ } ++ ++ pa_assert_not_reached(); ++} ++ ++static int model_from_string(const char *str, enum model *model) { ++ pa_assert(str); ++ pa_assert(model); ++ ++ if (pa_streq(str, "none")) ++ *model = MODEL_NONE; ++ else if (pa_streq(str, "by-active-main-volume-context")) ++ *model = MODEL_BY_ACTIVE_MAIN_VOLUME_CONTEXT; ++ else ++ return -PA_ERR_INVALID; ++ ++ return 0; ++} ++ ++static struct context *context_new(struct userdata *u, const char *name) { ++ struct context *context; ++ ++ pa_assert(u); ++ pa_assert(name); ++ ++ context = pa_xnew0(struct context, 1); ++ context->userdata = u; ++ context->name = pa_xstrdup(name); ++ context->description = pa_xstrdup(name); ++ ++ return context; ++} ++ ++static int context_put(struct context *context) { ++ int r; ++ ++ pa_assert(context); ++ ++ r = pa_main_volume_context_new(context->userdata->main_volume_policy, context->name, context->description, ++ &context->main_volume_context); ++ if (r < 0) ++ goto fail; ++ ++ if (context->main_output_volume_control_target_info) ++ pa_main_volume_context_bind_main_output_volume_control(context->main_volume_context, ++ context->main_output_volume_control_target_info); ++ ++ if (context->main_input_volume_control_target_info) ++ pa_main_volume_context_bind_main_input_volume_control(context->main_volume_context, ++ context->main_input_volume_control_target_info); ++ ++ if (context->main_output_mute_control_target_info) ++ pa_main_volume_context_bind_main_output_mute_control(context->main_volume_context, ++ context->main_output_mute_control_target_info); ++ ++ if (context->main_input_mute_control_target_info) ++ pa_main_volume_context_bind_main_input_mute_control(context->main_volume_context, ++ context->main_input_mute_control_target_info); ++ ++ pa_main_volume_context_put(context->main_volume_context); ++ ++ return 0; ++ ++fail: ++ context_unlink(context); ++ ++ return r; ++} ++ ++static void context_unlink(struct context *context) { ++ pa_assert(context); ++ ++ if (context->unlinked) ++ return; ++ ++ context->unlinked = true; ++ ++ if (context->main_volume_context) { ++ pa_main_volume_context_free(context->main_volume_context); ++ context->main_volume_context = NULL; ++ } ++} ++ ++static void context_free(struct context *context) { ++ pa_assert(context); ++ ++ if (!context->unlinked) ++ context_unlink(context); ++ ++ if (context->main_input_mute_control_target_info) ++ pa_binding_target_info_free(context->main_input_mute_control_target_info); ++ ++ if (context->main_output_mute_control_target_info) ++ pa_binding_target_info_free(context->main_output_mute_control_target_info); ++ ++ if (context->main_input_volume_control_target_info) ++ pa_binding_target_info_free(context->main_input_volume_control_target_info); ++ ++ if (context->main_output_volume_control_target_info) ++ pa_binding_target_info_free(context->main_output_volume_control_target_info); ++ ++ pa_xfree(context->description); ++ pa_xfree(context->name); ++ pa_xfree(context); ++} ++ ++static void context_set_description(struct context *context, const char *description) { ++ pa_assert(context); ++ pa_assert(description); ++ ++ pa_xfree(context->description); ++ context->description = pa_xstrdup(description); ++} ++ ++static void context_set_main_control_target_info(struct context *context, enum control_type type, pa_direction_t direction, ++ pa_binding_target_info *info) { ++ pa_assert(context); ++ ++ switch (type) { ++ case CONTROL_TYPE_VOLUME: ++ if (direction == PA_DIRECTION_OUTPUT) { ++ if (context->main_output_volume_control_target_info) ++ pa_binding_target_info_free(context->main_output_volume_control_target_info); ++ ++ if (info) ++ context->main_output_volume_control_target_info = pa_binding_target_info_copy(info); ++ else ++ context->main_output_volume_control_target_info = NULL; ++ } else { ++ if (context->main_input_volume_control_target_info) ++ pa_binding_target_info_free(context->main_input_volume_control_target_info); ++ ++ if (info) ++ context->main_input_volume_control_target_info = pa_binding_target_info_copy(info); ++ else ++ context->main_input_volume_control_target_info = NULL; ++ } ++ break; ++ ++ case CONTROL_TYPE_MUTE: ++ if (direction == PA_DIRECTION_OUTPUT) { ++ if (context->main_output_mute_control_target_info) ++ pa_binding_target_info_free(context->main_output_mute_control_target_info); ++ ++ if (info) ++ context->main_output_mute_control_target_info = pa_binding_target_info_copy(info); ++ else ++ context->main_output_mute_control_target_info = NULL; ++ } else { ++ if (context->main_input_mute_control_target_info) ++ pa_binding_target_info_free(context->main_input_mute_control_target_info); ++ ++ if (info) ++ context->main_input_mute_control_target_info = pa_binding_target_info_copy(info); ++ else ++ context->main_input_mute_control_target_info = NULL; ++ } ++ break; ++ } ++} ++ ++static pa_hook_result_t active_main_volume_context_changed_cb(void *hook_data, void *call_data, void *userdata) { ++ struct userdata *u = userdata; ++ pa_main_volume_context *context; ++ pa_volume_api *api; ++ pa_binding_target_info *info = NULL; ++ ++ pa_assert(u); ++ ++ context = u->main_volume_policy->active_main_volume_context; ++ api = u->main_volume_policy->volume_api; ++ ++ if (u->output_volume_model == MODEL_BY_ACTIVE_MAIN_VOLUME_CONTEXT) { ++ if (context) { ++ info = pa_binding_target_info_new(PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_TYPE, context->name, ++ PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_OUTPUT_VOLUME_CONTROL); ++ pa_volume_api_bind_main_output_volume_control(api, info); ++ } else ++ pa_volume_api_set_main_output_volume_control(api, NULL); ++ } ++ ++ if (u->input_volume_model == MODEL_BY_ACTIVE_MAIN_VOLUME_CONTEXT) { ++ if (context) { ++ info = pa_binding_target_info_new(PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_TYPE, context->name, ++ PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_INPUT_VOLUME_CONTROL); ++ pa_volume_api_bind_main_input_volume_control(api, info); ++ } else ++ pa_volume_api_set_main_input_volume_control(api, NULL); ++ } ++ ++ if (u->output_mute_model == MODEL_BY_ACTIVE_MAIN_VOLUME_CONTEXT) { ++ if (context) { ++ info = pa_binding_target_info_new(PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_TYPE, context->name, ++ PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_OUTPUT_MUTE_CONTROL); ++ pa_volume_api_bind_main_output_mute_control(api, info); ++ } else ++ pa_volume_api_set_main_output_mute_control(api, NULL); ++ } ++ ++ if (u->input_mute_model == MODEL_BY_ACTIVE_MAIN_VOLUME_CONTEXT) { ++ if (context) { ++ info = pa_binding_target_info_new(PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_TYPE, context->name, ++ PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_INPUT_MUTE_CONTROL); ++ pa_volume_api_bind_main_input_mute_control(api, info); ++ } else ++ pa_volume_api_set_main_input_mute_control(api, NULL); ++ } ++ ++ if (info) ++ pa_binding_target_info_free(info); ++ ++ return PA_HOOK_OK; ++} ++ ++static int parse_model(pa_config_parser_state *state) { ++ int r; ++ ++ pa_assert(state); ++ ++ r = model_from_string(state->rvalue, state->data); ++ if (r < 0) ++ pa_log("[%s:%u] Failed to parse model: %s", state->filename, state->lineno, state->rvalue); ++ ++ return r; ++} ++ ++static int parse_main_volume_contexts(pa_config_parser_state *state) { ++ struct userdata *u; ++ char *name; ++ const char *split_state = NULL; ++ ++ pa_assert(state); ++ ++ u = state->userdata; ++ ++ while ((name = pa_split_spaces(state->rvalue, &split_state))) ++ pa_hashmap_put(u->context_names, name, name); ++ ++ return 0; ++} ++ ++static struct context *get_context(struct userdata *u, const char *section) { ++ const char *name; ++ struct context *context; ++ ++ pa_assert(u); ++ ++ if (!section) ++ return NULL; ++ ++ if (!pa_startswith(section, "MainVolumeContext ")) ++ return NULL; ++ ++ name = section + 18; ++ ++ context = pa_hashmap_get(u->unused_contexts, name); ++ if (!context) { ++ context = context_new(u, name); ++ pa_hashmap_put(u->unused_contexts, context->name, context); ++ } ++ ++ return context; ++} ++ ++static int parse_description(pa_config_parser_state *state) { ++ struct userdata *u; ++ struct context *context; ++ ++ pa_assert(state); ++ ++ u = state->userdata; ++ ++ context = get_context(u, state->section); ++ if (!context) { ++ pa_log("[%s:%u] Key \"%s\" not expected in section %s.", state->filename, state->lineno, state->lvalue, ++ pa_strnull(state->section)); ++ return -PA_ERR_INVALID; ++ } ++ ++ context_set_description(context, state->rvalue); ++ ++ return 0; ++} ++ ++static const char *get_target_field_name(enum control_type type) { ++ switch (type) { ++ case CONTROL_TYPE_VOLUME: ++ return "volume_control"; ++ ++ case CONTROL_TYPE_MUTE: ++ return "mute_control"; ++ } ++ ++ pa_assert_not_reached(); ++} ++ ++static int parse_main_control(pa_config_parser_state *state, enum control_type type, pa_direction_t direction) { ++ struct userdata *u; ++ struct context *context; ++ ++ pa_assert(state); ++ ++ u = state->userdata; ++ ++ context = get_context(u, state->section); ++ if (!context) { ++ pa_log("[%s:%u] Key \"%s\" not expected in section %s.", state->filename, state->lineno, state->lvalue, ++ pa_strnull(state->section)); ++ return -PA_ERR_INVALID; ++ } ++ ++ if (pa_streq(state->rvalue, "none")) ++ context_set_main_control_target_info(context, type, direction, NULL); ++ else if (pa_startswith(state->rvalue, "bind:")) { ++ int r; ++ pa_binding_target_info *info; ++ ++ r = pa_binding_target_info_new_from_string(state->rvalue, get_target_field_name(type), &info); ++ if (r < 0) { ++ pa_log("[%s:%u] Failed to parse binding target \"%s\".", state->filename, state->lineno, state->rvalue); ++ return r; ++ } ++ ++ context_set_main_control_target_info(context, type, direction, info); ++ pa_binding_target_info_free(info); ++ } else { ++ pa_log("[%s:%u] Failed to parse value \"%s\".", state->filename, state->lineno, state->rvalue); ++ return -PA_ERR_INVALID; ++ } ++ ++ return 0; ++} ++ ++static int parse_main_output_volume_control(pa_config_parser_state *state) { ++ pa_assert(state); ++ ++ return parse_main_control(state, CONTROL_TYPE_VOLUME, PA_DIRECTION_OUTPUT); ++} ++ ++static int parse_main_input_volume_control(pa_config_parser_state *state) { ++ pa_assert(state); ++ ++ return parse_main_control(state, CONTROL_TYPE_VOLUME, PA_DIRECTION_INPUT); ++} ++ ++static int parse_main_output_mute_control(pa_config_parser_state *state) { ++ pa_assert(state); ++ ++ return parse_main_control(state, CONTROL_TYPE_MUTE, PA_DIRECTION_OUTPUT); ++} ++ ++static int parse_main_input_mute_control(pa_config_parser_state *state) { ++ pa_assert(state); ++ ++ return parse_main_control(state, CONTROL_TYPE_MUTE, PA_DIRECTION_INPUT); ++} ++ ++static void finalize_config(struct userdata *u) { ++ const char *context_name; ++ void *state; ++ struct context *context; ++ ++ pa_assert(u); ++ ++ PA_HASHMAP_FOREACH(context_name, u->context_names, state) { ++ int r; ++ ++ context = pa_hashmap_remove(u->unused_contexts, context_name); ++ if (!context) ++ context = context_new(u, context_name); ++ ++ r = context_put(context); ++ if (r < 0) { ++ pa_log_warn("Failed to create main volume context %s.", context_name); ++ context_free(context); ++ continue; ++ } ++ ++ pa_assert_se(pa_hashmap_put(u->contexts, context->name, context) >= 0); ++ } ++ ++ PA_HASHMAP_FOREACH(context, u->unused_contexts, state) ++ pa_log_debug("Main volume context %s is not used.", context->name); ++ ++ pa_hashmap_free(u->unused_contexts); ++ u->unused_contexts = NULL; ++ ++ pa_hashmap_free(u->context_names); ++ u->context_names = NULL; ++} ++ ++int pa__init(pa_module *module) { ++ struct userdata *u; ++ FILE *f; ++ char *fn = NULL; ++ ++ pa_assert(module); ++ ++ u = module->userdata = pa_xnew0(struct userdata, 1); ++ u->main_volume_policy = pa_main_volume_policy_get(module->core); ++ u->output_volume_model = MODEL_NONE; ++ u->input_volume_model = MODEL_NONE; ++ u->output_mute_model = MODEL_NONE; ++ u->input_mute_model = MODEL_NONE; ++ u->contexts = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, ++ (pa_free_cb_t) context_free); ++ u->active_main_volume_context_changed_slot = ++ pa_hook_connect(&u->main_volume_policy->hooks[PA_MAIN_VOLUME_POLICY_HOOK_ACTIVE_MAIN_VOLUME_CONTEXT_CHANGED], ++ PA_HOOK_NORMAL, active_main_volume_context_changed_cb, u); ++ u->context_names = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, pa_xfree); ++ u->unused_contexts = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, ++ (pa_free_cb_t) context_free); ++ ++ f = pa_open_config_file(PA_DEFAULT_CONFIG_DIR PA_PATH_SEP "main-volume-policy.conf", "main-volume-policy.conf", NULL, &fn); ++ if (f) { ++ pa_config_item config_items[] = { ++ { "output-volume-model", parse_model, &u->output_volume_model, "General" }, ++ { "input-volume-model", parse_model, &u->input_volume_model, "General" }, ++ { "output-mute-model", parse_model, &u->output_mute_model, "General" }, ++ { "input-mute-model", parse_model, &u->input_mute_model, "General" }, ++ { "main-volume-contexts", parse_main_volume_contexts, NULL, "General" }, ++ { "description", parse_description, NULL, NULL }, ++ { "main-output-volume-control", parse_main_output_volume_control, NULL, NULL }, ++ { "main-input-volume-control", parse_main_input_volume_control, NULL, NULL }, ++ { "main-output-mute-control", parse_main_output_mute_control, NULL, NULL }, ++ { "main-input-mute-control", parse_main_input_mute_control, NULL, NULL }, ++ { NULL }, ++ }; ++ ++ pa_config_parse(fn, f, config_items, NULL, u); ++ pa_xfree(fn); ++ fn = NULL; ++ fclose(f); ++ f = NULL; ++ } ++ ++ finalize_config(u); ++ ++ pa_log_debug("Output volume model: %s", model_to_string(u->output_volume_model)); ++ pa_log_debug("Input volume model: %s", model_to_string(u->input_volume_model)); ++ pa_log_debug("Output mute model: %s", model_to_string(u->output_mute_model)); ++ pa_log_debug("Input mute model: %s", model_to_string(u->input_mute_model)); ++ ++ return 0; ++} ++ ++void pa__done(pa_module *module) { ++ struct userdata *u; ++ ++ pa_assert(module); ++ ++ u = module->userdata; ++ if (!u) ++ return; ++ ++ if (u->active_main_volume_context_changed_slot) ++ pa_hook_slot_free(u->active_main_volume_context_changed_slot); ++ ++ if (u->contexts) ++ pa_hashmap_free(u->contexts); ++ ++ if (u->main_volume_policy) ++ pa_main_volume_policy_unref(u->main_volume_policy); ++ ++ pa_xfree(u); ++} +-- +2.1.4 + +--- a/po/POTFILES.in 2016-04-14 13:03:50.715006116 +0200 ++++ b/po/POTFILES.in 2016-04-14 13:04:23.097006062 +0200 +@@ -200,3 +200,4 @@ + src/utils/pax11publish.c + src/modules/volume-api/device-creator.c + src/pulse/ext-volume-api.c ++src/modules/main-volume-policy/module-main-volume-policy.c diff --git a/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0039-main-volume-policy-adapt-to-pa6rev.patch b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0039-main-volume-policy-adapt-to-pa6rev.patch new file mode 100644 index 000000000..4f2777112 --- /dev/null +++ b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0039-main-volume-policy-adapt-to-pa6rev.patch @@ -0,0 +1,11 @@ +--- a/src/modules/main-volume-policy/module-main-volume-policy.c 2016-04-18 10:59:46.124086205 +0200 ++++ b/src/modules/main-volume-policy/module-main-volume-policy.c 2016-04-18 11:01:31.497089360 +0200 +@@ -517,7 +517,7 @@ + { NULL }, + }; + +- pa_config_parse(fn, f, config_items, NULL, u); ++ pa_config_parse(fn, f, config_items, NULL, false, u); + pa_xfree(fn); + fn = NULL; + fclose(f); diff --git a/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio_%.bbappend b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio_%.bbappend new file mode 100644 index 000000000..a54ec60f1 --- /dev/null +++ b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio_%.bbappend @@ -0,0 +1,28 @@ +FILESEXTRAPATHS_append := ":${THISDIR}/${PN}" + +inherit systemd + +do_install_append() { + # Install pulseaudio systemd service + if ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'true', 'false', d)}; then + install -m 644 -p -D ${WORKDIR}/build/src/pulseaudio.service ${D}${systemd_user_unitdir}/pulseaudio.service + install -m 644 -p -D ${WORKDIR}/pulseaudio-${PV}/src/daemon/systemd/user/pulseaudio.socket ${D}${systemd_user_unitdir}/pulseaudio.socket + + # Execute these manually on behalf of systemctl script (from systemd-systemctl-native.bb) + # because it does not support systemd's user mode. + install -d ${D}${systemd_user_unitdir}/sockets.target.wants/ + ln -sf ${systemd_user_unitdir}/pulseaudio.socket ${D}${systemd_user_unitdir}/sockets.target.wants/ + + install -d ${D}${systemd_user_unitdir}/default.target.wants/ + ln -sf ${systemd_user_unitdir}/pulseaudio.service ${D}${systemd_user_unitdir}/default.target.wants/ + fi + mkdir -p ${D}/${bindir} + install -m 755 -p -D ${WORKDIR}/build/src/.libs/pacat ${D}/${bindir}/ +} + +FILES_${PN}-server += " \ + ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', '${systemd_user_unitdir}/pulseaudio.socket', '', d)} \ + ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', '${systemd_user_unitdir}/sockets.target.wants/pulseaudio.socket', '', d)} \ + ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', '${systemd_user_unitdir}/pulseaudio.service', '', d)} \ + ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', '${systemd_user_unitdir}/default.target.wants/pulseaudio.service', '', d)} \ +" diff --git a/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio_10.0.bbappend b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio_10.0.bbappend new file mode 100644 index 000000000..f59ee89d5 --- /dev/null +++ b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio_10.0.bbappend @@ -0,0 +1,15 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/pulseaudio-10.0:" + +SRC_URI += " \ + file://0001-install-files-for-a-module-development.patch \ + file://0002-volume-ramp-additions-to-the-low-level-infra.patch \ + file://0003-volume-ramp-adding-volume-ramping-to-sink-input.patch \ + file://0004-sink-input-Code-cleanup-regarding-volume-ramping.patch \ + file://0005-sink-input-volume-Add-support-for-volume-ramp-factor.patch \ + file://0006-sink-input-Remove-pa_sink_input_set_volume_ramp.patch;apply=no \ + file://enable-ofono-hfp-backend.patch \ +" + +PACKAGES =+ " pulseaudio-module-dev" + +FILES_pulseaudio-module-dev = "${includedir}/pulsemodule/* ${libdir}/pkgconfig/pulseaudio-module-devel.pc" diff --git a/meta-agl-profile-core/recipes-navigation/geoclue/files/org.freedesktop.GeoClue2.Client.conf b/meta-agl-profile-core/recipes-navigation/geoclue/files/org.freedesktop.GeoClue2.Client.conf new file mode 100644 index 000000000..a7486d055 --- /dev/null +++ b/meta-agl-profile-core/recipes-navigation/geoclue/files/org.freedesktop.GeoClue2.Client.conf @@ -0,0 +1,8 @@ + + + + + + diff --git a/meta-agl-profile-core/recipes-navigation/geoclue/geoclue_%.bbappend b/meta-agl-profile-core/recipes-navigation/geoclue/geoclue_%.bbappend new file mode 100644 index 000000000..9d61a9f61 --- /dev/null +++ b/meta-agl-profile-core/recipes-navigation/geoclue/geoclue_%.bbappend @@ -0,0 +1,9 @@ +inherit gobject-introspection + +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" +SRC_URI_append = "file://org.freedesktop.GeoClue2.Client.conf" + +do_install_append() { + install -d ${D}/etc/dbus-1/system.d + install -m 0644 ${WORKDIR}/org.freedesktop.GeoClue2.Client.conf ${D}/etc/dbus-1/system.d/org.freedesktop.GeoClue2.Client.conf +} diff --git a/meta-agl-profile-core/recipes-navigation/gpsd/gpsd_%.bbappend b/meta-agl-profile-core/recipes-navigation/gpsd/gpsd_%.bbappend new file mode 100644 index 000000000..af72aece9 --- /dev/null +++ b/meta-agl-profile-core/recipes-navigation/gpsd/gpsd_%.bbappend @@ -0,0 +1,14 @@ +SYSTEMD_SERVICE_${PN} += " gpsdctl@.service" + +do_install_append() { + # use the systemd compatible gpsd.rules + install -d ${D}/${sysconfdir}/udev/rules.d + install -m 0644 ${S}/gpsd.rules ${D}/${sysconfdir}/udev/rules.d/60-gpsd.rules + + #support for systemd + install -d ${D}${systemd_unitdir}/system/ + install -m 0644 ${S}/systemd/gpsdctl@.service ${D}${systemd_unitdir}/system + + #autoprobe usb gps devices + echo 'USBAUTO="true"' >> ${D}${sysconfdir}/default/gpsd.default +} diff --git a/meta-agl-profile-core/recipes-support/libsoup/libsoup-2.4_%.bbappend b/meta-agl-profile-core/recipes-support/libsoup/libsoup-2.4_%.bbappend new file mode 100644 index 000000000..06651fc11 --- /dev/null +++ b/meta-agl-profile-core/recipes-support/libsoup/libsoup-2.4_%.bbappend @@ -0,0 +1 @@ +EXTRA_OECONF_append_class-native = " --disable-tls-check" diff --git a/meta-agl-profile-core/recipes-test/aiostress/aiostress_0.22.bb b/meta-agl-profile-core/recipes-test/aiostress/aiostress_0.22.bb new file mode 100644 index 000000000..7803d74ed --- /dev/null +++ b/meta-agl-profile-core/recipes-test/aiostress/aiostress_0.22.bb @@ -0,0 +1,24 @@ +SUMMARY = "Async IO testing utility" +DESCRIPTION = "aio-stress will open or create each file on the command line, and start a series of aio to it.\ +aio is done in a rotating loop. first file1 gets 8 requests, then file2, then file3 etc.\ +As each file finishes writing, it is switched to reads io buffers are aligned in case you want to do raw io" +HOMEPAGE = "https://oss.oracle.com/~mason/aio-stress/" +LICENSE = "GPLv2" + +S="${WORKDIR}" + +LIC_FILES_CHKSUM = "file://${S}/aio-stress.c;md5=ccb5d196a3736bbd835d582a4e2329c3" + +SRC_URI = "https://oss.oracle.com/~mason/aio-stress/aio-stress.c" +SRC_URI[md5sum] = "ccb5d196a3736bbd835d582a4e2329c3" +SRC_URI[sha256sum] = "3f4cffcc946fb717fff9d8fe932c7c2ee606efff198408d9fbe16955151445f7" + +do_compile () { + ${CC} -Wall -Wshadow -o aio-stress -lpthread -laio aio-stress.c +} + +do_install () { + install -d ${D}${bindir} + install -m 0755 aio-stress ${D}${bindir} +} + diff --git a/meta-agl-profile-core/recipes-test/blobsallad/blobsallad/0001-Makefile.patch b/meta-agl-profile-core/recipes-test/blobsallad/blobsallad/0001-Makefile.patch new file mode 100644 index 000000000..0ae56cee1 --- /dev/null +++ b/meta-agl-profile-core/recipes-test/blobsallad/blobsallad/0001-Makefile.patch @@ -0,0 +1,53 @@ +--- a/Makefile.orig 2016-04-01 15:50:20.636358716 +0200 ++++ b/Makefile 2016-04-01 15:51:58.916361191 +0200 +@@ -1,3 +1,9 @@ ++INCDIR = $(SDKROOT)/usr/include ++LIBDIR = $(SDKROOT)/usr/lib ++ ++EXTRA_CFLAGS=-I$(INCDIR) ++EXTRA_LDFLAGS=-Wl,-rpath-link=$(LIBDIR) -L$(LIBDIR) ++ + OBJECTS = bs_main.o \ + bs_vector.o \ + bs_pointmass.o \ +@@ -15,21 +21,21 @@ + bs_profiler.o \ + bs_rubberband.o + +-CC = gcc ++#CC = gcc + + DISTDIR = blobsallad-src + +-CFLAGS = `pkg-config --cflags cairo; sdl-config --cflags` +-LIBS = `pkg-config --libs cairo; sdl-config --libs` -lm -lGL -lGLU ++EXTRA_CFLAGS += -I$(INCDIR)/cairo -I$(INCDIR)/SDL -D_GNU_SOURCE=1 -D_REENTRANT ++EXTRA_LDFLAGS += -lcairo -lSDL -lpthread -lm + + all: $(OBJECTS) +- $(CC) -g -o blobsallad $(OBJECTS) $(LIBS) ++ $(CC) -g -o blobsallad $(OBJECTS) $(EXTRA_LDFLAGS) + + map: +- gcc -o createmap create_testdata.c -Wall -g -lm ++ $(CC) -o createmap create_testdata.c -Wall -g -lm + + octree: +- gcc -o test_octree test_octree.c bs_octree.c bs_list.c bs_vector.c bs_vector_util.c bs_timer.c bs_array.c -Wall -O2 $(LIBS) $(CFLAGS) ++ $(CC) -o test_octree test_octree.c bs_octree.c bs_list.c bs_vector.c bs_vector_util.c bs_timer.c bs_array.c -Wall -O2 $(EXTRA_LDFLAGS) $(EXTRA_CFLAGS) + + GFX_OBJECTS = gfx_main.o \ + bs_gfx.o \ +@@ -41,10 +47,10 @@ + bs_list.o + + gfx: $(GFX_OBJECTS) +- gcc -o gfx_main -Wall -g $(GFX_OBJECTS) $(LIBS) ++ $(CC) -o gfx_main -Wall -g $(GFX_OBJECTS) $(EXTRA_LDFLAGS) + + .c.o: +- $(CC) -g -Wall $(CFLAGS) $ -c $< ++ $(CC) -g -Wall $(EXTRA_CFLAGS) $ -c $< + + clean: + rm -f *.o; rm -f blobsallad; diff --git a/meta-agl-profile-core/recipes-test/blobsallad/blobsallad/0002-auto.patch b/meta-agl-profile-core/recipes-test/blobsallad/blobsallad/0002-auto.patch new file mode 100644 index 000000000..b61da2c1f --- /dev/null +++ b/meta-agl-profile-core/recipes-test/blobsallad/blobsallad/0002-auto.patch @@ -0,0 +1,95 @@ +--- a/bs_main.c ++++ b/bs_main.c +@@ -11,6 +11,9 @@ + #include "bs_profiler.h" + #include "bs_rubberband.h" + ++static struct timeval beginTime; /* Time of the benchmark start */ ++static int cur_step; /* Current benchmark phase. Used to subsequently increase number of objects each 10 seconds */ ++ + typedef struct bs_main_data_st + { + bs_cairo_sdl_t *pCairoSdl; +@@ -113,7 +116,9 @@ + SDL_Event event; + SDL_UserEvent userevent; + bs_main_data_t *pMainData; +- ++ struct timeval curTime; ++ int hunsec; ++ + pMainData = (bs_main_data_t*) pUserData; + + userevent.type = SDL_USEREVENT; +@@ -121,6 +126,20 @@ + userevent.data1 = NULL; + userevent.data2 = NULL; + ++ gettimeofday(&curTime, NULL); ++ hunsec = curTime.tv_sec - beginTime.tv_sec; ++ ++ /* increase cur_step each 10 seconds */ ++ if (cur_step < hunsec / 10) { ++ printf("%d objects = %.2f fps\n", 1 << (cur_step + 1), pMainData->fps); ++ userevent.code = 2; /* add more objects */ ++ cur_step++; ++ } ++ ++ /* exit if requested number of objects is reached */ ++ if (cur_step == 4) ++ userevent.code = 3; ++ + event.type = SDL_USEREVENT; + event.user = userevent; + +@@ -152,14 +171,19 @@ + pMainData->newTimerInterval = 50; + pMainData->fps = 20.0; + pMainData->running = TRUE; +- ++ ++ cur_step = 0; ++ + bs_profiler_init(); + ++ gettimeofday(&beginTime, NULL); + gettimeofday(&startTime, NULL); + pMainData->lastFrameTimeStamp = startTime.tv_sec * 1000 + startTime.tv_usec / 1000; + + SDL_AddTimer(50, bs_main_sdl_timer_callback, pMainData); + ++ bs_blob_collective_split(pMainData->pCollective); ++ + for(;;) + { + SDL_WaitEvent(&event); +@@ -253,8 +277,7 @@ + break; + + case SDL_USEREVENT: +- if(event.user.code == 1) +- { ++ if (event.user.code == 1) { + gettimeofday(&startTime, NULL); + bs_main_update_simulation(pMainData); + bs_main_redraw(pMainData); +@@ -268,10 +291,15 @@ + usedTime = 50; + } + +- pMainData->newTimerInterval = usedTime; +- } +- break; +- ++ pMainData->newTimerInterval = usedTime; ++ } else if (event.user.code == 2) { ++ int i; ++ for (i = 0; i < (1 << cur_step); i++) ++ bs_blob_collective_split(pMainData->pCollective); ++ } else if (event.user.code == 3) { ++ exit(0); ++ } ++ break; + case SDL_QUIT: + exit(0); + break; diff --git a/meta-agl-profile-core/recipes-test/blobsallad/blobsallad/0003-printcleanup.patch b/meta-agl-profile-core/recipes-test/blobsallad/blobsallad/0003-printcleanup.patch new file mode 100644 index 000000000..630871dfd --- /dev/null +++ b/meta-agl-profile-core/recipes-test/blobsallad/blobsallad/0003-printcleanup.patch @@ -0,0 +1,11 @@ +--- a/bs_blob_collective.c ++++ b/bs_blob_collective.c +@@ -152,7 +152,7 @@ + + bs_list_unlink_p_cont(pCollective->pBlobs, bs_blob_collective_remove_blob_cb, findData.pMotherBlob); + +- printf("number of blobs: %d\n", bs_list_get_length(pCollective->pBlobs)); ++/* printf("number of blobs: %d\n", bs_list_get_length(pCollective->pBlobs)); */ + } + + typedef struct bs_blob_collective_join_find_smallest_st diff --git a/meta-agl-profile-core/recipes-test/blobsallad/blobsallad/0004-bs_main.c.patch b/meta-agl-profile-core/recipes-test/blobsallad/blobsallad/0004-bs_main.c.patch new file mode 100644 index 000000000..ae15408de --- /dev/null +++ b/meta-agl-profile-core/recipes-test/blobsallad/blobsallad/0004-bs_main.c.patch @@ -0,0 +1,15 @@ +--- a/bs_main.c ++++ b/bs_main.c +@@ -165,9 +165,9 @@ + //pMainData->pRubberband = bs_rubberband_create(2.5f, 3.0f); + pMainData->pEnv = bs_env_create(0.0f, 0.0f, 6.0f, 4.0f); + pMainData->pGravity = bs_vector_create(0.0f, 10.0f); +- pMainData->pCairoSdl = bs_cairo_sdl_create(600, 400); +- pMainData->width = 600.0; +- pMainData->height = 400.0; ++ pMainData->pCairoSdl = bs_cairo_sdl_create(1600, 1024); ++ pMainData->width = 1600.0; ++ pMainData->height = 1024.0; + pMainData->newTimerInterval = 50; + pMainData->fps = 20.0; + pMainData->running = TRUE; diff --git a/meta-agl-profile-core/recipes-test/blobsallad/blobsallad_2006-11-14-23-57.bb b/meta-agl-profile-core/recipes-test/blobsallad/blobsallad_2006-11-14-23-57.bb new file mode 100644 index 000000000..373d4ddc6 --- /dev/null +++ b/meta-agl-profile-core/recipes-test/blobsallad/blobsallad_2006-11-14-23-57.bb @@ -0,0 +1,36 @@ +DESCRIPTION = "" +HOMEPAGE = "http://blobsallad.se/" +LICENSE = "CLOSED" +LIC_FILES_CHKSUM = "" + +SRC_URI = " \ + http://blobsallad.se/src/blobsallad-src-${PV}.tar.gz \ + file://0001-Makefile.patch \ + file://0002-auto.patch \ + file://0003-printcleanup.patch \ + file://0004-bs_main.c.patch" + +SRC_URI[md5sum] = "a2e3342cbf0f3a4a9b110af2663bed36" +SRC_URI[sha256sum] = "cd6309df1929d3e6b7bce1dbecc751849aeaafe17c01e05fd2567dc4267faaa2" + +DEPENDS = "cairo virtual/libsdl" + +INSANE_SKIP_${PN} = "ldflags" + +S = "${WORKDIR}/blobsallad-src" + +do_configure () { + # Specify any needed configure commands here + : +} + +do_compile () { + # You will almost certainly need to add additional arguments here + oe_runmake SDKROOT=${STAGING_DIR_HOST} +} + +do_install () { + install -d ${D}${bindir} + install -m 0755 blobsallad ${D}${bindir} +} + diff --git a/meta-agl-profile-core/recipes-test/dung/dung_3.4.25-m2.bb b/meta-agl-profile-core/recipes-test/dung/dung_3.4.25-m2.bb new file mode 100644 index 000000000..28bf858a0 --- /dev/null +++ b/meta-agl-profile-core/recipes-test/dung/dung_3.4.25-m2.bb @@ -0,0 +1,18 @@ +SUMMARY = "Kernel test scripts" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6" + +SRC_URI = "git://gerrit.automotivelinux.org/gerrit/src/qa-test-misc;protocol=https;branch=${AGL_BRANCH}" +SRCREV = "e2472c7b1d061aef8bb05a4d7940fd8159c4a329" + +inherit allarch + +S = "${WORKDIR}/git/${PN}-${PV}" + +do_install () { + for subdir in arch_timer cmt common scifab sdhi.0; do + install -d -m 0755 ${D}/${datadir}/${PN}/$subdir + install -m 0755 -t ${D}/${datadir}/${PN}/$subdir ${S}/$subdir/* + done +} + diff --git a/meta-agl-profile-core/recipes-test/ebizzy/ebizzy_0.3.bb b/meta-agl-profile-core/recipes-test/ebizzy/ebizzy_0.3.bb new file mode 100644 index 000000000..08b0425c0 --- /dev/null +++ b/meta-agl-profile-core/recipes-test/ebizzy/ebizzy_0.3.bb @@ -0,0 +1,20 @@ +DESCRIPTION = "Benchmark tool that generates a workload resembling common web application server workloads" +HOMEPAGE = "http://ebizzy.sourceforge.net/" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://LICENSE;md5=eb723b61539feef013de476e68b5c50a" + +SRC_URI = "http://downloads.sourceforge.net/project/ebizzy/ebizzy/${PV}/ebizzy-${PV}.tar.gz" +SRC_URI[md5sum] = "af038bc506066bb3d28db08aba62bc38" +SRC_URI[sha256sum] = "77286029d6348f3d9b3f04eae1feadb5ad1ad07b9f688f4d9f002960862467f2" + +INSANE_SKIP_${PN} = "ldflags" + +do_compile () { + ${CC} -Wall -Wshadow -lpthread -o ebizzy ebizzy.c +} + +do_install () { + install -d ${D}${bindir} + install -m 0755 ebizzy ${D}${bindir} +} + diff --git a/meta-agl-profile-core/recipes-test/ffsb/ffsb_6.0-rc2.bb b/meta-agl-profile-core/recipes-test/ffsb/ffsb_6.0-rc2.bb new file mode 100644 index 000000000..66db133e3 --- /dev/null +++ b/meta-agl-profile-core/recipes-test/ffsb/ffsb_6.0-rc2.bb @@ -0,0 +1,14 @@ +DESCRIPTION = "Flexible File System Benchmark" +HOMEPAGE = "https://sourceforge.net/projects/ffsb/" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://LICENSE;md5=fd5d9bcabd8ed5a54a01ce8d183d592a" + +SRC_URI = "http://downloads.sourceforge.net/project/ffsb/ffsb/ffsb-${PV}/ffsb-${PV}.tar.bz2" +SRC_URI[md5sum] = "cabfc1021c2ec6c6b168fefc84210891" +SRC_URI[sha256sum] = "e5867692aae8c9bfbcdc774599022289c4d89c1d90f4dd7101fb9865ac773c71" + +inherit autotools + +# extra args to configure +EXTRA_OECONF = "" + diff --git a/meta-agl-profile-core/recipes-test/fontconfig/fontconfig_%.bbappend b/meta-agl-profile-core/recipes-test/fontconfig/fontconfig_%.bbappend new file mode 100644 index 000000000..c4bebdc1f --- /dev/null +++ b/meta-agl-profile-core/recipes-test/fontconfig/fontconfig_%.bbappend @@ -0,0 +1,17 @@ +PACKAGES =+ "fontconfig-test" + +do_install_append() { + install -m 755 -d ${D}/${datadir}/fontconfig-test + install -m 755 ${S}/test/run-test.sh ${D}/${datadir}/fontconfig-test/ + + sed -i -e "s/FCLIST=\.\.\/fc\-list\/fc\-list/FCLIST=\/usr\/bin\/fc\-list/g" -e "s/FCCACHE=\.\.\/fc\-cache\/fc\-cache/FCCACHE=\/usr\/bin\/fc\-cache/g" ${D}/${datadir}/fontconfig-test/run-test.sh + + for x in 4x6.pcf 8x16.pcf out.expected fonts.conf.in; do + install -m 644 ${S}/test/$x ${D}/${datadir}/fontconfig-test/ + done +} + +DEBIAN_NOAUTONAME_fontconfig-test = "1" +FILES_fontconfig-test = "${datadir}/fontconfig-test/*" + + diff --git a/meta-agl-profile-core/recipes-test/freetype/files/0001-Makefile-dont-build-gfx-demos.patch b/meta-agl-profile-core/recipes-test/freetype/files/0001-Makefile-dont-build-gfx-demos.patch new file mode 100644 index 000000000..1f3acf28e --- /dev/null +++ b/meta-agl-profile-core/recipes-test/freetype/files/0001-Makefile-dont-build-gfx-demos.patch @@ -0,0 +1,32 @@ +diff -urN /tmp/ft2demos-2.6.orig/Makefile /tmp/ft2demos-2.6/Makefile +--- ft2demos-2.6.orig/Makefile 2015-06-07 07:34:19.000000000 +0000 ++++ ft2demos-2.6/Makefile 2016-06-17 14:25:37.640456725 +0000 +@@ -153,7 +153,8 @@ + + ifeq ($(PLATFORM),unix) + CC = $(CCraw) +- LINK_CMD = $(subst /,$(SEP),$(OBJ_BUILD)/libtool) \ ++ LIBTOOL = $(OBJ_BUILD)/libtool ++ LINK_CMD = $(subst /,$(SEP),$(LIBTOOL)) \ + --mode=link $(CC) \ + $(subst /,$(COMPILER_SEP),$(LDFLAGS)) + LINK_LIBS = $(subst /,$(COMPILER_SEP),$(FTLIB) $(EFENCE)) +@@ -279,12 +280,12 @@ + ttdebug + + # Comment out the next line if you don't have a graphics subsystem. +- EXES += ftdiff \ +- ftgamma \ +- ftgrid \ +- ftmulti \ +- ftstring \ +- ftview ++ # EXES += ftdiff \ ++ # ftgamma \ ++ # ftgrid \ ++ # ftmulti \ ++ # ftstring \ ++ # ftview + + # ftvalid requires ftgxval.c and ftotval.c + # diff --git a/meta-agl-profile-core/recipes-test/freetype/files/0001-ft2demos-Makefile-Do-not-hardcode-libtool-path.patch b/meta-agl-profile-core/recipes-test/freetype/files/0001-ft2demos-Makefile-Do-not-hardcode-libtool-path.patch new file mode 100644 index 000000000..7803ad7e0 --- /dev/null +++ b/meta-agl-profile-core/recipes-test/freetype/files/0001-ft2demos-Makefile-Do-not-hardcode-libtool-path.patch @@ -0,0 +1,30 @@ +From 8c4f135619de929f9348b830a07a46a0c2c38e51 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jan-Simon=20M=C3=B6ller?= +Date: Fri, 7 Oct 2016 15:26:20 +0200 +Subject: [PATCH] Do not hardcode libtool path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +It is already known and imported through config.mk. + +Signed-off-by: Jan-Simon Möller +--- + Makefile | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/Makefile b/Makefile +index a5d34bd..254aad4 100644 +--- a/Makefile ++++ b/Makefile +@@ -153,7 +153,6 @@ else + + ifeq ($(PLATFORM),unix) + CC = $(CCraw) +- LIBTOOL = $(OBJ_BUILD)/libtool + LINK_CMD = $(subst /,$(SEP),$(LIBTOOL)) \ + --mode=link $(CC) \ + $(subst /,$(COMPILER_SEP),$(LDFLAGS)) +-- +2.1.4 + diff --git a/meta-agl-profile-core/recipes-test/freetype/freetype_2.8.bbappend b/meta-agl-profile-core/recipes-test/freetype/freetype_2.8.bbappend new file mode 100644 index 000000000..282ce784a --- /dev/null +++ b/meta-agl-profile-core/recipes-test/freetype/freetype_2.8.bbappend @@ -0,0 +1,32 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +SRC_URI =+ "${SOURCEFORGE_MIRROR}/freetype/ft2demos-${PV}.tar.bz2;name=ft2demos \ + file://0001-Makefile-dont-build-gfx-demos.patch;patchdir=../ft2demos-${PV} \ + file://0001-ft2demos-Makefile-Do-not-hardcode-libtool-path.patch;patchdir=../ft2demos-${PV} \ + " +SRC_URI[ft2demos.md5sum] = "61db5831e213acb843f0fc6d10186054" +SRC_URI[ft2demos.sha256sum] = "2b6ce0d36bcb43fcc8aac07a0287982d855571ee271c3803c768e501f9c1a233" + +PACKAGES =+ "${PN}-demos" + +B = "${S}" + +do_compile_append () { + + oe_runmake -C ${WORKDIR}/ft2demos-${PV} TOP_DIR=${WORKDIR}/${BPN}-${PV}/ +} + +do_install_append () { + install -d -m 0755 ${D}/${bindir} + for x in ftbench ftdump ftlint ftvalid ttdebug; do + install -m 0755 ${WORKDIR}/ft2demos-${PV}/bin/.libs/$x ${D}/${bindir} + done +} + +FILES_${PN}-demos = "\ + ${bindir}/ftbench \ + ${bindir}/ftdump \ + ${bindir}/ftlint \ + ${bindir}/ftvalid \ + ${bindir}/ttdebug \ +" diff --git a/meta-agl-profile-core/recipes-test/fsfuzzer/files/0001-fix_missing_header_sys_stat.patch b/meta-agl-profile-core/recipes-test/fsfuzzer/files/0001-fix_missing_header_sys_stat.patch new file mode 100644 index 000000000..e834becf3 --- /dev/null +++ b/meta-agl-profile-core/recipes-test/fsfuzzer/files/0001-fix_missing_header_sys_stat.patch @@ -0,0 +1,11 @@ +diff -urN fsfuzzer-0.7.orig/fstest.c fsfuzzer-0.7/fstest.c +--- fsfuzzer-0.7.orig/fstest.c 2009-01-25 14:50:06.000000000 +0000 ++++ fsfuzzer-0.7/fstest.c 2016-06-16 17:49:27.264565819 +0000 +@@ -35,6 +35,7 @@ + #include + #include + #include ++#include + + #define LOGGIT 1 + #define CHECK_XATTR 1 diff --git a/meta-agl-profile-core/recipes-test/fsfuzzer/fsfuzzer_0.7.bb b/meta-agl-profile-core/recipes-test/fsfuzzer/fsfuzzer_0.7.bb new file mode 100644 index 000000000..d2ddb59b1 --- /dev/null +++ b/meta-agl-profile-core/recipes-test/fsfuzzer/fsfuzzer_0.7.bb @@ -0,0 +1,18 @@ +SUMMARY = "The fsfuzzer is a filesystem fuzzer tool that does stress tests of various filesystems in a reproducible and logged way." +DESCRIPTION = "This tool creates initial (valid) filesystem images and then manipulates their binary format and structure for detecting flaws/bugs/design problems in the parsing/handling code for that particular filesystem. The program expects that you have a /media directory. It uses that one for mounting test images in." +HOMEPAGE = "https://www.ee.oulu.fi/research/ouspg/fsfuzzer" + +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://COPYING;md5=94d55d512a9ba36caa9b7df079bae19f" + +SRC_URI = "http://people.redhat.com/sgrubb/files/fsfuzzer-${PV}.tar.gz \ + file://0001-fix_missing_header_sys_stat.patch \ + " +SRC_URI[md5sum] = "d69ac4b67aaba52a889c9188eb456c15" +SRC_URI[sha256sum] = "094aa17c4f66c525a04e5db5ad444b4a561b6f8e310d0bd70b9ca421cdf0a434" + +inherit autotools + +# Specify any options you want to pass to the configure script using EXTRA_OECONF: +EXTRA_OECONF = "" + diff --git a/meta-agl-profile-core/recipes-test/glmark2/glmark2_%.bbappend b/meta-agl-profile-core/recipes-test/glmark2/glmark2_%.bbappend new file mode 100644 index 000000000..a64e0506c --- /dev/null +++ b/meta-agl-profile-core/recipes-test/glmark2/glmark2_%.bbappend @@ -0,0 +1,2 @@ +PACKAGECONFIG = "wayland-gles2" +PACKAGECONFIG[wayland-gles2] = ",,virtual/egl virtual/libgles2 wayland" diff --git a/meta-agl-profile-core/recipes-test/himeno/himeno_2.0.bb b/meta-agl-profile-core/recipes-test/himeno/himeno_2.0.bb new file mode 100644 index 000000000..f890e23a4 --- /dev/null +++ b/meta-agl-profile-core/recipes-test/himeno/himeno_2.0.bb @@ -0,0 +1,27 @@ +DESCRIPTION = "Himeno Benchmark" +LICENSE = "LGPL-2.0" +URL = "http://accc.riken.jp/en/supercom/himenobmt/" + +SRC_URI = "http://accc.riken.jp/en/wp-content/uploads/sites/2/2015/07/himenobmt.c.zip" +SRC_URI[md5sum] = "8d8e837dfc3e00a3b322eb4ae3edd551" +SRC_URI[sha256sum] = "8780bfbdacb0d4dcab2931e65cadd69411731e3f2afcc1231d0743a036298077" + +LIC_FILES_CHKSUM = "file://himenoBMT.c;md5=8e8771ddc01c6d1a795e088e2d6dee78" + +# Upstream ZIP file contains an LZH archive, thus a 2 steps "unpack" is required. +# The LZH archive is unpacked after native tools dependency resolution, +# thus. after "configure" task in our case: + +DEPENDS = "p7zip-native" + +do_configure_append() { + 7z x -y -o${S} ${WORKDIR}/himenobmt.c.lzh + cd ${S} + sed -i -e 's/CC= gcc/#CC= gcc/' Makefile + sed -i -e 's/CFLAGS = /#CFLAGS = /' Makefile +} + +do_install () { + install -d ${D}${bindir} + install -m 0755 bmt ${D}${bindir} +} diff --git a/meta-agl-profile-core/recipes-test/interbench/files/interbench.c.patch b/meta-agl-profile-core/recipes-test/interbench/files/interbench.c.patch new file mode 100644 index 000000000..c882739ba --- /dev/null +++ b/meta-agl-profile-core/recipes-test/interbench/files/interbench.c.patch @@ -0,0 +1,68 @@ +--- interbench.c.orig 2009-10-30 23:14:59.000000000 -0500 ++++ interbench.c 2012-07-10 19:06:00.000000000 -0500 +@@ -71,6 +71,7 @@ struct user_data { + char datestamp[13]; + FILE *logfile; + } ud = { ++ .ram = 0, + .duration = 30, + .cpu_load = 4, + .log = 1, +@@ -652,6 +653,8 @@ void emulate_write(struct thread *th) + terminal_error("fopen"); + if (stat(name, &statbuf) == -1) + terminal_fileopen_error(fp, "stat"); ++ if (statbuf.st_blksize < MIN_BLK_SIZE) ++ statbuf.st_blksize = MIN_BLK_SIZE; + for (i = 0 ; i < mem; i++) { + if (fwrite(buf, statbuf.st_blksize, 1, fp) != 1) + terminal_fileopen_error(fp, "fwrite"); +@@ -1136,14 +1139,17 @@ void get_ram(void) + if(!(meminfo = fopen("/proc/meminfo", "r"))) + terminal_error("fopen"); + +- ud.ram = ud.swap = 0; +- while( !feof(meminfo) && !fscanf(meminfo, "MemTotal: %lu kB", &ud.ram) ) +- fgets(aux,sizeof(aux),meminfo); ++ if (!ud.ram) ++ { ++ while( !feof(meminfo) && !fscanf(meminfo, "MemTotal: %lu kB", &ud.ram) ) ++ fgets(aux,sizeof(aux),meminfo); ++ } ++ ud.swap = 0; + while( !feof(meminfo) && !fscanf(meminfo, "SwapTotal: %lu kB", &ud.swap) ) + fgets(aux,sizeof(aux),meminfo); + if (fclose(meminfo) == -1) + terminal_error("fclose"); +- ++ + if( !ud.ram || !ud.swap ) { + unsigned long i; + fprintf(stderr, "\nCould not get memory or swap size. "); +@@ -1399,6 +1405,7 @@ void usage(void) + fprintf(stderr, "\t[-h]\n\n"); + fprintf(stderr, " -l\tUse loops per sec (default: use saved benchmark)\n"); + fprintf(stderr, " -L\tUse cpu load of with burn load (default: 4)\n"); ++ fprintf(stderr, " -M\tForce RAM size to . Useful when disk is smaller than RAM.\n"); + fprintf(stderr, " -t\tSeconds to run each benchmark (default: 30)\n"); + fprintf(stderr, " -B\tNice the benchmarked thread to (default: 0)\n"); + fprintf(stderr, " -N\tNice the load thread to (default: 0)\n"); +@@ -1482,7 +1489,7 @@ int main(int argc, char **argv) + terminal_error("signal"); + #endif + +- while ((q = getopt(argc, argv, "hl:L:B:N:ut:bcnrC:I:m:w:x:W:X:")) != -1) { ++ while ((q = getopt(argc, argv, "hl:L:M:B:N:ut:bcnrC:I:m:w:x:W:X:")) != -1) { + switch (q) { + case 'h': + usage(); +@@ -1496,6 +1503,9 @@ int main(int argc, char **argv) + case 'L': + ud.cpu_load = atoi(optarg); + break; ++ case 'M': ++ ud.ram = atoi(optarg); ++ break; + case 'B': + ud.bench_nice = atoi(optarg); + break; diff --git a/meta-agl-profile-core/recipes-test/interbench/interbench_0.31.bb b/meta-agl-profile-core/recipes-test/interbench/interbench_0.31.bb new file mode 100644 index 000000000..3e6490374 --- /dev/null +++ b/meta-agl-profile-core/recipes-test/interbench/interbench_0.31.bb @@ -0,0 +1,31 @@ +DESCRIPTION = "The Linux interactivity benchmark" +HOMEPAGE = "http://users.tpg.com.au/ckolivas/interbench/" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://COPYING;md5=393a5ca445f6965873eca0259a17f833" +SRC_URI = "http://ck.kolivas.org/apps/interbench/interbench-${PV}.tar.bz2" + +SRC_URI += "file://interbench.c.patch;striplevel=0" + +inherit autotools + +INSANE_SKIP_${PN} = "ldflags" + +B = "${S}" +EXTRA_OEMAKE = "CC='${CC}'" + +# upstream tarball contains x86_64 binaries, we need a clean source tree +do_compile() { + oe_runmake clean + oe_runmake +} + +do_install() { + install -d ${D}${bindir} ${D}${datadir}/doc/${PN}/ ${D}${mandir}/man8/ + install -m 0755 ${B}/interbench ${D}${bindir} + install -m 0644 ${S}/readme* ${D}${datadir}/doc/${PN}/ + install -m 0644 ${S}/interbench.8 ${D}${mandir}/man8/ +} + +SRC_URI[md5sum] = "832254d7fd1255c548ebea7b97f01015" +SRC_URI[sha256sum] = "89d438b28aef22d26e79812762a57a9f9344a8dd8826edebfe60dad48ee1c784" + diff --git a/meta-agl-profile-core/recipes-test/iperf/iperf-2.0.9/0001-fix-out-of-tree-config.patch b/meta-agl-profile-core/recipes-test/iperf/iperf-2.0.9/0001-fix-out-of-tree-config.patch new file mode 100644 index 000000000..e8a029790 --- /dev/null +++ b/meta-agl-profile-core/recipes-test/iperf/iperf-2.0.9/0001-fix-out-of-tree-config.patch @@ -0,0 +1,52 @@ +iperf: fix out of tree configuration + +The configure step uses a package header to check for support of types/declares, +this package header encapsulates all the required system header for providing +the needed resources. When configured from an out of tree directory the package +header is not found due to the hard path. +We now make the path for package header relative to our 'srcdir' so it is +found appropriately. + +Signed-off-by: Awais Belal +--- +diff --git a/configure.ac b/configure.ac +index 2b3fd20..d420f9e 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -176,8 +176,8 @@ dnl Check for system services + + dnl check for multicast + if test "$ac_cv_multicast" != no; then +- AC_CHECK_TYPES(struct ip_mreq,,,[#include "compat/headers_slim.h"]) +- AC_CHECK_DECLS(IP_ADD_MEMBERSHIP,,,[#include "compat/headers_slim.h"]) ++ AC_CHECK_TYPES(struct ip_mreq,,,[#include "${srcdir}/compat/headers_slim.h"]) ++ AC_CHECK_DECLS(IP_ADD_MEMBERSHIP,,,[#include "${srcdir}/compat/headers_slim.h"]) + AC_MSG_CHECKING(for multicast support) + ac_cv_multicast=no + if test "$ac_cv_have_decl_IP_ADD_MEMBERSHIP" = yes; then +@@ -193,9 +193,9 @@ fi + + dnl check for IPv6 + if test "$ac_cv_have_ipv6" != no; then +- AC_CHECK_TYPES(struct sockaddr_storage,,,[#include "compat/headers_slim.h"]) +- AC_CHECK_TYPES(struct sockaddr_in6,,,[#include "compat/headers_slim.h"]) +- AC_CHECK_DECLS(AF_INET6,,,[#include "compat/headers_slim.h"]) ++ AC_CHECK_TYPES(struct sockaddr_storage,,,[#include "${srcdir}/compat/headers_slim.h"]) ++ AC_CHECK_TYPES(struct sockaddr_in6,,,[#include "${srcdir}/compat/headers_slim.h"]) ++ AC_CHECK_DECLS(AF_INET6,,,[#include "${srcdir}/compat/headers_slim.h"]) + AC_MSG_CHECKING(for IPv6 headers and structures) + ac_cv_have_ipv6=no + if test "$ac_cv_type_struct_sockaddr_storage" = yes; then +@@ -211,9 +211,9 @@ fi + + if test "$ac_cv_have_ipv6" = yes; then + if test "$ac_cv_multicast" = yes; then +- AC_CHECK_TYPES(struct ipv6_mreq,,,[#include "compat/headers_slim.h"]) +- AC_CHECK_DECLS(IPV6_ADD_MEMBERSHIP,,,[#include "compat/headers_slim.h"]) +- AC_CHECK_DECLS(IPV6_MULTICAST_HOPS,,,[#include "compat/headers_slim.h"]) ++ AC_CHECK_TYPES(struct ipv6_mreq,,,[#include "${srcdir}/compat/headers_slim.h"]) ++ AC_CHECK_DECLS(IPV6_ADD_MEMBERSHIP,,,[#include "${srcdir}/compat/headers_slim.h"]) ++ AC_CHECK_DECLS(IPV6_MULTICAST_HOPS,,,[#include "${srcdir}/compat/headers_slim.h"]) + AC_MSG_CHECKING(for IPv6 multicast support) + ac_cv_have_ipv6_multicast=no + if test "$ac_cv_type_struct_ipv6_mreq" = yes; then diff --git a/meta-agl-profile-core/recipes-test/iperf/iperf-2.0.9/0002-fix-bool-size-m4.patch b/meta-agl-profile-core/recipes-test/iperf/iperf-2.0.9/0002-fix-bool-size-m4.patch new file mode 100644 index 000000000..348e316ce --- /dev/null +++ b/meta-agl-profile-core/recipes-test/iperf/iperf-2.0.9/0002-fix-bool-size-m4.patch @@ -0,0 +1,16 @@ +--- iperf-2.0.5/m4/dast.m4.orig 2016-06-15 11:42:03.945581785 -0400 ++++ iperf-2.0.5/m4/dast.m4 2016-06-15 11:42:11.053581641 -0400 +@@ -11,7 +11,12 @@ + + AC_DEFUN(DAST_CHECK_BOOL, [ + +-AC_CHECK_SIZEOF(bool) ++if test "$ac_cv_header_stdbool_h" = yes; then ++ AC_CHECK_SIZEOF(bool,,[#include ]) ++else ++ AC_CHECK_SIZEOF(bool) ++fi ++ + if test "$ac_cv_sizeof_bool" = 0 ; then + AC_DEFINE(bool, int) + fi diff --git a/meta-agl-profile-core/recipes-test/iperf/iperf-2.0.9/iperf-2.0.5_ManPage.patch b/meta-agl-profile-core/recipes-test/iperf/iperf-2.0.9/iperf-2.0.5_ManPage.patch new file mode 100644 index 000000000..12e8f4631 --- /dev/null +++ b/meta-agl-profile-core/recipes-test/iperf/iperf-2.0.9/iperf-2.0.5_ManPage.patch @@ -0,0 +1,8 @@ +diff --git iperf-2.0.5/man/Makefile.am iperf-2.0.5/man/Makefile.am + index ed97bc6..728873f 100644 +--- iperf-2.0.5/man/Makefile.am ++++ iperf-2.0.5/man/Makefile.am +@@ -1,2 +1 @@ +-man_MANS = iperf.1 +-dist_man_MANS = $(man_MANS) ++dist_man_MANS = iperf.1 diff --git a/meta-agl-profile-core/recipes-test/iperf/iperf_2.0.9.bb b/meta-agl-profile-core/recipes-test/iperf/iperf_2.0.9.bb new file mode 100644 index 000000000..f297f7f7f --- /dev/null +++ b/meta-agl-profile-core/recipes-test/iperf/iperf_2.0.9.bb @@ -0,0 +1,20 @@ +DESCRIPTION = "Iperf is a tool to measure maximum TCP bandwidth, allowing the tuning of various parameters and UDP characteristics" +HOMEPAGE = "http://dast.nlanr.net/Projects/Iperf/" +SECTION = "console/network" +LICENSE = "BSD-2-Clause" +LIC_FILES_CHKSUM = "file://COPYING;md5=e8478eae9f479e39bc34975193360298" + +SRC_URI = " https://iperf.fr/download/source/${BP}-source.tar.gz \ + " + +SRC_URI[md5sum] = "1bb3a1d98b1973aee6e8f171933c0f61" +SRC_URI[sha256sum] = "a5350777b191e910334d3a107b5e5219b72ffa393da4186da1e0a4552aeeded6" + +S = "${WORKDIR}/${BP}" + +inherit autotools pkgconfig + +EXTRA_OECONF = "--exec-prefix=${STAGING_DIR_HOST}${layout_exec_prefix}" + +PACKAGECONFIG ??= "${@bb.utils.contains('DISTRO_FEATURES', 'ipv6', 'ipv6', '', d)}" +PACKAGECONFIG[ipv6] = "--enable-ipv6,--disable-ipv6," diff --git a/meta-agl-profile-core/recipes-test/ipv6connect/ipv6connect.bb b/meta-agl-profile-core/recipes-test/ipv6connect/ipv6connect.bb new file mode 100644 index 000000000..a8b93716a --- /dev/null +++ b/meta-agl-profile-core/recipes-test/ipv6connect/ipv6connect.bb @@ -0,0 +1,24 @@ +SUMMARY = "ipv6connect test" +HOMEPAGE = "https://chromium.googlesource.com/chromiumos/third_party/autotest/+/0.12.369.B/client/tests/ipv6connect" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://${S}/${PN}/LICENSE;md5=b234ee4d69f5fce4486a80fdaf4a4263" + +SRC_URI = "git://gerrit.automotivelinux.org/gerrit/src/qa-test-misc;protocol=https;branch=${AGL_BRANCH}" +SRCREV = "b355b7e1f43a19938895964f314484ffd8a39542" + +inherit autotools + +INSANE_SKIP_${PN} = "ldflags" + +B = "${WORKDIR}/git/ipv6connect" +S = "${WORKDIR}/git" + +# configure script is not delivered, only a makefile. +do_configure() { + : +} + +do_install() { + install -d ${D}${bindir} + install -m 0755 ${B}/ipv6connect ${D}${bindir} +} diff --git a/meta-agl-profile-core/recipes-test/linpack/linpack.bb b/meta-agl-profile-core/recipes-test/linpack/linpack.bb new file mode 100644 index 000000000..84bed0ff6 --- /dev/null +++ b/meta-agl-profile-core/recipes-test/linpack/linpack.bb @@ -0,0 +1,23 @@ +SUMMARY = "Linpack benchmark" +LICENSE = "BSD" +LIC_FILES_CHKSUM = "file://${S}/${PN}/linpack.c;md5=076f1fd8d313056103f98d4253862eae" + +SRC_URI = "git://gerrit.automotivelinux.org/gerrit/src/qa-test-misc;protocol=https;branch=${AGL_BRANCH}" +SRCREV = "920cae73a918d1f516113b0ae967be3ecaba86ef" + +DEPENDS += "rsync-native" + +inherit autotools + +S = "${WORKDIR}/git" + +# configure script is not delivered, only a makefile. +do_configure() { + mkdir -p ${B} + rsync -a ${S}/${PN}/* ${B} +} + +do_install() { + install -d ${D}${bindir} + install -m 0755 ${B}/linpack ${D}${bindir} +} diff --git a/meta-agl-profile-core/recipes-test/linus-stress/linus-stress.bb b/meta-agl-profile-core/recipes-test/linus-stress/linus-stress.bb new file mode 100644 index 000000000..01b3cfce5 --- /dev/null +++ b/meta-agl-profile-core/recipes-test/linus-stress/linus-stress.bb @@ -0,0 +1,23 @@ +SUMMARY = "linus_stress test" +HOMEPAGE = "https://chromium.googlesource.com/chromiumos/third_party/autotest/+/master/client/tests/linus_stress" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://${S}/linus_stress/LICENSE;md5=b234ee4d69f5fce4486a80fdaf4a4263" + +SRC_URI = "git://gerrit.automotivelinux.org/gerrit/src/qa-test-misc;protocol=https;branch=${AGL_BRANCH}" +SRCREV = "87cdfd4626c0cb47fc22f328867e49d6268df85c" + +inherit autotools +INSANE_SKIP_${PN} = "ldflags" + +B = "${WORKDIR}/git/linus_stress" +S = "${WORKDIR}/git" + +# configure script is not delivered, only a makefile. +do_configure() { + : +} + +do_install() { + install -d ${D}${bindir} + install -m 0755 ${B}/linus_stress ${D}${bindir} +} diff --git a/meta-agl-profile-core/recipes-test/packagegroups/packagegroup-agl-test.bb b/meta-agl-profile-core/recipes-test/packagegroups/packagegroup-agl-test.bb new file mode 100644 index 000000000..1c3412e84 --- /dev/null +++ b/meta-agl-profile-core/recipes-test/packagegroups/packagegroup-agl-test.bb @@ -0,0 +1,57 @@ +SUMMARY = "Utilities for testing of AGL" +DESCRIPTION = "A set of common packages required by testing AGL for Quality Assurance" + +LICENSE = "MIT" + +inherit packagegroup + +PACKAGES = "\ + packagegroup-agl-test \ + packagegroup-agl-test-ltp \ + packagegroup-ivi-common-test \ + " + +ALLOW_EMPTY_${PN} = "1" + +RDEPENDS_${PN} += "\ + bc \ + blobsallad \ + dbench \ + ebizzy \ + ffsb \ + interbench \ + iozone3 \ + iperf \ + ipv6connect \ + linpack \ + linus-stress \ + lmbench \ + nbench-byte \ + rt-tests \ + stress \ + " +# to be added, but needs LICENSE_FLAGS_WHITELIST="non-commercial" +# netperf + +# FTBS, SPEC-316 +# himeno +# FTBS, SPEC-1384 +# trinity + +# packagegroup-agl-test-ltp \ +# ltp \ +# + +# Packages for shell commands which are required by LTP +# readelf, logrotate, vsftpd, crontab, sar, arp, ftp, +# host, rcp, rlogin, rsh, tcpdump, expect, iptables, dnsmasq, +# pgrep +RDEPENDS_packagegroup-agl-test-ltp += " \ + initscripts-functions bind-utils binutils \ + cronie dnsmasq expect inetutils-ftp inetutils-rsh \ + iptables logrotate net-tools sysstat tcpdump vsftpd \ + " + +RDEPENDS_packagegroup-ivi-common-test = " \ + packagegroup-agl-test \ + " diff --git a/meta-agl-profile-core/recipes-test/trinity/trinity_git.bb b/meta-agl-profile-core/recipes-test/trinity/trinity_git.bb new file mode 100644 index 000000000..f0f09a855 --- /dev/null +++ b/meta-agl-profile-core/recipes-test/trinity/trinity_git.bb @@ -0,0 +1,42 @@ +SUMMARY = "a Linux System call fuzz teste." +DESCRIPTION = "Trinity, a Linux System call fuzz tester." +HOMEPAGE = "http://codemonkey.org.uk/projects/trinity/" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://${S}/COPYING;md5=96094d47cfbd2cc45eb46ce0fc423c04" + +COMPATIBLE_HOST = "(x86_64|arm|aarch64).*-linux" + +PV = "1.5" +SRCREV = "edc2e693e298e0372010a361354c4a79a3cd93f3" +SRC_URI = "git://github.com/kernelslacker/trinity.git;protocol=https;nobranch=1 \ + " + +S = "${WORKDIR}/git" + +inherit useradd + +USERADD_PACKAGES = "${PN}" +USERADD_PARAM_${PN} = "--system --create-home --shell /bin/sh ${PN} " + +do_configure () { + ./configure.sh +} + +# workaround random build failures +do_compile () { + ${MAKE} +} + +do_install () { + oe_runmake install DESTDIR=${D}/usr + install -o ${PN} -d -m 0755 ${D}/${datadir}/${PN} + install -o ${PN} -m 0755 ${S}/scripts/test-all-syscalls-parallel.sh ${D}/${datadir}/${PN} + install -o ${PN} -m 0755 ${S}/scripts/test-all-syscalls-sequentially.sh ${D}/${datadir}/${PN} + install -o ${PN} -m 0755 ${S}/scripts/test-multi.sh ${D}/${datadir}/${PN} + install -o ${PN} -m 0755 ${S}/scripts/test-vm.sh ${D}/${datadir}/${PN} +} + +PACKAGES =+ "${PN}-example" + +FILES_${PN} = "${bindir}/trinity" +FILES_${PN}-example = "${datadir}/${PN}" diff --git a/meta-agl-profile-demo/conf/layer.conf b/meta-agl-profile-demo/conf/layer.conf new file mode 100644 index 000000000..bf7347e58 --- /dev/null +++ b/meta-agl-profile-demo/conf/layer.conf @@ -0,0 +1,10 @@ +# We have a conf and classes directory, add to BBPATH +BBPATH =. "${LAYERDIR}:" + +# We have recipes-* directories, add to BBFILES +BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \ + ${LAYERDIR}/recipes-*/*/*.bbappend" + +BBFILE_COLLECTIONS += "aglprofiledemo" +BBFILE_PATTERN_aglprofiledemo = "^${LAYERDIR}/" +BBFILE_PRIORITY_aglprofiledemo = "70" diff --git a/meta-agl-profile-demo/recipes-connectivity/bluez-alsa/bluez-alsa_git.bb b/meta-agl-profile-demo/recipes-connectivity/bluez-alsa/bluez-alsa_git.bb new file mode 100644 index 000000000..6379ec38f --- /dev/null +++ b/meta-agl-profile-demo/recipes-connectivity/bluez-alsa/bluez-alsa_git.bb @@ -0,0 +1,38 @@ +SUMMARY = "Bluetooth Audio ALSA Backend" +HOMEPAGE = "https://github.com/Arkq/bluez-alsa" +SECTION = "libs" + +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://LICENSE.txt;md5=bb3e99e80c5d718213f35ae1def4c106" + +SRC_URI = "git://github.com/Arkq/bluez-alsa.git;protocol=https;branch=master" +SRCREV = "9045edb436ea755f395a2e09e4525b5defad286a" + +SRC_URI += "file://bluez-alsa.service" + +S = "${WORKDIR}/git" + +DEPENDS += "alsa-lib bluez5 systemd glib-2.0 sbc" + +PACKAGECONFIG[aac] = "--enable-aac, --disable-aac, " +PACKAGECONFIG[aptx] = "--enable-aptx,--disable-aptx," +PACKAGECONFIG[hcitop] = "--enable-hcitop, --disable-hcitop, libbsd ncurses" + +inherit autotools pkgconfig +inherit systemd + +SYSTEMD_AUTO_ENABLE = "enable" +SYSTEMD_SERVICE_${PN} = "bluez-alsa.service" + +PACKAGECONFIG += "hcitop" + +do_install_append () { + install -d ${D}${base_libdir}/systemd/system + install -m 0644 ${WORKDIR}/bluez-alsa.service ${D}${base_libdir}/systemd/system +} + +FILES_${PN} += "\ + ${datadir}/alsa/alsa.conf.d/20-bluealsa.conf\ + ${libdir}/alsa-lib/libasound_module_ctl_bluealsa.so\ + ${libdir}/alsa-lib/libasound_module_pcm_bluealsa.so\ +" diff --git a/meta-agl-profile-demo/recipes-connectivity/bluez-alsa/files/bluez-alsa.service b/meta-agl-profile-demo/recipes-connectivity/bluez-alsa/files/bluez-alsa.service new file mode 100644 index 000000000..671815e03 --- /dev/null +++ b/meta-agl-profile-demo/recipes-connectivity/bluez-alsa/files/bluez-alsa.service @@ -0,0 +1,11 @@ +[Unit] +Description=Bluetooth Audio ALSA Backend +After=bluetooth.service +Requires=bluetooth.service + +[Service] +Type=simple +ExecStart=/usr/bin/bluealsa + +[Install] +WantedBy=multi-user.target diff --git a/meta-agl-profile-demo/recipes-connectivity/bluez5/bluez5/bluetooth.conf b/meta-agl-profile-demo/recipes-connectivity/bluez5/bluez5/bluetooth.conf new file mode 100644 index 000000000..1f2762de7 --- /dev/null +++ b/meta-agl-profile-demo/recipes-connectivity/bluez5/bluez5/bluetooth.conf @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/meta-agl-profile-demo/recipes-connectivity/bluez5/bluez5_%.bbappend b/meta-agl-profile-demo/recipes-connectivity/bluez5/bluez5_%.bbappend new file mode 100644 index 000000000..ffb9d5b53 --- /dev/null +++ b/meta-agl-profile-demo/recipes-connectivity/bluez5/bluez5_%.bbappend @@ -0,0 +1,6 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/${BPN}:" +SRC_URI_append = " file://bluetooth.conf" + +do_install_append() { + install -m 0644 ${WORKDIR}/bluetooth.conf ${D}${sysconfdir}/dbus-1/system.d/bluetooth.conf +} diff --git a/meta-agl-profile-demo/recipes-connectivity/busybox/busybox_%.bbappend b/meta-agl-profile-demo/recipes-connectivity/busybox/busybox_%.bbappend new file mode 100644 index 000000000..198b651dd --- /dev/null +++ b/meta-agl-profile-demo/recipes-connectivity/busybox/busybox_%.bbappend @@ -0,0 +1,2 @@ +SRC_URI += "file://enable-wget-https.cfg" +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" diff --git a/meta-agl-profile-demo/recipes-connectivity/busybox/files/enable-wget-https.cfg b/meta-agl-profile-demo/recipes-connectivity/busybox/files/enable-wget-https.cfg new file mode 100644 index 000000000..e92006bef --- /dev/null +++ b/meta-agl-profile-demo/recipes-connectivity/busybox/files/enable-wget-https.cfg @@ -0,0 +1,3 @@ +# Thu Jun 8 17:32:07 2017 +CONFIG_FEATURE_WGET_OPENSSL=y +CONFIG_FEATURE_WGET_SSL_HELPER=y diff --git a/meta-agl-profile-demo/recipes-connectivity/connman-ncurses/connman-ncurses_git.bb b/meta-agl-profile-demo/recipes-connectivity/connman-ncurses/connman-ncurses_git.bb new file mode 100644 index 000000000..02afef75f --- /dev/null +++ b/meta-agl-profile-demo/recipes-connectivity/connman-ncurses/connman-ncurses_git.bb @@ -0,0 +1,26 @@ +SUMMARY = "A simple ncurses interface for connman" +DESCRIPTION = "A simple ncurses interface for connman" +HOMEPAGE = "https://gitlab.com/iotbzh/connman-json-client" + +SECTION = "console/network" + +DEPENDS = "dbus ncurses connman json-c" + +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://LICENSE;md5=8c16666ae6c159876a0ba63099614381" + +SRC_URI = "git://gitlab.com/iotbzh/connman-json-client.git;protocol=https;rev=ad4261a2f87c914667b1f6841c913f6b08d373e2" + +inherit autotools pkgconfig + +EXTRA_AUTORECONF += " -i" +EXTRA_OECONF += " --disable-optimization --enable-debug" + +S = "${WORKDIR}/git" + +do_install () { + install -dm755 ${D}${bindir} + install -Dm755 connman_ncurses ${D}${bindir} +} + +FILES_${PN} = "${bindir}/connman_ncurses" diff --git a/meta-agl-profile-demo/recipes-connectivity/connman/.appends.core b/meta-agl-profile-demo/recipes-connectivity/connman/.appends.core new file mode 100644 index 000000000..e69de29bb diff --git a/meta-agl-profile-demo/recipes-connectivity/connman/connman_%.bbappend b/meta-agl-profile-demo/recipes-connectivity/connman/connman_%.bbappend new file mode 100644 index 000000000..e41cbe954 --- /dev/null +++ b/meta-agl-profile-demo/recipes-connectivity/connman/connman_%.bbappend @@ -0,0 +1,3 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +SRC_URI += "file://0001-disable-when-booting-over-nfs.patch" diff --git a/meta-agl-profile-demo/recipes-connectivity/connman/files/0001-disable-when-booting-over-nfs.patch b/meta-agl-profile-demo/recipes-connectivity/connman/files/0001-disable-when-booting-over-nfs.patch new file mode 100644 index 000000000..95fc0a905 --- /dev/null +++ b/meta-agl-profile-demo/recipes-connectivity/connman/files/0001-disable-when-booting-over-nfs.patch @@ -0,0 +1,11 @@ +--- a/src/connman.service.in 2016-08-15 13:51:03.479478140 +0200 ++++ b/src/connman.service.in 2016-08-15 13:51:33.469478267 +0200 +@@ -7,6 +7,7 @@ RequiresMountsFor=@localstatedir@/lib/co + After=dbus.service network-pre.target systemd-sysusers.service + Before=network.target multi-user.target shutdown.target + Wants=network.target + Conflicts=systemd-resolved.service ++ConditionKernelCommandLine=!root=/dev/nfs + + [Service] + Type=dbus diff --git a/meta-agl-profile-demo/recipes-connectivity/rtl-sdr/rtl-sdr/0001-remove-I-usr-include-in-pkg-config.patch b/meta-agl-profile-demo/recipes-connectivity/rtl-sdr/rtl-sdr/0001-remove-I-usr-include-in-pkg-config.patch new file mode 100644 index 000000000..86b7392df --- /dev/null +++ b/meta-agl-profile-demo/recipes-connectivity/rtl-sdr/rtl-sdr/0001-remove-I-usr-include-in-pkg-config.patch @@ -0,0 +1,40 @@ +From 3aeaf8054fcb2617ca8f6196ca32be3e69337f77 Mon Sep 17 00:00:00 2001 +From: Martin Kelly +Date: Fri, 21 Apr 2017 10:29:19 -0700 +Subject: [PATCH] remove -I/usr/include in pkg-config + +This shouldn't be necessary as it's part of the default compiler include +paths anyway. Morever, it can cause GCC 6 C++ build failures in +downstream packages when combined with QMake (such as +qtmultimedia-rtlfm-radio-plugin). + +Fix these issues by removing it. + +Upstream-Status: Inappropriate [disable-feature] + +This patch should not go upstream because it breaks the ability to build +with --prefix. That's not a problem for Openembedded, but it is for +upstream more generally. See this mail thread for more information: + +http://lists.osmocom.org/pipermail/osmocom-sdr/2017-April/001580.html + +Signed-off-by: Martin Kelly +--- + librtlsdr.pc.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/librtlsdr.pc.in b/librtlsdr.pc.in +index 5e55049..84b6d0c 100644 +--- a/librtlsdr.pc.in ++++ b/librtlsdr.pc.in +@@ -6,6 +6,6 @@ includedir=@includedir@ + Name: RTL-SDR Library + Description: C Utility Library + Version: @VERSION@ +-Cflags: -I${includedir}/ @RTLSDR_PC_CFLAGS@ ++Cflags: @RTLSDR_PC_CFLAGS@ + Libs: -L${libdir} -lrtlsdr -lusb-1.0 + Libs.private: @RTLSDR_PC_LIBS@ +-- +2.1.4 + diff --git a/meta-agl-profile-demo/recipes-connectivity/rtl-sdr/rtl-sdr_0.5.3.bb b/meta-agl-profile-demo/recipes-connectivity/rtl-sdr/rtl-sdr_0.5.3.bb new file mode 100644 index 000000000..7d5c0217d --- /dev/null +++ b/meta-agl-profile-demo/recipes-connectivity/rtl-sdr/rtl-sdr_0.5.3.bb @@ -0,0 +1,26 @@ +SUMMARY = "Turns a Realtek RTL2832U-based DVB dongle into a SDR receiver" +DESCRIPTION = "DVB-T dongles based on the Realtek RTL2832U chipset can be used as Software Digital Radio adapters, since the chip allows transferring raw I/Q samples to the host, which is really used for DAB/DAB+/FM demodulation." +HOMEPAGE = "http://sdr.osmocom.org/trac/wiki/rtl-sdr" + +LICENSE = "GPLv2+" +LIC_FILES_CHKSUM = "file://COPYING;md5=751419260aa954499f7abaabaa882bbe \ + file://src/librtlsdr.c;endline=18;md5=1b05599c3ebd4d74857a0a7c45f3d4ef" + +DEPENDS = "libusb1" + +SRC_URI = "git://git.osmocom.org/rtl-sdr \ + file://0001-remove-I-usr-include-in-pkg-config.patch \ + " +SRCREV = "e3c03f738f5aef4dc51e2b741fbdb542b9cc1bb1" +S = "${WORKDIR}/git" + +inherit autotools pkgconfig + +EXTRA_OECONF = "--enable-driver-detach" +#CFLAGS_remove = " +do_configure_append() { + # remove included temporary path from pc file due to pass-through of OE CFLAGS + # debug-prefix-map + # See: http://lists.openembedded.org/pipermail/openembedded-devel/2016-May/107456.html + sed -i -e "s# -fdebug-prefix-map=.*##g" librtlsdr.pc +} \ No newline at end of file diff --git a/meta-agl-profile-demo/recipes-connectivity/rygel/.appends.meta-multimedia b/meta-agl-profile-demo/recipes-connectivity/rygel/.appends.meta-multimedia new file mode 100644 index 000000000..e69de29bb diff --git a/meta-agl-profile-demo/recipes-connectivity/rygel/files/0001-Fix-missing-link-to-unistring-for-lms-plugin.patch b/meta-agl-profile-demo/recipes-connectivity/rygel/files/0001-Fix-missing-link-to-unistring-for-lms-plugin.patch new file mode 100644 index 000000000..57b97a6ca --- /dev/null +++ b/meta-agl-profile-demo/recipes-connectivity/rygel/files/0001-Fix-missing-link-to-unistring-for-lms-plugin.patch @@ -0,0 +1,28 @@ +From 10602ca53b1c1231e96d8d446904617528c11dae Mon Sep 17 00:00:00 2001 +From: Ronan Le Martret +Date: Mon, 13 Mar 2017 15:31:41 +0100 +Subject: [PATCH] Fix missing link to unistring for lms plugin + +Signed-off-by: Ronan Le Martret +--- + configure.ac | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/configure.ac b/configure.ac +index c5cbc00..2f7dc78 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -248,6 +248,10 @@ AS_IF([test "x$enable_lms_plugin" = "xyes"], + gio-2.0 >= $GIO_REQUIRED + sqlite3 >= $LIBSQLITE3_REQUIRED]) + RYGEL_PLUGIN_LMS_DEPS_VALAFLAGS="$RYGEL_COMMON_MODULES_VALAFLAGS --pkg gio-2.0 --pkg gee-0.8 --pkg sqlite3" ++ AS_IF([test "x$have_unistring" = "xyes"], ++ [ ++ RYGEL_PLUGIN_LMS_DEPS_LIBS="$RYGEL_PLUGIN_LMS_DEPS_LIBS -lunistring" ++ ]) + AC_SUBST([RYGEL_PLUGIN_LMS_DEPS_VALAFLAGS]) + ]) + +-- +2.6.6 + diff --git a/meta-agl-profile-demo/recipes-connectivity/rygel/files/rygel.service b/meta-agl-profile-demo/recipes-connectivity/rygel/files/rygel.service new file mode 100644 index 000000000..fb94d7160 --- /dev/null +++ b/meta-agl-profile-demo/recipes-connectivity/rygel/files/rygel.service @@ -0,0 +1,13 @@ +[Unit] +Description=Rygel +After=lightmediascanner.service +Requires=lightmediascanner.service + +[Service] +Type=dbus +BusName=org.gnome.Rygel1 +ExecStart=/usr/bin/rygel -c /etc/rygel.conf + +[Install] +WantedBy=default.target +Alias=dbus-org.gnome.Rygel1.service diff --git a/meta-agl-profile-demo/recipes-connectivity/rygel/rygel_%.bbappend b/meta-agl-profile-demo/recipes-connectivity/rygel/rygel_%.bbappend new file mode 100644 index 000000000..4ae59259f --- /dev/null +++ b/meta-agl-profile-demo/recipes-connectivity/rygel/rygel_%.bbappend @@ -0,0 +1,25 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +# Disable everything but the media-export plugin, add the lms plugin +PACKAGECONFIG = "media-export lms" +PACKAGECONFIG[lms] = "--enable-lms-plugin,--disable-lms-plugin,sqlite3" + +# LightMediaScanner plugin patches +SRC_URI += "\ + file://0001-Fix-missing-link-to-unistring-for-lms-plugin.patch \ + file://rygel.service \ +" + +do_install_prepend() { + # Install rygel systemd service + if ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'true', 'false', d)}; then + install -m 644 -p -D ${WORKDIR}/rygel.service ${D}${systemd_user_unitdir}/rygel.service + + # Execute these manually on behalf of systemctl script (from systemd-systemctl-native.bb) + # because it does not support systemd's user mode. + # However, systemctl --global should be checked + #mkdir -p ${D}/etc/systemd/user/default.target.wants/ + #ln -sf ${systemd_user_unitdir}/rygel.service ${D}/etc/systemd/user/dbus-org.gnome.Rygel1.service + #ln -sf ${systemd_user_unitdir}/rygel.service ${D}/etc/systemd/user/default.target.wants/rygel.service + fi +} diff --git a/meta-agl-profile-demo/recipes-core/packagegroups/packagegroup-ivi-common-core-multimedia.bb b/meta-agl-profile-demo/recipes-core/packagegroups/packagegroup-ivi-common-core-multimedia.bb new file mode 100644 index 000000000..abe6786f2 --- /dev/null +++ b/meta-agl-profile-demo/recipes-core/packagegroups/packagegroup-ivi-common-core-multimedia.bb @@ -0,0 +1,13 @@ +DESCRIPTION = "The minimal set of packages for Multimedia Subsystem" +LICENSE = "MIT" + +inherit packagegroup + +PACKAGES = "\ + packagegroup-ivi-common-core-multimedia \ + " + +ALLOW_EMPTY_${PN} = "1" + +RDEPENDS_${PN} += "\ + " diff --git a/meta-agl-profile-demo/recipes-extended/dlt-daemon/dlt-daemon/0001-Fix-build-with-systemd-209.patch b/meta-agl-profile-demo/recipes-extended/dlt-daemon/dlt-daemon/0001-Fix-build-with-systemd-209.patch new file mode 100644 index 000000000..5bf6bf88e --- /dev/null +++ b/meta-agl-profile-demo/recipes-extended/dlt-daemon/dlt-daemon/0001-Fix-build-with-systemd-209.patch @@ -0,0 +1,30 @@ +From 8080b7395c1638baee60fb3c46667f21e00b87fb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Erik=20Bot=C3=B6?= +Date: Fri, 4 Apr 2014 10:59:18 +0200 +Subject: [PATCH 1/4] Fix build with systemd >= 209 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Upstream-Status: Inappropriate [Configuration Specific] +Signed-off-by: Erik Botö +--- + src/system/CMakeLists.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/system/CMakeLists.txt b/src/system/CMakeLists.txt +index ce87914..1d0d224 100644 +--- a/src/system/CMakeLists.txt ++++ b/src/system/CMakeLists.txt +@@ -23,7 +23,7 @@ set(dlt_system_SRCS dlt-system.c dlt-system-options.c dlt-system-process-handlin + dlt-system-syslog.c dlt-system-watchdog.c dlt-system-journal.c) + add_executable(dlt-system ${dlt_system_SRCS} ${systemd_SRCS}) + if(WITH_SYSTEMD_JOURNAL) +- target_link_libraries(dlt-system dlt ${ZLIB_LIBRARIES} systemd-journal systemd-id128) ++ target_link_libraries(dlt-system dlt ${ZLIB_LIBRARIES} systemd) + else(WITH_SYSTEMD_JOURNAL) + target_link_libraries(dlt-system dlt ${ZLIB_LIBRARIES}) + endif(WITH_SYSTEMD_JOURNAL) +-- +1.9.3 + diff --git a/meta-agl-profile-demo/recipes-extended/dlt-daemon/dlt-daemon/0002-Don-t-execute-processes-as-a-specific-user.patch b/meta-agl-profile-demo/recipes-extended/dlt-daemon/dlt-daemon/0002-Don-t-execute-processes-as-a-specific-user.patch new file mode 100644 index 000000000..168847990 --- /dev/null +++ b/meta-agl-profile-demo/recipes-extended/dlt-daemon/dlt-daemon/0002-Don-t-execute-processes-as-a-specific-user.patch @@ -0,0 +1,81 @@ +From bcca4c99394ba422d03a5e76f2a0023ef248824a Mon Sep 17 00:00:00 2001 +From: Andrei Gherzan +Date: Tue, 18 Nov 2014 15:47:22 +0100 +Subject: [PATCH 2/4] Don't execute processes as a specific user. + +Upstream-Status: Inappropriate [Configuration Specific] +Signed-off-by: Andrei Gherzan +--- + systemd/dlt-adaptor-udp.service.cmake | 1 - + systemd/dlt-example-user.service.cmake | 1 - + systemd/dlt-receive.service.cmake | 1 - + systemd/dlt-system.service.cmake | 1 - + systemd/dlt.service.cmake | 1 - + 5 files changed, 5 deletions(-) + +diff --git a/systemd/dlt-adaptor-udp.service.cmake b/systemd/dlt-adaptor-udp.service.cmake +index 8dac1f2..ecf9f9e 100644 +--- a/systemd/dlt-adaptor-udp.service.cmake ++++ b/systemd/dlt-adaptor-udp.service.cmake +@@ -21,9 +21,8 @@ Wants=dlt.service + + [Service] + Type=simple +-User=@DLT_USER@ + ExecStart=@CMAKE_INSTALL_PREFIX@/bin/dlt-adaptor-udp -a @DLT_ADAPTOR_UDP_APPID@ -c @DLT_ADAPTOR_UDP_CTID@ -p @DLT_ADAPTOR_UDP_PORT@ + LimitCORE=infinity + + [Install] +-WantedBy=multi-user.target +\ No newline at end of file ++WantedBy=multi-user.target +diff --git a/systemd/dlt-example-user.service.cmake b/systemd/dlt-example-user.service.cmake +index b665742..35009b0 100644 +--- a/systemd/dlt-example-user.service.cmake ++++ b/systemd/dlt-example-user.service.cmake +@@ -21,6 +21,5 @@ Wants=dlt.service + + [Service] + Type=simple +-User=@DLT_USER@ + ExecStart=@CMAKE_INSTALL_PREFIX@/bin/dlt-example-user "Hallo from GENIVI DLT example user application" +-LimitCORE=infinity +\ No newline at end of file ++LimitCORE=infinity +diff --git a/systemd/dlt-receive.service.cmake b/systemd/dlt-receive.service.cmake +index c07d447..8f88f00 100644 +--- a/systemd/dlt-receive.service.cmake ++++ b/systemd/dlt-receive.service.cmake +@@ -22,6 +22,5 @@ Wants=dlt.service + + [Service] + Type=simple +-User=@DLT_USER@ + ExecStart=@CMAKE_INSTALL_PREFIX@/bin/dlt-receive -o /tmp/dlt_receive_log.dlt localhost +-LimitCORE=infinity +\ No newline at end of file ++LimitCORE=infinity +diff --git a/systemd/dlt-system.service.cmake b/systemd/dlt-system.service.cmake +index 0e91f42..1a5b913 100755 +--- a/systemd/dlt-system.service.cmake ++++ b/systemd/dlt-system.service.cmake +@@ -22,7 +22,6 @@ Wants=dlt.service + + [Service] + Type=simple +-User=@DLT_USER@ + ExecStart=@CMAKE_INSTALL_PREFIX@/bin/dlt-system + WatchdogSec=@DLT_WatchdogSec@ + NotifyAccess=main +diff --git a/systemd/dlt.service.cmake b/systemd/dlt.service.cmake +index 0b3ee2c..e4753a2 100755 +--- a/systemd/dlt.service.cmake ++++ b/systemd/dlt.service.cmake +@@ -21,7 +21,6 @@ Documentation=man:dlt-daemon(1) man:dlt.conf(5) + + [Service] + Type=simple +-User=@DLT_USER@ + ExecStart=@CMAKE_INSTALL_PREFIX@/bin/dlt-daemon + WatchdogSec=@DLT_WatchdogSec@ + NotifyAccess=main diff --git a/meta-agl-profile-demo/recipes-extended/dlt-daemon/dlt-daemon/0003-systemd-unit-type-should-be-in-lowercase-so-use-Type.patch b/meta-agl-profile-demo/recipes-extended/dlt-daemon/dlt-daemon/0003-systemd-unit-type-should-be-in-lowercase-so-use-Type.patch new file mode 100644 index 000000000..691a50027 --- /dev/null +++ b/meta-agl-profile-demo/recipes-extended/dlt-daemon/dlt-daemon/0003-systemd-unit-type-should-be-in-lowercase-so-use-Type.patch @@ -0,0 +1,98 @@ +From 6804c68ed61f4436818c58cb0abe1c21b4d48aea Mon Sep 17 00:00:00 2001 +From: Andrei Gherzan +Date: Tue, 18 Nov 2014 15:48:50 +0100 +Subject: [PATCH 3/4] systemd/*: unit type should be in lowercase, so use + Type=simple + +Upstream-Status: Submitted [http://lists.genivi.org/pipermail/genivi-diagnostic-log-and-trace/2014-October/000546.html] +Signed-off-by: Andrei Gherzan +--- + systemd/dlt-adaptor-udp.service.cmake | 2 +- + systemd/dlt-dbus.service.cmake | 2 +- + systemd/dlt-example-user.service.cmake | 2 +- + systemd/dlt-receive.service.cmake | 2 +- + systemd/dlt-system.service.cmake | 2 +- + systemd/dlt.service.cmake | 2 +- + 6 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/systemd/dlt-adaptor-udp.service.cmake b/systemd/dlt-adaptor-udp.service.cmake +index f446757..81a7158 100644 +--- a/systemd/dlt-adaptor-udp.service.cmake ++++ b/systemd/dlt-adaptor-udp.service.cmake +@@ -19,7 +19,7 @@ Description=GENIVI DLT adaptor stdin. Adaptor for forwarding received UDP messag + Wants=dlt.service + + [Service] +-Type=Simple ++Type=simple + ExecStart=@CMAKE_INSTALL_PREFIX@/bin/dlt-adaptor-udp -a @DLT_ADAPTOR_UDP_APPID@ -c @DLT_ADAPTOR_UDP_CTID@ -p @DLT_ADAPTOR_UDP_PORT@ + LimitCORE=infinity + +diff --git a/systemd/dlt-dbus.service.cmake b/systemd/dlt-dbus.service.cmake +index d1e3b12..75dcdc3 100755 +--- a/systemd/dlt-dbus.service.cmake ++++ b/systemd/dlt-dbus.service.cmake +@@ -20,7 +20,7 @@ Documentation=man:dlt-dbus(1) man:dlt-dbus.conf(5) + Wants=dlt.service + + [Service] +-Type=Simple ++Type=simple + ExecStart=@CMAKE_INSTALL_PREFIX@/bin/dlt-dbus + WatchdogSec=@DLT_WatchdogSec@ + NotifyAccess=main +diff --git a/systemd/dlt-example-user.service.cmake b/systemd/dlt-example-user.service.cmake +index b67a83c..fe9c567 100644 +--- a/systemd/dlt-example-user.service.cmake ++++ b/systemd/dlt-example-user.service.cmake +@@ -19,6 +19,6 @@ Description=GENIVI DLT example user. Generate DLT messages and store them to fil + Wants=dlt.service + + [Service] +-Type=Simple ++Type=simple + ExecStart=@CMAKE_INSTALL_PREFIX@/bin/dlt-example-user "Hallo from GENIVI DLT example user application" + LimitCORE=infinity +\ No newline at end of file +diff --git a/systemd/dlt-receive.service.cmake b/systemd/dlt-receive.service.cmake +index 4bbdfc2..3b47dd3 100644 +--- a/systemd/dlt-receive.service.cmake ++++ b/systemd/dlt-receive.service.cmake +@@ -20,6 +20,6 @@ Documentation=man:dlt-receive(1) + Wants=dlt.service + + [Service] +-Type=Simple ++Type=simple + ExecStart=@CMAKE_INSTALL_PREFIX@/bin/dlt-receive -o /tmp/dlt_receive_log.dlt localhost + LimitCORE=infinity +\ No newline at end of file +diff --git a/systemd/dlt-system.service.cmake b/systemd/dlt-system.service.cmake +index 7ec995c..d4a4c96 100755 +--- a/systemd/dlt-system.service.cmake ++++ b/systemd/dlt-system.service.cmake +@@ -20,7 +20,7 @@ Documentation=man:dlt-system(1) man:dlt-system.conf(5) + Wants=dlt.service + + [Service] +-Type=Simple ++Type=simple + ExecStart=@CMAKE_INSTALL_PREFIX@/bin/dlt-system + WatchdogSec=@DLT_WatchdogSec@ + NotifyAccess=main +diff --git a/systemd/dlt.service.cmake b/systemd/dlt.service.cmake +index 7bb05bc..5386ffd 100755 +--- a/systemd/dlt.service.cmake ++++ b/systemd/dlt.service.cmake +@@ -19,7 +19,7 @@ Description=GENIVI DLT logging daemon + Documentation=man:dlt-daemon(1) man:dlt.conf(5) + + [Service] +-Type=Simple ++Type=simple + ExecStart=@CMAKE_INSTALL_PREFIX@/bin/dlt-daemon + WatchdogSec=@DLT_WatchdogSec@ + NotifyAccess=main +-- +1.9.3 + diff --git a/meta-agl-profile-demo/recipes-extended/dlt-daemon/dlt-daemon/0004-Modify-systemd-config-directory.patch b/meta-agl-profile-demo/recipes-extended/dlt-daemon/dlt-daemon/0004-Modify-systemd-config-directory.patch new file mode 100644 index 000000000..685dfcddc --- /dev/null +++ b/meta-agl-profile-demo/recipes-extended/dlt-daemon/dlt-daemon/0004-Modify-systemd-config-directory.patch @@ -0,0 +1,24 @@ +From 9a5e655cf57301008cd61d53c8a410a7f397e650 Mon Sep 17 00:00:00 2001 +From: Andrei Gherzan +Date: Tue, 18 Nov 2014 15:51:30 +0100 +Subject: [PATCH 4/4] Modify systemd config directory + +Upstream-Status: Inappropriate [Configuration Specific] +Signed-off-by: Andrei Gherzan +--- + systemd/CMakeLists.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index e6b44a2..0e885bf 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -175,7 +175,7 @@ if(WITH_SYSTEMD OR WITH_SYSTEMD_WATCHDOG OR WITH_SYSTEMD_JOURNAL) + + set( systemd_SRCS ${CMAKE_SOURCE_DIR}/systemd/3rdparty/sd-daemon.c) + +- set(SYSTEMD_UNITDIR "${CMAKE_INSTALL_PREFIX}/lib/systemd/system" CACHE PATH ++ set(SYSTEMD_UNITDIR "/lib/systemd/system" CACHE PATH + "Set directory to install systemd unit files") + + add_subdirectory( systemd ) diff --git a/meta-agl-profile-demo/recipes-extended/dlt-daemon/dlt-daemon_2.11.1.bb b/meta-agl-profile-demo/recipes-extended/dlt-daemon/dlt-daemon_2.11.1.bb new file mode 100644 index 000000000..b521bca91 --- /dev/null +++ b/meta-agl-profile-demo/recipes-extended/dlt-daemon/dlt-daemon_2.11.1.bb @@ -0,0 +1,54 @@ +SUMMARY = "Diagnostic Log and Trace" +DESCRIPTION = "This component provides a standardised log and trace interface, \ +based on the standardised protocol specified in the AUTOSAR standard 4.0 DLT. \ +This component can be used by GENIVI components and other applications as \ +logging facility providing: \ +- the DLT shared library \ +- the DLT daemon, including startup scripts \ +- the DLT daemon adaptors- the DLT client console utilities \ +- the DLT test applications" +HOMEPAGE = "https://www.genivi.org/" +SECTION = "console/utils" +LICENSE = "MPLv2" +LIC_FILES_CHKSUM = "file://LICENSE.txt;md5=99ba60c3fad7eaf8c56bca6dd75cba09 \ + file://MPL.txt;md5=ccdb2761cef70c8b2612624c323f89dc" + +DEPENDS = "dbus zlib pigz-native" +do_unpack[depends] += "pigz-native:do_populate_sysroot" + +# FIX ME +# This should be TAG = "v${PV}" but yocto doesn't support lightweight tags for now +# https://bugzilla.yoctoproject.org/show_bug.cgi?id=6881 +TAG = "b8b3ea3a31f7deb681941a19878c82e7b7350ae7" +BRANCH = "v2.11.x" +SRC_URI = "git://git.projects.genivi.org/${PN}.git;branch=${BRANCH};tag=${TAG} \ + file://0001-Fix-build-with-systemd-209.patch \ + file://0002-Don-t-execute-processes-as-a-specific-user.patch \ + file://0003-systemd-unit-type-should-be-in-lowercase-so-use-Type.patch \ + file://0004-Modify-systemd-config-directory.patch" +S = "${WORKDIR}/git" + +inherit autotools gettext cmake systemd + +# -fPIC is needed to prevent relocation errors when we compile gtest with +# Yocto security flags. See this issue for more details: +# +# https://github.com/google/googletest/issues/854 +# +# If that issue is fixed, we can probably remove the manual -fPIC flags here. +OECMAKE_C_FLAGS += "-fPIC" +OECMAKE_CXX_FLAGS += "-fPIC" + +PACKAGES += "${PN}-systemd" +SYSTEMD_PACKAGES = "${PN} ${PN}-systemd" +SYSTEMD_SERVICE_${PN} = "dlt-system.service dlt.service" +SYSTEMD_AUTO_ENABLE_${PN} = "enable" +SYSTEMD_SERVICE_${PN}-systemd = "dlt-example-user.service \ + dlt-dbus.service \ + dlt-adaptor-udp.service \ + dlt-receive.service" +SYSTEMD_AUTO_ENABLE_${PN}-systemd = "disable" + +EXTRA_OECMAKE = "-DWITH_SYSTEMD=ON" + +FILES_${PN}-doc += "/usr/share/dlt-filetransfer" diff --git a/meta-agl-profile-demo/recipes-extended/dlt-daemon/dlt-daemon_2.15.0.bb b/meta-agl-profile-demo/recipes-extended/dlt-daemon/dlt-daemon_2.15.0.bb new file mode 100644 index 000000000..dbc87c9ac --- /dev/null +++ b/meta-agl-profile-demo/recipes-extended/dlt-daemon/dlt-daemon_2.15.0.bb @@ -0,0 +1,52 @@ +SUMMARY = "Diagnostic Log and Trace" +DESCRIPTION = "This component provides a standardised log and trace interface, \ +based on the standardised protocol specified in the AUTOSAR standard 4.0 DLT. \ +This component can be used by GENIVI components and other applications as \ +logging facility providing: \ +- the DLT shared library \ +- the DLT daemon, including startup scripts \ +- the DLT daemon adaptors- the DLT client console utilities \ +- the DLT test applications" +HOMEPAGE = "https://www.genivi.org/" +SECTION = "console/utils" +LICENSE = "MPLv2" +LIC_FILES_CHKSUM = "file://LICENSE;md5=8184208060df880fe3137b93eb88aeea" + +DEPENDS = "dbus zlib pigz-native" +do_unpack[depends] += "pigz-native:do_populate_sysroot" + +SRCREV = "e9a486a08fff6d3cc7133a350cec3ee10f463207" +SRC_URI = "git://git.projects.genivi.org/${BPN}.git;protocol=http \ + file://0002-Don-t-execute-processes-as-a-specific-user.patch \ + file://0004-Modify-systemd-config-directory.patch \ + " +S = "${WORKDIR}/git" + +inherit autotools gettext cmake systemd + +# -fPIC is needed to prevent relocation errors when we compile gtest with +# Yocto security flags. See this issue for more details: +# +# https://github.com/google/googletest/issues/854 +# +# If that issue is fixed, we can probably remove the manual -fPIC flags here. +OECMAKE_C_FLAGS += "-fPIC" +OECMAKE_CXX_FLAGS += "-fPIC" + +PACKAGES += "${PN}-systemd" +SYSTEMD_PACKAGES = "${PN} ${PN}-systemd" +SYSTEMD_SERVICE_${PN} = "dlt-system.service dlt.service" +SYSTEMD_AUTO_ENABLE_${PN} = "enable" +SYSTEMD_SERVICE_${PN}-systemd = "dlt-example-user.service \ + dlt-dbus.service \ + dlt-adaptor-udp.service \ + dlt-receive.service" +SYSTEMD_AUTO_ENABLE_${PN}-systemd = "disable" + +EXTRA_OECMAKE = "-DWITH_SYSTEMD=ON" + +FILES_${PN}-doc += "/usr/share/dlt-filetransfer" + +do_install_append() { + rm -f ${D}${bindir}/dlt-test-* +} diff --git a/meta-agl-profile-demo/recipes-multimedia/audiomanager/audiomanager/0001-Fix-duplicated-command-line-arg-t.patch b/meta-agl-profile-demo/recipes-multimedia/audiomanager/audiomanager/0001-Fix-duplicated-command-line-arg-t.patch new file mode 100644 index 000000000..fcdf9c540 --- /dev/null +++ b/meta-agl-profile-demo/recipes-multimedia/audiomanager/audiomanager/0001-Fix-duplicated-command-line-arg-t.patch @@ -0,0 +1,25 @@ +From c4b6030f575e38dfc9cca7dfd029d207f3af6a13 Mon Sep 17 00:00:00 2001 +From: "Andre Moreira Magalhaes (andrunko)" +Date: Thu, 5 May 2016 00:01:19 -0300 +Subject: [PATCH] Fix duplicated command line arg -t. + +--- + AudioManagerDaemon/src/main.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/AudioManagerDaemon/src/main.cpp b/AudioManagerDaemon/src/main.cpp +index 795795d..67c0977 100755 +--- a/AudioManagerDaemon/src/main.cpp ++++ b/AudioManagerDaemon/src/main.cpp +@@ -87,7 +87,7 @@ TCLAP::ValueArg commandPluginDir("l","CommandPluginDir","path for l + TCLAP::ValueArg databasePath ("p","databasePath","path for sqlite database (default is in memory)",false,":memory:","string"); + TCLAP::ValueArg telnetPort ("t","telnetport","The port that is used for telnet",false,DEFAULT_TELNETPORT,"int"); + TCLAP::ValueArg maxConnections ("m","maxConnections","Maximal number of connections for telnet",false,MAX_TELNETCONNECTIONS,"int"); +-TCLAP::SwitchArg dbusWrapperTypeBool ("t","dbusType","DbusType to be used by CAmDbusWrapper: if option is selected, DBUS_SYSTEM is used otherwise DBUS_SESSION",false); ++TCLAP::SwitchArg dbusWrapperTypeBool ("T","dbusType","DbusType to be used by CAmDbusWrapper: if option is selected, DBUS_SYSTEM is used otherwise DBUS_SESSION",false); + TCLAP::SwitchArg enableNoDLTDebug ("V","logDlt","print DLT logs to stdout",false); + TCLAP::SwitchArg currentSettings("i","currentSettings","print current settings and exit",false); + TCLAP::SwitchArg daemonizeAM("d","daemonize","daemonize Audiomanager. Better use systemd...",false); +-- +2.5.0 + diff --git a/meta-agl-profile-demo/recipes-multimedia/audiomanager/audiomanager/audiomanager.service b/meta-agl-profile-demo/recipes-multimedia/audiomanager/audiomanager/audiomanager.service new file mode 100644 index 000000000..2210a377b --- /dev/null +++ b/meta-agl-profile-demo/recipes-multimedia/audiomanager/audiomanager/audiomanager.service @@ -0,0 +1,17 @@ +# AudioManager systemd service file + +[Unit] +Description=GENIVI AudioManager +Requires=dbus.service +After=dbus.service +Before=pulseaudio.service + +[Service] +Type=notify +ExecStart=/usr/bin/AudioManager -T +Restart=always +TimeoutSec=2 +WatchdogSec=2 + +[Install] +WantedBy=multi-user.target diff --git a/meta-agl-profile-demo/recipes-multimedia/audiomanager/audiomanager_7.4.bb b/meta-agl-profile-demo/recipes-multimedia/audiomanager/audiomanager_7.4.bb new file mode 100644 index 000000000..15eb36252 --- /dev/null +++ b/meta-agl-profile-demo/recipes-multimedia/audiomanager/audiomanager_7.4.bb @@ -0,0 +1,56 @@ +DESCRIPTION = "GENIVI Audio Manager" +HOMEPAGE = "http://projects.genivi.org/audio-manager/home" +LICENSE = "MPLv2" +SECTION = "multimedia" +DEPENDS = "dbus dlt-daemon systemd" +LIC_FILES_CHKSUM = "file://LICENCE;md5=f164349b56ed530a6642e9b9f244eec5" + +SRC_URI = " \ + git://github.com/GENIVI/AudioManager.git;protocol=https;branch=master \ + file://audiomanager.service \ +" +RDEPENDS_${PN} = "audiomanager-plugins module-router" +SRCREV = "daf851ee7a41d1b0572c0c95e15f61e427ce97f1" + +S = "${WORKDIR}/git" +inherit cmake systemd +SYSTEMD_PACKAGES = "${PN}" +SYSTEMD_SERVICE_${PN} = "audiomanager.service" +SYSTEMD_AUTO_ENABLE = "enable" + +EXTRA_OECMAKE = " \ + -DWITH_TESTS=OFF \ + -DWITH_DOCUMENTATION=OFF \ + -DWITH_DLT=ON \ + -DWITH_TELNET=OFF \ + -DWITH_SYSTEMD_WATCHDOG=ON \ + -DGLIB_DBUS_TYPES_TOLERANT=ON \ + -DWITH_CAPI_WRAPPER=OFF \ + -DWITH_DBUS_WRAPPER=ON \ + -DWITH_SHARED_UTILITIES=ON \ + -DWITH_SHARED_CORE=ON \ +" + +FILES_${PN} = " \ + ${bindir}/AudioManager \ + ${libdir}/libAudioManagerCore.so.7 \ + ${libdir}/libAudioManagerCore.so.7.4 \ + ${libdir}/libAudioManagerCore.so.7.4.12 \ + ${libdir}/libAudioManagerUtilities.so.7 \ + ${libdir}/libAudioManagerUtilities.so.7.4 \ + ${libdir}/libAudioManagerUtilities.so.7.4.12 \ + ${systemd_unitdir}/audiomanager.service \ +" + +FILES_${PN}-dev = " \ + ${includedir}/audiomanager/* \ + ${libdir}/cmake/* \ + ${libdir}/pkgconfig/* \ + ${libdir}/libAudioManagerCore.so \ + ${libdir}/libAudioManagerUtilities.so \ +" + +do_install_append() { + install -d ${D}${systemd_unitdir}/system/ + install -m 0644 ${WORKDIR}/audiomanager.service ${D}${systemd_unitdir}/system/ +} diff --git a/meta-agl-profile-graphical/classes/agl-graphical.bbclass b/meta-agl-profile-graphical/classes/agl-graphical.bbclass new file mode 100644 index 000000000..0004d9c1a --- /dev/null +++ b/meta-agl-profile-graphical/classes/agl-graphical.bbclass @@ -0,0 +1,7 @@ +WESTONTTY ??= "1" +WESTONUSER ??= "display" +WESTONGROUP ??= "display" +WESTONARGS ?= "--idle-time=0 --tty=${WESTONTTY} ${@bb.utils.contains("DISTRO_FEATURES", "gst-record", "--gst-record", "",d)}" +WESTONLAUNCHARGS ??= "--tty /dev/tty${WESTONTTY} --user ${WESTONUSER}" +DISPLAY_XDG_RUNTIME_DIR ??= "/run/platform/${WESTONUSER}" + diff --git a/meta-agl-profile-graphical/conf/layer.conf b/meta-agl-profile-graphical/conf/layer.conf new file mode 100644 index 000000000..4b0b8cb9b --- /dev/null +++ b/meta-agl-profile-graphical/conf/layer.conf @@ -0,0 +1,10 @@ +# We have a conf and classes directory, add to BBPATH +BBPATH =. "${LAYERDIR}:" + +# We have recipes-* directories, add to BBFILES +BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \ + ${LAYERDIR}/recipes-*/*/*.bbappend" + +BBFILE_COLLECTIONS += "aglprofilegraphical" +BBFILE_PATTERN_aglprofilegraphical = "^${LAYERDIR}/" +BBFILE_PRIORITY_aglprofilegraphical = "70" diff --git a/meta-agl-profile-graphical/recipes-config/agl-login-manager/agl-login-manager_0.1.bb b/meta-agl-profile-graphical/recipes-config/agl-login-manager/agl-login-manager_0.1.bb new file mode 100644 index 000000000..cd6dc6792 --- /dev/null +++ b/meta-agl-profile-graphical/recipes-config/agl-login-manager/agl-login-manager_0.1.bb @@ -0,0 +1,21 @@ +SUMMARY = "AGL Login manager" + +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420" + +inherit agl-graphical + +LOGIN_USER ??="1001 1002" + +RDEPENDS_${PN} += "af-main" + +do_install_append() { + + install -d ${D}${systemd_system_unitdir}/multi-user.target.wants/ + + for AGL_USER in ${LOGIN_USER};do + ln -s ../afm-user-session@.service ${D}${systemd_system_unitdir}/multi-user.target.wants/afm-user-session@${AGL_USER}.service + done +} + +FILES_${PN} += "${systemd_system_unitdir}" diff --git a/meta-agl-profile-graphical/recipes-graphics/agl-desktop-config/agl-desktop-config_0.1.bb b/meta-agl-profile-graphical/recipes-graphics/agl-desktop-config/agl-desktop-config_0.1.bb new file mode 100644 index 000000000..e0358d615 --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/agl-desktop-config/agl-desktop-config_0.1.bb @@ -0,0 +1,21 @@ +SUMMARY = "AGL desktop config" + +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420" + +SRC_URI += " \ + file://user-weston-term.service \ + file://user-weston-term.path \ +" + +do_install_append() { + install -d ${D}${systemd_user_unitdir} + install -m 0644 ${WORKDIR}/user-weston-term.service ${D}${systemd_user_unitdir} + install -m 0644 ${WORKDIR}/user-weston-term.path ${D}${systemd_user_unitdir} + + install -d ${D}${systemd_user_unitdir}/default.target.wants + ln -sf ${systemd_user_unitdir}/user-weston-term.path ${D}${libdir}/systemd/user/default.target.wants +} + +FILES_${PN} += "${systemd_user_unitdir}/*" +FILES_${PN} += "${systemd_user_unitdir}/default.target.wants/default.target.wants" diff --git a/meta-agl-profile-graphical/recipes-graphics/agl-desktop-config/files/user-weston-term.path b/meta-agl-profile-graphical/recipes-graphics/agl-desktop-config/files/user-weston-term.path new file mode 100644 index 000000000..9481840e5 --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/agl-desktop-config/files/user-weston-term.path @@ -0,0 +1,8 @@ +[Unit] +Description=Terminal for weston user unit path + +[Path] +PathExists=%t/wayland-0 + +[Install] +WantedBy=default.target diff --git a/meta-agl-profile-graphical/recipes-graphics/agl-desktop-config/files/user-weston-term.service b/meta-agl-profile-graphical/recipes-graphics/agl-desktop-config/files/user-weston-term.service new file mode 100644 index 000000000..ad8b9583b --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/agl-desktop-config/files/user-weston-term.service @@ -0,0 +1,12 @@ +[Unit] +Description=Terminal for weston user +After=user-config.service +Requires=user-config.service + +[Service] +Type=simple +ExecStart=/usr/bin/weston-terminal +Restart=always + +[Install] +WantedBy=multi-user.target diff --git a/meta-agl-profile-graphical/recipes-graphics/images/agl-image-weston.bb b/meta-agl-profile-graphical/recipes-graphics/images/agl-image-weston.bb new file mode 100644 index 000000000..427132ed6 --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/images/agl-image-weston.bb @@ -0,0 +1,12 @@ +SUMMARY = "A very basic Wayland image with a terminal" + +require agl-image-weston.inc + +LICENSE = "MIT" + +IMAGE_INSTALL_append = "\ + packagegroup-agl-image-weston \ + " + +DISTRO_FEATURES_append = " agl-core-image-profile" +IMAGE_INSTALL_append = " agl-desktop-config" diff --git a/meta-agl-profile-graphical/recipes-graphics/images/agl-image-weston.inc b/meta-agl-profile-graphical/recipes-graphics/images/agl-image-weston.inc new file mode 100644 index 000000000..947d22b50 --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/images/agl-image-weston.inc @@ -0,0 +1,7 @@ +require recipes-core/images/agl-image-minimal.inc + +IMAGE_FEATURES += "splash package-management ssh-server-dropbear" + +inherit distro_features_check + +REQUIRED_DISTRO_FEATURES = "wayland" diff --git a/meta-agl-profile-graphical/recipes-graphics/packagegroups/packagegroup-agl-image-weston.bb b/meta-agl-profile-graphical/recipes-graphics/packagegroups/packagegroup-agl-image-weston.bb new file mode 100644 index 000000000..dcf21bcfb --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/packagegroups/packagegroup-agl-image-weston.bb @@ -0,0 +1,17 @@ +DESCRIPTION = "The minimal set of packages required for basic Wayland image" +LICENSE = "MIT" + +inherit packagegroup + +PACKAGES = "\ + packagegroup-agl-image-weston \ + " + +ALLOW_EMPTY_${PN} = "1" + +RDEPENDS_${PN} += "weston weston-init weston-ini-conf weston-examples" +RDEPENDS_${PN} += "agl-login-manager" + +RDEPENDS_${PN} += "\ + packagegroup-agl-image-minimal \ + " diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/Readme.weston-ini-conf b/meta-agl-profile-graphical/recipes-graphics/wayland/Readme.weston-ini-conf new file mode 100644 index 000000000..bbd5a80c4 --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/Readme.weston-ini-conf @@ -0,0 +1,34 @@ +##Generate a weston.ini file: + +To modify any of the default sections (core, shell, ivi-shell), add a +do_configure() function to your bbappend: + +''' +do_configure() { + echo repaint-window=34 >> ${WORKDIR}/core.cfg + + echo transition-duration=300 >> ${WORKDIR}/ivishell.cfg + echo cursor-theme=default >> ${WORKDIR}/ivishell.cfg +} +''' +or: +''' +do_configure() { + sed -i -e 's/drm-backend/fbdev-backend/' ${WORKDIR}/core.cfg +} +''' + +To change the display from the default assumption of an HDMI-1-A connected +screen that needs to be rotated 270 degrees: + +''' +SRC_URI_remove = "file://hdmi-a-1-270.cfg" +SRC_URI += "file://hdmi-a-1-90.cfg" +''' + +To add new sections just list them in SRC_URI: +''' +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" + +SRC_URI += "file://dsi.cfg" +''' diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/wayland-ivi-extension/0001-Resolve-weston-crush-when-repeat-touching-very-quick.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/wayland-ivi-extension/0001-Resolve-weston-crush-when-repeat-touching-very-quick.patch new file mode 100644 index 000000000..636ecf1b9 --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/wayland-ivi-extension/0001-Resolve-weston-crush-when-repeat-touching-very-quick.patch @@ -0,0 +1,31 @@ +From 97af4843a4705cd7d5b6b69abb9002fd974a5b94 Mon Sep 17 00:00:00 2001 +From: Tadao Tanikawa +Date: Fri, 12 Jan 2018 01:53:01 +0900 +Subject: [PATCH] Resolve weston cursh when repeat touching very quickly + +Weston sometimes crush while the user repeat touching very +quickly icons/shortcuts on HomeScreen. + +Signed-off-by: Tadao Tanikawa +--- + ivi-input-modules/ivi-input-controller/src/ivi-input-controller.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/ivi-input-modules/ivi-input-controller/src/ivi-input-controller.c b/ivi-input-modules/ivi-input-controller/src/ivi-input-controller.c +index b0fe37d..f1a31d0 100644 +--- a/ivi-input-modules/ivi-input-controller/src/ivi-input-controller.c ++++ b/ivi-input-modules/ivi-input-controller/src/ivi-input-controller.c +@@ -557,6 +557,10 @@ touch_grab_up(struct weston_touch_grab *grab, uint32_t time, int touch_id) + const struct ivi_layout_interface *interface = + seat->input_ctx->ivi_layout_interface; + ++ /* if touch device has no focused view, there is nothing to do*/ ++ if (grab->touch->focus == NULL) ++ return; ++ + /* For each surface_ctx, check for focus and send */ + wl_list_for_each(surf_ctx, &seat->input_ctx->surface_list, link) { + struct weston_surface *surf, *send_surf; +-- +2.7.4 + diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/wayland-ivi-extension/0001-simple-id-agent-initial-commit.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/wayland-ivi-extension/0001-simple-id-agent-initial-commit.patch new file mode 100644 index 000000000..9e95167ed --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/wayland-ivi-extension/0001-simple-id-agent-initial-commit.patch @@ -0,0 +1,264 @@ +From 8f67f40f7c6b6f62e094f0bdc5044793ae76b1c7 Mon Sep 17 00:00:00 2001 +From: Emre Ucan +Date: Fri, 24 Nov 2017 16:24:51 +0100 +Subject: [PATCH 1/2] simple-id-agent: initial commit + +it is a very simple id-agent plugin. +It is possible to configure default surface id +offset. Assigned ids would start +from the given id offset. + +Please check the example weston.ini for loading +and configuring the simple-id-agent + +Signed-off-by: Emre Ucan +--- + CMakeLists.txt | 1 + + id-agent-modules/simple-id-agent/CMakeLists.txt | 72 ++++++++++++ + .../simple-id-agent/src/simple-id-agent.c | 124 +++++++++++++++++++++ + id-agent-modules/simple-id-agent/weston.ini.in | 11 ++ + 4 files changed, 208 insertions(+) + create mode 100644 id-agent-modules/simple-id-agent/CMakeLists.txt + create mode 100644 id-agent-modules/simple-id-agent/src/simple-id-agent.c + create mode 100644 id-agent-modules/simple-id-agent/weston.ini.in + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index bad85df..d07abf5 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -35,6 +35,7 @@ add_subdirectory(ivi-layermanagement-api/ilmClient) + add_subdirectory(ivi-layermanagement-api/ilmControl) + add_subdirectory(ivi-layermanagement-api/test) + add_subdirectory(ivi-layermanagement-examples) ++add_subdirectory(id-agent-modules/simple-id-agent) + + if(WITH_ILM_INPUT) + add_subdirectory(ivi-input-api/ilmInput) +diff --git a/id-agent-modules/simple-id-agent/CMakeLists.txt b/id-agent-modules/simple-id-agent/CMakeLists.txt +new file mode 100644 +index 0000000..8290722 +--- /dev/null ++++ b/id-agent-modules/simple-id-agent/CMakeLists.txt +@@ -0,0 +1,72 @@ ++############################################################################ ++# ++# Copyright (C) 2013 DENSO CORPORATION ++# Copyright 2014 BMW Car IT GmbH ++# ++# ++# Licensed under the Apache License, Version 2.0 (the "License"); ++# you may not use this file except in compliance with the License. ++# You may obtain a copy of the License at ++# ++# http://www.apache.org/licenses/LICENSE-2.0 ++# ++# Unless required by applicable law or agreed to in writing, software ++# distributed under the License is distributed on an "AS IS" BASIS, ++# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++# See the License for the specific language governing permissions and ++# limitations under the License. ++# ++############################################################################ ++ ++cmake_minimum_required (VERSION 2.6) ++ ++project(simple-id-agent) ++ ++find_package(PkgConfig REQUIRED) ++pkg_check_modules(WAYLAND_SERVER wayland-server>=1.13.0 REQUIRED) ++pkg_check_modules(WESTON weston>=2.0.0 REQUIRED) ++pkg_check_modules(PIXMAN pixman-1 REQUIRED) ++ ++find_package(Threads REQUIRED) ++ ++GET_TARGET_PROPERTY(IVI_EXTENSION_INCLUDE_DIRS ivi-extension-protocol INCLUDE_DIRECTORIES) ++ ++include_directories( ++ src ++ ${IVI_EXTENSION_INCLUDE_DIRS} ++ ${WAYLAND_SERVER_INCLUDE_DIRS} ++ ${WESTON_INCLUDE_DIRS} ++ ${PIXMAN_INCLUDE_DIRS} ++) ++ ++link_directories( ++ ${WAYLAND_SERVER_LIBRARY_DIRS} ++ ${PIXMAN_LIBRARY_DIRS} ++) ++ ++add_library(${PROJECT_NAME} MODULE ++ src/simple-id-agent.c ++) ++ ++set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "") ++ ++add_dependencies(${PROJECT_NAME} ++ ivi-extension-protocol ++ ${WAYLAND_SERVER_LIBRARIES} ++ ${PIXMAN_LIBRARIES} ++) ++ ++set(LIBS ++ ${LIBS} ++ ivi-extension-protocol ++ ${WAYLAND_SERVER_LIBRARIES} ++) ++ ++set(CMAKE_C_LDFLAGS "-module -avoid-version") ++ ++target_link_libraries(${PROJECT_NAME} ${LIBS}) ++ ++install ( ++ TARGETS ${PROJECT_NAME} ++ LIBRARY DESTINATION lib${LIB_SUFFIX}/weston ++) +diff --git a/id-agent-modules/simple-id-agent/src/simple-id-agent.c b/id-agent-modules/simple-id-agent/src/simple-id-agent.c +new file mode 100644 +index 0000000..3c9e989 +--- /dev/null ++++ b/id-agent-modules/simple-id-agent/src/simple-id-agent.c +@@ -0,0 +1,124 @@ ++/* ++ * Copyright (C) 2017 Advanced Driver Information Technology Joint Venture GmbH ++ * ++ * Permission to use, copy, modify, distribute, and sell this software and ++ * its documentation for any purpose is hereby granted without fee, provided ++ * that the above copyright notice appear in all copies and that both that ++ * copyright notice and this permission notice appear in supporting ++ * documentation, and that the name of the copyright holders not be used in ++ * advertising or publicity pertaining to distribution of the software ++ * without specific, written prior permission. The copyright holders make ++ * no representations about the suitability of this software for any ++ * purpose. It is provided "as is" without express or implied warranty. ++ * ++ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS ++ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND ++ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY ++ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ++ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF ++ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++struct ivi_id_agent ++{ ++ uint32_t default_id_offset; ++ uint32_t last_assigned_id; ++ struct weston_compositor *compositor; ++ const struct ivi_layout_interface *interface; ++ struct wl_listener desktop_surface_configured; ++}; ++ ++static void ++desktop_surface_event_configure(struct wl_listener *listener, ++ void *data) ++{ ++ struct ivi_id_agent *ida = wl_container_of(listener, ida, ++ desktop_surface_configured); ++ struct ivi_layout_surface *layout_surface = ++ (struct ivi_layout_surface *) data; ++ uint32_t tmp_id; ++ ++ tmp_id = ++ida->last_assigned_id; ++ ++ /* Find an unused id */ ++ while(ida->interface->get_surface_from_id(tmp_id)) { ++ weston_log("simple-id-agent: surface id: %d is already used\n", tmp_id); ++ tmp_id++; ++ } ++ ++ ida->last_assigned_id = tmp_id; ++ ++ if (ida->interface->surface_set_id(layout_surface, ida->last_assigned_id) != 0) ++ weston_log("simple-id-agent: failed to set surface id :%d\n", ida->last_assigned_id); ++} ++ ++static void ++deinit(struct ivi_id_agent *ida) ++{ ++ wl_list_remove(&ida->desktop_surface_configured.link); ++ free(ida); ++} ++ ++static int32_t ++read_config(struct ivi_id_agent *ida) ++{ ++ struct weston_config *config = NULL; ++ struct weston_config_section *section = NULL; ++ const char *name = NULL; ++ ++ config = wet_get_config(ida->compositor); ++ if (!config) ++ return -1; ++ ++ section = weston_config_get_section(config, "id-agent", NULL, NULL); ++ ++ if (section) { ++ ++ weston_config_section_get_uint(section, "default-id-offset", ++ &ida->default_id_offset, 0); ++ ++ } else { ++ ida->default_id_offset = 0; ++ } ++ ++ return 0; ++} ++ ++WL_EXPORT int32_t ++id_agent_module_init(struct weston_compositor *ec, ++ const struct ivi_layout_interface *interface, ++ size_t interface_version) ++{ ++ struct ivi_id_agent *ida; ++ ++ ida = calloc(1, sizeof *ida); ++ if (ida == NULL) { ++ weston_log("failed to allocate ivi_id_agent\n"); ++ return -1; ++ } ++ ++ ida->compositor = ec; ++ ida->interface = interface; ++ ida->desktop_surface_configured.notify = desktop_surface_event_configure; ++ ida->interface->add_listener_configure_desktop_surface(&ida->desktop_surface_configured); ++ ++ if(read_config(ida) != 0) { ++ deinit(ida); ++ return -1; ++ } ++ ++ ida->last_assigned_id = ida->default_id_offset; ++ ++ weston_log("id_agent_module_init: success\n"); ++ ++ return 0; ++} +diff --git a/id-agent-modules/simple-id-agent/weston.ini.in b/id-agent-modules/simple-id-agent/weston.ini.in +new file mode 100644 +index 0000000..b5e5fa1 +--- /dev/null ++++ b/id-agent-modules/simple-id-agent/weston.ini.in +@@ -0,0 +1,11 @@ ++[core] ++shell=ivi-shell.so ++require-input=false ++ ++[ivi-shell] ++ivi-module=ivi-controller.so ++ivi-input-module=ivi-input-controller.so ++id-agent-module=simple-id-agent.so ++ ++[id-agent] ++default-id-offset=10 +-- +2.13.6 + diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/wayland-ivi-extension/0002-ivi-controller-load-id-agent-module.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/wayland-ivi-extension/0002-ivi-controller-load-id-agent-module.patch new file mode 100644 index 000000000..f44786a36 --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/wayland-ivi-extension/0002-ivi-controller-load-id-agent-module.patch @@ -0,0 +1,69 @@ +From 26f2f7ce78ba2002809048b227ad9c35921a9cd8 Mon Sep 17 00:00:00 2001 +From: Emre Ucan +Date: Fri, 24 Nov 2017 16:27:01 +0100 +Subject: [PATCH 2/2] ivi-controller: load id-agent module + +Signed-off-by: Emre Ucan +--- + weston-ivi-shell/src/ivi-controller.c | 39 +++++++++++++++++++++++++++++++++++ + 1 file changed, 39 insertions(+) + +diff --git a/weston-ivi-shell/src/ivi-controller.c b/weston-ivi-shell/src/ivi-controller.c +index 312a978..47b6de2 100644 +--- a/weston-ivi-shell/src/ivi-controller.c ++++ b/weston-ivi-shell/src/ivi-controller.c +@@ -1518,6 +1518,40 @@ load_input_module(struct weston_compositor *ec, + return 0; + } + ++static int load_id_agent_module(struct weston_compositor *ec, ++ const struct ivi_layout_interface *interface, ++ size_t interface_version) ++{ ++ struct weston_config *config = wet_get_config(ec); ++ struct weston_config_section *section; ++ char *id_agent_module = NULL; ++ ++ int (*id_agent_module_init)(struct weston_compositor *ec, ++ const struct ivi_layout_interface *interface, ++ size_t interface_version); ++ ++ section = weston_config_get_section(config, "ivi-shell", NULL, NULL); ++ ++ if (weston_config_section_get_string(section, "id-agent-module", ++ &id_agent_module, NULL) < 0) { ++ weston_log("ivi-controller: No id-agent-module set\n"); ++ return 0; ++ } ++ ++ id_agent_module_init = wet_load_module_entrypoint(id_agent_module, "id_agent_module_init"); ++ if (!id_agent_module_init) ++ return -1; ++ ++ if (id_agent_module_init(ec, interface, ++ sizeof(struct ivi_layout_interface)) != 0) { ++ weston_log("ivi-controller: Initialization of id agent module fails\n"); ++ return -1; ++ } ++ ++ free(id_agent_module); ++ return 0; ++} ++ + WL_EXPORT int + controller_module_init(struct weston_compositor *compositor, + int *argc, char *argv[], +@@ -1555,5 +1589,10 @@ controller_module_init(struct weston_compositor *compositor, + return -1; + } + ++ if (load_id_agent_module(compositor, interface, interface_version) < 0) { ++ free(shell); ++ return -1; ++ } ++ + return 0; + } +-- +2.13.6 + diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/wayland-ivi-extension/0003-ivi-controller-add-resize-setting-suit-to-surface-si.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/wayland-ivi-extension/0003-ivi-controller-add-resize-setting-suit-to-surface-si.patch new file mode 100644 index 000000000..d2d027256 --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/wayland-ivi-extension/0003-ivi-controller-add-resize-setting-suit-to-surface-si.patch @@ -0,0 +1,62 @@ +From 525b5bf65303d661f44c01b11bafd5ba90976850 Mon Sep 17 00:00:00 2001 +From: Wataru Mizuno +Date: Wed, 6 Dec 2017 19:35:51 +0900 +Subject: [PATCH] ivi-controller: add resize setting suit to surface size + +The ivi-controller resizes surface size like desktop usecase. + +When window manager swicths the half size window to full size, +resize was not working correctly. +This patch fixs this issue by changing surface source region at +the same timing of destination region is changed. + +This patch is not necessary later version of wayland-ivi-extension +2.0 since this resize function has already been implemented by +appropriate manner. + +Signed-off-by: Wataru Mizuno +--- + weston-ivi-shell/src/ivi-controller.c | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +diff --git a/weston-ivi-shell/src/ivi-controller.c b/weston-ivi-shell/src/ivi-controller.c +index 312a978..9450cf2 100644 +--- a/weston-ivi-shell/src/ivi-controller.c ++++ b/weston-ivi-shell/src/ivi-controller.c +@@ -1334,7 +1334,7 @@ surface_event_configure(struct wl_listener *listener, void *data) + struct ivisurface *ivisurf = NULL; + struct ivi_layout_surface *layout_surface = + (struct ivi_layout_surface *) data; +- const struct ivi_layout_surface_properties *prop; ++ struct weston_surface *w_surface; + + ivisurf = get_surface(&shell->list_surface, layout_surface); + if (ivisurf == NULL) { +@@ -1342,11 +1342,22 @@ surface_event_configure(struct wl_listener *listener, void *data) + return; + } + +- prop = lyt->get_properties_of_surface(layout_surface); ++ w_surface = lyt->surface_get_weston_surface(layout_surface); ++ lyt->surface_set_destination_rectangle(layout_surface, ++ ivisurf->prop->dest_x, ++ ivisurf->prop->dest_y, ++ w_surface->width, ++ w_surface->height); ++ lyt->surface_set_source_rectangle(layout_surface, ++ 0, ++ 0, ++ w_surface->width, ++ w_surface->height); ++ lyt->commit_changes(); + + wl_resource_for_each(resource, &ivisurf->resource_list) { + send_surface_event(resource, ivisurf, +- prop, IVI_NOTIFICATION_CONFIGURE); ++ ivisurf->prop, IVI_NOTIFICATION_CONFIGURE); + } + } + +-- +2.7.4 + diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/wayland-ivi-extension/disable-sanitizer-tests.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/wayland-ivi-extension/disable-sanitizer-tests.patch new file mode 100644 index 000000000..df5d616fd --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/wayland-ivi-extension/disable-sanitizer-tests.patch @@ -0,0 +1,13 @@ +Index: git/ivi-layermanagement-api/test/CMakeLists.txt +=================================================================== +--- git.orig/ivi-layermanagement-api/test/CMakeLists.txt ++++ git/ivi-layermanagement-api/test/CMakeLists.txt +@@ -58,7 +58,7 @@ IF(BUILD_ILM_API_TESTS) + ) + + SET(GCC_SANITIZER_COMPILE_FLAGS "-fsanitize=address -fsanitize=undefined -fno-sanitize-recover -fstack-protector-all") +- SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_SANITIZER_COMPILE_FLAGS}" ) ++ SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" ) + SET( CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -static-libasan -static-libubsan" ) + + ADD_EXECUTABLE(${PROJECT_NAME} ${SRC_FILES}) diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/wayland-ivi-extension/wandboard_fix_build.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/wayland-ivi-extension/wandboard_fix_build.patch new file mode 100644 index 000000000..86b448be1 --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/wayland-ivi-extension/wandboard_fix_build.patch @@ -0,0 +1,13 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 3610fa9..8b4614d 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -34,7 +34,7 @@ add_subdirectory(ivi-layermanagement-api/ilmCommon) + add_subdirectory(ivi-layermanagement-api/ilmClient) + add_subdirectory(ivi-layermanagement-api/ilmControl) + add_subdirectory(ivi-layermanagement-api/test) +-add_subdirectory(ivi-layermanagement-examples) ++#add_subdirectory(ivi-layermanagement-examples) + + if(WITH_ILM_INPUT) + add_subdirectory(ivi-input-api/ilmInput) diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/wayland-ivi-extension_1.13.0.bb b/meta-agl-profile-graphical/recipes-graphics/wayland/wayland-ivi-extension_1.13.0.bb new file mode 100644 index 000000000..68e92adb5 --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/wayland-ivi-extension_1.13.0.bb @@ -0,0 +1,33 @@ +SUMMARY = "Wayland IVI Extension" +DESCRIPTION = "GENIVI Layer Management API based on Wayland IVI Extension" +HOMEPAGE = "http://projects.genivi.org/wayland-ivi-extension" +BUGTRACKER = "http://bugs.genivi.org/enter_bug.cgi?product=Wayland%20IVI%20Extension" +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://LICENSE;md5=1f1a56bb2dadf5f2be8eb342acf4ed79" + +SRCREV = "ede33c1c898eeaf673dd2c275e92763a5aabd066" +SRC_URI = "git://github.com/GENIVI/${BPN}.git;protocol=http \ + file://0001-simple-id-agent-initial-commit.patch;patch=1 \ + file://0002-ivi-controller-load-id-agent-module.patch;patch=1 \ + file://0003-ivi-controller-add-resize-setting-suit-to-surface-si.patch \ + file://0001-Resolve-weston-crush-when-repeat-touching-very-quick.patch \ +" +S = "${WORKDIR}/git" + +DEPENDS = "weston virtual/libgles2 pixman wayland-native" + +inherit cmake + +EXTRA_OECMAKE := "-DWITH_ILM_INPUT=1" + +FILES_${PN} += "${libdir}/weston/*" +FILES_${PN}-dbg += "${libdir}/weston/.debug/*" + +EXTRA_OECMAKE += "-DLIB_SUFFIX=${@d.getVar('baselib', True).replace('lib', '')}" + +FILESEXTRAPATHS_prepend := ":${THISDIR}/wayland-ivi-extension:" + +SRC_URI_append_wandboard = " file://wandboard_fix_build.patch" + +# workaround paralellism issue: +PARALLEL_MAKE = "" diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/wayland-ivi-extension_2.0.2.bb b/meta-agl-profile-graphical/recipes-graphics/wayland/wayland-ivi-extension_2.0.2.bb new file mode 100644 index 000000000..ea74e384c --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/wayland-ivi-extension_2.0.2.bb @@ -0,0 +1,31 @@ +SUMMARY = "Wayland IVI Extension" +DESCRIPTION = "GENIVI Layer Management API based on Wayland IVI Extension" +HOMEPAGE = "http://projects.genivi.org/wayland-ivi-extension" +BUGTRACKER = "http://bugs.genivi.org/enter_bug.cgi?product=Wayland%20IVI%20Extension" +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://LICENSE;md5=1f1a56bb2dadf5f2be8eb342acf4ed79" + +SRCREV = "ff067a640451de46836200624ece7ac777977c30" +SRC_URI = "git://github.com/GENIVI/${BPN}.git;branch=2.0;protocol=http \ + " +SRC_URI_append_wandboard = " file://wandboard_fix_build.patch" + +S = "${WORKDIR}/git" + +DEPENDS = "weston virtual/libgles2 pixman wayland-native" + +FILESEXTRAPATHS_prepend := ":${THISDIR}/wayland-ivi-extension:" + +# workaround paralellism issue: +PARALLEL_MAKE = "" + +inherit cmake + +EXTRA_OECMAKE := "-DWITH_ILM_INPUT=1" + +FILES_${PN} += "${libdir}/weston/*" +FILES_${PN} += "${datadir}/wayland-protocols/stable/ivi-application/*" + +FILES_${PN}-dbg += "${libdir}/weston/.debug/*" + +EXTRA_OECMAKE += "-DLIB_SUFFIX=${@d.getVar('baselib', True).replace('lib', '')}" diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/wayland/0001-Change-socket-mode-add-rw-for-group.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/wayland/0001-Change-socket-mode-add-rw-for-group.patch new file mode 100644 index 000000000..b04127b57 --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/wayland/0001-Change-socket-mode-add-rw-for-group.patch @@ -0,0 +1,29 @@ +From 9162f7d4cfeec7103474e8703218b3679ca9ed10 Mon Sep 17 00:00:00 2001 +From: Ronan Le Martret +Date: Tue, 18 Apr 2017 13:53:26 +0200 +Subject: [PATCH] Change socket mode:add rw for group + +Signed-off-by: Ronan Le Martret +--- + src/wayland-server.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/src/wayland-server.c b/src/wayland-server.c +index 64d1bec..313c5a0 100644 +--- a/src/wayland-server.c ++++ b/src/wayland-server.c +@@ -1189,7 +1189,10 @@ _wl_display_add_socket(struct wl_display *display, struct wl_socket *s) + wl_log("bind() failed with error: %m\n"); + return -1; + } +- ++ if (chmod(s->addr.sun_path, 0660) < 0) { ++ wl_log("chmod() failed with error: %m\n"); ++ return -1; ++ } + if (listen(s->fd, 128) < 0) { + wl_log("listen() failed with error: %m\n"); + return -1; +-- +2.6.6 + diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/wayland_%.bbappend b/meta-agl-profile-graphical/recipes-graphics/wayland/wayland_%.bbappend new file mode 100644 index 000000000..7a1a6c6c1 --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/wayland_%.bbappend @@ -0,0 +1,6 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" + +SRC_URI_append = "\ + file://0001-Change-socket-mode-add-rw-for-group.patch \ + " +EXTRA_OECONF_append = " --enable-ivi-shell" diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston-ini-conf.bb b/meta-agl-profile-graphical/recipes-graphics/wayland/weston-ini-conf.bb new file mode 100644 index 000000000..4628f96f8 --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/weston-ini-conf.bb @@ -0,0 +1,30 @@ +SUMMARY = "Startup script and systemd unit file for the Weston Wayland compositor" +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" + +SRC_URI = "file://core.cfg \ + file://ivishell.cfg \ + file://id-agent.cfg \ + file://shell.cfg \ + file://hdmi-a-1-270.cfg \ + " + +S = "${WORKDIR}" + +PACKAGE_ARCH = "${MACHINE_ARCH}" + +do_compile() { + # Put all of our cfg files together. + rm -f ${WORKDIR}/weston.ini + for F in ${WORKDIR}/*.cfg; do + cat $F >> ${WORKDIR}/weston.ini + echo >> ${WORKDIR}/weston.ini + done + sed -i -e '$ d' ${WORKDIR}/weston.ini +} + +do_install_append() { + WESTON_INI_CONFIG=${sysconfdir}/xdg/weston + install -d ${D}${WESTON_INI_CONFIG} + install -m 0644 ${WORKDIR}/weston.ini ${D}${WESTON_INI_CONFIG}/weston.ini +} diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston-ini-conf/core.cfg b/meta-agl-profile-graphical/recipes-graphics/wayland/weston-ini-conf/core.cfg new file mode 100644 index 000000000..a0ec1e181 --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/weston-ini-conf/core.cfg @@ -0,0 +1,4 @@ +[core] +shell=ivi-shell.so +backend=drm-backend.so +require-input=false diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston-ini-conf/hdmi-a-1-270.cfg b/meta-agl-profile-graphical/recipes-graphics/wayland/weston-ini-conf/hdmi-a-1-270.cfg new file mode 100644 index 000000000..dffc2b6dd --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/weston-ini-conf/hdmi-a-1-270.cfg @@ -0,0 +1,6 @@ +# A display is connected to HDMI-A-1 and needs to be rotated 270 degrees +# to have a proper orientation of the homescreen. For example the various sizes +# of the GeChic display or the Dell display. +[output] +name=HDMI-A-1 +transform=270 diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston-ini-conf/hdmi-a-1-90.cfg b/meta-agl-profile-graphical/recipes-graphics/wayland/weston-ini-conf/hdmi-a-1-90.cfg new file mode 100644 index 000000000..88a692a1b --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/weston-ini-conf/hdmi-a-1-90.cfg @@ -0,0 +1,6 @@ +# A display is connected to HDMI-A-1 and needs to be rotated 90 degrees +# to have a proper orientation of the homescreen. For example, the 'eGalax' +# display used in some instances. +[output] +name=HDMI-A-1 +transform=90 diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston-ini-conf/id-agent.cfg b/meta-agl-profile-graphical/recipes-graphics/wayland/weston-ini-conf/id-agent.cfg new file mode 100644 index 000000000..726fca5f1 --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/weston-ini-conf/id-agent.cfg @@ -0,0 +1,2 @@ +[id-agent] +default-id-offset=1000 diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston-ini-conf/ivishell.cfg b/meta-agl-profile-graphical/recipes-graphics/wayland/weston-ini-conf/ivishell.cfg new file mode 100644 index 000000000..f0548f291 --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/weston-ini-conf/ivishell.cfg @@ -0,0 +1,4 @@ +[ivi-shell] +ivi-input-module=ivi-input-controller.so +ivi-module=ivi-controller.so +id-agent-module=simple-id-agent.so diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston-ini-conf/shell.cfg b/meta-agl-profile-graphical/recipes-graphics/wayland/weston-ini-conf/shell.cfg new file mode 100644 index 000000000..056770427 --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/weston-ini-conf/shell.cfg @@ -0,0 +1,3 @@ +[shell] +locking=true +panel-location=none diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston-init.bbappend b/meta-agl-profile-graphical/recipes-graphics/wayland/weston-init.bbappend new file mode 100644 index 000000000..1ca63b5de --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/weston-init.bbappend @@ -0,0 +1,79 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" + +inherit agl-graphical + +WESTONSTART ??= "/usr/bin/weston ${WESTONARGS}" +WESTONSTART_append = " ${@bb.utils.contains("IMAGE_FEATURES", "debug-tweaks", " --log=${DISPLAY_XDG_RUNTIME_DIR}/weston.log", "",d)}" + +SRC_URI += " \ + file://weston_tmpfiles.conf \ + file://weston.service.add \ +" + +do_install_append() { + sed -i "/\[Unit\]/aConflicts=getty@tty${WESTONTTY}.service" \ + ${D}${systemd_system_unitdir}/weston.service + + sed -i "/\[Service\]/r ${S}/weston.service.add" \ + ${D}${systemd_system_unitdir}/weston.service + + if ! grep -q '^Group=' ${D}${systemd_system_unitdir}/weston.service; then + sed -i "/\[Service\]/aGroup=root" ${D}${systemd_system_unitdir}/weston.service + fi + if ! grep -q '^User=' ${D}${systemd_system_unitdir}/weston.service; then + sed -i "/\[Service\]/aUser=root" ${D}${systemd_system_unitdir}/weston.service + fi + + sed -e 's,User=root,User=${WESTONUSER},g' \ + -e 's,Group=root,Group=${WESTONGROUP},g' \ + -e 's,ExecStart=.*,ExecStart=${WESTONSTART},g' \ + -e 's,@WESTONTTY@,${WESTONTTY},g' \ + -e 's,@XDG_RUNTIME_DIR@,${DISPLAY_XDG_RUNTIME_DIR},g' \ + -i ${D}${systemd_system_unitdir}/weston.service + + # Add a rule to ensure the 'display' user has permissions to + # open the graphics device + install -d ${D}${sysconfdir}/init.d + install -d ${D}${sysconfdir}/udev/rules.d + cat >${D}${sysconfdir}/udev/rules.d/zz-dri.rules <<'EOF' +SUBSYSTEM=="drm", MODE="0660", GROUP="${WESTONGROUP}", SECLABEL{smack}="*", TAG+="systemd", ENV{SYSTEMD_WANTS}="weston.service" +EOF + + # user 'display' must own /dev/tty${WESTONTTY} for weston to start correctly + cat >${D}${sysconfdir}/udev/rules.d/zz-tty.rules <<'EOF' +SUBSYSTEM=="tty", KERNEL=="tty${WESTONTTY}", OWNER="${WESTONUSER}", SECLABEL{smack}="^", TAG+="systemd", ENV{SYSTEMD_WANTS}="weston.service" +EOF + + # user 'display' must also be able to access /dev/input/* + cat >${D}${sysconfdir}/udev/rules.d/zz-input.rules <<'EOF' +SUBSYSTEM=="input", MODE="0660", GROUP="input", SECLABEL{smack}="^", TAG+="systemd", ENV{SYSTEMD_WANTS}="weston.service" +EOF + + # user 'display' must also be able to access /dev/media*, etc. + cat >${D}${sysconfdir}/udev/rules.d/zz-remote-display.rules <<'EOF' +SUBSYSTEM=="media", MODE="0660", GROUP="display", SECLABEL{smack}="*", TAG+="systemd", ENV{SYSTEMD_WANTS}="weston.service" +SUBSYSTEM=="video4linux", MODE="0660", GROUP="display", SECLABEL{smack}="*", TAG+="systemd", ENV{SYSTEMD_WANTS}="weston.service" +KERNEL=="uvcs", SUBSYSTEM=="misc", MODE="0660", GROUP="display", SECLABEL{smack}="*" +KERNEL=="rgnmm", SUBSYSTEM=="misc", MODE="0660", GROUP="display", SECLABEL{smack}="*" +EOF + + install -d ${D}${sysconfdir}/tmpfiles.d + install -Dm755 ${WORKDIR}/weston_tmpfiles.conf ${D}/${libdir}/tmpfiles.d/weston.conf + + sed -e 's,@WESTONUSER@,${WESTONUSER},g' \ + -e 's,@WESTONGROUP@,${WESTONGROUP},g' \ + -i ${D}/${libdir}/tmpfiles.d/weston.conf +} + +do_install_append_imx() { + + install -d ${D}${sysconfdir}/udev/rules.d + cat >>${D}${sysconfdir}/udev/rules.d/zz-dri.rules <<'EOF' +SUBSYSTEM=="gpu_class", MODE="0660", GROUP="${WESTONGROUP}", SECLABEL{smack}="*" +EOF + +} + +FILES_${PN} += "${libdir}/tmpfiles.d/*.conf" + + diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston-init/weston.service.add b/meta-agl-profile-graphical/recipes-graphics/wayland/weston-init/weston.service.add new file mode 100644 index 000000000..3596e9c39 --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/weston-init/weston.service.add @@ -0,0 +1,7 @@ +Environment="XDG_RUNTIME_DIR=@XDG_RUNTIME_DIR@" +TTYPath=/dev/tty@WESTONTTY@ +StandardInput=tty +TTYReset=yes +TTYVHangup=yes +TTYVTDisallocate=yes +UtmpIdentifier=tty@WESTONTTY@ diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston-init/weston_tmpfiles.conf b/meta-agl-profile-graphical/recipes-graphics/wayland/weston-init/weston_tmpfiles.conf new file mode 100644 index 000000000..c4b302faf --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/weston-init/weston_tmpfiles.conf @@ -0,0 +1,6 @@ +# This file is distributed to create weston XDG_RUNTIME_DIR (/run/deamon/@WESTONUSER@) +# +# See tmpfiles.d(5) for details + +d /run/platform/ 0775 root root - +d /run/platform/@WESTONUSER@ 0770 @WESTONUSER@ @WESTONGROUP@ - diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0001-Allow-regular-users-to-launch-Weston_2.0.0.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0001-Allow-regular-users-to-launch-Weston_2.0.0.patch new file mode 100644 index 000000000..bd1a72b0f --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0001-Allow-regular-users-to-launch-Weston_2.0.0.patch @@ -0,0 +1,46 @@ +From 6c145cea35f0b77613d6e3f48679c976b9839d7c Mon Sep 17 00:00:00 2001 +From: Ronan Le Martret +Date: Wed, 31 May 2017 22:48:18 +0000 +Subject: [PATCH] Allow regular users to launch Weston + +Signed-off-by: Ronan Le Martret +--- + configure.ac | 6 ++++++ + libweston/launcher-direct.c | 2 ++ + 2 files changed, 8 insertions(+) + +diff --git a/configure.ac b/configure.ac +index 7e84c14..8b3e17e 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -155,6 +155,12 @@ if test x$enable_xkbcommon = xyes; then + true) + fi + ++AC_ARG_ENABLE(sys-uid, [ --enable-sys-uid],, ++ enable_sys_uid=no) ++if test x$enable_sys_uid = xyes; then ++ AC_DEFINE(ENABLE_SYS_UID, [1], [Allow regular users to launch Weston]) ++fi ++ + AC_ARG_ENABLE(setuid-install, [ --enable-setuid-install],, + enable_setuid_install=yes) + AM_CONDITIONAL(ENABLE_SETUID_INSTALL, test x$enable_setuid_install = xyes) +diff --git a/libweston/launcher-direct.c b/libweston/launcher-direct.c +index 4fc1c3c..8f16a69 100644 +--- a/libweston/launcher-direct.c ++++ b/libweston/launcher-direct.c +@@ -275,8 +275,10 @@ launcher_direct_connect(struct weston_launcher **out, struct weston_compositor * + { + struct launcher_direct *launcher; + ++#ifndef ENABLE_SYS_UID + if (geteuid() != 0) + return -EINVAL; ++#endif + + launcher = zalloc(sizeof(*launcher)); + if (launcher == NULL) +-- +2.7.4 + diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0001-ivi-shell-rework-goto-labels-to-avoid-memory-leaks.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0001-ivi-shell-rework-goto-labels-to-avoid-memory-leaks.patch new file mode 100644 index 000000000..449b7a0fd --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0001-ivi-shell-rework-goto-labels-to-avoid-memory-leaks.patch @@ -0,0 +1,66 @@ +index 67619b8f..e9ddf9a4 100644 +--- a/ivi-shell/ivi-shell.c ++++ b/ivi-shell/ivi-shell.c +@@ -497,44 +497,53 @@ wet_shell_init(struct weston_compositor *compositor, + { + struct ivi_shell *shell; + struct ivi_shell_setting setting = { }; +- int retval = -1; + + shell = zalloc(sizeof *shell); + if (shell == NULL) + return -1; + + if (ivi_shell_setting_create(&setting, compositor, argc, argv) != 0) +- return -1; ++ goto err_shell; + + init_ivi_shell(compositor, shell, &setting); ++ /* TODO deinit_ivi_shell should be implemented, since init_ivi_shell is ++ * initializing multiple lists. */ + + shell->destroy_listener.notify = shell_destroy; + wl_signal_add(&compositor->destroy_signal, &shell->destroy_listener); + + if (input_panel_setup(shell) < 0) +- goto out_settings; ++ goto err_settings; + + shell->text_backend = text_backend_init(compositor); + if (!shell->text_backend) +- goto out_settings; ++ goto err_settings; + + if (wl_global_create(compositor->wl_display, + &ivi_application_interface, 1, + shell, bind_ivi_application) == NULL) +- goto out_settings; ++ goto err_text_backend; + + ivi_layout_init_with_compositor(compositor); ++ /* TODO ivi_layout_destroy should be implemented, since multiple lists ++ * and signals are initialized.*/ + shell_add_bindings(compositor, shell); + + /* Call module_init of ivi-modules which are defined in weston.ini */ + if (load_controller_modules(compositor, setting.ivi_module, + argc, argv) < 0) +- goto out_settings; ++ goto err_text_backend; ++ ++ return IVI_SUCCEEDED; + +- retval = 0; ++err_text_backend: ++ text_backend_destroy(shell->text_backend); + +-out_settings: ++err_settings: + free(setting.ivi_module); + +- return retval; ++err_shell: ++ free(shell); ++ ++ return IVI_FAILED; + } diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0002-ivi-shell-removed-assert.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0002-ivi-shell-removed-assert.patch new file mode 100644 index 000000000..4507e769c --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0002-ivi-shell-removed-assert.patch @@ -0,0 +1,11 @@ +index e9ddf9a4..f3156d35 100644 +--- a/ivi-shell/ivi-shell.c ++++ b/ivi-shell/ivi-shell.c +@@ -114,7 +114,6 @@ shell_surface_send_configure(struct weston_surface *surface, + struct ivi_shell_surface *shsurf; + + shsurf = get_ivi_shell_surface(surface); +- assert(shsurf); + if (!shsurf) + return; + diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0003-ivi-shell-introduction-of-IVI_INVALID_ID.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0003-ivi-shell-introduction-of-IVI_INVALID_ID.patch new file mode 100644 index 000000000..6f683ca92 --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0003-ivi-shell-introduction-of-IVI_INVALID_ID.patch @@ -0,0 +1,18 @@ +index 2317d6e9..e1e897ed 100644 +--- a/ivi-shell/ivi-layout-export.h ++++ b/ivi-shell/ivi-layout-export.h +@@ -56,12 +56,14 @@ extern "C" { + #endif /* __cplusplus */ + + #include ++#include + + #include "stdbool.h" + #include "compositor.h" + + #define IVI_SUCCEEDED (0) + #define IVI_FAILED (-1) ++#define IVI_INVALID_ID UINT_MAX + + struct ivi_layout_layer; + struct ivi_layout_screen; diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0004-layout-interface-added-interface-to-change-surface-id.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0004-layout-interface-added-interface-to-change-surface-id.patch new file mode 100644 index 000000000..6401c5b81 --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0004-layout-interface-added-interface-to-change-surface-id.patch @@ -0,0 +1,73 @@ +index e1e897ed..5b1f12f0 100644 +--- a/ivi-shell/ivi-layout-export.h ++++ b/ivi-shell/ivi-layout-export.h +@@ -320,6 +320,12 @@ struct ivi_layout_interface { + struct ivi_layout_surface *ivisurf, + uint32_t duration); + ++ /** ++ * \brief set id of ivi_layout_surface ++ */ ++ int32_t (*surface_set_id)(struct ivi_layout_surface *ivisurf, ++ uint32_t id_surface); ++ + /** + * layer controller interface + */ +diff --git a/ivi-shell/ivi-layout.c b/ivi-shell/ivi-layout.c +index 298e18ea..fa8e75f6 100644 +--- a/ivi-shell/ivi-layout.c ++++ b/ivi-shell/ivi-layout.c +@@ -1901,6 +1901,44 @@ ivi_layout_surface_set_transition_duration(struct ivi_layout_surface *ivisurf, + return 0; + } + ++/* ++ * This interface enables e.g. an id agent to set the id of an ivi-layout ++ * surface, that has been created by a desktop application. This can only be ++ * done once as long as the initial surface id equals IVI_INVALID_ID. Afterwards ++ * two events are emitted, namely surface_created and surface_configured. ++ */ ++static int32_t ++ivi_layout_surface_set_id(struct ivi_layout_surface *ivisurf, ++ uint32_t id_surface) ++{ ++ struct ivi_layout *layout = get_instance(); ++ struct ivi_layout_surface *search_ivisurf = NULL; ++ ++ if (!ivisurf) { ++ weston_log("%s: invalid argument\n", __func__); ++ return IVI_FAILED; ++ } ++ ++ if (ivisurf->id_surface != IVI_INVALID_ID) { ++ weston_log("surface id can only be set once\n"); ++ return IVI_FAILED; ++ } ++ ++ search_ivisurf = get_surface(&layout->surface_list, id_surface); ++ if (search_ivisurf) { ++ weston_log("id_surface(%d) is already created\n", id_surface); ++ return IVI_FAILED; ++ } ++ ++ ivisurf->id_surface = id_surface; ++ ++ wl_signal_emit(&layout->surface_notification.created, ivisurf); ++ wl_signal_emit(&layout->surface_notification.configure_changed, ++ ivisurf); ++ ++ return IVI_SUCCEEDED; ++} ++ + static int32_t + ivi_layout_surface_set_transition(struct ivi_layout_surface *ivisurf, + enum ivi_layout_transition_type type, +@@ -2058,6 +2096,7 @@ static struct ivi_layout_interface ivi_layout_interface = { + .surface_get_weston_surface = ivi_layout_surface_get_weston_surface, + .surface_set_transition = ivi_layout_surface_set_transition, + .surface_set_transition_duration = ivi_layout_surface_set_transition_duration, ++ .surface_set_id = ivi_layout_surface_set_id, + + /** + * layer controller interfaces diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0005-ivi-layout-introcuded-configure_desktop_changed.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0005-ivi-layout-introcuded-configure_desktop_changed.patch new file mode 100644 index 000000000..ddd949e35 --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0005-ivi-layout-introcuded-configure_desktop_changed.patch @@ -0,0 +1,74 @@ +index 5b1f12f0..dd0997aa 100644 +--- a/ivi-shell/ivi-layout-export.h ++++ b/ivi-shell/ivi-layout-export.h +@@ -187,6 +187,16 @@ struct ivi_layout_interface { + */ + int32_t (*add_listener_configure_surface)(struct wl_listener *listener); + ++ /** ++ * \brief add a listener for notification when desktop_surface is configured ++ * ++ * When an desktop_surface is configured, a signal is emitted ++ * to the listening controller plugins. ++ * The pointer of the configured desktop_surface is sent as the void *data argument ++ * to the wl_listener::notify callback function of the listener. ++ */ ++ int32_t (*add_listener_configure_desktop_surface)(struct wl_listener *listener); ++ + /** + * \brief Get all ivi_surfaces which are currently registered and managed + * by the services +diff --git a/ivi-shell/ivi-layout-private.h b/ivi-shell/ivi-layout-private.h +index 2b8bd472..fe5be01a 100644 +--- a/ivi-shell/ivi-layout-private.h ++++ b/ivi-shell/ivi-layout-private.h +@@ -104,6 +104,7 @@ struct ivi_layout { + struct wl_signal created; + struct wl_signal removed; + struct wl_signal configure_changed; ++ struct wl_signal configure_desktop_changed; + } surface_notification; + + struct weston_layer layout_layer; +diff --git a/ivi-shell/ivi-layout.c b/ivi-shell/ivi-layout.c +index fa8e75f6..690af742 100644 +--- a/ivi-shell/ivi-layout.c ++++ b/ivi-shell/ivi-layout.c +@@ -1040,6 +1040,21 @@ ivi_layout_add_listener_configure_surface(struct wl_listener *listener) + return IVI_SUCCEEDED; + } + ++static int32_t ++ivi_layout_add_listener_configure_desktop_surface(struct wl_listener *listener) ++{ ++ struct ivi_layout *layout = get_instance(); ++ ++ if (!listener) { ++ weston_log("ivi_layout_add_listener_configure_desktop_surface: invalid argument\n"); ++ return IVI_FAILED; ++ } ++ ++ wl_signal_add(&layout->surface_notification.configure_desktop_changed, listener); ++ ++ return IVI_SUCCEEDED; ++} ++ + uint32_t + ivi_layout_get_id_of_surface(struct ivi_layout_surface *ivisurf) + { +@@ -2057,6 +2072,7 @@ ivi_layout_init_with_compositor(struct weston_compositor *ec) + wl_signal_init(&layout->surface_notification.created); + wl_signal_init(&layout->surface_notification.removed); + wl_signal_init(&layout->surface_notification.configure_changed); ++ wl_signal_init(&layout->surface_notification.configure_desktop_changed); + + /* Add layout_layer at the last of weston_compositor.layer_list */ + weston_layer_init(&layout->layout_layer, ec); +@@ -2081,6 +2097,7 @@ static struct ivi_layout_interface ivi_layout_interface = { + .add_listener_create_surface = ivi_layout_add_listener_create_surface, + .add_listener_remove_surface = ivi_layout_add_listener_remove_surface, + .add_listener_configure_surface = ivi_layout_add_listener_configure_surface, ++ .add_listener_configure_desktop_surface = ivi_layout_add_listener_configure_desktop_surface, + .get_surface = shell_get_ivi_layout_surface, + .get_surfaces = ivi_layout_get_surfaces, + .get_id_of_surface = ivi_layout_get_id_of_surface, diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0006-ivi-layout-introcuded-surface_create_and_configure.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0006-ivi-layout-introcuded-surface_create_and_configure.patch new file mode 100644 index 000000000..04461a1d4 --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0006-ivi-layout-introcuded-surface_create_and_configure.patch @@ -0,0 +1,117 @@ +index 68ca68ba..c86cbb11 100644 +--- a/ivi-shell/ivi-layout-shell.h ++++ b/ivi-shell/ivi-layout-shell.h +@@ -39,6 +39,14 @@ struct weston_view; + struct weston_surface; + struct ivi_layout_surface; + ++void ++ivi_layout_desktop_surface_configure(struct ivi_layout_surface *ivisurf, ++ int32_t width, int32_t height); ++ ++struct ivi_layout_surface* ++ivi_layout_desktop_surface_create(struct weston_surface *wl_surface, ++ uint32_t id_surface); ++ + void + ivi_layout_surface_configure(struct ivi_layout_surface *ivisurf, + int32_t width, int32_t height); +diff --git a/ivi-shell/ivi-layout.c b/ivi-shell/ivi-layout.c +index 690af742..086d0fd2 100644 +--- a/ivi-shell/ivi-layout.c ++++ b/ivi-shell/ivi-layout.c +@@ -1995,20 +1995,8 @@ ivi_layout_surface_dump(struct weston_surface *surface, + * methods of interaction between ivi-shell with ivi-layout + */ + +-void +-ivi_layout_surface_configure(struct ivi_layout_surface *ivisurf, +- int32_t width, int32_t height) +-{ +- struct ivi_layout *layout = get_instance(); +- +- /* emit callback which is set by ivi-layout api user */ +- wl_signal_emit(&layout->surface_notification.configure_changed, +- ivisurf); +-} +- +-struct ivi_layout_surface* +-ivi_layout_surface_create(struct weston_surface *wl_surface, +- uint32_t id_surface) ++static struct ivi_layout_surface* ++surface_create(struct weston_surface *wl_surface, uint32_t id_surface) + { + struct ivi_layout *layout = get_instance(); + struct ivi_layout_surface *ivisurf = NULL; +@@ -2018,14 +2006,6 @@ ivi_layout_surface_create(struct weston_surface *wl_surface, + return NULL; + } + +- ivisurf = get_surface(&layout->surface_list, id_surface); +- if (ivisurf != NULL) { +- if (ivisurf->surface != NULL) { +- weston_log("id_surface(%d) is already created\n", id_surface); +- return NULL; +- } +- } +- + ivisurf = calloc(1, sizeof *ivisurf); + if (ivisurf == NULL) { + weston_log("fails to allocate memory\n"); +@@ -2049,7 +2029,55 @@ ivi_layout_surface_create(struct weston_surface *wl_surface, + + wl_list_insert(&layout->surface_list, &ivisurf->link); + +- wl_signal_emit(&layout->surface_notification.created, ivisurf); ++ return ivisurf; ++} ++ ++void ++ivi_layout_desktop_surface_configure(struct ivi_layout_surface *ivisurf, ++ int32_t width, int32_t height) ++{ ++ struct ivi_layout *layout = get_instance(); ++ ++ /* emit callback which is set by ivi-layout api user */ ++ wl_signal_emit(&layout->surface_notification.configure_desktop_changed, ++ ivisurf); ++} ++ ++struct ivi_layout_surface* ++ivi_layout_desktop_surface_create(struct weston_surface *wl_surface, ++ uint32_t id_surface) ++{ ++ return surface_create(wl_surface, id_surface); ++} ++ ++void ++ivi_layout_surface_configure(struct ivi_layout_surface *ivisurf, ++ int32_t width, int32_t height) ++{ ++ struct ivi_layout *layout = get_instance(); ++ ++ /* emit callback which is set by ivi-layout api user */ ++ wl_signal_emit(&layout->surface_notification.configure_changed, ++ ivisurf); ++} ++ ++struct ivi_layout_surface* ++ivi_layout_surface_create(struct weston_surface *wl_surface, ++ uint32_t id_surface) ++{ ++ struct ivi_layout *layout = get_instance(); ++ struct ivi_layout_surface *ivisurf = NULL; ++ ++ ivisurf = get_surface(&layout->surface_list, id_surface); ++ if (ivisurf) { ++ weston_log("id_surface(%d) is already created\n", id_surface); ++ return NULL; ++ } ++ ++ ivisurf = surface_create(wl_surface, id_surface); ++ ++ if (ivisurf) ++ wl_signal_emit(&layout->surface_notification.created, ivisurf); + + return ivisurf; + } diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0007-ivi-shell-linked-libweston-desktop-and-added-structs.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0007-ivi-shell-linked-libweston-desktop-and-added-structs.patch new file mode 100644 index 000000000..9286ba00b --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0007-ivi-shell-linked-libweston-desktop-and-added-structs.patch @@ -0,0 +1,74 @@ +diff --git a/Makefile.am b/Makefile.am +index cdf82ab4..d990d400 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -993,6 +993,7 @@ ivi_shell_la_LDFLAGS = -module -avoid-version + ivi_shell_la_LIBADD = \ + libshared.la \ + libweston-@LIBWESTON_MAJOR@.la \ ++ libweston-desktop-@LIBWESTON_MAJOR@.la \ + $(COMPOSITOR_LIBS) + ivi_shell_la_CFLAGS = $(AM_CFLAGS) $(COMPOSITOR_CFLAGS) + ivi_shell_la_SOURCES = \ +diff --git a/ivi-shell/ivi-layout-private.h b/ivi-shell/ivi-layout-private.h +index fe5be01a..c054130b 100644 +--- a/ivi-shell/ivi-layout-private.h ++++ b/ivi-shell/ivi-layout-private.h +@@ -30,6 +30,7 @@ + + #include "compositor.h" + #include "ivi-layout-export.h" ++#include "libweston-desktop/libweston-desktop.h" + + struct ivi_layout_view { + struct wl_list link; /* ivi_layout::view_list */ +@@ -52,6 +53,7 @@ struct ivi_layout_surface { + + struct ivi_layout *layout; + struct weston_surface *surface; ++ struct weston_desktop_surface *weston_desktop_surface; + + struct ivi_layout_surface_properties prop; + +diff --git a/ivi-shell/ivi-shell.c b/ivi-shell/ivi-shell.c +index f3156d35..84db2c97 100644 +--- a/ivi-shell/ivi-shell.c ++++ b/ivi-shell/ivi-shell.c +@@ -44,7 +44,7 @@ + + #include "ivi-shell.h" + #include "ivi-application-server-protocol.h" +-#include "ivi-layout-export.h" ++#include "ivi-layout-private.h" + #include "ivi-layout-shell.h" + #include "shared/helpers.h" + #include "compositor/weston.h" +@@ -271,6 +271,8 @@ application_surface_create(struct wl_client *client, + return; + } + ++ layout_surface->weston_desktop_surface = NULL; ++ + ivisurf = zalloc(sizeof *ivisurf); + if (ivisurf == NULL) { + wl_resource_post_no_memory(resource); +diff --git a/ivi-shell/ivi-shell.h b/ivi-shell/ivi-shell.h +index e35f75f2..be430853 100644 +--- a/ivi-shell/ivi-shell.h ++++ b/ivi-shell/ivi-shell.h +@@ -30,6 +30,7 @@ + #include + + #include "compositor.h" ++#include "libweston-desktop/libweston-desktop.h" + + struct ivi_shell + { +@@ -37,6 +38,7 @@ struct ivi_shell + + struct weston_compositor *compositor; + ++ struct weston_desktop *desktop; + struct wl_list ivi_surface_list; /* struct ivi_shell_surface::link */ + + struct text_backend *text_backend; diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0008-ivi-layout-use-libweston-desktop-api-for-views.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0008-ivi-layout-use-libweston-desktop-api-for-views.patch new file mode 100644 index 000000000..e53a8c458 --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0008-ivi-layout-use-libweston-desktop-api-for-views.patch @@ -0,0 +1,30 @@ +index 086d0fd2..6b854503 100644 +--- a/ivi-shell/ivi-layout.c ++++ b/ivi-shell/ivi-layout.c +@@ -153,7 +153,10 @@ ivi_view_destroy(struct ivi_layout_view *ivi_view) + wl_list_remove(&ivi_view->pending_link); + wl_list_remove(&ivi_view->order_link); + +- weston_view_destroy(ivi_view->view); ++ if (weston_surface_is_desktop_surface(ivi_view->ivisurf->surface)) ++ weston_desktop_surface_unlink_view(ivi_view->view); ++ else ++ weston_view_destroy(ivi_view->view); + + free(ivi_view); + } +@@ -170,7 +173,13 @@ ivi_view_create(struct ivi_layout_layer *ivilayer, + return NULL; + } + +- ivi_view->view = weston_view_create(ivisurf->surface); ++ if (weston_surface_is_desktop_surface(ivisurf->surface)) { ++ ivi_view->view = weston_desktop_surface_create_view( ++ ivisurf->weston_desktop_surface); ++ } else { ++ ivi_view->view = weston_view_create(ivisurf->surface); ++ } ++ + if (ivi_view->view == NULL) { + weston_log("fails to allocate memory\n"); + free(ivi_view); diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0009-ivi-shell-added-libweston-desktop-api_implementation.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0009-ivi-shell-added-libweston-desktop-api_implementation.patch new file mode 100644 index 000000000..6a72f15d8 --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0009-ivi-shell-added-libweston-desktop-api_implementation.patch @@ -0,0 +1,166 @@ +index 84db2c97..e797e4f9 100644 +--- a/ivi-shell/ivi-shell.c ++++ b/ivi-shell/ivi-shell.c +@@ -489,6 +489,162 @@ shell_add_bindings(struct weston_compositor *compositor, + shell); + } + ++/* ++ * libweston-desktop ++ */ ++ ++static void ++desktop_surface_ping_timeout(struct weston_desktop_client *client, ++ void *user_data) ++{ ++ weston_log("ivi-shell: desktop_surface_ping_timeout is not supported\n"); ++} ++ ++static void ++desktop_surface_pong(struct weston_desktop_client *client, ++ void *user_data) ++{ ++ weston_log("ivi-shell: desktop_surface_pong is not supported\n"); ++} ++ ++static void ++desktop_surface_added(struct weston_desktop_surface *surface, ++ void *user_data) ++{ ++ struct ivi_shell *shell = (struct ivi_shell *) user_data; ++ struct ivi_layout_surface *layout_surface; ++ struct ivi_shell_surface *ivisurf; ++ struct weston_surface *weston_surf = ++ weston_desktop_surface_get_surface(surface); ++ ++ layout_surface = ivi_layout_desktop_surface_create(weston_surf, ++ IVI_INVALID_ID); ++ if (!layout_surface) { ++ return; ++ } ++ ++ layout_surface->weston_desktop_surface = surface; ++ ++ ivisurf = zalloc(sizeof *ivisurf); ++ if (!ivisurf) { ++ return; ++ } ++ ++ ivisurf->shell = shell; ++ ivisurf->id_surface = IVI_INVALID_ID; ++ ++ ivisurf->width = 0; ++ ivisurf->height = 0; ++ ivisurf->layout_surface = layout_surface; ++ ivisurf->surface = weston_surf; ++ ++ weston_desktop_surface_set_user_data(surface, ivisurf); ++} ++ ++static void ++desktop_surface_removed(struct weston_desktop_surface *surface, ++ void *user_data) ++{ ++ struct ivi_shell_surface *ivisurf = (struct ivi_shell_surface *) ++ weston_desktop_surface_get_user_data(surface); ++ ++ assert(ivisurf != NULL); ++ ++ if (ivisurf->layout_surface) ++ layout_surface_cleanup(ivisurf); ++} ++ ++static void ++desktop_surface_committed(struct weston_desktop_surface *surface, ++ int32_t sx, int32_t sy, void *user_data) ++{ ++ struct ivi_shell_surface *ivisurf = (struct ivi_shell_surface *) ++ weston_desktop_surface_get_user_data(surface); ++ struct weston_surface *weston_surf = ++ weston_desktop_surface_get_surface(surface); ++ ++ if(!ivisurf) ++ return; ++ ++ if (weston_surf->width == 0 || weston_surf->height == 0) ++ return; ++ ++ if (ivisurf->width != weston_surf->width || ++ ivisurf->height != weston_surf->height) { ++ ivisurf->width = weston_surf->width; ++ ivisurf->height = weston_surf->height; ++ ++ ivi_layout_desktop_surface_configure(ivisurf->layout_surface, ++ weston_surf->width, ++ weston_surf->height); ++ } ++} ++ ++static void ++desktop_surface_move(struct weston_desktop_surface *surface, ++ struct weston_seat *seat, uint32_t serial, void *user_data) ++{ ++ weston_log("ivi-shell: desktop_surface_move is not supported\n"); ++} ++ ++static void ++desktop_surface_resize(struct weston_desktop_surface *surface, ++ struct weston_seat *seat, uint32_t serial, ++ enum weston_desktop_surface_edge edges, void *user_data) ++{ ++ weston_log("ivi-shell: desktop_surface_resize is not supported\n"); ++} ++ ++static void ++desktop_surface_fullscreen_requested(struct weston_desktop_surface *surface, ++ bool fullscreen, ++ struct weston_output *output, ++ void *user_data) ++{ ++ weston_log("ivi-shell: desktop_surface_fullscreen_requested is not supported\n"); ++} ++ ++static void ++desktop_surface_maximized_requested(struct weston_desktop_surface *surface, ++ bool maximized, void *user_data) ++{ ++ weston_log("ivi-shell: desktop_surface_maximized_requested is not supported\n"); ++} ++ ++static void ++desktop_surface_minimized_requested(struct weston_desktop_surface *surface, ++ void *user_data) ++{ ++ weston_log("ivi-shell: desktop_surface_minimized_requested is not supported\n"); ++} ++ ++static void ++desktop_surface_set_xwayland_position(struct weston_desktop_surface *surface, ++ int32_t x, int32_t y, void *user_data) ++{ ++ weston_log("ivi-shell: desktop_surface_set_xwayland_position is not supported\n"); ++} ++ ++static const struct weston_desktop_api shell_desktop_api = { ++ .struct_size = sizeof(struct weston_desktop_api), ++ .ping_timeout = desktop_surface_ping_timeout, ++ .pong = desktop_surface_pong, ++ .surface_added = desktop_surface_added, ++ .surface_removed = desktop_surface_removed, ++ .committed = desktop_surface_committed, ++ ++ .move = desktop_surface_move, ++ .resize = desktop_surface_resize, ++ .fullscreen_requested = desktop_surface_fullscreen_requested, ++ .maximized_requested = desktop_surface_maximized_requested, ++ .minimized_requested = desktop_surface_minimized_requested, ++ .set_xwayland_position = desktop_surface_set_xwayland_position, ++}; ++ ++/* ++ * end of libweston-desktop ++ */ ++ + /* + * Initialization of ivi-shell. + */ diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0010-ivi-shell-remove-surface_destroy_listener.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0010-ivi-shell-remove-surface_destroy_listener.patch new file mode 100644 index 000000000..b76c35d4f --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0010-ivi-shell-remove-surface_destroy_listener.patch @@ -0,0 +1,24 @@ +index e797e4f9..5f64e72d 100644 +--- a/ivi-shell/ivi-shell.c ++++ b/ivi-shell/ivi-shell.c +@@ -162,6 +162,10 @@ layout_surface_cleanup(struct ivi_shell_surface *ivisurf) + { + assert(ivisurf->layout_surface != NULL); + ++ /* destroy weston_surface destroy signal. */ ++ if (!ivisurf->layout_surface->weston_desktop_surface) ++ wl_list_remove(&ivisurf->surface_destroy_listener.link); ++ + ivi_layout_surface_destroy(ivisurf->layout_surface); + ivisurf->layout_surface = NULL; + +@@ -169,9 +173,6 @@ layout_surface_cleanup(struct ivi_shell_surface *ivisurf) + ivisurf->surface->committed_private = NULL; + weston_surface_set_label_func(ivisurf->surface, NULL); + ivisurf->surface = NULL; +- +- // destroy weston_surface destroy signal. +- wl_list_remove(&ivisurf->surface_destroy_listener.link); + } + + /* diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0011-ivi-shell-create-weston-desktop-in_wet_shell_init.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0011-ivi-shell-create-weston-desktop-in_wet_shell_init.patch new file mode 100644 index 000000000..551e449ad --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0011-ivi-shell-create-weston-desktop-in_wet_shell_init.patch @@ -0,0 +1,34 @@ +index 5f64e72d..dc8e6f1d 100644 +--- a/ivi-shell/ivi-shell.c ++++ b/ivi-shell/ivi-shell.c +@@ -677,10 +677,14 @@ wet_shell_init(struct weston_compositor *compositor, + if (!shell->text_backend) + goto err_settings; + ++ shell->desktop = weston_desktop_create(compositor, &shell_desktop_api, shell); ++ if (!shell->desktop) ++ goto err_text_backend; ++ + if (wl_global_create(compositor->wl_display, + &ivi_application_interface, 1, + shell, bind_ivi_application) == NULL) +- goto err_text_backend; ++ goto err_desktop; + + ivi_layout_init_with_compositor(compositor); + /* TODO ivi_layout_destroy should be implemented, since multiple lists +@@ -690,10 +694,13 @@ wet_shell_init(struct weston_compositor *compositor, + /* Call module_init of ivi-modules which are defined in weston.ini */ + if (load_controller_modules(compositor, setting.ivi_module, + argc, argv) < 0) +- goto err_text_backend; ++ goto err_desktop; + + return IVI_SUCCEEDED; + ++err_desktop: ++ weston_desktop_destroy(shell->desktop); ++ + err_text_backend: + text_backend_destroy(shell->text_backend); + diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0012-hmi-controller-register-for-desktop_surface_configured.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0012-hmi-controller-register-for-desktop_surface_configured.patch new file mode 100644 index 000000000..c5d85bb17 --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0012-hmi-controller-register-for-desktop_surface_configured.patch @@ -0,0 +1,133 @@ +index d5403e06..7b2f2707 100644 +--- a/ivi-shell/hmi-controller.c ++++ b/ivi-shell/hmi-controller.c +@@ -129,9 +129,9 @@ struct hmi_controller { + struct weston_compositor *compositor; + struct wl_listener destroy_listener; + +- struct wl_listener surface_created; + struct wl_listener surface_removed; + struct wl_listener surface_configured; ++ struct wl_listener desktop_surface_configured; + + struct wl_client *user_interface; + struct ui_setting ui_setting; +@@ -581,28 +581,6 @@ create_layer(struct weston_output *output, + /** + * Internal set notification + */ +-static void +-set_notification_create_surface(struct wl_listener *listener, void *data) +-{ +- struct hmi_controller *hmi_ctrl = +- wl_container_of(listener, hmi_ctrl, +- surface_created); +- struct ivi_layout_surface *ivisurf = data; +- struct hmi_controller_layer *layer_link = +- wl_container_of(hmi_ctrl->application_layer_list.prev, +- layer_link, +- link); +- struct ivi_layout_layer *application_layer = layer_link->ivilayer; +- int32_t ret = 0; +- +- /* skip ui widgets */ +- if (is_surf_in_ui_widget(hmi_ctrl, ivisurf)) +- return; +- +- ret = ivi_layout_interface->layer_add_surface(application_layer, ivisurf); +- assert(!ret); +-} +- + static void + set_notification_remove_surface(struct wl_listener *listener, void *data) + { +@@ -670,6 +648,42 @@ set_notification_configure_surface(struct wl_listener *listener, void *data) + switch_mode(hmi_ctrl, hmi_ctrl->layout_mode); + } + ++static void ++set_notification_configure_desktop_surface(struct wl_listener *listener, void *data) ++{ ++ struct hmi_controller *hmi_ctrl = ++ wl_container_of(listener, hmi_ctrl, ++ desktop_surface_configured); ++ struct ivi_layout_surface *ivisurf = data; ++ struct hmi_controller_layer *layer_link = ++ wl_container_of(hmi_ctrl->application_layer_list.prev, ++ layer_link, ++ link); ++ struct ivi_layout_layer *application_layer = layer_link->ivilayer; ++ struct weston_surface *surface; ++ int32_t ret = 0; ++ ++ /* skip ui widgets */ ++ if (is_surf_in_ui_widget(hmi_ctrl, ivisurf)) ++ return; ++ ++ ret = ivi_layout_interface->layer_add_surface(application_layer, ivisurf); ++ assert(!ret); ++ ++ /* ++ * if application changes size of wl_buffer. The source rectangle shall be ++ * fit to the size. ++ */ ++ surface = ivi_layout_interface->surface_get_weston_surface(ivisurf); ++ if (surface) { ++ ivi_layout_interface->surface_set_source_rectangle(ivisurf, 0, ++ 0, surface->width, surface->height); ++ } ++ ++ ivi_layout_interface->commit_changes(); ++ switch_mode(hmi_ctrl, hmi_ctrl->layout_mode); ++} ++ + /** + * A hmi_controller used 4 ivi_layers to manage ivi_surfaces. The IDs of + * corresponding ivi_layer are defined in weston.ini. Default scene graph +@@ -852,6 +866,9 @@ hmi_controller_create(struct weston_compositor *ec) + hmi_ctrl->surface_configured.notify = set_notification_configure_surface; + ivi_layout_interface->add_listener_configure_surface(&hmi_ctrl->surface_configured); + ++ hmi_ctrl->desktop_surface_configured.notify = set_notification_configure_desktop_surface; ++ ivi_layout_interface->add_listener_configure_desktop_surface(&hmi_ctrl->desktop_surface_configured); ++ + hmi_ctrl->destroy_listener.notify = hmi_controller_destroy; + wl_signal_add(&hmi_ctrl->compositor->destroy_signal, + &hmi_ctrl->destroy_listener); +@@ -1275,13 +1292,6 @@ ivi_hmi_controller_UI_ready(struct wl_client *client, + ivi_layout_interface->commit_changes(); + + ivi_hmi_controller_add_launchers(hmi_ctrl, 256); +- +- /* Add surface_created listener after the initialization of launchers. +- * Otherwise, surfaces of the launchers will be added to application +- * layer too.*/ +- hmi_ctrl->surface_created.notify = set_notification_create_surface; +- ivi_layout_interface->add_listener_create_surface(&hmi_ctrl->surface_created); +- + hmi_ctrl->is_initialized = 1; + } + +diff --git a/ivi-shell/ivi-layout.c b/ivi-shell/ivi-layout.c +index 6b854503..22d63708 100644 +--- a/ivi-shell/ivi-layout.c ++++ b/ivi-shell/ivi-layout.c +@@ -787,9 +787,15 @@ commit_surface_list(struct ivi_layout *layout) + ivisurf->pending.prop.transition_type = IVI_LAYOUT_TRANSITION_NONE; + + if (configured && !is_surface_transition(ivisurf)) { +- shell_surface_send_configure(ivisurf->surface, +- ivisurf->prop.dest_width, +- ivisurf->prop.dest_height); ++ if (ivisurf->weston_desktop_surface) { ++ weston_desktop_surface_set_size(ivisurf->weston_desktop_surface, ++ ivisurf->prop.dest_width, ++ ivisurf->prop.dest_height); ++ } else { ++ shell_surface_send_configure(ivisurf->surface, ++ ivisurf->prop.dest_width, ++ ivisurf->prop.dest_height); ++ } + } + } else { + configured = 0; diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0013-simple-egl-remove-ivi-application-support.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0013-simple-egl-remove-ivi-application-support.patch new file mode 100644 index 000000000..8094f9b85 --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0013-simple-egl-remove-ivi-application-support.patch @@ -0,0 +1,164 @@ +index 23f79dfe..f9c8010b 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -616,9 +616,7 @@ demo_clients += weston-simple-egl + weston_simple_egl_SOURCES = clients/simple-egl.c + nodist_weston_simple_egl_SOURCES = \ + protocol/xdg-shell-unstable-v6-protocol.c \ +- protocol/xdg-shell-unstable-v6-client-protocol.h \ +- protocol/ivi-application-protocol.c \ +- protocol/ivi-application-client-protocol.h ++ protocol/xdg-shell-unstable-v6-client-protocol.h + weston_simple_egl_CFLAGS = $(AM_CFLAGS) $(SIMPLE_EGL_CLIENT_CFLAGS) + weston_simple_egl_LDADD = $(SIMPLE_EGL_CLIENT_LIBS) -lm + endif +diff --git a/clients/simple-egl.c b/clients/simple-egl.c +index dad0f09b..07e7e785 100644 +--- a/clients/simple-egl.c ++++ b/clients/simple-egl.c +@@ -45,8 +45,6 @@ + #include "xdg-shell-unstable-v6-client-protocol.h" + #include + #include +-#include "ivi-application-client-protocol.h" +-#define IVI_SURFACE_ID 9000 + + #include "shared/helpers.h" + #include "shared/platform.h" +@@ -74,7 +72,6 @@ struct display { + EGLConfig conf; + } egl; + struct window *window; +- struct ivi_application *ivi_application; + + PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC swap_buffers_with_damage; + }; +@@ -97,7 +94,6 @@ struct window { + struct wl_surface *surface; + struct zxdg_surface_v6 *xdg_surface; + struct zxdg_toplevel_v6 *xdg_toplevel; +- struct ivi_surface *ivi_surface; + EGLSurface egl_surface; + struct wl_callback *callback; + int fullscreen, opaque, buffer_size, frame_sync, delay; +@@ -355,27 +351,22 @@ static const struct zxdg_toplevel_v6_listener xdg_toplevel_listener = { + }; + + static void +-handle_ivi_surface_configure(void *data, struct ivi_surface *ivi_surface, +- int32_t width, int32_t height) ++create_surface(struct window *window) + { +- struct window *window = data; +- +- wl_egl_window_resize(window->native, width, height, 0, 0); +- +- window->geometry.width = width; +- window->geometry.height = height; ++ struct display *display = window->display; ++ EGLBoolean ret; + +- if (!window->fullscreen) +- window->window_size = window->geometry; +-} ++ window->surface = wl_compositor_create_surface(display->compositor); + +-static const struct ivi_surface_listener ivi_surface_listener = { +- handle_ivi_surface_configure, +-}; ++ window->native = ++ wl_egl_window_create(window->surface, ++ window->geometry.width, ++ window->geometry.height); ++ window->egl_surface = ++ weston_platform_create_egl_surface(display->egl.dpy, ++ display->egl.conf, ++ window->native, NULL); + +-static void +-create_xdg_surface(struct window *window, struct display *display) +-{ + window->xdg_surface = zxdg_shell_v6_get_xdg_surface(display->shell, + window->surface); + zxdg_surface_v6_add_listener(window->xdg_surface, +@@ -390,50 +381,6 @@ create_xdg_surface(struct window *window, struct display *display) + + window->wait_for_configure = true; + wl_surface_commit(window->surface); +-} +- +-static void +-create_ivi_surface(struct window *window, struct display *display) +-{ +- uint32_t id_ivisurf = IVI_SURFACE_ID + (uint32_t)getpid(); +- window->ivi_surface = +- ivi_application_surface_create(display->ivi_application, +- id_ivisurf, window->surface); +- +- if (window->ivi_surface == NULL) { +- fprintf(stderr, "Failed to create ivi_client_surface\n"); +- abort(); +- } +- +- ivi_surface_add_listener(window->ivi_surface, +- &ivi_surface_listener, window); +-} +- +-static void +-create_surface(struct window *window) +-{ +- struct display *display = window->display; +- EGLBoolean ret; +- +- window->surface = wl_compositor_create_surface(display->compositor); +- +- window->native = +- wl_egl_window_create(window->surface, +- window->geometry.width, +- window->geometry.height); +- window->egl_surface = +- weston_platform_create_egl_surface(display->egl.dpy, +- display->egl.conf, +- window->native, NULL); +- +- +- if (display->shell) { +- create_xdg_surface(window, display); +- } else if (display->ivi_application ) { +- create_ivi_surface(window, display); +- } else { +- assert(0); +- } + + ret = eglMakeCurrent(window->display->egl.dpy, window->egl_surface, + window->egl_surface, window->display->egl.ctx); +@@ -465,8 +412,6 @@ destroy_surface(struct window *window) + zxdg_toplevel_v6_destroy(window->xdg_toplevel); + if (window->xdg_surface) + zxdg_surface_v6_destroy(window->xdg_surface); +- if (window->display->ivi_application) +- ivi_surface_destroy(window->ivi_surface); + wl_surface_destroy(window->surface); + + if (window->callback) +@@ -821,10 +766,6 @@ registry_handle_global(void *data, struct wl_registry *registry, + fprintf(stderr, "unable to load default left pointer\n"); + // TODO: abort ? + } +- } else if (strcmp(interface, "ivi_application") == 0) { +- d->ivi_application = +- wl_registry_bind(registry, name, +- &ivi_application_interface, 1); + } + } + +@@ -939,9 +880,6 @@ main(int argc, char **argv) + if (display.shell) + zxdg_shell_v6_destroy(display.shell); + +- if (display.ivi_application) +- ivi_application_destroy(display.ivi_application); +- + if (display.compositor) + wl_compositor_destroy(display.compositor); + diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0014-simple-shm-remove-ivi-application-support.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0014-simple-shm-remove-ivi-application-support.patch new file mode 100644 index 000000000..495e50ca2 --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0014-simple-shm-remove-ivi-application-support.patch @@ -0,0 +1,107 @@ +index f9c8010b..c37cd00b 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -574,9 +574,7 @@ nodist_weston_simple_shm_SOURCES = \ + protocol/xdg-shell-unstable-v6-protocol.c \ + protocol/xdg-shell-unstable-v6-client-protocol.h \ + protocol/fullscreen-shell-unstable-v1-protocol.c \ +- protocol/fullscreen-shell-unstable-v1-client-protocol.h \ +- protocol/ivi-application-protocol.c \ +- protocol/ivi-application-client-protocol.h ++ protocol/fullscreen-shell-unstable-v1-client-protocol.h + weston_simple_shm_CFLAGS = $(AM_CFLAGS) $(SIMPLE_CLIENT_CFLAGS) + weston_simple_shm_LDADD = $(SIMPLE_CLIENT_LIBS) libshared.la + +diff --git a/clients/simple-shm.c b/clients/simple-shm.c +index 9fa2e214..fc2ef001 100644 +--- a/clients/simple-shm.c ++++ b/clients/simple-shm.c +@@ -40,10 +40,6 @@ + #include "xdg-shell-unstable-v6-client-protocol.h" + #include "fullscreen-shell-unstable-v1-client-protocol.h" + +-#include +-#include "ivi-application-client-protocol.h" +-#define IVI_SURFACE_ID 9000 +- + struct display { + struct wl_display *display; + struct wl_registry *registry; +@@ -52,7 +48,6 @@ struct display { + struct zwp_fullscreen_shell_v1 *fshell; + struct wl_shm *shm; + bool has_xrgb; +- struct ivi_application *ivi_application; + }; + + struct buffer { +@@ -67,7 +62,6 @@ struct window { + struct wl_surface *surface; + struct zxdg_surface_v6 *xdg_surface; + struct zxdg_toplevel_v6 *xdg_toplevel; +- struct ivi_surface *ivi_surface; + struct buffer buffers[2]; + struct buffer *prev_buffer; + struct wl_callback *callback; +@@ -165,17 +159,6 @@ static const struct zxdg_toplevel_v6_listener xdg_toplevel_listener = { + handle_xdg_toplevel_close, + }; + +-static void +-handle_ivi_surface_configure(void *data, struct ivi_surface *ivi_surface, +- int32_t width, int32_t height) +-{ +- /* Simple-shm is resizable */ +-} +- +-static const struct ivi_surface_listener ivi_surface_listener = { +- handle_ivi_surface_configure, +-}; +- + static struct window * + create_window(struct display *display, int width, int height) + { +@@ -213,19 +196,6 @@ create_window(struct display *display, int width, int height) + window->surface, + ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_DEFAULT, + NULL); +- } else if (display->ivi_application ) { +- uint32_t id_ivisurf = IVI_SURFACE_ID + (uint32_t)getpid(); +- window->ivi_surface = +- ivi_application_surface_create(display->ivi_application, +- id_ivisurf, window->surface); +- if (window->ivi_surface == NULL) { +- fprintf(stderr, "Failed to create ivi_client_surface\n"); +- abort(); +- } +- +- ivi_surface_add_listener(window->ivi_surface, +- &ivi_surface_listener, window); +- + } else { + assert(0); + } +@@ -407,11 +377,6 @@ registry_handle_global(void *data, struct wl_registry *registry, + id, &wl_shm_interface, 1); + wl_shm_add_listener(d->shm, &shm_listener, d); + } +- else if (strcmp(interface, "ivi_application") == 0) { +- d->ivi_application = +- wl_registry_bind(registry, id, +- &ivi_application_interface, 1); +- } + } + + static void +@@ -555,11 +520,6 @@ main(int argc, char **argv) + + fprintf(stderr, "simple-shm exiting\n"); + +- if (window->display->ivi_application) { +- ivi_surface_destroy(window->ivi_surface); +- ivi_application_destroy(window->display->ivi_application); +- } +- + destroy_window(window); + destroy_display(display); + diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0015-window-client-remove-ivi-application-support.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0015-window-client-remove-ivi-application-support.patch new file mode 100644 index 000000000..f3d2fe47f --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0015-window-client-remove-ivi-application-support.patch @@ -0,0 +1,130 @@ +index c37cd00b..f30ddbe9 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -665,8 +665,6 @@ nodist_libtoytoolkit_la_SOURCES = \ + protocol/viewporter-client-protocol.h \ + protocol/xdg-shell-unstable-v6-protocol.c \ + protocol/xdg-shell-unstable-v6-client-protocol.h \ +- protocol/ivi-application-protocol.c \ +- protocol/ivi-application-client-protocol.h \ + protocol/pointer-constraints-unstable-v1-protocol.c \ + protocol/pointer-constraints-unstable-v1-client-protocol.h \ + protocol/relative-pointer-unstable-v1-protocol.c \ +diff --git a/clients/window.c b/clients/window.c +index 95796d46..aac43abd 100644 +--- a/clients/window.c ++++ b/clients/window.c +@@ -82,10 +82,6 @@ typedef void *EGLContext; + + #include "window.h" + +-#include +-#include "ivi-application-client-protocol.h" +-#define IVI_SURFACE_ID 9000 +- + #define ZWP_RELATIVE_POINTER_MANAGER_V1_VERSION 1 + #define ZWP_POINTER_CONSTRAINTS_V1_VERSION 1 + +@@ -107,7 +103,6 @@ struct display { + struct wl_data_device_manager *data_device_manager; + struct text_cursor_position *text_cursor_position; + struct zxdg_shell_v6 *xdg_shell; +- struct ivi_application *ivi_application; /* ivi style shell */ + struct zwp_relative_pointer_manager_v1 *relative_pointer_manager; + struct zwp_pointer_constraints_v1 *pointer_constraints; + EGLDisplay dpy; +@@ -269,8 +264,6 @@ struct window { + struct window *parent; + struct window *last_parent; + +- struct ivi_surface *ivi_surface; +- + struct window_frame *frame; + + /* struct surface::link, contains also main_surface */ +@@ -1441,19 +1434,6 @@ window_get_display(struct window *window) + return window->display; + } + +-static void +-handle_ivi_surface_configure(void *data, struct ivi_surface *ivi_surface, +- int32_t width, int32_t height) +-{ +- struct window *window = data; +- +- window_schedule_resize(window, width, height); +-} +- +-static const struct ivi_surface_listener ivi_surface_listener = { +- handle_ivi_surface_configure, +-}; +- + static void + surface_create_surface(struct surface *surface, uint32_t flags) + { +@@ -1604,9 +1584,6 @@ window_destroy(struct window *window) + if (window->xdg_surface) + zxdg_surface_v6_destroy(window->xdg_surface); + +- if (window->ivi_surface) +- ivi_surface_destroy(window->ivi_surface); +- + surface_destroy(window->main_surface); + + wl_list_remove(&window->link); +@@ -5200,7 +5177,7 @@ window_create_internal(struct display *display, int custom) + surface = surface_create(window); + window->main_surface = surface; + +- assert(custom || display->xdg_shell || display->ivi_application); ++ assert(custom || display->xdg_shell); + + window->custom = custom; + window->preferred_format = WINDOW_PREFERRED_FORMAT_NONE; +@@ -5220,7 +5197,6 @@ struct window * + window_create(struct display *display) + { + struct window *window; +- uint32_t id_ivisurf; + + window = window_create_internal(display, 0); + +@@ -5243,16 +5219,6 @@ window_create(struct display *display) + window_inhibit_redraw(window); + + wl_surface_commit(window->main_surface->surface); +- } else if (display->ivi_application) { +- /* auto generation of ivi_id based on process id + basement of id */ +- id_ivisurf = IVI_SURFACE_ID + (uint32_t)getpid(); +- window->ivi_surface = +- ivi_application_surface_create(display->ivi_application, +- id_ivisurf, window->main_surface->surface); +- fail_on_null(window->ivi_surface, 0, __FILE__, __LINE__); +- +- ivi_surface_add_listener(window->ivi_surface, +- &ivi_surface_listener, window); + } + + return window; +@@ -6013,11 +5979,6 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t id, + wl_registry_bind(registry, id, + &wl_subcompositor_interface, 1); + } +- else if (strcmp(interface, "ivi_application") == 0) { +- d->ivi_application = +- wl_registry_bind(registry, id, +- &ivi_application_interface, 1); +- } + + if (d->global_handler) + d->global_handler(d, id, interface, version, d->user_data); +@@ -6316,9 +6277,6 @@ display_destroy(struct display *display) + if (display->xdg_shell) + zxdg_shell_v6_destroy(display->xdg_shell); + +- if (display->ivi_application) +- ivi_application_destroy(display->ivi_application); +- + if (display->shm) + wl_shm_destroy(display->shm); + diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0016-ivi-shell_add_screen_remove_layer_api.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0016-ivi-shell_add_screen_remove_layer_api.patch new file mode 100644 index 000000000..3e85e93f6 --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/weston/0016-ivi-shell_add_screen_remove_layer_api.patch @@ -0,0 +1,82 @@ +From deee858b0b199d8cfa8033a46d7078f30b23725e Mon Sep 17 00:00:00 2001 +From: "Ucan, Emre (ADITG/SW1)" +Date: Thu, 2 Mar 2017 08:47:33 +0000 +Subject: ivi-shell: add_screen_remove_layer API + +It is analagous to layer_remove_surface API. +The API removes a layer from the render order +of the screen. + +v3: +add the new vfunc at the end of +the ivi_layout_interface struct. + +Signed-off-by: Emre Ucan +Reviewed-by: Eugen Friedrich +Reviewed-by: Pekka Paalanen + +diff --git a/ivi-shell/ivi-layout-export.h b/ivi-shell/ivi-layout-export.h +index 2317d6e..39ffde1 100644 +--- a/ivi-shell/ivi-layout-export.h ++++ b/ivi-shell/ivi-layout-export.h +@@ -578,6 +578,16 @@ struct ivi_layout_interface { + */ + struct ivi_layout_surface * + (*get_surface)(struct weston_surface *surface); ++ ++ /** ++ * \brief Remove a ivi_layer to a weston_output which is currently managed ++ * by the service ++ * ++ * \return IVI_SUCCEEDED if the method call was successful ++ * \return IVI_FAILED if the method call was failed ++ */ ++ int32_t (*screen_remove_layer)(struct weston_output *output, ++ struct ivi_layout_layer *removelayer); + }; + + #ifdef __cplusplus +diff --git a/ivi-shell/ivi-layout.c b/ivi-shell/ivi-layout.c +index 298e18e..8e4280b 100644 +--- a/ivi-shell/ivi-layout.c ++++ b/ivi-shell/ivi-layout.c +@@ -1664,6 +1664,27 @@ ivi_layout_screen_add_layer(struct weston_output *output, + } + + static int32_t ++ivi_layout_screen_remove_layer(struct weston_output *output, ++ struct ivi_layout_layer *removelayer) ++{ ++ struct ivi_layout_screen *iviscrn; ++ ++ if (output == NULL || removelayer == NULL) { ++ weston_log("ivi_layout_screen_remove_layer: invalid argument\n"); ++ return IVI_FAILED; ++ } ++ ++ iviscrn = get_screen_from_output(output); ++ ++ wl_list_remove(&removelayer->pending.link); ++ wl_list_init(&removelayer->pending.link); ++ ++ iviscrn->order.dirty = 1; ++ ++ return IVI_SUCCEEDED; ++} ++ ++static int32_t + ivi_layout_screen_set_render_order(struct weston_output *output, + struct ivi_layout_layer **pLayer, + const int32_t number) +@@ -2088,6 +2109,7 @@ static struct ivi_layout_interface ivi_layout_interface = { + */ + .get_screens_under_layer = ivi_layout_get_screens_under_layer, + .screen_add_layer = ivi_layout_screen_add_layer, ++ .screen_remove_layer = ivi_layout_screen_remove_layer, + .screen_set_render_order = ivi_layout_screen_set_render_order, + + /** +-- +cgit v0.10.2 + + diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/weston_2.0.0.bbappend b/meta-agl-profile-graphical/recipes-graphics/wayland/weston_2.0.0.bbappend new file mode 100644 index 000000000..f6f88a6d6 --- /dev/null +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/weston_2.0.0.bbappend @@ -0,0 +1,23 @@ +FILESEXTRAPATHS_append := ":${THISDIR}/${PN}" + +SRC_URI_append = "\ + file://0001-Allow-regular-users-to-launch-Weston_2.0.0.patch \ + file://0001-ivi-shell-rework-goto-labels-to-avoid-memory-leaks.patch \ + file://0002-ivi-shell-removed-assert.patch \ + file://0003-ivi-shell-introduction-of-IVI_INVALID_ID.patch \ + file://0004-layout-interface-added-interface-to-change-surface-id.patch \ + file://0005-ivi-layout-introcuded-configure_desktop_changed.patch \ + file://0006-ivi-layout-introcuded-surface_create_and_configure.patch \ + file://0007-ivi-shell-linked-libweston-desktop-and-added-structs.patch \ + file://0008-ivi-layout-use-libweston-desktop-api-for-views.patch \ + file://0009-ivi-shell-added-libweston-desktop-api_implementation.patch \ + file://0010-ivi-shell-remove-surface_destroy_listener.patch \ + file://0011-ivi-shell-create-weston-desktop-in_wet_shell_init.patch \ + file://0012-hmi-controller-register-for-desktop_surface_configured.patch \ + file://0013-simple-egl-remove-ivi-application-support.patch \ + file://0014-simple-shm-remove-ivi-application-support.patch \ + file://0015-window-client-remove-ivi-application-support.patch \ + file://0016-ivi-shell_add_screen_remove_layer_api.patch \ + " + +EXTRA_OECONF_append = " --enable-sys-uid" diff --git a/meta-agl/classes/.gitkeep b/meta-agl/classes/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/meta-agl/classes/agl-graphical.bbclass b/meta-agl/classes/agl-graphical.bbclass deleted file mode 100644 index 0004d9c1a..000000000 --- a/meta-agl/classes/agl-graphical.bbclass +++ /dev/null @@ -1,7 +0,0 @@ -WESTONTTY ??= "1" -WESTONUSER ??= "display" -WESTONGROUP ??= "display" -WESTONARGS ?= "--idle-time=0 --tty=${WESTONTTY} ${@bb.utils.contains("DISTRO_FEATURES", "gst-record", "--gst-record", "",d)}" -WESTONLAUNCHARGS ??= "--tty /dev/tty${WESTONTTY} --user ${WESTONUSER}" -DISPLAY_XDG_RUNTIME_DIR ??= "/run/platform/${WESTONUSER}" - diff --git a/meta-agl/classes/cloc.bbclass b/meta-agl/classes/cloc.bbclass deleted file mode 100644 index 53713bfc3..000000000 --- a/meta-agl/classes/cloc.bbclass +++ /dev/null @@ -1,29 +0,0 @@ -# (C) 2017 Jan-Simon Möller -# -# License: GPLv2 -# -# summary with -# cloc --sum-reports `find . -name "*clocreport" | grep -v "\-native" ` --out summary.report - -CLOC_DIRECTORY ??= "${DEPLOY_DIR}/cloc/" -CLOCSTATEDIR = "${WORKDIR}/cloc-destdir/" - -python do_cloc() { - - import subprocess - - source_dir = d.getVar('S', True) - pn = d.getVar('PN', True) - - destdir = d.expand('${CLOCSTATEDIR}') - bb.utils.mkdirhier(destdir) - - cloc_cmd = 'cloc %s -q --out=%s/%s.clocreport' % (source_dir, destdir, pn ) - subprocess.call(cloc_cmd, shell=True) - -} - - -addtask cloc before do_configure after do_unpack - -EXPORT_FUNCTIONS do_cloc diff --git a/meta-agl/conf/include/agl-devel.inc b/meta-agl/conf/include/agl-devel.inc deleted file mode 100644 index fd11ade75..000000000 --- a/meta-agl/conf/include/agl-devel.inc +++ /dev/null @@ -1,15 +0,0 @@ -IMAGE_FEATURES =+ "debug-tweaks eclipse-debug tools-debug tools-profile" - -IMAGE_INSTALL_append = " \ - packagegroup-agl-devel \ -" - -IMAGE_INSTALL_append = "${@bb.utils.contains('IMAGE_FSTYPES', 'wic.vmdk', ' open-vm-tools vboxguestdrivers', '', d)}" - -# disable install of debug files in SDK -# initial value: SDKIMAGE_FEATURES="dev-pkgs dbg-pkgs staticdev-pkgs" -SDKIMAGE_FEATURES="dev-pkgs" - -# allows insertion of code or items specific to developement -OVERRIDES .= ":agl-devel" -DISTRO_FEATURES_append = " agl-devel" diff --git a/meta-agl/conf/include/agl-gplv2.inc b/meta-agl/conf/include/agl-gplv2.inc deleted file mode 100644 index fc9a4072b..000000000 --- a/meta-agl/conf/include/agl-gplv2.inc +++ /dev/null @@ -1,8 +0,0 @@ -# GPLv3 Compliance -PREFERRED_VERSION_bash = "3.2.%" -PREFERRED_VERSION_gawk = "3.1.%" -PREFERRED_VERSION_gdbm = "1.8.%" -PREFERRED_VERSION_gnupg = "1.4.7" -PREFERRED_VERSION_gnutls = "3.3.%" -PREFERRED_VERSION_mc = "4.7.5.%" -PREFERRED_VERSION_readline = "5.2" diff --git a/meta-agl/conf/include/base-agl.inc b/meta-agl/conf/include/base-agl.inc deleted file mode 100644 index a332c08a4..000000000 --- a/meta-agl/conf/include/base-agl.inc +++ /dev/null @@ -1,19 +0,0 @@ -# AGL includes all kernel modules here for ease-of-use during development. -# Comment this out to be able to select the kernel modules yourself. -IMAGE_INSTALL_append = " kernel-modules" - -# Likewise as we included all kernel modules by default in the filesystem, -# we do not need a separate tarball stored. -# Comment this out to receive the separate modules tarball again. -MODULE_TARBALL_DEPLOY ?= "0" - -# Comment out below if want to use QtWebkit -PACKAGECONFIG_remove_pn-qtquick1 = "webkit" - - -ASSUME_PROVIDED_remove = "tar-native" - -# Use static IDs to enable full-filesystem updates -USERADDEXTENSION = "useradd-staticids" -USERADD_ERROR_DYNAMIC = "error" - diff --git a/meta-agl/files/group b/meta-agl/files/group deleted file mode 100644 index f8a3843bd..000000000 --- a/meta-agl/files/group +++ /dev/null @@ -1,90 +0,0 @@ -root::0: -daemon::1: -bin::2: -sys::3: -adm::4: -tty::5: -disk::6: -lp::7: -mail::8: -news::9: -uucp::10: -man::12: -proxy::13: -kmem::15: -input::19: -dialout::20: -fax::21: -voice::22: -cdrom::24: -floppy::25: -tape::26: -sudo::27: -audio::29: -dip::30: -www-data::33: -backup::34: -operator::37: -list::38: -irc::39: -src::40: -gnats::41: -shadow::42: -utmp::43: -video::44: -sasl::45: -plugdev::46: -staff::50: -games::60: -shutdown::70: -users::100: -nogroup::65534: -cynara::999: -dhcp::998: -avahi::997: -tracing::1000: -sshd::996: -systemd-bus-proxy::995: -netdev::993: -messagebus::994: -afm::992: -weston-launch::986: -lock::990: -systemd-journal::989: -systemd-timesync::988: -pulse::991: -bind::987: -trinity::985: -mpd::984: -mysql::983: -polkitd::982: -datetime::981: -network::980: -zabbix::979: -nm-openvpn::978: -xuser::1002: -builder::977: -rpc::976: -crontab::975: -lpadmin::974: -_apt::972: -rpcuser::970: -avahi-autoipd::969: -ntp::968: -dovecot::967: -dovenull::966: -quagga::965: -quaggavty::964: -rwhod::963: -ftp::962: -squid::960: -postfix::959: -vmail::958: -opensaf::957: -lldpd::956: -postdrop::954: -display::200: -agl-driver::1001: -agl-passenger::1002: -systemd-network::1005: -systemd-resolve::1006: diff --git a/meta-agl/files/passwd b/meta-agl/files/passwd deleted file mode 100644 index 754cb819a..000000000 --- a/meta-agl/files/passwd +++ /dev/null @@ -1,60 +0,0 @@ -root::0:0::: -daemon::1:1::: -bin::2:2::: -sys::3:3::: -sync::4:65534::: -games::5:60::: -man::6:12::: -lp::7:7::: -mail::8:8::: -news::9:9::: -uucp::10:10::: -proxy::13:13::: -www-data::33:33::: -backup::34:34::: -list::38:38::: -irc::39:39::: -gnats::41:41::: -nobody::65534:65534::: -cynara::999:999::: -dhcp::998:998::: -avahi::997:997::: -sshd::996:996::: -systemd-bus-proxy::995:995::: -agl-driver::1001:1001::: -agl-passenger::1002:1002::: -messagebus::994:994::: -afm::992:992::: -systemd-timesync::988:988::: -pulse::991:991::: -bind::987:987::: -trinity::985:985::: -mpd::984:984::: -mysql::983:983::: -polkitd::982:982::: -zabbix::979:979::: -nm-openvpn::978:978::: -xuser::1002:1002::: -builder::977:977::: -rpc::976:976::: -distcc::973:65534::: -_apt::972:972::: -ppp::971:65534::: -rpcuser::970:970::: -avahi-autoipd::969:969::: -ntp::968:968::: -dovecot::967:967::: -dovenull::966:966::: -quagga::965:965::: -rwhod::963:963::: -ftp::962:962::: -radvd::961:65534::: -squid::960:960::: -postfix::959:959::: -vmail::958:958::: -opensaf::957:957::: -lldpd::956:956::: -cyrus::955:8::: -display::200:200::: -systemd-network::1005:1005::: -systemd-resolve::1006:1006::: diff --git a/meta-agl/recipes-automotive/.gitkeep b/meta-agl/recipes-automotive/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/meta-agl/recipes-bsp/.gitkeep b/meta-agl/recipes-bsp/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/meta-agl/recipes-config/agl-login-manager/agl-login-manager_0.1.bb b/meta-agl/recipes-config/agl-login-manager/agl-login-manager_0.1.bb deleted file mode 100644 index cd6dc6792..000000000 --- a/meta-agl/recipes-config/agl-login-manager/agl-login-manager_0.1.bb +++ /dev/null @@ -1,21 +0,0 @@ -SUMMARY = "AGL Login manager" - -LICENSE = "MIT" -LIC_FILES_CHKSUM = "file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420" - -inherit agl-graphical - -LOGIN_USER ??="1001 1002" - -RDEPENDS_${PN} += "af-main" - -do_install_append() { - - install -d ${D}${systemd_system_unitdir}/multi-user.target.wants/ - - for AGL_USER in ${LOGIN_USER};do - ln -s ../afm-user-session@.service ${D}${systemd_system_unitdir}/multi-user.target.wants/afm-user-session@${AGL_USER}.service - done -} - -FILES_${PN} += "${systemd_system_unitdir}" diff --git a/meta-agl/recipes-connectivity/bluez-alsa/bluez-alsa_git.bb b/meta-agl/recipes-connectivity/bluez-alsa/bluez-alsa_git.bb deleted file mode 100644 index 6379ec38f..000000000 --- a/meta-agl/recipes-connectivity/bluez-alsa/bluez-alsa_git.bb +++ /dev/null @@ -1,38 +0,0 @@ -SUMMARY = "Bluetooth Audio ALSA Backend" -HOMEPAGE = "https://github.com/Arkq/bluez-alsa" -SECTION = "libs" - -LICENSE = "MIT" -LIC_FILES_CHKSUM = "file://LICENSE.txt;md5=bb3e99e80c5d718213f35ae1def4c106" - -SRC_URI = "git://github.com/Arkq/bluez-alsa.git;protocol=https;branch=master" -SRCREV = "9045edb436ea755f395a2e09e4525b5defad286a" - -SRC_URI += "file://bluez-alsa.service" - -S = "${WORKDIR}/git" - -DEPENDS += "alsa-lib bluez5 systemd glib-2.0 sbc" - -PACKAGECONFIG[aac] = "--enable-aac, --disable-aac, " -PACKAGECONFIG[aptx] = "--enable-aptx,--disable-aptx," -PACKAGECONFIG[hcitop] = "--enable-hcitop, --disable-hcitop, libbsd ncurses" - -inherit autotools pkgconfig -inherit systemd - -SYSTEMD_AUTO_ENABLE = "enable" -SYSTEMD_SERVICE_${PN} = "bluez-alsa.service" - -PACKAGECONFIG += "hcitop" - -do_install_append () { - install -d ${D}${base_libdir}/systemd/system - install -m 0644 ${WORKDIR}/bluez-alsa.service ${D}${base_libdir}/systemd/system -} - -FILES_${PN} += "\ - ${datadir}/alsa/alsa.conf.d/20-bluealsa.conf\ - ${libdir}/alsa-lib/libasound_module_ctl_bluealsa.so\ - ${libdir}/alsa-lib/libasound_module_pcm_bluealsa.so\ -" diff --git a/meta-agl/recipes-connectivity/bluez-alsa/files/bluez-alsa.service b/meta-agl/recipes-connectivity/bluez-alsa/files/bluez-alsa.service deleted file mode 100644 index 671815e03..000000000 --- a/meta-agl/recipes-connectivity/bluez-alsa/files/bluez-alsa.service +++ /dev/null @@ -1,11 +0,0 @@ -[Unit] -Description=Bluetooth Audio ALSA Backend -After=bluetooth.service -Requires=bluetooth.service - -[Service] -Type=simple -ExecStart=/usr/bin/bluealsa - -[Install] -WantedBy=multi-user.target diff --git a/meta-agl/recipes-connectivity/bluez5/bluez5/bluetooth.conf b/meta-agl/recipes-connectivity/bluez5/bluez5/bluetooth.conf deleted file mode 100644 index 1f2762de7..000000000 --- a/meta-agl/recipes-connectivity/bluez5/bluez5/bluetooth.conf +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/meta-agl/recipes-connectivity/bluez5/bluez5_%.bbappend b/meta-agl/recipes-connectivity/bluez5/bluez5_%.bbappend deleted file mode 100644 index ffb9d5b53..000000000 --- a/meta-agl/recipes-connectivity/bluez5/bluez5_%.bbappend +++ /dev/null @@ -1,6 +0,0 @@ -FILESEXTRAPATHS_prepend := "${THISDIR}/${BPN}:" -SRC_URI_append = " file://bluetooth.conf" - -do_install_append() { - install -m 0644 ${WORKDIR}/bluetooth.conf ${D}${sysconfdir}/dbus-1/system.d/bluetooth.conf -} diff --git a/meta-agl/recipes-connectivity/busybox/busybox_%.bbappend b/meta-agl/recipes-connectivity/busybox/busybox_%.bbappend deleted file mode 100644 index 198b651dd..000000000 --- a/meta-agl/recipes-connectivity/busybox/busybox_%.bbappend +++ /dev/null @@ -1,2 +0,0 @@ -SRC_URI += "file://enable-wget-https.cfg" -FILESEXTRAPATHS_prepend := "${THISDIR}/files:" diff --git a/meta-agl/recipes-connectivity/busybox/files/enable-wget-https.cfg b/meta-agl/recipes-connectivity/busybox/files/enable-wget-https.cfg deleted file mode 100644 index e92006bef..000000000 --- a/meta-agl/recipes-connectivity/busybox/files/enable-wget-https.cfg +++ /dev/null @@ -1,3 +0,0 @@ -# Thu Jun 8 17:32:07 2017 -CONFIG_FEATURE_WGET_OPENSSL=y -CONFIG_FEATURE_WGET_SSL_HELPER=y diff --git a/meta-agl/recipes-connectivity/connman-ncurses/connman-ncurses_git.bb b/meta-agl/recipes-connectivity/connman-ncurses/connman-ncurses_git.bb deleted file mode 100644 index 02afef75f..000000000 --- a/meta-agl/recipes-connectivity/connman-ncurses/connman-ncurses_git.bb +++ /dev/null @@ -1,26 +0,0 @@ -SUMMARY = "A simple ncurses interface for connman" -DESCRIPTION = "A simple ncurses interface for connman" -HOMEPAGE = "https://gitlab.com/iotbzh/connman-json-client" - -SECTION = "console/network" - -DEPENDS = "dbus ncurses connman json-c" - -LICENSE = "GPLv2" -LIC_FILES_CHKSUM = "file://LICENSE;md5=8c16666ae6c159876a0ba63099614381" - -SRC_URI = "git://gitlab.com/iotbzh/connman-json-client.git;protocol=https;rev=ad4261a2f87c914667b1f6841c913f6b08d373e2" - -inherit autotools pkgconfig - -EXTRA_AUTORECONF += " -i" -EXTRA_OECONF += " --disable-optimization --enable-debug" - -S = "${WORKDIR}/git" - -do_install () { - install -dm755 ${D}${bindir} - install -Dm755 connman_ncurses ${D}${bindir} -} - -FILES_${PN} = "${bindir}/connman_ncurses" diff --git a/meta-agl/recipes-connectivity/connman/.appends.core b/meta-agl/recipes-connectivity/connman/.appends.core deleted file mode 100644 index e69de29bb..000000000 diff --git a/meta-agl/recipes-connectivity/connman/connman_%.bbappend b/meta-agl/recipes-connectivity/connman/connman_%.bbappend deleted file mode 100644 index e41cbe954..000000000 --- a/meta-agl/recipes-connectivity/connman/connman_%.bbappend +++ /dev/null @@ -1,3 +0,0 @@ -FILESEXTRAPATHS_prepend := "${THISDIR}/files:" - -SRC_URI += "file://0001-disable-when-booting-over-nfs.patch" diff --git a/meta-agl/recipes-connectivity/connman/files/0001-disable-when-booting-over-nfs.patch b/meta-agl/recipes-connectivity/connman/files/0001-disable-when-booting-over-nfs.patch deleted file mode 100644 index 95fc0a905..000000000 --- a/meta-agl/recipes-connectivity/connman/files/0001-disable-when-booting-over-nfs.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/src/connman.service.in 2016-08-15 13:51:03.479478140 +0200 -+++ b/src/connman.service.in 2016-08-15 13:51:33.469478267 +0200 -@@ -7,6 +7,7 @@ RequiresMountsFor=@localstatedir@/lib/co - After=dbus.service network-pre.target systemd-sysusers.service - Before=network.target multi-user.target shutdown.target - Wants=network.target - Conflicts=systemd-resolved.service -+ConditionKernelCommandLine=!root=/dev/nfs - - [Service] - Type=dbus diff --git a/meta-agl/recipes-connectivity/rtl-sdr/rtl-sdr/0001-remove-I-usr-include-in-pkg-config.patch b/meta-agl/recipes-connectivity/rtl-sdr/rtl-sdr/0001-remove-I-usr-include-in-pkg-config.patch deleted file mode 100644 index 86b7392df..000000000 --- a/meta-agl/recipes-connectivity/rtl-sdr/rtl-sdr/0001-remove-I-usr-include-in-pkg-config.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 3aeaf8054fcb2617ca8f6196ca32be3e69337f77 Mon Sep 17 00:00:00 2001 -From: Martin Kelly -Date: Fri, 21 Apr 2017 10:29:19 -0700 -Subject: [PATCH] remove -I/usr/include in pkg-config - -This shouldn't be necessary as it's part of the default compiler include -paths anyway. Morever, it can cause GCC 6 C++ build failures in -downstream packages when combined with QMake (such as -qtmultimedia-rtlfm-radio-plugin). - -Fix these issues by removing it. - -Upstream-Status: Inappropriate [disable-feature] - -This patch should not go upstream because it breaks the ability to build -with --prefix. That's not a problem for Openembedded, but it is for -upstream more generally. See this mail thread for more information: - -http://lists.osmocom.org/pipermail/osmocom-sdr/2017-April/001580.html - -Signed-off-by: Martin Kelly ---- - librtlsdr.pc.in | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/librtlsdr.pc.in b/librtlsdr.pc.in -index 5e55049..84b6d0c 100644 ---- a/librtlsdr.pc.in -+++ b/librtlsdr.pc.in -@@ -6,6 +6,6 @@ includedir=@includedir@ - Name: RTL-SDR Library - Description: C Utility Library - Version: @VERSION@ --Cflags: -I${includedir}/ @RTLSDR_PC_CFLAGS@ -+Cflags: @RTLSDR_PC_CFLAGS@ - Libs: -L${libdir} -lrtlsdr -lusb-1.0 - Libs.private: @RTLSDR_PC_LIBS@ --- -2.1.4 - diff --git a/meta-agl/recipes-connectivity/rtl-sdr/rtl-sdr_0.5.3.bb b/meta-agl/recipes-connectivity/rtl-sdr/rtl-sdr_0.5.3.bb deleted file mode 100644 index 7d5c0217d..000000000 --- a/meta-agl/recipes-connectivity/rtl-sdr/rtl-sdr_0.5.3.bb +++ /dev/null @@ -1,26 +0,0 @@ -SUMMARY = "Turns a Realtek RTL2832U-based DVB dongle into a SDR receiver" -DESCRIPTION = "DVB-T dongles based on the Realtek RTL2832U chipset can be used as Software Digital Radio adapters, since the chip allows transferring raw I/Q samples to the host, which is really used for DAB/DAB+/FM demodulation." -HOMEPAGE = "http://sdr.osmocom.org/trac/wiki/rtl-sdr" - -LICENSE = "GPLv2+" -LIC_FILES_CHKSUM = "file://COPYING;md5=751419260aa954499f7abaabaa882bbe \ - file://src/librtlsdr.c;endline=18;md5=1b05599c3ebd4d74857a0a7c45f3d4ef" - -DEPENDS = "libusb1" - -SRC_URI = "git://git.osmocom.org/rtl-sdr \ - file://0001-remove-I-usr-include-in-pkg-config.patch \ - " -SRCREV = "e3c03f738f5aef4dc51e2b741fbdb542b9cc1bb1" -S = "${WORKDIR}/git" - -inherit autotools pkgconfig - -EXTRA_OECONF = "--enable-driver-detach" -#CFLAGS_remove = " -do_configure_append() { - # remove included temporary path from pc file due to pass-through of OE CFLAGS - # debug-prefix-map - # See: http://lists.openembedded.org/pipermail/openembedded-devel/2016-May/107456.html - sed -i -e "s# -fdebug-prefix-map=.*##g" librtlsdr.pc -} \ No newline at end of file diff --git a/meta-agl/recipes-connectivity/rygel/.appends.meta-multimedia b/meta-agl/recipes-connectivity/rygel/.appends.meta-multimedia deleted file mode 100644 index e69de29bb..000000000 diff --git a/meta-agl/recipes-connectivity/rygel/files/0001-Fix-missing-link-to-unistring-for-lms-plugin.patch b/meta-agl/recipes-connectivity/rygel/files/0001-Fix-missing-link-to-unistring-for-lms-plugin.patch deleted file mode 100644 index 57b97a6ca..000000000 --- a/meta-agl/recipes-connectivity/rygel/files/0001-Fix-missing-link-to-unistring-for-lms-plugin.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 10602ca53b1c1231e96d8d446904617528c11dae Mon Sep 17 00:00:00 2001 -From: Ronan Le Martret -Date: Mon, 13 Mar 2017 15:31:41 +0100 -Subject: [PATCH] Fix missing link to unistring for lms plugin - -Signed-off-by: Ronan Le Martret ---- - configure.ac | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/configure.ac b/configure.ac -index c5cbc00..2f7dc78 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -248,6 +248,10 @@ AS_IF([test "x$enable_lms_plugin" = "xyes"], - gio-2.0 >= $GIO_REQUIRED - sqlite3 >= $LIBSQLITE3_REQUIRED]) - RYGEL_PLUGIN_LMS_DEPS_VALAFLAGS="$RYGEL_COMMON_MODULES_VALAFLAGS --pkg gio-2.0 --pkg gee-0.8 --pkg sqlite3" -+ AS_IF([test "x$have_unistring" = "xyes"], -+ [ -+ RYGEL_PLUGIN_LMS_DEPS_LIBS="$RYGEL_PLUGIN_LMS_DEPS_LIBS -lunistring" -+ ]) - AC_SUBST([RYGEL_PLUGIN_LMS_DEPS_VALAFLAGS]) - ]) - --- -2.6.6 - diff --git a/meta-agl/recipes-connectivity/rygel/files/rygel.service b/meta-agl/recipes-connectivity/rygel/files/rygel.service deleted file mode 100644 index fb94d7160..000000000 --- a/meta-agl/recipes-connectivity/rygel/files/rygel.service +++ /dev/null @@ -1,13 +0,0 @@ -[Unit] -Description=Rygel -After=lightmediascanner.service -Requires=lightmediascanner.service - -[Service] -Type=dbus -BusName=org.gnome.Rygel1 -ExecStart=/usr/bin/rygel -c /etc/rygel.conf - -[Install] -WantedBy=default.target -Alias=dbus-org.gnome.Rygel1.service diff --git a/meta-agl/recipes-connectivity/rygel/rygel_%.bbappend b/meta-agl/recipes-connectivity/rygel/rygel_%.bbappend deleted file mode 100644 index 4ae59259f..000000000 --- a/meta-agl/recipes-connectivity/rygel/rygel_%.bbappend +++ /dev/null @@ -1,25 +0,0 @@ -FILESEXTRAPATHS_prepend := "${THISDIR}/files:" - -# Disable everything but the media-export plugin, add the lms plugin -PACKAGECONFIG = "media-export lms" -PACKAGECONFIG[lms] = "--enable-lms-plugin,--disable-lms-plugin,sqlite3" - -# LightMediaScanner plugin patches -SRC_URI += "\ - file://0001-Fix-missing-link-to-unistring-for-lms-plugin.patch \ - file://rygel.service \ -" - -do_install_prepend() { - # Install rygel systemd service - if ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'true', 'false', d)}; then - install -m 644 -p -D ${WORKDIR}/rygel.service ${D}${systemd_user_unitdir}/rygel.service - - # Execute these manually on behalf of systemctl script (from systemd-systemctl-native.bb) - # because it does not support systemd's user mode. - # However, systemctl --global should be checked - #mkdir -p ${D}/etc/systemd/user/default.target.wants/ - #ln -sf ${systemd_user_unitdir}/rygel.service ${D}/etc/systemd/user/dbus-org.gnome.Rygel1.service - #ln -sf ${systemd_user_unitdir}/rygel.service ${D}/etc/systemd/user/default.target.wants/rygel.service - fi -} diff --git a/meta-agl/recipes-core/dbus/.appends.core b/meta-agl/recipes-core/dbus/.appends.core deleted file mode 100644 index e69de29bb..000000000 diff --git a/meta-agl/recipes-core/dbus/dbus-cynara_%.bbappend b/meta-agl/recipes-core/dbus/dbus-cynara_%.bbappend deleted file mode 120000 index fcdfb1783..000000000 --- a/meta-agl/recipes-core/dbus/dbus-cynara_%.bbappend +++ /dev/null @@ -1 +0,0 @@ -dbus_%.bbappend \ No newline at end of file diff --git a/meta-agl/recipes-core/dbus/dbus/dbus.service b/meta-agl/recipes-core/dbus/dbus/dbus.service deleted file mode 100644 index dee6ad741..000000000 --- a/meta-agl/recipes-core/dbus/dbus/dbus.service +++ /dev/null @@ -1,10 +0,0 @@ -[Unit] -Description=D-Bus User Message Bus -Documentation=man:dbus-daemon(1) -Requires=dbus.socket - -[Service] -ExecStart=/usr/bin/dbus-daemon --session --address=systemd: --nofork --nopidfile --systemd-activation -ExecReload=/usr/bin/dbus-send --print-reply --session --type=method_call --dest=org.freedesktop.DBus / org.freedesktop.DBus.ReloadConfig -Restart=always -RestartSec=1 diff --git a/meta-agl/recipes-core/dbus/dbus/dbus.socket b/meta-agl/recipes-core/dbus/dbus/dbus.socket deleted file mode 100644 index af76b2f12..000000000 --- a/meta-agl/recipes-core/dbus/dbus/dbus.socket +++ /dev/null @@ -1,9 +0,0 @@ -[Unit] -Description=D-Bus User Message Bus Socket -Before=sockets.target - -[Socket] -ListenStream=%t/bus - -[Install] -WantedBy=default.target diff --git a/meta-agl/recipes-core/dbus/dbus/dbus_env.conf b/meta-agl/recipes-core/dbus/dbus/dbus_env.conf deleted file mode 100644 index f8f02669b..000000000 --- a/meta-agl/recipes-core/dbus/dbus/dbus_env.conf +++ /dev/null @@ -1,5 +0,0 @@ -[Unit] -Wants=dbus.service - -[Service] -Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/%I/bus diff --git a/meta-agl/recipes-core/dbus/dbus_%.bbappend b/meta-agl/recipes-core/dbus/dbus_%.bbappend deleted file mode 100644 index e63ea0f28..000000000 --- a/meta-agl/recipes-core/dbus/dbus_%.bbappend +++ /dev/null @@ -1,28 +0,0 @@ -FILESEXTRAPATHS_append := ":${THISDIR}/dbus" - -SRC_URI_append = "file://dbus.service \ - file://dbus.socket \ - file://dbus_env.conf \ - " - -inherit systemd - -do_install_append() { - if [ "${PN}" != "nativesdk-dbus" ]; then - if ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'true', 'false', d)}; then - install -m 644 -p -D ${WORKDIR}/dbus.service ${D}${systemd_user_unitdir}/dbus.service - install -m 644 -p -D ${WORKDIR}/dbus.socket ${D}${systemd_user_unitdir}/dbus.socket - install -m 644 -p -D ${WORKDIR}/dbus_env.conf ${D}${systemd_system_unitdir}/user@.service.d/dbus_env.conf - - # Execute these manually on behalf of systemctl script (from systemd-systemctl-native.bb) - # because it does not support systemd's user mode. - mkdir -p ${D}/etc/systemd/user/default.target.wants/ - ln -sf ${systemd_user_unitdir}/dbus.socket ${D}/etc/systemd/user/default.target.wants/dbus.socket - fi - fi -} - -FILES_${PN} += " \ - ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', '${systemd_user_unitdir}/dbus.*', '', d)} \ - ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', '${systemd_system_unitdir}/user@.service.d/dbus_env.conf', '', d)} \ - " diff --git a/meta-agl/recipes-core/glibc/.appends.core b/meta-agl/recipes-core/glibc/.appends.core deleted file mode 100644 index e69de29bb..000000000 diff --git a/meta-agl/recipes-core/glibc/glibc/arm/local-arm-futex.diff b/meta-agl/recipes-core/glibc/glibc/arm/local-arm-futex.diff deleted file mode 100644 index 27d1144d0..000000000 --- a/meta-agl/recipes-core/glibc/glibc/arm/local-arm-futex.diff +++ /dev/null @@ -1,22 +0,0 @@ -Description: Lie about futex_atomic_cmpxchg_inatomic kernel support. - In past versions of glibc, we incorrectly assumed all ARM kernels - in all configurations supported futex_atomic_cmpxchg_inatomic. This - was clearly a lie, however it was a lie that we relied on, because - the fallback implementation appears to not play nicely with certain - applications like pulseaudio. Restore the lie for kernels > 2.6.32 - and plug our ears and scream "LA LA LA" about how wrong this is. -Author: Adam Conrad -Bug-Ubuntu: https://launchpad.net/bugs/1436162 -Bug-Debian: https://bugs.debian.org/788799 -Last-Update: 2015-03-25 - ---- a/sysdeps/unix/sysv/linux/arm/kernel-features.h -+++ b/sysdeps/unix/sysv/linux/arm/kernel-features.h -@@ -22,7 +22,7 @@ - /* The ARM kernel before 3.14.3 may or may not support - futex_atomic_cmpxchg_inatomic, depending on kernel - configuration. */ --#if __LINUX_KERNEL_VERSION < 0x030E03 -+#if __LINUX_KERNEL_VERSION < 0x020620 - # undef __ASSUME_SET_ROBUST_LIST - #endif diff --git a/meta-agl/recipes-core/glibc/glibc_2.2%.bbappend b/meta-agl/recipes-core/glibc/glibc_2.2%.bbappend deleted file mode 100644 index 0868a2c7d..000000000 --- a/meta-agl/recipes-core/glibc/glibc_2.2%.bbappend +++ /dev/null @@ -1,3 +0,0 @@ -FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" - -SRC_URI_append_arm = " file://arm/local-arm-futex.diff " diff --git a/meta-agl/recipes-core/images/agl-image-minimal-qa.bb b/meta-agl/recipes-core/images/agl-image-minimal-qa.bb deleted file mode 100644 index b162f2904..000000000 --- a/meta-agl/recipes-core/images/agl-image-minimal-qa.bb +++ /dev/null @@ -1,12 +0,0 @@ -SUMMARY = "An AGL small image just capable of allowing a device to boot and run tests." - -DESCRIPTION = "A minimal set of AGL Distribution. This image also has additional \ -packages (e.g. commandline tools) for Quality Assurance(QA)." - -require agl-image-minimal.bb - -LICENSE = "MIT" - -IMAGE_INSTALL_append = " \ - packagegroup-ivi-common-test \ - " diff --git a/meta-agl/recipes-core/images/agl-image-minimal.bb b/meta-agl/recipes-core/images/agl-image-minimal.bb deleted file mode 100644 index 1fd213d0f..000000000 --- a/meta-agl/recipes-core/images/agl-image-minimal.bb +++ /dev/null @@ -1,9 +0,0 @@ -SUMMARY = "An AGL small image just capable of allowing a device to boot." - -require agl-image-minimal.inc - -LICENSE = "MIT" - -IMAGE_INSTALL_append = "\ - packagegroup-agl-image-minimal \ - " diff --git a/meta-agl/recipes-core/images/agl-image-minimal.inc b/meta-agl/recipes-core/images/agl-image-minimal.inc deleted file mode 100644 index 825393978..000000000 --- a/meta-agl/recipes-core/images/agl-image-minimal.inc +++ /dev/null @@ -1,10 +0,0 @@ -IMAGE_LINGUAS = " " - -inherit core-image - -IMAGE_INSTALL = "${CORE_IMAGE_EXTRA_INSTALL}" - -IMAGE_ROOTFS_SIZE ?= "8192" - -# Allow extra IMAGE_FSTYPES to be added by boards configs -IMAGE_FSTYPES += "${AGL_EXTRA_IMAGE_FSTYPES}" diff --git a/meta-agl/recipes-core/packagegroups/packagegroup-agl-core-automotive.bb b/meta-agl/recipes-core/packagegroups/packagegroup-agl-core-automotive.bb deleted file mode 100644 index d9f2279e1..000000000 --- a/meta-agl/recipes-core/packagegroups/packagegroup-agl-core-automotive.bb +++ /dev/null @@ -1,13 +0,0 @@ -DESCRIPTION = "The minimal set of packages for Automotive Subsystem" -LICENSE = "MIT" - -inherit packagegroup - -PACKAGES = "\ - packagegroup-agl-core-automotive \ - " - -ALLOW_EMPTY_${PN} = "1" - -RDEPENDS_${PN} += "\ - " diff --git a/meta-agl/recipes-core/packagegroups/packagegroup-agl-core-connectivity.bb b/meta-agl/recipes-core/packagegroups/packagegroup-agl-core-connectivity.bb deleted file mode 100644 index e909d5e5f..000000000 --- a/meta-agl/recipes-core/packagegroups/packagegroup-agl-core-connectivity.bb +++ /dev/null @@ -1,15 +0,0 @@ -DESCRIPTION = "The minimal set of packages for Connectivity Subsystem" -LICENSE = "MIT" - -inherit packagegroup - -PACKAGES = "\ - packagegroup-agl-core-connectivity \ - " - -ALLOW_EMPTY_${PN} = "1" - -RDEPENDS_${PN} += "\ - dhcp-server \ - ${@bb.utils.contains('VIRTUAL-RUNTIME_net_manager','connman','connman connman-client connman-tests connman-tools connman-ncurses','',d)} \ - " diff --git a/meta-agl/recipes-core/packagegroups/packagegroup-agl-core-graphics.bb b/meta-agl/recipes-core/packagegroups/packagegroup-agl-core-graphics.bb deleted file mode 100644 index 1cc6f457b..000000000 --- a/meta-agl/recipes-core/packagegroups/packagegroup-agl-core-graphics.bb +++ /dev/null @@ -1,10 +0,0 @@ -DESCRIPTION = "The minimal set of packages for Graphics Subsystem" -LICENSE = "MIT" - -inherit packagegroup - -PACKAGES = "\ - packagegroup-agl-core-graphics \ - " - -ALLOW_EMPTY_${PN} = "1" diff --git a/meta-agl/recipes-core/packagegroups/packagegroup-agl-core-kernel.bb b/meta-agl/recipes-core/packagegroups/packagegroup-agl-core-kernel.bb deleted file mode 100644 index 3d5556fd5..000000000 --- a/meta-agl/recipes-core/packagegroups/packagegroup-agl-core-kernel.bb +++ /dev/null @@ -1,13 +0,0 @@ -DESCRIPTION = "The minimal set of packages for Kernel Subsystem" -LICENSE = "MIT" - -inherit packagegroup - -PACKAGES = "\ - packagegroup-agl-core-kernel \ - " - -ALLOW_EMPTY_${PN} = "1" - -RDEPENDS_${PN} += "\ - " diff --git a/meta-agl/recipes-core/packagegroups/packagegroup-agl-core-multimedia.bb b/meta-agl/recipes-core/packagegroups/packagegroup-agl-core-multimedia.bb deleted file mode 100644 index 01ca4cb85..000000000 --- a/meta-agl/recipes-core/packagegroups/packagegroup-agl-core-multimedia.bb +++ /dev/null @@ -1,13 +0,0 @@ -DESCRIPTION = "The minimal set of packages for Multimedia Subsystem" -LICENSE = "MIT" - -inherit packagegroup - -PACKAGES = "\ - packagegroup-agl-core-multimedia \ - " - -ALLOW_EMPTY_${PN} = "1" - -RDEPENDS_${PN} += "\ - " diff --git a/meta-agl/recipes-core/packagegroups/packagegroup-agl-core-navi-lbs.bb b/meta-agl/recipes-core/packagegroups/packagegroup-agl-core-navi-lbs.bb deleted file mode 100644 index 2b04d5387..000000000 --- a/meta-agl/recipes-core/packagegroups/packagegroup-agl-core-navi-lbs.bb +++ /dev/null @@ -1,13 +0,0 @@ -DESCRIPTION = "The minimal set of packages for Navigation and Location Based Services Subsystem" -LICENSE = "MIT" - -inherit packagegroup - -PACKAGES = "\ - packagegroup-agl-core-navi-lbs \ - " - -ALLOW_EMPTY_${PN} = "1" - -RDEPENDS_${PN} += "\ - " diff --git a/meta-agl/recipes-core/packagegroups/packagegroup-agl-core-os-commonlibs.bb b/meta-agl/recipes-core/packagegroups/packagegroup-agl-core-os-commonlibs.bb deleted file mode 100644 index c44166e12..000000000 --- a/meta-agl/recipes-core/packagegroups/packagegroup-agl-core-os-commonlibs.bb +++ /dev/null @@ -1,13 +0,0 @@ -DESCRIPTION = "The minimal set of packages for Operating System and Common libraries Subsystem" -LICENSE = "MIT" - -inherit packagegroup - -PACKAGES = "\ - packagegroup-agl-core-os-commonlibs \ - " - -ALLOW_EMPTY_${PN} = "1" - -RDEPENDS_${PN} += "\ - " diff --git a/meta-agl/recipes-core/packagegroups/packagegroup-agl-core-security.bb b/meta-agl/recipes-core/packagegroups/packagegroup-agl-core-security.bb deleted file mode 100644 index eb5a68f0a..000000000 --- a/meta-agl/recipes-core/packagegroups/packagegroup-agl-core-security.bb +++ /dev/null @@ -1,13 +0,0 @@ -DESCRIPTION = "The minimal set of packages for Security Subsystem" -LICENSE = "MIT" - -inherit packagegroup - -PACKAGES = "\ - packagegroup-agl-core-security \ - " - -ALLOW_EMPTY_${PN} = "1" - -RDEPENDS_${PN} += "\ - " diff --git a/meta-agl/recipes-core/packagegroups/packagegroup-agl-core-speech-services.bb b/meta-agl/recipes-core/packagegroups/packagegroup-agl-core-speech-services.bb deleted file mode 100644 index a494e5889..000000000 --- a/meta-agl/recipes-core/packagegroups/packagegroup-agl-core-speech-services.bb +++ /dev/null @@ -1,13 +0,0 @@ -DESCRIPTION = "The minimal set of packages for Speech Services Subsystem" -LICENSE = "MIT" - -inherit packagegroup - -PACKAGES = "\ - packagegroup-agl-core-speech-services \ - " - -ALLOW_EMPTY_${PN} = "1" - -RDEPENDS_${PN} += "\ - " diff --git a/meta-agl/recipes-core/packagegroups/packagegroup-agl-image-minimal.bb b/meta-agl/recipes-core/packagegroups/packagegroup-agl-image-minimal.bb deleted file mode 100644 index 630c11d43..000000000 --- a/meta-agl/recipes-core/packagegroups/packagegroup-agl-image-minimal.bb +++ /dev/null @@ -1,27 +0,0 @@ -DESCRIPTION = "The minimal set of packages required by AGL" -LICENSE = "MIT" - -inherit packagegroup - -PACKAGES = "\ - packagegroup-agl-image-minimal \ - " - -ALLOW_EMPTY_${PN} = "1" - -RDEPENDS_${PN} += "\ - packagegroup-core-boot-agl \ - " - - -RDEPENDS_${PN} += "\ - packagegroup-agl-core-automotive \ - packagegroup-agl-core-connectivity \ - packagegroup-agl-core-graphics \ - packagegroup-agl-core-multimedia \ - packagegroup-agl-core-navi-lbs \ - packagegroup-agl-core-os-commonlibs \ - packagegroup-agl-core-speech-services \ - packagegroup-agl-core-security \ - packagegroup-agl-core-kernel \ - " diff --git a/meta-agl/recipes-core/packagegroups/packagegroup-core-boot-agl.bb b/meta-agl/recipes-core/packagegroups/packagegroup-core-boot-agl.bb deleted file mode 100644 index c9d679879..000000000 --- a/meta-agl/recipes-core/packagegroups/packagegroup-core-boot-agl.bb +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright (C) 2007 OpenedHand Ltd. -# -# derived from oe-core: meta/recipes-core/packagegroups/packagegroup-core-boot.bb - -SUMMARY = "Minimal boot requirements" -DESCRIPTION = "The minimal set of packages required to boot the system" -LICENSE = "MIT" - -PACKAGE_ARCH = "${MACHINE_ARCH}" - -inherit packagegroup - -# -# Set by the machine configuration with packages essential for device bootup -# -MACHINE_ESSENTIAL_EXTRA_RDEPENDS ?= "" -MACHINE_ESSENTIAL_EXTRA_RRECOMMENDS ?= "" - -# Distro can override the following VIRTUAL-RUNTIME providers: -VIRTUAL-RUNTIME_dev_manager ?= "udev" -VIRTUAL-RUNTIME_login_manager ?= "busybox" -VIRTUAL-RUNTIME_init_manager ?= "sysvinit" -VIRTUAL-RUNTIME_initscripts ?= "initscripts" -VIRTUAL-RUNTIME_keymaps ?= "keymaps" - -SYSVINIT_SCRIPTS = "${@bb.utils.contains('MACHINE_FEATURES', 'rtc', 'busybox-hwclock', '', d)} \ - modutils-initscripts \ - init-ifupdown \ - ${VIRTUAL-RUNTIME_initscripts} \ - " - -RDEPENDS_${PN} = "\ - base-files \ - base-passwd \ - busybox \ - run-agl-postinsts \ - ${@bb.utils.contains("DISTRO_FEATURES", "sysvinit", "${SYSVINIT_SCRIPTS}", "", d)} \ - ${@bb.utils.contains("MACHINE_FEATURES", "keyboard", "${VIRTUAL-RUNTIME_keymaps}", "", d)} \ - netbase \ - ${VIRTUAL-RUNTIME_login_manager} \ - ${VIRTUAL-RUNTIME_init_manager} \ - ${VIRTUAL-RUNTIME_dev_manager} \ - ${VIRTUAL-RUNTIME_update-alternatives} \ - ${MACHINE_ESSENTIAL_EXTRA_RDEPENDS}" - -RRECOMMENDS_${PN} = "\ - tzdata \ - ${MACHINE_ESSENTIAL_EXTRA_RRECOMMENDS}" - diff --git a/meta-agl/recipes-core/psplash/.appends.core b/meta-agl/recipes-core/psplash/.appends.core deleted file mode 100644 index e69de29bb..000000000 diff --git a/meta-agl/recipes-core/psplash/files/psplash-anim b/meta-agl/recipes-core/psplash/files/psplash-anim deleted file mode 100755 index ac9bf674a..000000000 --- a/meta-agl/recipes-core/psplash/files/psplash-anim +++ /dev/null @@ -1,11 +0,0 @@ -#/bin/bash - -psplash-default "$@" & -sleep .2 -while :; do - for x in 0 1 2 3 4 5 6 7 8 9 10 -9 -8 -7 -6 -5 -4 -3 -2 -1 0 -1 -2 -3 -4 -5 -6 -7 -8 -9 10 9 8 7 6 5 4 3 2 1; do - psplash-write "PROGRESS ${x}0" || exit 0 - psplash-write "MSG $(journalctl -n1 -ocat)" || exit 0 - sleep .1 - done -done diff --git a/meta-agl/recipes-core/psplash/files/psplash-colors.h b/meta-agl/recipes-core/psplash/files/psplash-colors.h deleted file mode 100644 index 447490397..000000000 --- a/meta-agl/recipes-core/psplash/files/psplash-colors.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * pslash - a lightweight framebuffer splashscreen for embedded devices. - * - * Copyright (c) 2012 sleep(5) ltd - * Author: Tomas Frydrych - * - * This program is free software; you can redistribute 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. - * - */ - -#ifndef _HAVE_PSPLASH_COLORS_H -#define _HAVE_PSPLASH_COLORS_H - -/* This is the overall background color */ -#define PSPLASH_BACKGROUND_COLOR 0xff,0xff,0xff - -/* This is the color of any text output */ -#define PSPLASH_TEXT_COLOR 0x00,0x00,0x00 - -/* This is the color of the progress bar indicator */ -#define PSPLASH_BAR_COLOR 0x00,0x00,0x00 - -/* This is the color of the progress bar background */ -#define PSPLASH_BAR_BACKGROUND_COLOR 0xff,0xff,0xff - -#endif diff --git a/meta-agl/recipes-core/psplash/files/psplash-poky-img.h b/meta-agl/recipes-core/psplash/files/psplash-poky-img.h deleted file mode 100644 index c0e8b0818..000000000 --- a/meta-agl/recipes-core/psplash/files/psplash-poky-img.h +++ /dev/null @@ -1,5411 +0,0 @@ -/* GdkPixbuf RGB C-Source image dump 1-byte-run-length-encoded */ - -#define POKY_IMG_ROWSTRIDE (1800) -#define POKY_IMG_WIDTH (600) -#define POKY_IMG_HEIGHT (400) -#define POKY_IMG_BYTES_PER_PIXEL (3) /* 3:RGB, 4:RGBA */ -#define POKY_IMG_RLE_PIXEL_DATA ((uint8*) \ - "\377\377\377\377\377\377\377\377\203\377\377\377\1\376\376\376\221\377" \ - "\377\377\1\376\376\376\215\377\377\377\1\376\376\376\203\377\377\377" \ - "\1\376\376\376\233\377\377\377\1\376\376\376\203\377\377\377\1\376\376" \ - "\376\202\377\377\377\5\376\376\376\377\377\377\376\376\376\377\377\377" \ - "\376\376\376\206\377\377\377\1\376\376\376\203\377\377\377\1\376\376" \ - "\376\204\377\377\377\1\376\376\376\203\377\377\377\5\376\376\376\377" \ - "\377\377\376\376\376\377\377\377\376\376\376\377\377\377\377\377\377" \ - "\377\377\377\377\377\377\377\377\377\377\202\376\376\376\207\377\377" \ - "\377\1\376\376\376\205\377\377\377\1\376\376\376\211\377\377\377\3\376" \ - "\376\376\377\377\377\376\376\376\235\377\377\377\1\376\376\376\203\377" \ - "\377\377\1\376\376\376\213\377\377\377\3\376\376\376\377\377\377\376" \ - "\376\376\216\377\377\377\1\376\376\376\202\377\377\377\1\376\376\376" \ - "\377\377\377\377\377\377\377\377\377\377\377\377\365\377\377\377\1\376" \ - "\376\376\203\377\377\377\1\376\376\376\207\377\377\377\1\376\376\376" \ - "\203\377\377\377\1\376\376\376\202\377\377\377\1\376\376\376\205\377" \ - "\377\377\1\376\376\376\203\377\377\377\12\376\376\376\377\377\377\346" \ - "\346\346\315\315\315\316\316\316\265\265\265\235\235\235\234\234\234" \ - "\233\233\233\204\204\204\203kkm\202lln\2EEG;;=\215::<\204kkm\3kkkxxx" \ - "\235\235\235\202\234\234\234\1\265\265\265\202\316\316\316\1\332\332" \ - "\332\207\377\377\377\202\376\376\376\2\377\377\377\376\376\376\211\377" \ - "\377\377\3\376\376\376\377\377\377\376\376\376\203\377\377\377\5\376" \ - "\376\376\377\377\377\376\376\376\377\377\377\376\376\376\377\377\377" \ - "\377\377\377\377\377\377\377\377\377\366\377\377\377\1\376\376\376\205" \ - "\377\377\377\1\376\376\376\214\377\377\377\11\376\376\376\332\332\332" \ - "\316\316\320\247\247\251\236\236\240\204\204\206kkm__a<<>\202::<\11;" \ - ";=99;;;=99;::<;;=::<;;=99;\203::<\1<<>\213::<\13;;=::<;;=::<;;=::<;;" \ - "=::<;;=::<;;=\207::<\3SSUllnxxz\202\234\234\236\202\316\316\316\2\377" \ - "\377\377\376\376\376\214\377\377\377\1\376\376\376\203\377\377\377\1" \ - "\376\376\376\377\377\377\377\377\377\377\377\377\377\377\377\376\377" \ - "\377\377\1\376\376\376\203\377\377\377\1\376\376\376\203\377\377\377" \ - "\7\332\332\334\302\302\304\234\234\236\203\203\205llnEEG;;=\202::<\6" \ - ";;=::<;;=::<;;=99;\204::<\1""99;\202;;=\1""99;\205::<\1;;=\213::<\11" \ - ";;=::<;;=::<;;=::<;;=::<;;=\202::<\1""99;\206::<\1;;=\203::<\13;;=99" \ - ";;;=::<;;=::\202::<\7llnkkm\233" \ - "\233\235\235\235\237\302\302\304\316\316\320\347\347\351\241\377\377" \ - "\377\202\376\376\376\203\377\377\377\17\376\376\376\377\377\377\376\376" \ - "\376\377\377\377\376\376\376\363\363\363\316\316\316\315\315\315\234" \ - "\234\234\235\235\235xxxllnFFH::<;;=\205::<\5;;=99;;;=::<;;=\212::<\202" \ - ";;=\212::<\5;;=99;;;=::<99;\202::<\5__a\250\250\252\346\346\346\377\377" \ - "\377\376\376\376\202\377\377\377\1\376\376\376\377\377\377\377\377\377" \ - "\377\377\377\377\377\377\271\377\377\377\202\376\376\376\2\377\377\377" \ - "\376\376\376\203\377\377\377\3\363\363\363\266\266\266wwy\202;;=\210" \ - "::<\1<<>\203::<\2<<>99;\215::<\1;;=\205::<\11;;=::<;;;___xxx\235\235" \ - "\235\266\266\266\315\315\315\364\364\364\207\377\377\377\1\376\376\376" \ - "\213\377\377\377\1\376\376\376\231\377\377\377\5\376\376\376\377\377" \ - "\377\376\376\376\377\377\377\376\376\376\202\377\377\377\1\376\376\376" \ - "\204\377\377\377\1\376\376\376\202\377\377\377\5\316\316\316\302\302" \ - "\302\233\233\233yyykkk\202::<\6;;=::<;;=::<99;;;=\211::<\1;;=\202::<" \ - "\1;;=\206::<\1""99;\202;;=\202::<\203;;=\1""99;\202::<\3__a\251\251\253" \ - "\346\346\346\204\377\377\377\3\376\376\376\377\377\377\376\376\376\377" \ - "\377\377\377\377\377\377\377\377\377\377\377\266\377\377\377\1\376\376" \ - "\376\202\377\377\377\2\302\302\302xxx\203::<\3;;=::<;;=\232::<\1;;=\202" \ - "::<\6RRTkkm\235\235\237\301\301\303\332\332\334\376\376\376\222\377\377" \ - "\377\1\376\376\376\260\377\377\377\3\376\376\376\377\377\377\376\376" \ - "\376\202\377\377\377\5\345\345\347\316\316\320\235\235\237xxzSSU\215" \ - "::<\202;;=\202::<\203;;=\2::<;;=\203::<\1;;=\204::<\10;;=::<;;=::<;;" \ - "=kkm\266\266\266\363\363\363\202\377\377\377\1\376\376\376\377\377\377" \ - "\377\377\377\377\377\377\377\377\377\245\377\377\377\1\376\376\376\214" \ - "\377\377\377\1\376\376\376\202\377\377\377\5\376\376\376\377\377\377" \ - "\332\332\332\205\205\207GGI\202::<\1;;=\211::<\202;;=\205::<\2;;=::<" \ - "\202;;=\203::<\14;;=99;::<;;=99;;;=FFFxxx\234\234\234\315\315\315\364" \ - "\364\364\376\376\376\323\377\377\377\4\317\317\317\250\250\250xxxSSS" \ - "\202::<\1;;=\206::<\2;;=::<\203;;=\202::<\2;;=99;\204::<\7;;=::<;;=:" \ - ":<;;=::<;;=\204::<\3\204\204\206\301\301\301\376\376\376\220\377\377" \ - "\377\1\376\376\376\377\377\377\377\377\377\377\377\377\377\377\377\225" \ - "\377\377\377\1\376\376\376\203\377\377\377\1\376\376\376\206\377\377" \ - "\377\1\376\376\376\202\377\377\377\4\363\363\363\251\251\251___;;=\202" \ - "::<\1;;=\202::<\202;;=\204::<\1;;=\202::<\7;;=::<;;=::<;;=::<;;=\203" \ - "::<\3""99;::<;;=\202::<\5;;=__a\221\221\223\265\265\267\346\346\346\323" \ - "\377\377\377\1\376\376\376\211\377\377\377\5\363\363\363\301\301\303" \ - "\235\235\237lln::<\202;;=\203::<\1;;=\204::<\1;;=\202::<\2""99;;;=\205" \ - "::<\2;;=99;\203::<\1""99;\204::<\3TTT\233\233\233\346\346\346\207\377" \ - "\377\377\1\376\376\376\377\377\377\377\377\377\377\377\377\377\377\377" \ - "\250\377\377\377\3\316\316\316\204\204\204;;=\203::<\1;;=\203::<\1;;" \ - "=\202::<\1;;=\205::<\3;;=::<;;=\202::<\4""99;;;=::<;;=\202::<\202;;=" \ - "\4___\221\221\221\301\301\303\363\363\365\203\377\377\377\1\376\376\376" \ - "\203\377\377\377\202\376\376\376\321\377\377\377\1\376\376\376\210\377" \ - "\377\377\1\376\376\376\202\377\377\377\4\316\316\316\235\235\235kkk;" \ - ";=\202::<\202;;=\203::<\5;;=::<;;=99;;;=\204::<\202;;=\7::<;;=99;::<" \ - ";;=::<;;=\202::<\202;;=\2xxz\302\302\304\213\377\377\377\1\376\376\376" \ - "\377\377\377\377\377\377\377\377\377\377\377\377\224\377\377\377\1\376" \ - "\376\376\212\377\377\377\3\363\363\363\266\266\266TTV\203::<\3;;=::<" \ - ";;=\202::<\203;;=\202::<\202;;=\205::<\1;;=\202::<\1;;=\204::<\4SSU\221" \ - "\221\223\301\301\301\363\363\363\206\377\377\377\1\376\376\376\203\377" \ - "\377\377\1\376\376\376\202\377\377\377\1\376\376\376\315\377\377\377" \ - "\202\376\376\376\202\377\377\377\1\376\376\376\210\377\377\377\1\376" \ - "\376\376\202\377\377\377\1\376\376\376\202\377\377\377\3\316\316\316" \ - "\221\221\223__a\203::<\1;;=\203::<\3;;=::<;;=\203::<\5;;=99;;;=::<;;" \ - "=\204::<\1""99;\205::<\3SSU\234\234\236\346\346\346\207\377\377\377\3" \ - "\376\376\376\377\377\377\376\376\376\377\377\377\377\377\377\377\377" \ - "\377\377\377\377\233\377\377\377\4\376\376\376\347\347\347\221\221\221" \ - "FFH\207::<\4""99;;;=::<;;=\20299;\202;;=\202::<\1;;=\203::<\2;;=::<\202" \ - ";;=\202::<\3xxz\250\250\252\346\346\350\215\377\377\377\203\376\376\376" \ - "\316\377\377\377\1\376\376\376\202\377\377\377\1\376\376\376\211\377" \ - "\377\377\1\376\376\376\211\377\377\377\4\363\363\363\265\265\267\205" \ - "\205\207FFH\210::<\3;;=::<;;=\204::<\1;;=\207::<\2;;=::<\202;;=\2\203" \ - "\203\205\317\317\321\206\377\377\377\1\376\376\376\377\377\377\377\377" \ - "\377\377\377\377\377\377\377\233\377\377\377\3\316\316\316yy{99;\206" \ - "::<\2;;=99;\202;;=\205::<\5""99;::<;;=::<;;=\202::<\6;;=::<;;=SSU\204" \ - "\204\204\301\301\301\226\377\377\377\1\376\376\376\317\377\377\377\1" \ - "\376\376\376\203\377\377\377\1\376\376\376\204\377\377\377\1\376\376" \ - "\376\204\377\377\377\1\376\376\376\205\377\377\377\1\376\376\376\202" \ - "\377\377\377\3\316\316\316\221\221\221SSU\203::<\3;;=::<99;\204::<\1" \ - ";;=\203::<\2""99;;;=\202::<\1;;=\204::<\5""99;<<>::99;\202::<\4""99;;;=F" \ - "FF\234\234\234\377\377\377\377\377\377\377\377\375\377\377\377\11\316" \ - "\316\320kkm::<;;=::<;;=99;::<;;=\203::<\202;;=\2::<99;\205::<\13;;=F" \ - "FH\221\221\221\346\346\346\376\376\376\377\377\377\376\376\376\377\377" \ - "\377\376\376\376\377\377\377\376\376\376\204\377\377\377\1\376\376\376" \ - "\273\377\377\377\2\376\376\376\317\317\317\212::<\6;;=;;;\316\316\316" \ - "\376\376\376\377\377\377\376\376\376\304\377\377\377\1\376\376\376\206" \ - "\377\377\377\5\376\376\376\377\377\377\376\376\376\377\377\377\376\376" \ - "\376\204\377\377\377\4\363\363\363\235\235\235RRT;;=\202::<\202;;=\7" \ - "::<;;=99;::<;;=::<;;=\203::<\1;;=\202::<\6;;=::\202::<\2FFH\331\331\333\377\377\377\377\205\377" \ - "\377\377\1\316\316\316\214::<\1\316\316\316\377\377\377\377\216\377\377" \ - "\377\1\376\376\376\203\377\377\377\4\376\376\376\377\377\377\363\363" \ - "\363__a\204::<\2;;=99;\206::<\2;;=\204\204\204\203\377\377\377\1\376" \ - "\376\376\377\377\377\377\377\377\377\377\220\377\377\377\1\204\204\204" \ - "\205::<\1;;=\203::<\1;;=\203::<\4__a\363\363\363\377\377\377\376\376" \ - "\376\377\377\377\377\204\377\377\377\1\316\316\316\214::<\1\316\316\316" \ - "\377\377\377\377\224\377\377\377\4\376\376\376\363\363\363xxx::<\202" \ - ";;=\202::<\1;;=\203::<\1;;=\203::<\1\205\205\207\204\377\377\377\1\376" \ - "\376\376\377\377\377\377\377\377\377\377\215\377\377\377\1\250\250\250" \ - "\205::<\1;;=\203::<\12;;=99;;;=::<__a\363\363\365\377\377\377\376\376" \ - "\376\377\377\377\376\376\376\377\377\377\377\203\377\377\377\1\316\316" \ - "\316\214::<\1\316\316\316\377\377\377\377\227\377\377\377\5\204\204\204" \ - "::<;;=::<;;=\204::<\1""99;\204::<\1\204\204\204\377\377\377\377\377\377" \ - "\377\377\213\377\377\377\1\376\376\376\202\377\377\377\4\376\376\376" \ - "\377\377\377\265\265\267;;=\212::<\4;;=::<__a\363\363\363\217\377\377" \ - "\377\1\376\376\376\367\377\377\377\1\316\316\316\214::<\1\316\316\316" \ - "\376\377\377\377\202\377\377\375\3\377\376\377\377\377\377\376\377\375" \ - "\224\377\377\377\3\204\204\206::<;;=\211::<\7""99;::<\203\203\205\377" \ - "\377\377\376\376\376\377\377\377\376\376\376\205\377\377\377\1\376\376" \ - "\376\202\377\377\377\202\376\376\376\377\377\377\377\377\377\377\377" \ - "\2\264\264\266;;=\202::<\202;;=\1""99;\207::<\2__a\363\363\365\217\377" \ - "\377\377\3\376\376\376\377\377\377\376\376\376\366\377\377\377\1\316" \ - "\316\316\214::<\1\316\316\316\375\377\377\377\5\377\377\375\377\376\377" \ - "\377\375\377\377\377\375\377\377\377\202\377\376\377\221\377\377\377" \ - "\1\376\376\376\202\377\377\377\1\204\204\206\203::<\1;;=\202::<\2;;=" \ - "::<\202;;=\202::<\3;;=\204\204\204\376\376\376\211\377\377\377\3\376" \ - "\376\376\377\377\377\376\376\376\377\377\377\377\375\377\377\377\7\376" \ - "\376\376\264\264\266;;=99;::<;;=99;\204::<\1;;=\203::<\2aac\363\363\363" \ - "\221\377\377\377\1\376\376\376\367\377\377\377\1\316\316\316\214::<\1" \ - "\316\316\316\375\377\377\377\202\376\376\376\203\377\377\377\202\376" \ - "\377\377\222\377\377\377\10\376\376\376\377\377\377\376\376\376\204\204" \ - "\206::<;;=::<;;=\203::<\202;;=\202::<\6""99;;;=\205\205\207\376\376\376" \ - "\377\377\377\376\376\376\203\377\377\377\202\376\376\376\202\377\377" \ - "\377\1\376\376\376\377\377\377\377\375\377\377\377\3\376\376\376\302" \ - "\302\304;;=\203::<\1;;=\204::<\6;;=99;;;=::\202::<\2__a\363\363\365\202\377\377\377\1" \ - "\376\376\376\213\377\377\377\1\376\376\376\375\377\377\377\1\316\316" \ - "\316\214::<\1\316\316\316\374\377\377\377\7\377\376\377\376\377\377\376" \ - "\376\374\377\376\377\377\377\375\376\377\377\377\377\375\226\377\377" \ - "\377\1\376\376\376\202\377\377\377\1\203\203\203\214::<\2;;=\265\265" \ - "\265\206\377\377\377\1\376\376\376\377\377\377\377\374\377\377\377\4" \ - "\364\364\364GGI99;;;=\206::<\1;;=\203::<\2__a\363\363\363\205\377\377" \ - "\377\1\376\376\376\212\377\377\377\1\363\363\363\203\377\377\377\1\376" \ - "\376\376\370\377\377\377\1\316\316\316\214::<\1\316\316\316\374\377\377" \ - "\377\10\377\377\375\377\376\377\377\377\377\377\377\375\377\376\377\370" \ - "\373\362\370\373\364\377\376\377\220\377\377\377\1\376\376\376\202\377" \ - "\377\377\1\376\376\376\202\377\377\377\1\376\376\376\202\377\377\377" \ - "\1\204\204\204\203::<\1;;=\210::<\2FFH\332\332\334\204\377\377\377\1" \ - "\376\376\376\377\377\377\377\374\377\377\377\3\363\363\363___;;=\202" \ - "::<\1;;=\204::<\6;;=99;;;=::<__a\363\363\365\220\377\377\377\3\265\265" \ - "\265FFF\333\333\333\373\377\377\377\1\316\316\316\214::<\1\316\316\316" \ - "\376\377\377\377\6\374\377\377\377\377\375\371\374\365\242\320c\240\322" \ - "c\371\372\362\221\377\377\377\1\376\376\376\210\377\377\377\2\203\203" \ - "\203;;=\202::<\1;;=\203::<\1;;=\203::<\3;;=FFH\333\333\333\202\377\377" \ - "\377\1\376\376\376\377\377\377\377\371\377\377\377\1\376\376\376\203" \ - "\377\377\377\2kkm::<\202;;=\1""99;\205::<\202;;=\3::<__a\363\363\363" \ - "\220\377\377\377\5\265\265\267::<;;=FFH\332\332\332\206\377\377\377\3" \ - "\376\376\376\377\377\377\376\376\376\361\377\377\377\1\316\316\316\213" \ - "::<\2;;=\316\316\316\365\377\377\377\22\376\376\377\377\377\375\377\377" \ - "\377\377\377\375\377\377\377\377\376\377\377\377\375\377\377\377\376" \ - "\376\377\377\377\377\371\374\365\242\320c\215\307\77\215\305@\242\322" \ - "e\372\373\365\376\377\375\377\376\377\230\377\377\377\3\205\205\207:" \ - ":<;;=\206::<\1;;=\202::<\4;;=SSU\363\363\365\376\376\376\377\377\377" \ - "\377\374\377\377\377\13\376\376\376\204\204\204::<;;=99;::<;;=::<;;=" \ - "::<;;=\203::<\3__a\364\364\366\376\376\376\217\377\377\377\1\265\265" \ - "\267\203::<\3;;=FFF\332\332\332\206\377\377\377\1\376\376\376\361\377" \ - "\377\377\2\376\376\376\317\317\317\212::<\6;;=;;;\316\316\316\376\376" \ - "\376\377\377\377\376\376\376\361\377\377\377\6\376\376\377\377\376\377" \ - "\375\376\377\376\377\377\377\377\375\375\377\376\202\377\377\377\17\376" \ - "\376\376\377\377\377\371\372\364\240\322a\215\305@\212\307>\215\307\77" \ - "\215\305>\242\320c\370\372\365\377\377\377\377\376\377\376\377\375\377" \ - "\377\375\377\376\377\225\377\377\377\5kkm::<;;=99;;;=\210::<\4__a\364" \ - "\364\364\376\376\376\377\377\377\202\376\376\376\377\377\377\377\363" \ - "\377\377\377\3\376\376\376\377\377\377\376\376\376\202\377\377\377\4" \ - "\250\250\252::<;;=99;\202;;=\205::<\202;;=\3FFH\345\345\345\376\376\376" \ - "\217\377\377\377\4\264\264\266;;=::<;;=\203::<\2GGI\332\332\332\203\377" \ - "\377\377\1\376\376\376\356\377\377\377\1\376\376\376\205\377\377\377" \ - "\2\315\315\315;;;\211::<\3;;;:::\315\315\315\202\377\377\377\1\376\376" \ - "\376\361\377\377\377\23\377\377\375\375\376\377\376\377\377\376\377\375" \ - "\377\374\377\377\377\375\375\377\376\377\377\377\377\377\375\371\372" \ - "\364\242\321g\215\306A\212\307>\215\306A\212\306@\214\305@\212\306B\241" \ - "\322_\367\372\361\204\377\377\377\1\377\377\375\220\377\377\377\1\376" \ - "\376\376\203\377\377\377\3\363\363\363__a99;\202::<\6;;=::<99;;;=99;" \ - ";;=\203::<\1\205\205\207\204\377\377\377\1\376\376\376\377\377\377\377" \ - "\362\377\377\377\1\376\376\376\202\377\377\377\22\376\376\376\265\265" \ - "\267::<99;;;=::<;;=99;;;=::<;;=::<;;=::\214\305@\214" \ - "\306>\202\214\305@\4\241\321a\371\374\365\376\376\377\377\377\375\202" \ - "\376\377\377\221\377\377\377\1\376\376\376\203\377\377\377\3\362\362" \ - "\362``b99;\205::<\1;;=\203::<\6;;=99;\235\235\237\376\376\376\377\377" \ - "\377\376\376\376\377\377\377\377\366\377\377\377\2\332\332\332FFH\202" \ - ";;=\4""99;;;=::<;;=\205::<\2FFH\332\332\334\202\377\377\377\3\376\376" \ - "\376\377\377\377\376\376\376\213\377\377\377\4\266\266\26699;::<;;=\202" \ - "::<\1;;=\202::<\4;;=::\215\305" \ - "@\212\306@\213\310=\214\306<\216\306\77\214\304=\214\306>\241\321c\372" \ - "\375\362\376\376\376\377\376\377\376\376\374\220\377\377\377\2\376\376" \ - "\376\377\377\377\203\376\376\376\4\377\377\377\364\364\364FFH;;=\202" \ - "::<\1;;=\202::<\1;;=\203::<\3;;=::<\265\265\265\377\377\377\377\367\377" \ - "\377\377\4\362\362\362SSU::<;;=\205::<\1""99;\202;;=\3::<;;=\265\265" \ - "\267\216\377\377\377\3\376\376\376\377\377\377\265\265\265\202::<\5;" \ - ";=99;;;=::<;;=\204::<\4;;=FFH\332\332\332\376\376\376\205\377\377\377" \ - "\1\376\376\376\355\377\377\377\1\376\376\376\214\377\377\377\1\376\376" \ - "\376\366\377\377\377\1\375\377\376\202\377\377\375\24\377\377\377\376" \ - "\376\376\373\373\363\243\322b\213\307A\214\306>\215\305@\214\305@\212" \ - "\307>\214\306>\215\305>\213\307A\214\305@\216\310@\214\306>\215\305>" \ - "\242\320c\366\373\364\375\377\376\377\376\377\221\377\377\377\1\376\376" \ - "\376\204\377\377\377\3\376\376\376\333\333\333EEG\202;;=\2::<;;=\207" \ - "::<\3GGI\332\332\332\376\376\376\377\377\377\377\365\377\377\377\1__" \ - "a\205::<\10;;=::<;;=::<;;=::<;;=\265\265\265\202\377\377\377\3\376\376" \ - "\376\377\377\377\376\376\376\213\377\377\377\1\266\266\266\203::<\5""9" \ - "9;<<>::<;;=::<\202;;=\203::<\4;;=FFH\333\333\333\376\376\376\202\377" \ - "\377\377\1\376\376\376\355\377\377\377\1\376\376\376\202\377\377\377" \ - "\1\376\376\376\215\377\377\377\1\376\376\376\363\377\377\377\3\377\376" \ - "\377\377\377\377\375\377\376\202\377\377\377\2\373\373\363\241\321d\202" \ - "\214\306>\17\216\306=\215\305@\215\307\77\214\306>\217\304>\214\306>" \ - "\214\305B\215\307\77\211\305A\215\306A\216\306\77\214\305@\242\322e\370" \ - "\373\364\377\377\375\230\377\377\377\1\333\333\335\203::<\202;;=\206" \ - "::<\3;;=FFH\363\363\363\377\377\377\377\364\377\377\377\1\204\204\206" \ - "\203::<\1;;=\207::<\2;;=\204\204\206\220\377\377\377\1\346\346\346\204" \ - "::<\1;;=\203::<\1;;=\202::<\202;;=\203::<\2FFH\332\332\332\357\377\377" \ - "\377\3\376\376\376\377\377\377\376\376\376\377\377\377\377\204\377\377" \ - "\377\1\377\377\375\202\377\377\377\17\377\376\377\370\373\364\243\322" \ - "b\214\306>\213\310\77\212\307>\214\306>\215\306C\212\307>\214\306<\213" \ - "\310\77\214\305@\214\306<\214\306>\216\306\77\203\214\306>\3\214\306" \ - "<\265\334\211\376\376\376\222\377\377\377\1\376\376\376\205\377\377\377" \ - "\4\376\376\377\265\265\267::<;;=\212::<\1___\377\377\377\377\363\377" \ - "\377\377\1\265\265\267\204::<\1;;=\206::<\2;;=\203\203\203\222\377\377" \ - "\377\2\265\265\265;;=\203::<\1;;=\205::<\1;;=\204::<\3;;=FFH\332\332" \ - "\332\206\377\377\377\3\376\376\376\377\377\377\376\376\376\377\377\377" \ - "\377\345\377\377\377\10\376\376\377\377\377\375\377\377\377\377\377\375" \ - "\377\377\377\377\376\377\377\377\375\376\377\377\202\377\377\377\6\370" \ - "\373\362\243\322b\211\307B\213\310=\214\305@\214\306<\202\215\305@\4" \ - "\214\306<\214\305@\214\306<\215\307\77\202\214\306>\6\212\307>\214\306" \ - ">\215\307\77\214\305@\244\317c\367\375\361\233\377\377\377\3\234\234" \ - "\236::<99;\211::<\2;;=\204\204\206\377\377\377\377\360\377\377\377\13" \ - "\376\376\376\332\332\33299;::<99;;;=::<99;;;=::<;;=\202::<\3;;=^^`\364" \ - "\364\364\223\377\377\377\12\265\265\267;;=::<;;=99;;;=::<;;=::<;;=\202" \ - "::<\1;;=\203::<\3;;=FFF\332\332\332\206\377\377\377\1\376\376\376\377" \ - "\377\377\377\345\377\377\377\6\376\376\377\377\376\377\375\376\377\376" \ - "\377\377\377\377\375\375\377\376\203\377\377\377\27\377\377\375\372\373" \ - "\366\241\321a\217\304@\212\307<\214\306>\215\305>\215\305@\213\310=\212" \ - "\306@\214\306>\214\305B\215\307\77\215\305>\215\306A\212\307>\214\306" \ - ">\215\307\77\214\306>\242\322b\370\373\362\376\376\377\377\375\376\233" \ - "\377\377\377\1\204\204\206\203::<\13;;=::<;;=::<;;=::<;;=::<;;=\266\266" \ - "\266\376\376\376\203\377\377\377\1\376\376\376\377\377\377\377\352\377" \ - "\377\377\2\363\363\363TTV\202::<\3;;=99;;;=\204::<\4;;=99;FFH\363\363" \ - "\363\224\377\377\377\7\376\376\376\265\265\265;;=::<;;=::<;;=\203::<" \ - "\1;;=\203::<\1;;=\203::<\2GGI\332\332\332\203\377\377\377\1\376\376\376" \ - "\377\377\377\377\347\377\377\377\7\377\377\375\375\376\377\376\377\377" \ - "\376\377\375\377\374\377\377\377\375\375\377\376\202\377\377\377\5\372" \ - "\373\366\240\320b\215\307\77\212\306@\215\305>\202\214\305@\20\215\305" \ - "@\212\306@\214\305D\216\306\77\214\306>\215\307\77\214\306>\212\306@" \ - "\214\306>\215\307\77\215\305@\242\320c\370\373\362\377\377\373\377\376" \ - "\377\377\377\375\232\377\377\377\3\376\376\376\377\377\377^^`\202;;=" \ - "\205::<\1""99;\202;;=\5::<;;=\332\332\332\377\377\377\376\376\376\377" \ - "\377\377\377\347\377\377\377\1\376\376\376\204\377\377\377\1lln\204:" \ - ":<\202;;=\203::<\6;;=99;GGI\332\332\332\377\377\377\376\376\376\225\377" \ - "\377\377\2\264\264\264;;=\202::<\2""99;;;=\202::<\3""99;;;=::<\202;;" \ - "=\202::<\4;;=::\212\307<\214\306>\214\306<\214\306>\216" \ - "\306\77\215\305<\212\307>\213\307A\215\305>\212\307>\215\307\77\214\306" \ - ">\242\321a\373\374\364\377\377\377\376\377\377\376\376\376\376\377\377" \ - "\234\377\377\377\2\364\364\364RRT\202::<\4""99;;;=::<;;=\205::<\3SSU" \ - "\362\362\362\377\377\377\202\376\376\376\377\377\377\377\351\377\377" \ - "\377\1\234\234\236\204::<\1;;=\203::<\1;;=\203::<\1\265\265\267\231\377" \ - "\377\377\2\265\265\267;;=\203::<\2""99;;;=\202::<\1;;=\202::<\1;;=\202" \ - "::<\4;;=::\212\307>\212\306@\214\305B" \ - "\214\305@\214\305B\214\306>\212\307>\212\310\77\214\306>\217\304@\214" \ - "\306>\214\305@\242\322b\370\373\362\377\377\377\202\377\376\377\1\377" \ - "\377\375\235\377\377\377\3\376\376\376\332\332\334GGI\202;;=\6::<;;=" \ - "99;;;=::<;;=\203::<\1yyy\202\376\376\376\202\377\377\377\1\376\376\376" \ - "\377\377\377\377\345\377\377\377\4\376\376\376\317\317\317::<;;=\202" \ - "::<\3;;=99;;;=\204::<\6;;=\221\221\223\377\377\377\376\376\376\377\377" \ - "\377\376\376\376\226\377\377\377\3\376\376\376\265\265\267;;=\202::<" \ - "\2;;=99;\205::<\1;;=\204::<\4;;=FFH\332\332\332\376\376\376\205\377\377" \ - "\377\1\376\376\376\377\377\377\377\342\377\377\377\1\375\377\376\202" \ - "\377\377\375\34\377\377\377\376\376\376\373\373\363\243\322b\211\307" \ - "B\212\307<\215\305>\214\306>\212\307>\214\305@\217\304>\212\307<\214" \ - "\306<\214\306>\215\307\77\213\307A\214\306>\215\305@\215\307\77\212\307" \ - ">\244\317c\370\373\362\377\377\373\376\377\377\377\376\377\375\376\377" \ - "\377\377\375\377\376\377\236\377\377\377\4\265\265\267::<;;=99;\202;" \ - ";=\205::<\202;;=\1\250\250\250\202\377\377\377\1\376\376\376\377\377" \ - "\377\377\343\377\377\377\1\376\376\376\202\377\377\377\3\363\363\363" \ - "FFH;;=\202::<\5;;=::<;;=::<99;\202;;=\2::\213\310=\214\306>\214" \ - "\305@\213\310=\212\306@\217\304>\202\215\307=\14\214\306>\215\305>\214" \ - "\306>\215\305>\217\304@\215\307\77\215\307=\242\320c\367\375\361\376" \ - "\376\377\377\376\377\376\376\376\202\377\377\375\2\374\377\377\377\376" \ - "\377\234\377\377\377\1\376\376\376\202\377\377\377\10\221\221\221::<" \ - ";;=99;::<;;=::<;;=\205::<\2\333\333\333\376\376\376\377\377\377\377\347" \ - "\377\377\377\1kkk\202::<\1;;=\205::<\1;;=\202::<\2RRT\363\363\365\236" \ - "\377\377\377\1\265\265\267\203::<\2""99;;;=\203::<\1;;=\202::<\202;;" \ - "=\203::<\2FFH\332\332\332\377\377\377\377\346\377\377\377\1\377\377\375" \ - "\202\377\377\377\32\377\376\377\370\373\364\243\322b\214\306>\213\310" \ - "\77\214\305@\215\305>\215\305@\214\306>\214\305B\212\307<\215\307=\214" \ - "\305B\214\306>\215\306A\212\306@\212\307>\214\306>\212\307<\244\317c" \ - "\370\373\364\377\377\377\377\375\376\377\377\375\376\377\377\377\377" \ - "\377\202\377\376\377\241\377\377\377\2kkm::<\202;;=\1""99;\204::<\203" \ - ";;=\2SSU\364\364\364\377\377\377\377\336\377\377\377\3\376\376\376\377" \ - "\377\377\376\376\376\204\377\377\377\2\376\376\376\250\250\252\202::" \ - "<\1;;=\210::<\2FFH\333\333\333\202\377\377\377\1\376\376\376\235\377" \ - "\377\377\2\265\265\265;;=\203::<\1;;=\205::<\1;;=\204::<\3;;=FFH\332" \ - "\332\332\206\377\377\377\3\376\376\376\377\377\377\376\376\376\243\377" \ - "\377\377\4\376\377\377\377\377\375\377\376\377\376\376\377\202\377\377" \ - "\377\2\376\377\375\376\377\377\230\377\377\377\10\376\377\377\377\376" \ - "\377\376\377\377\376\377\375\376\376\376\376\377\377\377\377\377\377" \ - "\376\377\231\377\377\377\7\377\376\377\376\376\374\376\377\377\377\377" \ - "\375\374\377\377\376\377\377\377\376\377\231\377\377\377\17\375\377\374" \ - "\377\377\375\377\377\377\377\376\377\376\377\377\377\376\377\377\377" \ - "\377\376\377\377\376\376\374\377\377\377\377\377\373\377\377\377\376" \ - "\377\377\377\377\377\377\377\375\220\377\377\377\4\377\377\373\377\377" \ - "\377\377\377\375\377\377\377\202\376\377\377\2\377\377\375\377\377\373" \ - "\251\377\377\377\10\376\376\377\377\377\375\377\377\377\377\377\375\377" \ - "\377\377\377\376\377\377\377\375\376\377\377\202\377\377\377\6\370\373" \ - "\362\243\322b\211\307B\213\310=\214\305@\214\306<\202\215\305@\4\214" \ - "\306<\214\305@\214\306<\215\307\77\202\214\306>\6\212\307>\214\306>\215" \ - "\307\77\214\305@\244\317c\367\375\361\251\377\377\377\6\363\363\363T" \ - "TT::<;;=::<;;=\206::<\2;;=www\204\377\377\377\1\376\376\376\377\377\377" \ - "\377\340\377\377\377\2\332\332\332;;=\203::<\3;;=99;;;=\203::<\3;;=:" \ - ":<\265\265\267\204\377\377\377\1\376\376\376\235\377\377\377\12\265\265" \ - "\267;;=::<;;=99;;;=::<;;=::<;;=\202::<\1;;=\203::<\3;;=FFF\332\332\332" \ - "\206\377\377\377\1\376\376\376\244\377\377\377\202\377\377\375\1\377" \ - "\377\377\202\376\377\375\3\376\376\377\377\377\377\377\376\377\230\377" \ - "\377\377\3\376\377\375\377\377\377\377\377\373\202\377\376\377\2\377" \ - "\377\377\376\376\376\231\377\377\377\10\376\377\373\376\375\377\377\377" \ - "\375\377\376\377\377\375\377\377\377\373\377\376\377\377\377\375\230" \ - "\377\377\377\12\377\376\377\377\377\377\377\375\376\376\377\377\376\377" \ - "\372\376\377\377\377\377\377\376\377\375\377\376\377\377\377\375\203" \ - "\377\377\377\202\376\377\375\1\375\376\377\227\377\377\377\1\377\374" \ - "\377\250\377\377\377\6\376\376\377\377\376\377\375\376\377\376\377\377" \ - "\377\377\375\375\377\376\203\377\377\377\27\377\377\375\372\373\366\241" \ - "\321a\217\304@\212\307<\214\306>\215\305>\215\305@\213\310=\212\306@" \ - "\214\306>\214\305B\215\307\77\215\305>\215\306A\212\307>\214\306>\215" \ - "\307\77\214\306>\242\322b\370\373\362\376\376\377\377\375\376\251\377" \ - "\377\377\2\331\331\331;;=\206::<\1;;=\203::<\2;;=\265\265\265\204\377" \ - "\377\377\1\376\376\376\202\377\377\377\1\376\376\376\377\377\377\377" \ - "\322\377\377\377\1\376\376\376\203\377\377\377\3\376\376\376\377\377" \ - "\377\376\376\376\202\377\377\377\2\363\363\363SSU\203::<\2;;=::<\202" \ - ";;=\2""99;;;=\202::<\1\204\204\204\206\377\377\377\1\376\376\376\234" \ - "\377\377\377\7\376\376\376\265\265\265;;=::<;;=::<;;=\203::<\1;;=\203" \ - "::<\1;;=\203::<\2GGI\332\332\332\203\377\377\377\1\376\376\376\247\377" \ - "\377\377\1\377\377\375\202\377\376\377\1\377\375\377\202\377\377\377" \ - "\1\377\376\377\232\377\377\377\6\377\377\375\377\377\377\375\377\376" \ - "\376\377\375\377\377\375\377\375\377\230\377\377\377\202\377\377\375" \ - "\2\377\377\377\376\376\376\202\377\377\377\2\376\377\377\374\377\377" \ - "\230\377\377\377\1\377\377\375\202\377\376\377\1\375\376\377\203\377" \ - "\377\377\1\377\377\375\202\377\377\377\6\376\376\377\377\377\375\377" \ - "\377\377\377\375\377\377\376\377\377\377\375\220\377\377\377\1\376\377" \ - "\377\202\377\377\377\3\376\377\375\376\376\376\377\376\377\252\377\377" \ - "\377\7\377\377\375\375\376\377\376\377\377\376\377\375\377\374\377\377" \ - "\377\375\375\377\376\202\377\377\377\5\372\373\366\240\320b\215\307\77" \ - "\212\306@\215\305>\202\214\305@\20\215\305@\212\306@\214\305D\216\306" \ - "\77\214\306>\215\307\77\214\306>\212\306@\214\306>\215\307\77\215\305" \ - "@\242\320c\370\373\362\377\377\373\377\376\377\377\377\375\252\377\377" \ - "\377\2\250\250\25099;\204::<\12;;=99;::<;;=99;::\212\307<\214\306" \ - ">\214\306<\214\306>\216\306\77\215\305<\212\307>\213\307A\215\305>\212" \ - "\307>\215\307\77\214\306>\242\321a\373\374\364\377\377\377\376\377\377" \ - "\376\376\376\376\377\377\253\377\377\377\1yyy\205::<\3;;=::<99;\202;" \ - ";=\3::<__a\376\376\376\377\377\377\377\335\377\377\377\1\376\376\376" \ - "\202\377\377\377\5\301\301\301::<;;=99;;;=\207::<\2GGI\332\332\332\203" \ - "\377\377\377\1\376\376\376\243\377\377\377\2\265\265\267;;=\203::<\2" \ - "99;;;=\202::<\1;;=\202::<\1;;=\202::<\4;;=::\212\307>\212\306@\214\305B\214\305@\214\305B\214\306>" \ - "\212\307>\212\310\77\214\306>\217\304@\214\306>\214\305@\242\322b\370" \ - "\373\362\377\377\377\202\377\376\377\1\377\377\375\254\377\377\377\4" \ - "\363\363\363SSU;;=99;\202;;=\1""99;\204::<\3;;=::<\235\235\237\377\377" \ - "\377\377\334\377\377\377\1\376\376\376\202\377\377\377\2\363\363\363" \ - "GGI\202::<\7;;=::<99;::<;;=::<;;=\202::<\2\266\266\266\376\376\376\204" \ - "\377\377\377\202\376\376\376\202\377\377\377\1\376\376\376\236\377\377" \ - "\377\3\376\376\376\265\265\267;;=\202::<\2;;=99;\205::<\1;;=\204::<\4" \ - ";;=FFH\332\332\332\376\376\376\205\377\377\377\1\376\376\376\240\377" \ - "\377\377\10\376\377\375\377\375\377\377\377\375\376\377\375\377\377\377" \ - "\377\376\377\377\377\377\376\376\374\230\377\377\377\10\374\377\377\377" \ - "\376\374\377\377\377\376\376\374\377\376\377\376\377\377\377\377\377" \ - "\377\376\377\230\377\377\377\3\377\377\375\377\377\377\376\377\375\203" \ - "\377\377\377\1\377\376\377\231\377\377\377\6\377\375\377\376\376\374" \ - "\377\377\377\377\376\377\376\377\375\377\376\377\202\377\377\377\2\377" \ - "\376\377\377\377\377\202\376\377\377\2\376\376\377\376\377\377\222\377" \ - "\377\377\2\377\377\375\377\375\377\202\376\377\377\4\376\376\376\376" \ - "\377\377\375\377\374\377\375\377\251\377\377\377\1\375\377\376\202\377" \ - "\377\375\34\377\377\377\376\376\376\373\373\363\243\322b\211\307B\212" \ - "\307<\215\305>\214\306>\212\307>\214\305@\217\304>\212\307<\214\306<" \ - "\214\306>\215\307\77\213\307A\214\306>\215\305@\215\307\77\212\307>\244" \ - "\317c\370\373\362\377\377\373\376\377\377\377\376\377\375\376\377\377" \ - "\377\375\377\376\377\252\377\377\377\5\376\376\376\377\377\377\333\333" \ - "\33399;;;=\202::<\5;;=99;;;=99;;;=\203::<\1\332\332\334\377\377\377\377" \ - "\330\377\377\377\1\376\376\376\205\377\377\377\1xxx\202::<\1;;=\202:" \ - ":<\1;;=\204::<\4:::xxx\376\376\376\377\377\377\202\376\376\376\205\377" \ - "\377\377\3\376\376\376\377\377\377\376\376\376\237\377\377\377\1\265" \ - "\265\265\204::<\6;;=::<;;=::<;;=::<\202;;=\203::<\4;;=FFH\333\333\333" \ - "\376\376\376\202\377\377\377\1\376\376\376\242\377\377\377\7\376\376" \ - "\376\377\376\377\326\352\267\247\324o\247\324m\252\324r\247\324o\231" \ - "\252\324p\10\323\353\271\377\376\377\377\377\377\376\377\377\350\365" \ - "\333\253\323p\250\324r\251\324k\230\252\324p\10\250\325n\252\324p\277" \ - "\337\223\376\377\377\377\377\377\375\377\376\376\377\377\276\336\222" \ - "\230\252\324p\7\250\325p\250\324r\247\324o\253\324n\251\323m\346\364" \ - "\332\377\376\377\202\377\377\377\7\323\352\266\253\323p\251\323m\253" \ - "\323r\251\323o\247\324m\252\324r\220\252\324p\10\252\324n\253\324n\247" \ - "\324k\252\324p\254\325o\247\324m\252\324p\324\353\267\250\377\377\377" \ - "\3\377\376\377\377\377\377\375\377\376\202\377\377\377\11\373\373\363" \ - "\241\321d\214\306>\213\310=\214\306>\214\305@\213\310=\212\306@\217\304" \ - ">\202\215\307=\14\214\306>\215\305>\214\306>\215\305>\217\304@\215\307" \ - "\77\215\307=\242\320c\367\375\361\376\376\377\377\376\377\376\376\376" \ - "\202\377\377\375\2\374\377\377\377\376\377\254\377\377\377\2\376\376" \ - "\376\251\251\251\202::<\5;;=::<;;=99;;;=\204::<\1``b\377\377\377\377" \ - "\334\377\377\377\3\376\376\376\301\301\301:::\205::<\1""99;\202::<\4" \ - ";;=::\10\304\341\237\377\374\377\377\376\377\377\377\377" \ - "\341\362\322\215\305>\212\307>\215\305>\230\214\306>\4\215\305<\214\305" \ - "@\252\324r\376\377\377\202\377\377\377\2\377\377\375\250\324r\230\214" \ - "\306>\20\215\307\77\214\306>\214\306<\214\305B\212\307>\337\363\320\377" \ - "\376\377\376\377\377\376\376\374\305\342\240\214\305@\213\310=\215\305" \ - "@\214\306>\212\307<\214\305@\220\214\306>\10\214\305@\215\306C\212\307" \ - "<\214\306>\215\305>\212\306@\215\305>\304\343\237\250\377\377\377\1\377" \ - "\377\375\202\377\377\377\32\377\376\377\370\373\364\243\322b\214\306" \ - ">\213\310\77\214\305@\215\305>\215\305@\214\306>\214\305B\212\307<\215" \ - "\307=\214\305B\214\306>\215\306A\212\306@\212\307>\214\306>\212\307<" \ - "\244\317c\370\373\364\377\377\377\377\375\376\377\377\375\376\377\377" \ - "\377\377\377\202\377\376\377\257\377\377\377\1kkm\202::<\2;;=::<\202" \ - ";;=\3::<;;=::<\202;;=\1\233\233\233\377\377\377\377\330\377\377\377\1" \ - "\376\376\376\202\377\377\377\3\364\364\366FFH;;=\205::<\3;;=::<;;=\202" \ - "::<\1\316\316\316\256\377\377\377\2\265\265\265;;=\203::<\1;;=\205::" \ - "<\1;;=\204::<\3;;=FFH\332\332\332\206\377\377\377\3\376\376\376\377\377" \ - "\377\376\376\376\235\377\377\377\1\304\343\240\235\214\306>\1\305\342" \ - "\237\203\377\377\377\1\342\362\316\235\214\306>\1\250\325p\204\377\377" \ - "\377\1\252\324p\234\214\306>\2\215\307\77\342\362\316\203\377\377\377" \ - "\3\305\342\237\214\305@\215\305>\202\214\306>\1\214\305@\222\214\306" \ - ">\1\214\305@\205\214\306>\1\305\342\237\241\377\377\377\10\376\376\377" \ - "\377\377\375\377\377\377\377\377\375\377\377\377\377\376\377\377\377" \ - "\375\376\377\377\202\377\377\377\6\370\373\362\243\322b\211\307B\213" \ - "\310=\214\305@\214\306<\202\215\305@\4\214\306<\214\305@\214\306<\215" \ - "\307\77\202\214\306>\6\212\307>\214\306>\215\307\77\214\305@\244\317" \ - "c\367\375\361\267\377\377\377\2\363\363\363FFF\204::<\1;;=\203::<\4:" \ - "9>::<;;=\332\332\332\377\377\377\377\332\377\377\377\1yy{\202::<\2""9" \ - "9;;;=\202::<\6;;=99;::<;;=::<\234\234\236\260\377\377\377\12\265\265" \ - "\267;;=::<;;=99;;;=::<;;=::<;;=\202::<\1;;=\203::<\3;;=FFF\332\332\332" \ - "\206\377\377\377\1\376\376\376\236\377\377\377\1\304\343\240\235\214" \ - "\306>\1\305\342\237\203\377\377\377\1\342\362\316\235\214\306>\1\250" \ - "\325p\204\377\377\377\1\252\324p\234\214\306>\2\215\307\77\342\362\316" \ - "\203\377\377\377\3\305\342\237\214\305@\215\305>\202\214\306>\1\214\305" \ - "@\222\214\306>\1\214\305@\205\214\306>\1\305\342\237\240\377\377\377" \ - "\6\376\376\377\377\376\377\375\376\377\376\377\377\377\377\375\375\377" \ - "\376\203\377\377\377\27\377\377\375\372\373\366\241\321a\217\304@\212" \ - "\307<\214\306>\215\305>\215\305@\213\310=\212\306@\214\306>\214\305B" \ - "\215\307\77\215\305>\215\306A\212\307>\214\306>\215\307\77\214\306>\242" \ - "\322b\370\373\362\376\376\377\377\375\376\267\377\377\377\1\301\301\301" \ - "\205::<\3;;=::<;;=\202::<\2""99;```\377\377\377\377\331\377\377\377\1" \ - "\301\301\301\202::<\1;;=\203::<\1;;=\202::<\3<<>::<__a\261\377\377\377" \ - "\7\376\376\376\265\265\265;;=::<;;=::<;;=\203::<\1;;=\203::<\1;;=\203" \ - "::<\2GGI\332\332\332\203\377\377\377\1\376\376\376\240\377\377\377\1" \ - "\304\343\240\235\214\306>\1\305\342\237\203\377\377\377\1\342\362\316" \ - "\235\214\306>\1\250\325p\204\377\377\377\1\252\324p\234\214\306>\2\215" \ - "\307\77\342\362\316\203\377\377\377\3\305\342\237\214\305@\215\305>\202" \ - "\214\306>\1\214\305@\222\214\306>\1\214\305@\205\214\306>\1\305\342\237" \ - "\240\377\377\377\7\377\377\375\375\376\377\376\377\377\376\377\375\377" \ - "\374\377\377\377\375\375\377\376\202\377\377\377\5\372\373\366\240\320" \ - "b\215\307\77\212\306@\215\305>\202\214\305@\20\215\305@\212\306@\214" \ - "\305D\216\306\77\214\306>\215\307\77\214\306>\212\306@\214\306>\215\307" \ - "\77\215\305@\242\320c\370\373\362\377\377\373\377\376\377\377\377\375" \ - "\270\377\377\377\3\204\204\204::<;;=\206::<\4;;=::<;;=\234\234\236\377" \ - "\377\377\377\325\377\377\377\4\376\376\376\377\377\377\363\363\363SS" \ - "U\211::<\4""99;::<\332\332\334\376\376\376\202\377\377\377\1\376\376" \ - "\376\257\377\377\377\2\264\264\264;;=\202::<\2""99;;;=\202::<\3""99;" \ - ";;=::<\202;;=\202::<\4;;=::\1\305\342\237\203\377" \ - "\377\377\1\342\362\316\235\214\306>\1\250\325p\204\377\377\377\1\252" \ - "\324p\234\214\306>\2\215\307\77\342\362\316\203\377\377\377\3\305\342" \ - "\237\214\305@\215\305>\202\214\306>\1\214\305@\222\214\306>\1\214\305" \ - "@\205\214\306>\1\305\342\237\241\377\377\377\37\376\377\377\376\377\375" \ - "\377\375\376\375\377\376\377\377\375\377\377\377\377\376\377\370\373" \ - "\362\241\321a\215\307\77\215\307=\214\305@\214\306>\212\307<\214\306" \ - ">\214\306<\214\306>\216\306\77\215\305<\212\307>\213\307A\215\305>\212" \ - "\307>\215\307\77\214\306>\242\321a\373\374\364\377\377\377\376\377\377" \ - "\376\376\376\376\377\377\270\377\377\377\3\363\363\363TTT;;=\202::<\1" \ - ";;=\203::<\5""99;;;=::<;;=\332\332\332\377\377\377\377\323\377\377\377" \ - "\1\376\376\376\202\377\377\377\4\221\221\221;;=99;;;=\202::<\1;;=\202" \ - "::<\1;;=\202::<\1\233\233\233\202\377\377\377\1\376\376\376\262\377\377" \ - "\377\2\265\265\267;;=\203::<\2""99;;;=\202::<\1;;=\202::<\1;;=\202::" \ - "<\4;;=::\1\305\342\237" \ - "\203\377\377\377\1\342\362\316\235\214\306>\1\250\325p\204\377\377\377" \ - "\1\252\324p\234\214\306>\2\215\307\77\342\362\316\203\377\377\377\3\305" \ - "\342\237\214\305@\215\305>\202\214\306>\1\214\305@\222\214\306>\1\214" \ - "\305@\205\214\306>\1\305\342\237\240\377\377\377\202\377\377\375\3\377" \ - "\374\377\375\377\376\376\377\377\202\377\377\377\25\370\373\364\243\322" \ - "b\217\304@\212\306@\214\305@\215\305>\212\307>\212\306@\214\305B\214" \ - "\305@\214\305B\214\306>\212\307>\212\310\77\214\306>\217\304@\214\306" \ - ">\214\305@\242\322b\370\373\362\377\377\377\202\377\376\377\1\377\377" \ - "\375\272\377\377\377\7\316\316\316::<;;=::<99;::<;;=\205::<\1kkm\377" \ - "\377\377\377\325\377\377\377\1\315\315\315\206::<\6""99;::<99;;;=::<" \ - "```\206\377\377\377\1\376\376\376\257\377\377\377\3\376\376\376\265\265" \ - "\267;;=\202::<\2;;=99;\205::<\1;;=\204::<\4;;=FFH\332\332\332\376\376" \ - "\376\205\377\377\377\1\376\376\376\232\377\377\377\1\304\343\240\235" \ - "\214\306>\1\305\342\237\203\377\377\377\1\342\362\316\235\214\306>\1" \ - "\250\325p\204\377\377\377\1\252\324p\234\214\306>\2\215\307\77\342\362" \ - "\316\203\377\377\377\3\305\342\237\214\305@\215\305>\202\214\306>\1\214" \ - "\305@\222\214\306>\1\214\305@\205\214\306>\1\305\342\237\241\377\377" \ - "\377\1\375\377\376\202\377\377\375\34\377\377\377\376\376\376\373\373" \ - "\363\243\322b\211\307B\212\307<\215\305>\214\306>\212\307>\214\305@\217" \ - "\304>\212\307<\214\306<\214\306>\215\307\77\213\307A\214\306>\215\305" \ - "@\215\307\77\212\307>\244\317c\370\373\362\377\377\373\376\377\377\377" \ - "\376\377\375\376\377\377\377\375\377\376\377\272\377\377\377\2\222\222" \ - "\22299;\205::<\1;;=\203::<\2;;=\250\250\250\377\377\377\377\324\377\377" \ - "\377\4```;;=99;;;=\204::<\5;;=::<;;=::<\331\331\331\207\377\377\377\1" \ - "\376\376\376\260\377\377\377\1\265\265\265\204::<\6;;=::<;;=::<;;=::" \ - "<\202;;=\203::<\4;;=FFH\333\333\333\376\376\376\202\377\377\377\1\376" \ - "\376\376\234\377\377\377\1\304\343\240\235\214\306>\1\305\342\237\203" \ - "\377\377\377\1\342\362\316\235\214\306>\1\250\325p\204\377\377\377\1" \ - "\252\324p\234\214\306>\2\215\307\77\342\362\316\203\377\377\377\3\305" \ - "\342\237\214\305@\215\305>\202\214\306>\1\214\305@\222\214\306>\1\214" \ - "\305@\205\214\306>\1\305\342\237\240\377\377\377\3\377\376\377\377\377" \ - "\377\375\377\376\202\377\377\377\11\373\373\363\241\321d\214\306>\213" \ - "\310=\214\306>\214\305@\213\310=\212\306@\217\304>\202\215\307=\14\214" \ - "\306>\215\305>\214\306>\215\305>\217\304@\215\307\77\215\307=\242\320" \ - "c\367\375\361\376\376\377\377\376\377\376\376\376\202\377\377\375\2\374" \ - "\377\377\377\376\377\262\377\377\377\2\376\376\376\377\377\377\202\376" \ - "\376\376\204\377\377\377\5\363\363\363SSU99;::<;;=\207::<\2GGG\363\363" \ - "\363\377\377\377\377\322\377\377\377\4\234\234\234:::::<;;=\202::<\1" \ - ";;=\203::<\202;;=\1\234\234\236\207\377\377\377\1\376\376\376\262\377" \ - "\377\377\1\265\265\267\203::<\2""99;;;=\203::<\1;;=\202::<\202;;=\203" \ - "::<\2FFH\332\332\332\237\377\377\377\1\304\343\240\235\214\306>\1\305" \ - "\342\237\203\377\377\377\1\342\362\316\235\214\306>\1\250\325p\204\377" \ - "\377\377\1\252\324p\234\214\306>\2\215\307\77\342\362\316\203\377\377" \ - "\377\3\305\342\237\214\305@\215\305>\202\214\306>\1\214\305@\222\214" \ - "\306>\1\214\305@\205\214\306>\1\305\342\237\240\377\377\377\1\377\377" \ - "\375\202\377\377\377\32\377\376\377\370\373\364\243\322b\214\306>\213" \ - "\310\77\214\305@\215\305>\215\305@\214\306>\214\305B\212\307<\215\307" \ - "=\214\305B\214\306>\215\306A\212\306@\212\307>\214\306>\212\307<\244" \ - "\317c\370\373\364\377\377\377\377\375\376\377\377\375\376\377\377\377" \ - "\377\377\202\377\376\377\273\377\377\377\2\376\376\376\316\316\316\206" \ - "::<\202;;=\4::<;;=::\1\305\342\237\203\377" \ - "\377\377\1\342\362\316\235\214\306>\1\250\325p\204\377\377\377\1\252" \ - "\324p\234\214\306>\2\215\307\77\342\362\316\203\377\377\377\3\305\342" \ - "\237\214\305@\215\305>\202\214\306>\1\214\305@\222\214\306>\1\214\305" \ - "@\205\214\306>\1\305\342\237\231\377\377\377\10\376\376\377\377\377\375" \ - "\377\377\377\377\377\375\377\377\377\377\376\377\377\377\375\376\377" \ - "\377\202\377\377\377\6\370\373\362\243\322b\211\307B\213\310=\214\305" \ - "@\214\306<\202\215\305@\4\214\306<\214\305@\214\306<\215\307\77\202\214" \ - "\306>\6\212\307>\214\306>\215\307\77\214\305@\244\317c\367\375\361\305" \ - "\377\377\377\2xxz;;=\203::<\3;;=::<;;=\203::<\2;;=\315\315\315\377\377" \ - "\377\377\313\377\377\377\203\376\376\376\202\377\377\377\3xxz;;=::<\202" \ - ";;=\1""99;\202;;=\202::<\4;;=::<\333\333\335\376\376\376\274\377\377" \ - "\377\12\265\265\267;;=::<;;=99;;;=::<;;=::<;;=\202::<\1;;=\202::<\4;" \ - ";=99;GGI\332\332\332\235\377\377\377\1\304\343\240\235\214\306>\1\305" \ - "\342\237\203\377\377\377\1\342\362\316\235\214\306>\1\250\325p\204\377" \ - "\377\377\1\252\324p\234\214\306>\2\215\307\77\342\362\316\203\377\377" \ - "\377\3\305\342\237\214\305@\215\305>\202\214\306>\1\214\305@\222\214" \ - "\306>\1\214\305@\205\214\306>\1\305\342\237\230\377\377\377\6\376\376" \ - "\377\377\376\377\375\376\377\376\377\377\377\377\375\375\377\376\203" \ - "\377\377\377\27\377\377\375\372\373\366\241\321a\217\304@\212\307<\214" \ - "\306>\215\305>\215\305@\213\310=\212\306@\214\306>\214\305B\215\307\77" \ - "\215\305>\215\306A\212\307>\214\306>\215\307\77\214\306>\242\322b\370" \ - "\373\362\376\376\377\377\375\376\304\377\377\377\2\364\364\364FFH\203" \ - "::<\2""99;;;=\203::<\4<<>99;TTT\376\376\376\377\377\377\377\310\377\377" \ - "\377\1\376\376\376\205\377\377\377\3\316\316\316::<99;\206::<\1;;=\202" \ - "::<\1\221\221\221\203\377\377\377\1\376\376\376\272\377\377\377\7\376" \ - "\376\376\265\265\265;;=::<;;=::<;;=\203::<\1;;=\203::<\6;;=::<;;=::<" \ - "FFH\332\332\332\234\377\377\377\1\304\343\240\235\214\306>\1\305\342" \ - "\237\203\377\377\377\1\342\362\316\235\214\306>\1\250\325p\204\377\377" \ - "\377\1\252\324p\234\214\306>\2\215\307\77\342\362\316\203\377\377\377" \ - "\3\305\342\237\214\305@\215\305>\202\214\306>\1\214\305@\222\214\306" \ - ">\1\214\305@\205\214\306>\1\305\342\237\230\377\377\377\7\377\377\375" \ - "\375\376\377\376\377\377\376\377\375\377\374\377\377\377\375\375\377" \ - "\376\202\377\377\377\5\372\373\366\240\320b\215\307\77\212\306@\215\305" \ - ">\202\214\305@\20\215\305@\212\306@\214\305D\216\306\77\214\306>\215" \ - "\307\77\214\306>\212\306@\214\306>\215\307\77\215\305@\242\320c\370\373" \ - "\362\377\377\373\377\376\377\377\377\375\304\377\377\377\3\376\376\376" \ - "\265\265\267;;=\204::<\1""99;\203::<\3;;=::<\234\234\234\203\377\377" \ - "\377\1\376\376\376\377\377\377\377\306\377\377\377\7\376\376\376\377" \ - "\377\377\376\376\376\377\377\377__a::<;;=\203::<\7;;=::<;;=::<;;=SSU" \ - "\363\363\363\300\377\377\377\2\264\264\264;;=\202::<\2""99;;;=\202::" \ - "<\3""99;;;=::<\202;;=\204::<\2FFH\332\332\332\233\377\377\377\1\304\343" \ - "\240\235\214\306>\1\305\342\237\203\377\377\377\1\342\362\316\235\214" \ - "\306>\1\250\325p\204\377\377\377\1\252\324p\234\214\306>\2\215\307\77" \ - "\342\362\316\203\377\377\377\3\305\342\237\214\305@\215\305>\202\214" \ - "\306>\1\214\305@\222\214\306>\1\214\305@\205\214\306>\1\305\342\237\231" \ - "\377\377\377\37\376\377\377\376\377\375\377\375\376\375\377\376\377\377" \ - "\375\377\377\377\377\376\377\370\373\362\241\321a\215\307\77\215\307" \ - "=\214\305@\214\306>\212\307<\214\306>\214\306<\214\306>\216\306\77\215" \ - "\305<\212\307>\213\307A\215\305>\212\307>\215\307\77\214\306>\242\321" \ - "a\373\374\364\377\377\377\376\377\377\376\376\376\376\377\377\301\377" \ - "\377\377\1\376\376\376\204\377\377\377\2kkm99;\203::<\202;;=\1""99;\203" \ - "::<\2FFH\363\363\363\377\377\377\377\310\377\377\377\1\376\376\376\203" \ - "\377\377\377\3\250\250\252::<;;=\203::<\1;;=\202::<\5;;=::<;;=\301\301" \ - "\301\376\376\376\301\377\377\377\2\265\265\267;;=\203::<\2""99;;;=\202" \ - "::<\1;;=\202::<\2;;=::<\202;;=\3::\1\305\342\237\203\377\377\377\1\342\362\316" \ - "\235\214\306>\1\250\325p\204\377\377\377\1\252\324p\234\214\306>\2\215" \ - "\307\77\342\362\316\203\377\377\377\3\305\342\237\214\305@\215\305>\202" \ - "\214\306>\1\214\305@\222\214\306>\1\214\305@\205\214\306>\1\305\342\237" \ - "\230\377\377\377\202\377\377\375\3\377\374\377\375\377\376\376\377\377" \ - "\202\377\377\377\25\370\373\364\243\322b\217\304@\212\306@\214\305@\215" \ - "\305>\212\307>\212\306@\214\305B\214\305@\214\305B\214\306>\212\307>" \ - "\212\310\77\214\306>\217\304@\214\306>\214\305@\242\322b\370\373\362" \ - "\377\377\377\202\377\376\377\1\377\377\375\301\377\377\377\1\376\376" \ - "\376\204\377\377\377\2\376\376\376\346\346\350\203::<\4;;=99;::<;;=\204" \ - "::<\3\203\203\203\377\377\377\376\376\376\377\377\377\377\311\377\377" \ - "\377\2\364\364\364FFH\202::<\5;;=::<;;=::<;;=\202::<\2;;=kkm\202\377" \ - "\377\377\1\376\376\376\300\377\377\377\3\376\376\376\265\265\267;;=\202" \ - "::<\2;;=99;\204::<\3;;=99;;;=\202::<\3;;=::<\265\265\265\232\377\377" \ - "\377\1\304\343\240\235\214\306>\1\305\342\237\203\377\377\377\1\342\362" \ - "\316\235\214\306>\1\250\325p\204\377\377\377\1\252\324p\234\214\306>" \ - "\2\215\307\77\342\362\316\203\377\377\377\3\305\342\237\214\305@\215" \ - "\305>\202\214\306>\1\214\305@\222\214\306>\1\214\305@\205\214\306>\1" \ - "\305\342\237\231\377\377\377\1\375\377\376\202\377\377\375\34\377\377" \ - "\377\376\376\376\373\373\363\243\322b\211\307B\212\307<\215\305>\214" \ - "\306>\212\307>\214\305@\217\304>\212\307<\214\306<\214\306>\215\307\77" \ - "\213\307A\214\306>\215\305@\215\307\77\212\307>\244\317c\370\373\362" \ - "\377\377\373\376\377\377\377\376\377\375\376\377\377\377\375\377\376" \ - "\377\301\377\377\377\202\376\376\376\2\377\377\377\376\376\376\202\377" \ - "\377\377\1\234\234\236\203::<\1;;=\206::<\2;;=\331\331\331\377\377\377" \ - "\377\306\377\377\377\1\376\376\376\203\377\377\377\4\233\233\233;;=:" \ - ":<;;=\202::<\3;;=99;;;=\203::<\1\346\346\350\305\377\377\377\1\265\265" \ - "\265\204::<\3;;=::<;;=\203::<\5;;=99;;;=::<\265\265\267\233\377\377\377" \ - "\1\304\343\240\235\214\306>\1\305\342\237\203\377\377\377\1\342\362\316" \ - "\235\214\306>\1\250\325p\204\377\377\377\1\252\324p\234\214\306>\2\215" \ - "\307\77\342\362\316\203\377\377\377\3\305\342\237\214\305@\215\305>\202" \ - "\214\306>\1\214\305@\222\214\306>\1\214\305@\205\214\306>\1\305\342\237" \ - "\230\377\377\377\3\377\376\377\377\377\377\375\377\376\202\377\377\377" \ - "\11\373\373\363\241\321d\214\306>\213\310=\214\306>\214\305@\213\310" \ - "=\212\306@\217\304>\202\215\307=\14\214\306>\215\305>\214\306>\215\305" \ - ">\217\304@\215\307\77\215\307=\242\320c\367\375\361\376\376\377\377\376" \ - "\377\376\376\376\202\377\377\375\2\374\377\377\377\376\377\301\377\377" \ - "\377\1\376\376\376\202\377\377\377\1\376\376\376\202\377\377\377\6\364" \ - "\364\364SSU::<;;=::<;;=\205::<\4""99;kkk\377\377\377\376\376\376\377" \ - "\377\377\377\307\377\377\377\2\346\346\346;;;\204::<\3;;=99;;;=\203:" \ - ":<\1\234\234\236\205\377\377\377\1\376\376\376\301\377\377\377\1\265" \ - "\265\267\203::<\2""99;;;=\202::<\1;;;\204::<\1\265\265\267\234\377\377" \ - "\377\1\304\343\240\235\214\306>\1\305\342\237\203\377\377\377\1\342\362" \ - "\316\235\214\306>\1\250\325p\204\377\377\377\1\252\324p\234\214\306>" \ - "\2\215\307\77\342\362\316\203\377\377\377\3\305\342\237\214\305@\215" \ - "\305>\202\214\306>\1\214\305@\222\214\306>\1\214\305@\205\214\306>\1" \ - "\305\342\237\230\377\377\377\1\377\377\375\202\377\377\377\32\377\376" \ - "\377\370\373\364\243\322b\214\306>\213\310\77\214\305@\215\305>\215\305" \ - "@\214\306>\214\305B\212\307<\215\307=\214\305B\214\306>\215\306A\212" \ - "\306@\212\307>\214\306>\212\307<\244\317c\370\373\364\377\377\377\377" \ - "\375\376\377\377\375\376\377\377\377\377\377\202\377\376\377\306\377" \ - "\377\377\1\376\376\376\202\377\377\377\2\301\301\303::<\202;;=\11::<" \ - ";;=::<;;=::<99;;;=::<\301\301\301\377\377\377\377\306\377\377\377\12" \ - "\376\376\376\377\377\377\204\204\204;;=::<:9>;;=::<99;;;=\203::<\5SS" \ - "U\363\363\363\376\376\376\377\377\377\376\376\376\305\377\377\377\5\265" \ - "\265\26599;;;=::<;;=\206::<\1\266\266\270\235\377\377\377\1\304\343\240" \ - "\235\214\306>\1\305\342\237\203\377\377\377\1\342\362\316\235\214\306" \ - ">\1\250\325p\204\377\377\377\1\252\324p\234\214\306>\2\215\307\77\342" \ - "\362\316\203\377\377\377\3\305\342\237\214\305@\215\305>\202\214\306" \ - ">\1\214\305@\222\214\306>\1\214\305@\205\214\306>\1\305\342\237\221\377" \ - "\377\377\10\376\376\377\377\377\375\377\377\377\377\377\375\377\377\377" \ - "\377\376\377\377\377\375\376\377\377\202\377\377\377\6\370\373\362\243" \ - "\322b\211\307B\213\310=\214\305@\214\306<\202\215\305@\4\214\306<\214" \ - "\305@\214\306<\215\307\77\202\214\306>\6\212\307>\214\306>\215\307\77" \ - "\214\305@\244\317c\367\375\361\322\377\377\377\1kkk\203::<\4;;=99;::" \ - "<;;=\203::<\1SSU\210\377\377\377\1\376\376\376\377\377\377\377\276\377" \ - "\377\377\1\316\316\316\202::<\1;;=\202::<\202;;=\202::<\4;;=::<\265\265" \ - "\267\376\376\376\307\377\377\377\3\376\376\376\377\377\377\265\265\267" \ - "\207::<\3""99;\266\266\270\376\376\377\202\377\377\377\1\376\376\376" \ - "\232\377\377\377\1\304\343\240\235\214\306>\1\305\342\237\203\377\377" \ - "\377\1\342\362\316\235\214\306>\1\250\325p\204\377\377\377\1\252\324" \ - "p\234\214\306>\2\215\307\77\342\362\316\203\377\377\377\3\305\342\237" \ - "\214\305@\215\305>\202\214\306>\1\214\305@\222\214\306>\1\214\305@\205" \ - "\214\306>\1\305\342\237\220\377\377\377\6\376\376\377\377\376\377\375" \ - "\376\377\376\377\377\377\377\375\375\377\376\203\377\377\377\27\377\377" \ - "\375\372\373\366\241\321a\217\304@\212\307<\214\306>\215\305>\215\305" \ - "@\213\310=\212\306@\214\306>\214\305B\215\307\77\215\305>\215\306A\212" \ - "\307>\214\306>\215\307\77\214\306>\242\322b\370\373\362\376\376\377\377" \ - "\375\376\321\377\377\377\1\346\346\346\204::<\1;;=\202::<\5;;=99;;;=" \ - "::<\266\266\266\205\377\377\377\202\376\376\376\2\377\377\377\376\376" \ - "\376\377\377\377\377\273\377\377\377\5\376\376\376\377\377\377kkm::<" \ - ";;=\202::<\1;;=\203::<\3;;=::\1\305\342\237" \ - "\203\377\377\377\1\342\362\316\235\214\306>\1\250\325p\204\377\377\377" \ - "\1\252\324p\234\214\306>\2\215\307\77\342\362\316\203\377\377\377\3\305" \ - "\342\237\214\305@\215\305>\202\214\306>\1\214\305@\222\214\306>\1\214" \ - "\305@\205\214\306>\1\305\342\237\220\377\377\377\7\377\377\375\375\376" \ - "\377\376\377\377\376\377\375\377\374\377\377\377\375\375\377\376\202" \ - "\377\377\377\5\372\373\366\240\320b\215\307\77\212\306@\215\305>\202" \ - "\214\305@\20\215\305@\212\306@\214\305D\216\306\77\214\306>\215\307\77" \ - "\214\306>\212\306@\214\306>\215\307\77\215\305@\242\320c\370\373\362" \ - "\377\377\373\377\376\377\377\377\375\322\377\377\377\1\221\221\223\202" \ - "::<\12;;=99;::<;;=::<;;=99;;;=EEG\364\364\364\203\377\377\377\1\376\376" \ - "\376\202\377\377\377\1\376\376\376\377\377\377\377\275\377\377\377\2" \ - "\316\316\320;;=\205::<\2""99;;;=\203::<\3\316\316\316\377\377\377\376" \ - "\376\376\313\377\377\377\3\265\265\265;;=99;\202::<\1\266\266\270\203" \ - "\377\377\377\3\376\376\376\377\377\377\376\376\376\232\377\377\377\1" \ - "\304\343\240\235\214\306>\1\305\342\237\203\377\377\377\1\342\362\316" \ - "\235\214\306>\1\250\325p\204\377\377\377\1\252\324p\234\214\306>\2\215" \ - "\307\77\342\362\316\203\377\377\377\3\305\342\237\214\305@\215\305>\202" \ - "\214\306>\1\214\305@\222\214\306>\1\214\305@\205\214\306>\1\305\342\237" \ - "\221\377\377\377\37\376\377\377\376\377\375\377\375\376\375\377\376\377" \ - "\377\375\377\377\377\377\376\377\370\373\362\241\321a\215\307\77\215" \ - "\307=\214\305@\214\306>\212\307<\214\306>\214\306<\214\306>\216\306\77" \ - "\215\305<\212\307>\213\307A\215\305>\212\307>\215\307\77\214\306>\242" \ - "\321a\373\374\364\377\377\377\376\377\377\376\376\376\376\377\377\322" \ - "\377\377\377\2\363\363\363FFH\203::<\202;;=\203::<\3;;=::<\235\235\235" \ - "\204\377\377\377\1\376\376\376\377\377\377\377\277\377\377\377\1__a\202" \ - "::<\1;;=\203::<\5;;=::<;;=::<\204\204\206\312\377\377\377\1\376\376\376" \ - "\202\377\377\377\7\376\376\376\377\377\377\265\265\267;;=99;\266\266" \ - "\270\376\376\377\203\377\377\377\202\376\376\376\233\377\377\377\1\304" \ - "\343\240\235\214\306>\1\305\342\237\203\377\377\377\1\342\362\316\235" \ - "\214\306>\1\250\325p\204\377\377\377\1\252\324p\234\214\306>\2\215\307" \ - "\77\342\362\316\203\377\377\377\3\305\342\237\214\305@\215\305>\202\214" \ - "\306>\1\214\305@\222\214\306>\1\214\305@\205\214\306>\1\305\342\237\220" \ - "\377\377\377\202\377\377\375\3\377\374\377\375\377\376\376\377\377\202" \ - "\377\377\377\25\370\373\364\243\322b\217\304@\212\306@\214\305@\215\305" \ - ">\212\307>\212\306@\214\305B\214\305@\214\305B\214\306>\212\307>\212" \ - "\310\77\214\306>\217\304@\214\306>\214\305@\242\322b\370\373\362\377" \ - "\377\377\202\377\376\377\1\377\377\375\324\377\377\377\4\234\234\234" \ - ";;=::<<<>\204::<\1;;=\202::<\2FFH\363\363\363\204\377\377\377\1\376\376" \ - "\376\202\377\377\377\1\376\376\376\377\377\377\377\272\377\377\377\1" \ - "\265\265\265\202::<\5;;=99;::<;;=::<\202;;=\3""99;;;=\346\346\346\320" \ - "\377\377\377\2\264\264\266\265\265\267\203\377\377\377\202\376\376\376" \ - "\235\377\377\377\1\304\343\240\235\214\306>\1\305\342\237\203\377\377" \ - "\377\1\342\362\316\235\214\306>\1\250\325p\204\377\377\377\1\252\324" \ - "p\234\214\306>\2\215\307\77\342\362\316\203\377\377\377\3\305\342\237" \ - "\214\305@\215\305>\202\214\306>\1\214\305@\222\214\306>\1\214\305@\205" \ - "\214\306>\1\305\342\237\221\377\377\377\1\375\377\376\202\377\377\375" \ - "\34\377\377\377\376\376\376\373\373\363\243\322b\211\307B\212\307<\215" \ - "\305>\214\306>\212\307>\214\305@\217\304>\212\307<\214\306<\214\306>" \ - "\215\307\77\213\307A\214\306>\215\305@\215\307\77\212\307>\244\317c\370" \ - "\373\362\377\377\373\376\377\377\377\376\377\375\376\377\377\377\375" \ - "\377\376\377\320\377\377\377\1\376\376\376\203\377\377\377\2SSU;;=\203" \ - "::<\1;;=\203::<\3""99;::<\234\234\236\203\377\377\377\1\376\376\376\377" \ - "\377\377\377\276\377\377\377\5RRT99;;;=99;;;=\203::<\4""99;;;=::<\234" \ - "\234\236\314\377\377\377\1\376\376\376\212\377\377\377\1\376\376\376" \ - "\235\377\377\377\1\304\343\240\235\214\306>\1\305\342\237\203\377\377" \ - "\377\1\342\362\316\235\214\306>\1\250\325p\204\377\377\377\1\252\324" \ - "p\234\214\306>\2\215\307\77\342\362\316\203\377\377\377\3\305\342\237" \ - "\214\305@\215\305>\202\214\306>\1\214\305@\222\214\306>\1\214\305@\205" \ - "\214\306>\1\305\342\237\220\377\377\377\3\377\376\377\377\377\377\375" \ - "\377\376\202\377\377\377\11\373\373\363\241\321d\214\306>\213\310=\214" \ - "\306>\214\305@\213\310=\212\306@\217\304>\202\215\307=\14\214\306>\215" \ - "\305>\214\306>\215\305>\217\304@\215\307\77\215\307=\242\320c\367\375" \ - "\361\376\376\377\377\376\377\376\376\376\202\377\377\375\2\374\377\377" \ - "\377\376\377\324\377\377\377\3\265\265\265;;=99;\202;;=\1""99;\202;;" \ - "=\5::<;;=::\1\305\342\237\203\377\377" \ - "\377\1\342\362\316\235\214\306>\1\250\325p\204\377\377\377\1\252\324" \ - "p\234\214\306>\2\215\307\77\342\362\316\203\377\377\377\3\305\342\237" \ - "\214\305@\215\305>\202\214\306>\1\214\305@\222\214\306>\1\214\305@\205" \ - "\214\306>\1\305\342\237\220\377\377\377\1\377\377\375\202\377\377\377" \ - "\32\377\376\377\370\373\364\243\322b\214\306>\213\310\77\214\305@\215" \ - "\305>\215\305@\214\306>\214\305B\212\307<\215\307=\214\305B\214\306>" \ - "\215\306A\212\306@\212\307>\214\306>\212\307<\244\317c\370\373\364\377" \ - "\377\377\377\375\376\377\377\375\376\377\377\377\377\377\202\377\376" \ - "\377\326\377\377\377\1__a\203::<\1;;=\203::<\1;;=\202::<\1\234\234\234" \ - "\377\377\377\377\274\377\377\377\1\376\376\376\203\377\377\377\3SSU;" \ - ";=99;\210::<\1\234\234\234\365\377\377\377\7\376\377\375\304\341\236" \ - "\215\306A\214\305B\215\307=\212\307>\212\306@\230\214\305@\1\304\341" \ - "\236\203\377\377\377\4\341\362\320\214\306>\213\310\77\215\305@\231\214" \ - "\305@\2\215\307\77\252\322q\202\377\376\377\202\377\377\377\1\250\325" \ - "n\230\214\305@\3\215\305>\215\306A\215\307\77\202\214\306<\10\342\360" \ - "\317\376\377\377\377\377\375\376\377\377\305\342\240\215\305@\212\306" \ - "@\215\305>\202\214\305@\1\215\307=\220\214\305@\10\214\306>\212\306@" \ - "\216\306A\212\307>\215\305>\215\305@\214\305@\304\343\237\211\377\377" \ - "\377\10\376\376\377\377\377\375\377\377\377\377\377\375\377\377\377\377" \ - "\376\377\377\377\375\376\377\377\202\377\377\377\6\370\373\362\243\322" \ - "b\211\307B\213\310=\214\305@\214\306<\202\215\305@\4\214\306<\214\305" \ - "@\214\306<\215\307\77\202\214\306>\6\212\307>\214\306>\215\307\77\214" \ - "\305@\244\317c\367\375\361\335\377\377\377\2\376\376\376\316\316\316" \ - "\211::<\3;;=GGI\363\363\365\203\377\377\377\1\376\376\376\377\377\377" \ - "\377\266\377\377\377\10\376\376\376\377\377\377\376\376\376\377\377\377" \ - "\265\265\265;;=::<;;=\207::<\2GGI\363\363\363\364\377\377\377\7\377\376" \ - "\377\377\377\375\304\341\236\215\305>\215\307\77\214\306>\214\305@\231" \ - "\214\306>\7\304\343\237\377\377\377\375\376\377\377\377\375\341\360\321" \ - "\215\306A\214\305@\233\214\306>\6\252\324n\376\376\376\377\377\377\376" \ - "\377\377\377\376\377\252\324p\230\214\306>\7\215\306A\212\307>\214\306" \ - ">\212\307>\214\306>\343\361\320\376\377\377\202\377\377\377\7\305\342" \ - "\237\215\305>\213\310\77\214\306>\214\305@\212\306@\215\307\77\222\214" \ - "\306>\6\215\305>\212\307>\214\306>\215\307=\215\305@\305\342\237\210" \ - "\377\377\377\6\376\376\377\377\376\377\375\376\377\376\377\377\377\377" \ - "\375\375\377\376\203\377\377\377\27\377\377\375\372\373\366\241\321a" \ - "\217\304@\212\307<\214\306>\215\305>\215\305@\213\310=\212\306@\214\306" \ - ">\214\305B\215\307\77\215\305>\215\306A\212\307>\214\306>\215\307\77" \ - "\214\306>\242\322b\370\373\362\376\376\377\377\375\376\336\377\377\377" \ - "\1kkm\202::<\1;;=\205::<\202;;=\3\233\233\235\377\377\377\376\376\376" \ - "\377\377\377\377\274\377\377\377\3SSU99;;;=\20299;\1;;=\203::<\3;;=:" \ - ":<\234\234\236\366\377\377\377\7\376\377\375\305\342\240\213\304\77\213" \ - "\310\77\214\305@\215\306A\216\306=\230\214\306>\10\305\342\240\377\377" \ - "\375\376\377\377\377\376\377\341\360\317\214\306<\214\305@\212\306@\231" \ - "\214\306>\7\215\305@\252\324p\377\377\377\377\377\375\376\377\377\377" \ - "\376\374\252\324p\230\214\306>\7\212\307>\215\307\77\216\306A\212\307" \ - ">\213\304\77\343\361\320\377\377\375\202\377\377\377\3\307\342\237\214" \ - "\304\77\213\310\77\203\214\306>\1\215\307\77\220\214\306>\4\214\305@" \ - "\214\306<\215\304B\213\310\77\202\212\307>\2\215\305@\305\342\240\210" \ - "\377\377\377\7\377\377\375\375\376\377\376\377\377\376\377\375\377\374" \ - "\377\377\377\375\375\377\376\202\377\377\377\5\372\373\366\240\320b\215" \ - "\307\77\212\306@\215\305>\202\214\305@\20\215\305@\212\306@\214\305D" \ - "\216\306\77\214\306>\215\307\77\214\306>\212\306@\214\306>\215\307\77" \ - "\215\305@\242\320c\370\373\362\377\377\373\377\376\377\377\377\375\331" \ - "\377\377\377\1\376\376\376\203\377\377\377\4\376\376\376\317\317\321" \ - "::<;;=\203::<\3;;=::<;;=\202::<\4FFH\363\363\363\377\377\377\376\376" \ - "\376\377\377\377\377\264\377\377\377\1\376\376\376\205\377\377\377\1" \ - "\265\265\267\202;;=\3::<99;;;=\202::<\202;;=\2::\231\214\306>\2\305\342\240\377\377\377\202\377\376\377\3\341" \ - "\362\316\216\306\77\214\306<\231\214\306>\3\215\305@\212\307>\252\324" \ - "p\203\377\377\377\2\377\376\377\247\324o\230\214\306>\20\215\306A\214" \ - "\305B\215\307\77\211\305\77\214\304;\342\362\315\377\377\377\377\376" \ - "\377\376\376\376\305\342\237\215\306A\210\307;\215\306A\216\306A\214" \ - "\306>\212\306@\220\214\306>\202\214\305@\6\216\305C\213\305=\214\305" \ - "B\215\307\77\216\306\77\303\344\237\211\377\377\377\37\376\377\377\376" \ - "\377\375\377\375\376\375\377\376\377\377\375\377\377\377\377\376\377" \ - "\370\373\362\241\321a\215\307\77\215\307=\214\305@\214\306>\212\307<" \ - "\214\306>\214\306<\214\306>\216\306\77\215\305<\212\307>\213\307A\215" \ - "\305>\212\307>\215\307\77\214\306>\242\321a\373\374\364\377\377\377\376" \ - "\377\377\376\376\376\376\377\377\331\377\377\377\3\376\376\376\377\377" \ - "\377\376\376\376\203\377\377\377\1kkm\202::<\6;;=::<;;=::<;;=::<\202" \ - ";;=\1\233\233\235\377\377\377\377\267\377\377\377\1\376\376\376\204\377" \ - "\377\377\2kkm;;=\202::<\2;;=::<\202;;=\203::<\5\265\265\267\377\377\377" \ - "\376\376\376\377\377\377\376\376\376\362\377\377\377\2\376\377\377\377" \ - "\376\377\202\377\377\377\202\377\376\377\2\377\377\377\377\377\375\231" \ - "\377\377\377\4\377\376\377\376\377\377\375\377\376\377\377\377\202\376" \ - "\377\377\231\377\377\377\10\374\377\375\377\376\377\377\377\375\376\376" \ - "\376\377\377\377\376\377\377\376\376\374\377\376\377\230\377\377\377" \ - "\1\377\376\377\203\377\377\375\4\376\377\377\377\375\377\377\377\377" \ - "\376\377\377\202\377\377\377\3\376\376\376\377\376\377\377\377\375\202" \ - "\376\377\377\1\377\377\375\220\377\377\377\10\377\377\375\377\377\377" \ - "\376\376\376\377\377\377\377\377\375\377\377\377\376\377\377\377\375" \ - "\377\210\377\377\377\202\377\377\375\3\377\374\377\375\377\376\376\377" \ - "\377\202\377\377\377\25\370\373\364\243\322b\217\304@\212\306@\214\305" \ - "@\215\305>\212\307>\212\306@\214\305B\214\305@\214\305B\214\306>\212" \ - "\307>\212\310\77\214\306>\217\304@\214\306>\214\305@\242\322b\370\373" \ - "\362\377\377\377\202\377\376\377\1\377\377\375\340\377\377\377\1\316" \ - "\316\316\203::<\3;;=99;;;=\204::<\2FFH\363\363\363\202\377\377\377\1" \ - "\376\376\376\377\377\377\377\264\377\377\377\1\376\376\376\202\377\377" \ - "\377\1\316\316\320\206::<\1;;=\203::<\2SSU\376\376\376\366\377\377\377" \ - "\1\377\377\375\202\377\376\377\202\377\377\377\3\377\377\375\377\377" \ - "\377\376\377\377\230\377\377\377\202\376\377\377\6\377\377\375\377\377" \ - "\377\376\377\375\377\377\377\376\377\375\377\377\375\231\377\377\377" \ - "\2\376\377\377\377\377\375\202\377\377\377\1\376\376\376\232\377\377" \ - "\377\5\377\376\377\377\377\377\376\377\375\377\377\377\377\377\375\204" \ - "\377\377\377\202\376\377\377\1\376\376\376\202\377\377\377\202\376\377" \ - "\377\220\377\377\377\1\377\377\375\202\377\377\377\4\376\376\374\377" \ - "\376\377\377\377\377\376\377\375\212\377\377\377\1\375\377\376\202\377" \ - "\377\375\34\377\377\377\376\376\376\373\373\363\243\322b\211\307B\212" \ - "\307<\215\305>\214\306>\212\307>\214\305@\217\304>\212\307<\214\306<" \ - "\214\306>\215\307\77\213\307A\214\306>\215\305@\215\307\77\212\307>\244" \ - "\317c\370\373\362\377\377\373\376\377\377\377\376\377\375\376\377\377" \ - "\377\375\377\376\377\334\377\377\377\1\376\376\376\202\377\377\377\10" \ - "\376\376\376kkm::<;;=99;;;=::<;;=\202::<\202;;=\1\234\234\236\203\377" \ - "\377\377\1\376\376\376\377\377\377\377\262\377\377\377\5\376\376\376" \ - "\377\377\377\376\376\376\377\377\377lln\210::<\3""99;;;=\265\265\265" \ - "\202\377\377\377\1\376\376\376\202\377\377\377\1\376\376\376\370\377" \ - "\377\377\1\376\377\377\230\377\377\377\7\377\376\377\377\377\375\377" \ - "\376\377\376\376\377\377\377\375\377\377\377\377\377\375\233\377\377" \ - "\377\1\377\376\377\203\377\377\377\1\376\377\375\231\377\377\377\5\377" \ - "\377\375\377\377\377\377\377\375\377\377\377\377\377\375\202\377\377" \ - "\377\1\377\377\375\203\377\377\377\2\376\376\376\377\376\377\226\377" \ - "\377\377\5\377\377\375\377\377\377\376\377\377\377\377\375\376\377\377" \ - "\210\377\377\377\3\377\376\377\377\377\377\375\377\376\202\377\377\377" \ - "\11\373\373\363\241\321d\214\306>\213\310=\214\306>\214\305@\213\310" \ - "=\212\306@\217\304>\202\215\307=\14\214\306>\215\305>\214\306>\215\305" \ - ">\217\304@\215\307\77\215\307=\242\320c\367\375\361\376\376\377\377\376" \ - "\377\376\376\376\202\377\377\375\2\374\377\377\377\376\377\333\377\377" \ - "\377\1\376\376\376\202\377\377\377\3\376\376\376\377\377\377\316\316" \ - "\320\203::<\1;;=\202::<\1;;=\203::<\2FFH\377\377\377\202\376\376\376" \ - "\377\377\377\377\262\377\377\377\5\376\376\376\377\377\377\376\376\376" \ - "\377\377\377\332\332\332\206::<\1;;=\202::<\5;;=FFH\363\363\363\377\377" \ - "\377\376\376\376\203\377\377\377\1\376\376\376\365\377\377\377\1\377" \ - "\377\375\202\377\377\377\1\377\377\375\230\377\377\377\2\376\377\377" \ - "\377\377\375\204\377\377\377\2\377\376\377\376\377\375\230\377\377\377" \ - "\4\377\377\375\377\377\377\377\377\373\376\377\377\203\377\377\377\1" \ - "\377\376\377\230\377\377\377\13\376\377\377\377\377\375\377\377\377\376" \ - "\377\377\377\375\376\377\377\377\377\377\375\376\377\377\377\376\377" \ - "\377\377\377\376\376\376\202\377\377\377\1\377\377\375\226\377\377\377" \ - "\202\376\377\377\2\377\377\375\377\376\377\210\377\377\377\1\377\377" \ - "\375\202\377\377\377\32\377\376\377\370\373\364\243\322b\214\306>\213" \ - "\310\77\214\305@\215\305>\215\305@\214\306>\214\305B\212\307<\215\307" \ - "=\214\305B\214\306>\215\306A\212\306@\212\307>\214\306>\212\307<\244" \ - "\317c\370\373\364\377\377\377\377\375\376\377\377\375\376\377\377\377" \ - "\377\377\202\377\376\377\333\377\377\377\1\376\376\376\204\377\377\377" \ - "\11\376\376\376\377\377\377kkm::<;;=99;;;=::<;;=\202::<\3;;=::<\264\264" \ - "\264\377\377\377\377\265\377\377\377\1\376\376\376\202\377\377\377\1" \ - "\204\204\204\203::<\1;;=\206::<\1\235\235\237\377\377\377\377\377\377" \ - "\377\377\203\377\377\377\10\376\376\377\377\377\375\377\377\377\377\377" \ - "\375\377\377\377\377\376\377\377\377\375\376\377\377\202\377\377\377" \ - "\6\370\373\362\243\322b\211\307B\213\310=\214\305@\214\306<\202\215\305" \ - "@\4\214\306<\214\305@\214\306<\215\307\77\202\214\306>\6\212\307>\214" \ - "\306>\215\307\77\214\305@\244\317c\367\375\361\352\377\377\377\1\316" \ - "\316\316\203::<\1;;=\203::<\202;;=\2::\215\305>\215" \ - "\305@\213\310=\212\306@\214\306>\214\305B\215\307\77\215\305>\215\306" \ - "A\212\307>\214\306>\215\307\77\214\306>\242\322b\370\373\362\376\376" \ - "\377\377\375\376\352\377\377\377\2kkm;;=\207::<\3;;=::<\301\301\301\377" \ - "\377\377\377\266\377\377\377\2\221\221\221;;=\202::<\202;;=\202::<\1" \ - ";;=\202::<\1\235\235\237\377\377\377\377\377\377\377\377\203\377\377" \ - "\377\7\377\377\375\375\376\377\376\377\377\376\377\375\377\374\377\377" \ - "\377\375\375\377\376\202\377\377\377\5\372\373\366\240\320b\215\307\77" \ - "\212\306@\215\305>\202\214\305@\20\215\305@\212\306@\214\305D\216\306" \ - "\77\214\306>\215\307\77\214\306>\212\306@\214\306>\215\307\77\215\305" \ - "@\242\320c\370\373\362\377\377\373\377\376\377\377\377\375\350\377\377" \ - "\377\4\376\376\376\377\377\377\265\265\26799;\203::<\3;;=::<;;=\203:" \ - ":<\2kkk\376\376\376\377\377\377\377\264\377\377\377\2\362\362\362FFH" \ - "\202::<\1;;=\203::<\5;;=::<;;=::<\363\363\363\377\377\377\377\377\377" \ - "\377\377\204\377\377\377\37\376\377\377\376\377\375\377\375\376\375\377" \ - "\376\377\377\375\377\377\377\377\376\377\370\373\362\241\321a\215\307" \ - "\77\215\307=\214\305@\214\306>\212\307<\214\306>\214\306<\214\306>\216" \ - "\306\77\215\305<\212\307>\213\307A\215\305>\212\307>\215\307\77\214\306" \ - ">\242\321a\373\374\364\377\377\377\376\377\377\376\376\376\376\377\377" \ - "\352\377\377\377\2\376\376\376TTV\204::<\7;;=99;::<;;=99;::<\332\332" \ - "\332\377\377\377\377\263\377\377\377\3\376\376\376\266\266\266;;=\203" \ - "::<\202;;=\204::<\1\205\205\207\377\377\377\377\377\377\377\377\204\377" \ - "\377\377\202\377\377\375\3\377\374\377\375\377\376\376\377\377\202\377" \ - "\377\377\25\370\373\364\243\322b\217\304@\212\306@\214\305@\215\305>" \ - "\212\307>\212\306@\214\305B\214\305@\214\305B\214\306>\212\307>\212\310" \ - "\77\214\306>\217\304@\214\306>\214\305@\242\322b\370\373\362\377\377" \ - "\377\202\377\376\377\1\377\377\375\354\377\377\377\2\265\265\267::<\202" \ - ";;=\205::<\4;;=::<\204\204\204\376\376\376\377\377\377\377\263\377\377" \ - "\377\1SSU\202::<\1;;=\206::<\2;;=\346\346\346\377\377\377\377\377\377" \ - "\377\377\205\377\377\377\1\375\377\376\202\377\377\375\34\377\377\377" \ - "\376\376\376\373\373\363\243\322b\211\307B\212\307<\215\305>\214\306" \ - ">\212\307>\214\305@\217\304>\212\307<\214\306<\214\306>\215\307\77\213" \ - "\307A\214\306>\215\305@\215\307\77\212\307>\244\317c\370\373\362\377" \ - "\377\373\376\377\377\377\376\377\375\376\377\377\377\375\377\376\377" \ - "\354\377\377\377\4FFH;;=99;;;=\203::<\5;;=99;;;=99;\364\364\364\377\377" \ - "\377\377\262\377\377\377\1\316\316\316\202;;=\1""99;\203::<\1;;=\203" \ - "::<\1xxz\377\377\377\377\377\377\377\377\205\377\377\377\3\377\376\377" \ - "\377\377\377\375\377\376\202\377\377\377\11\373\373\363\241\321d\214" \ - "\306>\213\310=\214\306>\214\305@\213\310=\212\306@\217\304>\202\215\307" \ - "=\14\214\306>\215\305>\214\306>\215\305>\217\304@\215\307\77\215\307" \ - "=\242\320c\367\375\361\376\376\377\377\376\377\376\376\376\202\377\377" \ - "\375\2\374\377\377\377\376\377\354\377\377\377\1\235\235\237\204::<\1" \ - "<<>\202::<\4;;=::<;;=\247\247\251\377\377\377\377\262\377\377\377\4\204" \ - "\204\204;;=::<;;=\206::<\2;;=\316\316\316\377\377\377\377\377\377\377" \ - "\377\205\377\377\377\1\377\377\375\202\377\377\377\32\377\376\377\370" \ - "\373\364\243\322b\214\306>\213\310\77\214\305@\215\305>\215\305@\214" \ - "\306>\214\305B\212\307<\215\307=\214\305B\214\306>\215\306A\212\306@" \ - "\212\307>\214\306>\212\307<\244\317c\370\373\364\377\377\377\377\375" \ - "\376\377\377\375\376\377\377\377\377\377\202\377\376\377\355\377\377" \ - "\377\1\363\363\363\212::<\1TTV\377\377\377\377\261\377\377\377\5\347" \ - "\347\351::<;;=::<;;=\204::<\3;;=::\6\212\307>\214\306>\215\307\77\214\305" \ - "@\244\317c\367\375\361\361\377\377\377\1\376\376\376\204\377\377\377" \ - "\1\204\204\204\202;;=\203::<\1;;=\202::<\202;;=\1\302\302\302\203\377" \ - "\377\377\1\376\376\376\377\377\377\377\244\377\377\377\1\376\376\376" \ - "\203\377\377\377\1\376\376\376\203\377\377\377\1\234\234\236\202::<\1" \ - ";;=\204::<\6;;=::<;;=\264\264\264\377\377\377\376\376\376\377\377\377" \ - "\377\373\377\377\377\6\376\376\377\377\376\377\375\376\377\376\377\377" \ - "\377\377\375\375\377\376\203\377\377\377\27\377\377\375\372\373\366\241" \ - "\321a\217\304@\212\307<\214\306>\215\305>\215\305@\213\310=\212\306@" \ - "\214\306>\214\305B\215\307\77\215\305>\215\306A\212\307>\214\306>\215" \ - "\307\77\214\306>\242\322b\370\373\362\376\376\377\377\375\376\365\377" \ - "\377\377\1\332\332\332\202::<\1;;=\202::<\6""99;::<;;=99;;;=xxx\205\377" \ - "\377\377\1\376\376\376\377\377\377\377\243\377\377\377\1\376\376\376" \ - "\206\377\377\377\4SSU;;=::<;;=\202::<\1;;=\203::<\3GGI\362\362\362\376" \ - "\376\376\377\377\377\377\374\377\377\377\7\377\377\375\375\376\377\376" \ - "\377\377\376\377\375\377\374\377\377\377\375\375\377\376\202\377\377" \ - "\377\5\372\373\366\240\320b\215\307\77\212\306@\215\305>\202\214\305" \ - "@\20\215\305@\212\306@\214\305D\216\306\77\214\306>\215\307\77\214\306" \ - ">\212\306@\214\306>\215\307\77\215\305@\242\320c\370\373\362\377\377" \ - "\373\377\376\377\377\377\375\364\377\377\377\3\376\376\376\377\377\377" \ - "__a\203::<\202;;=\6::<99;;;=::<;;=\345\345\345\203\377\377\377\1\376" \ - "\376\376\377\377\377\377\245\377\377\377\3\376\376\376\377\377\377\376" \ - "\376\376\202\377\377\377\2\316\316\316::<\202;;=\205::<\202;;=\1\203" \ - "\203\205\204\377\377\377\1\376\376\376\377\377\377\377\372\377\377\377" \ - "\37\376\377\377\376\377\375\377\375\376\375\377\376\377\377\375\377\377" \ - "\377\377\376\377\370\373\362\241\321a\215\307\77\215\307=\214\305@\214" \ - "\306>\212\307<\214\306>\214\306<\214\306>\216\306\77\215\305<\212\307" \ - ">\213\307A\215\305>\212\307>\215\307\77\214\306>\242\321a\373\374\364" \ - "\377\377\377\376\377\377\376\376\376\376\377\377\362\377\377\377\202" \ - "\376\376\376\3\377\377\377\376\376\376\265\265\267\202::<\1;;=\207::" \ - "<\3\251\251\253\377\377\377\376\376\376\203\377\377\377\1\376\376\376" \ - "\377\377\377\377\247\377\377\377\2\376\376\376\204\204\206\207::<\1;" \ - ";=\202::<\3\346\346\346\377\377\377\376\376\376\377\377\377\377\374\377" \ - "\377\377\202\377\377\375\3\377\374\377\375\377\376\376\377\377\202\377" \ - "\377\377\25\370\373\364\243\322b\217\304@\212\306@\214\305@\215\305>" \ - "\212\307>\212\306@\214\305B\214\305@\214\305B\214\306>\212\307>\212\310" \ - "\77\214\306>\217\304@\214\306>\214\305@\242\322b\370\373\362\377\377" \ - "\377\202\377\376\377\1\377\377\375\364\377\377\377\17\376\376\376\377" \ - "\377\377\376\376\376\377\377\377FFH;;=99;::<;;=::<;;=99;;;=::\214" \ - "\306>\212\307>\214\305@\217\304>\212\307<\214\306<\214\306>\215\307\77" \ - "\213\307A\214\306>\215\305@\215\307\77\212\307>\244\317c\370\373\362" \ - "\377\377\373\376\377\377\377\376\377\375\376\377\377\377\375\377\376" \ - "\377\361\377\377\377\202\376\376\376\2\377\377\377\376\376\376\202\377" \ - "\377\377\1\221\221\221\205::<\202;;=\5::<;;=99;\316\316\320\376\376\376" \ - "\377\377\377\377\250\377\377\377\1\376\376\376\202\377\377\377\4\266" \ - "\266\270::<99;;;=\203::<\1;;=\203::<\1\265\265\265\377\377\377\377\377" \ - "\377\377\377\3\377\376\377\377\377\377\375\377\376\202\377\377\377\11" \ - "\373\373\363\241\321d\214\306>\213\310=\214\306>\214\305@\213\310=\212" \ - "\306@\217\304>\202\215\307=\14\214\306>\215\305>\214\306>\215\305>\217" \ - "\304@\215\307\77\215\307=\242\320c\367\375\361\376\376\377\377\376\377" \ - "\376\376\376\202\377\377\375\2\374\377\377\377\376\377\360\377\377\377" \ - "\1\376\376\376\202\377\377\377\202\376\376\376\202\377\377\377\6\346" \ - "\346\346;;=99;::<99;;;=\204::<\2;;=\204\204\206\202\377\377\377\1\376" \ - "\376\376\377\377\377\377\251\377\377\377\1__a\203::<\3;;=::<;;=\203:" \ - ":<\4FFF\363\363\363\377\377\377\376\376\376\377\377\377\377\375\377\377" \ - "\377\1\377\377\375\202\377\377\377\32\377\376\377\370\373\364\243\322" \ - "b\214\306>\213\310\77\214\305@\215\305>\215\305@\214\306>\214\305B\212" \ - "\307<\215\307=\214\305B\214\306>\215\306A\212\306@\212\307>\214\306>" \ - "\212\307<\244\317c\370\373\364\377\377\377\377\375\376\377\377\375\376" \ - "\377\377\377\377\377\202\377\376\377\371\377\377\377\4^^`;;=::<;;=\202" \ - "::<\5;;=::<;;=::\6\212\307>\214\306" \ - ">\215\307\77\214\305@\244\317c\367\375\361\377\377\377\377\202\377\377" \ - "\377\3\265\265\267::<;;=\204::<\1;;=\202::<\2;;=\265\265\265\202\377" \ - "\377\377\1\376\376\376\377\377\377\377\246\377\377\377\2\376\376\376" \ - "\234\234\234\202;;=\203::<\1;;=\202::<\3""99;::<\332\332\332\377\377" \ - "\377\377\370\377\377\377\6\376\376\377\377\376\377\375\376\377\376\377" \ - "\377\377\377\375\375\377\376\203\377\377\377\27\377\377\375\372\373\366" \ - "\241\321a\217\304@\212\307<\214\306>\215\305>\215\305@\213\310=\212\306" \ - "@\214\306>\214\305B\215\307\77\215\305>\215\306A\212\307>\214\306>\215" \ - "\307\77\214\306>\242\322b\370\373\362\376\376\377\377\375\376\377\377" \ - "\377\377\5\377\377\377\363\363\365;;=::<;;=\202::<\3;;=::<;;=\202::<" \ - "\3xxz\377\377\377\376\376\376\377\377\377\377\246\377\377\377\3\376\376" \ - "\376\377\377\377SSS\202::<\1;;=\202::<\1;;=\202::<\6;;=SSU\377\377\377" \ - "\376\376\376\377\377\377\376\376\376\202\377\377\377\1\376\376\376\377" \ - "\377\377\377\362\377\377\377\7\377\377\375\375\376\377\376\377\377\376" \ - "\377\375\377\374\377\377\377\375\375\377\376\202\377\377\377\5\372\373" \ - "\366\240\320b\215\307\77\212\306@\215\305>\202\214\305@\20\215\305@\212" \ - "\306@\214\305D\216\306\77\214\306>\215\307\77\214\306>\212\306@\214\306" \ - ">\215\307\77\215\305@\242\320c\370\373\362\377\377\373\377\376\377\377" \ - "\377\375\377\377\377\377\11\377\377\377\376\376\376\204\204\206;;=::" \ - "<99;;;=::<;;=\204::<\3\362\362\362\377\377\377\376\376\376\377\377\377" \ - "\377\246\377\377\377\1\333\333\333\203::<\202;;=\202::<\5<<>99;::<\250" \ - "\250\252\376\376\376\203\377\377\377\1\376\376\376\377\377\377\377\365" \ - "\377\377\377\37\376\377\377\376\377\375\377\375\376\375\377\376\377\377" \ - "\375\377\377\377\377\376\377\370\373\362\241\321a\215\307\77\215\307" \ - "=\214\305@\214\306>\212\307<\214\306>\214\306<\214\306>\216\306\77\215" \ - "\305<\212\307>\213\307A\215\305>\212\307>\215\307\77\214\306>\242\321" \ - "a\373\374\364\377\377\377\376\377\377\376\376\376\376\377\377\377\377" \ - "\377\377\202\377\377\377\1\301\301\301\202::<\1;;=\203::<\1;;=\203::" \ - "<\1\266\266\270\377\377\377\377\250\377\377\377\2\220\220\220;;=\204" \ - "::<\6;;=::<99;;;=::<\346\346\346\205\377\377\377\1\376\376\376\377\377" \ - "\377\377\363\377\377\377\202\377\377\375\3\377\374\377\375\377\376\376" \ - "\377\377\202\377\377\377\25\370\373\364\243\322b\217\304@\212\306@\214" \ - "\305@\215\305>\212\307>\212\306@\214\305B\214\305@\214\305B\214\306>" \ - "\212\307>\212\310\77\214\306>\217\304@\214\306>\214\305@\242\322b\370" \ - "\373\362\377\377\377\202\377\376\377\1\377\377\375\377\377\377\377\204" \ - "\377\377\377\2TTV99;\202::<\1;;=\202::<\6;;=::<;;=__a\377\377\377\376" \ - "\376\376\377\377\377\377\244\377\377\377\3\376\376\376\377\377\377TT" \ - "V\207::<\3;;=99;```\377\377\377\377\373\377\377\377\1\375\377\376\202" \ - "\377\377\375\34\377\377\377\376\376\376\373\373\363\243\322b\211\307" \ - "B\212\307<\215\305>\214\306>\212\307>\214\305@\217\304>\212\307<\214" \ - "\306<\214\306>\215\307\77\213\307A\214\306>\215\305@\215\307\77\212\307" \ - ">\244\317c\370\373\362\377\377\373\376\377\377\377\376\377\375\376\377" \ - "\377\377\375\377\376\377\377\377\377\377\203\377\377\377\3\221\221\221" \ - "::<;;=\202::<\202;;=\203::<\2;;=\345\345\347\377\377\377\377\246\377" \ - "\377\377\4\332\332\332;;=::<;;=\203::<\1;;=\203::<\1\265\265\265\203" \ - "\377\377\377\3\376\376\376\377\377\377\376\376\376\377\377\377\377\364" \ - "\377\377\377\3\377\376\377\377\377\377\375\377\376\202\377\377\377\11" \ - "\373\373\363\241\321d\214\306>\213\310=\214\306>\214\305@\213\310=\212" \ - "\306@\217\304>\202\215\307=\14\214\306>\215\305>\214\306>\215\305>\217" \ - "\304@\215\307\77\215\307=\242\320c\367\375\361\376\376\377\377\376\377" \ - "\376\376\376\202\377\377\375\2\374\377\377\377\376\377\377\377\377\377" \ - "\202\377\377\377\5\376\376\376\332\332\332;;=::<;;=\202::<\6;;=::<;;" \ - "=99;::<\250\250\252\377\377\377\377\244\377\377\377\6\376\376\376\377" \ - "\377\377\221\221\223::<;;=99;\202::<\3;;=::<;;=\202::<\1\363\363\363" \ - "\377\377\377\377\372\377\377\377\1\377\377\375\202\377\377\377\32\377" \ - "\376\377\370\373\364\243\322b\214\306>\213\310\77\214\305@\215\305>\215" \ - "\305@\214\306>\214\305B\212\307<\215\307=\214\305B\214\306>\215\306A" \ - "\212\306@\212\307>\214\306>\212\307<\244\317c\370\373\364\377\377\377" \ - "\377\375\376\377\377\375\376\377\377\377\377\377\202\377\376\377\377" \ - "\377\377\377\204\377\377\377\2\376\376\376SSU\204::<\204;;=\2::<__a\377" \ - "\377\377\377\243\377\377\377\6\376\376\376\377\377\377\376\376\376TT" \ - "V99;;;=\204::<\4;;=99;<<>xxz\377\377\377\377\364\377\377\377\10\376\376" \ - "\377\377\377\375\377\377\377\377\377\375\377\377\377\377\376\377\377" \ - "\377\375\376\377\377\202\377\377\377\6\370\373\362\243\322b\211\307B" \ - "\213\310=\214\305@\214\306<\202\215\305@\4\214\306<\214\305@\214\306" \ - "<\215\307\77\202\214\306>\6\212\307>\214\306>\215\307\77\214\305@\244" \ - "\317c\367\375\361\377\377\377\377\213\377\377\377\5\376\376\376\377\377" \ - "\377\221\221\223::<;;=\204::<\5;;=::<;;=::<\363\363\363\204\377\377\377" \ - "\1\376\376\376\202\377\377\377\202\376\376\376\377\377\377\377\233\377" \ - "\377\377\5\332\332\332::<;;=99;<<>\202::<\1;;=\203::<\1\265\265\267\377" \ - "\377\377\377\363\377\377\377\6\376\376\377\377\376\377\375\376\377\376" \ - "\377\377\377\377\375\375\377\376\203\377\377\377\27\377\377\375\372\373" \ - "\366\241\321a\217\304@\212\307<\214\306>\215\305>\215\305@\213\310=\212" \ - "\306@\214\306>\214\305B\215\307\77\215\305>\215\306A\212\307>\214\306" \ - ">\215\307\77\214\306>\242\322b\370\373\362\376\376\377\377\375\376\377" \ - "\377\377\377\213\377\377\377\2\375\375\375\333\333\333\202::<\1;;=\202" \ - "::<\1;;=\202::<\3""99;::<\265\265\265\206\377\377\377\3\376\376\376\377" \ - "\377\377\376\376\376\377\377\377\377\233\377\377\377\2\235\235\23599" \ - ";\202;;=\1""99;\202;;=\202::<\3;;=::<\363\363\365\377\377\377\377\363" \ - "\377\377\377\7\377\377\375\375\376\377\376\377\377\376\377\375\377\374" \ - "\377\377\377\375\375\377\376\202\377\377\377\5\372\373\366\240\320b\215" \ - "\307\77\212\306@\215\305>\202\214\305@\20\215\305@\212\306@\214\305D" \ - "\216\306\77\214\306>\215\307\77\214\306>\212\306@\214\306>\215\307\77" \ - "\215\305@\242\320c\370\373\362\377\377\373\377\376\377\377\377\375\377" \ - "\377\377\377\214\377\377\377\2\376\376\376SSU\207::<\3;;=::\212\307<\214\306>\214\306<\214\306>\216\306" \ - "\77\215\305<\212\307>\213\307A\215\305>\212\307>\215\307\77\214\306>" \ - "\242\321a\373\374\364\377\377\377\376\377\377\376\376\376\376\377\377" \ - "\377\377\377\377\212\377\377\377\4\376\376\376\377\377\377\376\376\376" \ - "\222\222\222\205::<\1;;=\20299;\202::<\3\363\363\363\377\377\377\376" \ - "\376\376\377\377\377\377\240\377\377\377\1\346\346\346\202::<\1;;=\204" \ - "::<\1;;=\202::<\1\250\250\252\202\377\377\377\1\376\376\376\377\377\377" \ - "\377\361\377\377\377\202\377\377\375\3\377\374\377\375\377\376\376\377" \ - "\377\202\377\377\377\25\370\373\364\243\322b\217\304@\212\306@\214\305" \ - "@\215\305>\212\307>\212\306@\214\305B\214\305@\214\305B\214\306>\212" \ - "\307>\212\310\77\214\306>\217\304@\214\306>\214\305@\242\322b\370\373" \ - "\362\377\377\377\202\377\376\377\1\377\377\375\377\377\377\377\212\377" \ - "\377\377\1\376\376\376\203\377\377\377\2\332\332\332<<>\203::<\3;;=:" \ - ":<<<>\203::<\2\301\301\303\376\376\376\202\377\377\377\5\376\376\376" \ - "\377\377\377\376\376\376\377\377\377\376\376\376\377\377\377\377\231" \ - "\377\377\377\4\376\376\376\251\251\253::<;;=\204::<\5;;=::<99;::<\346" \ - "\346\346\377\377\377\377\365\377\377\377\1\375\377\376\202\377\377\375" \ - "\34\377\377\377\376\376\376\373\373\363\243\322b\211\307B\212\307<\215" \ - "\305>\214\306>\212\307>\214\305@\217\304>\212\307<\214\306<\214\306>" \ - "\215\307\77\213\307A\214\306>\215\305@\215\307\77\212\307>\244\317c\370" \ - "\373\362\377\377\373\376\377\377\377\376\377\375\376\377\377\377\375" \ - "\377\376\377\377\377\377\377\212\377\377\377\1\376\376\376\203\377\377" \ - "\377\1SSS\207::<\3;;=::<\205\205\207\205\377\377\377\1\376\376\376\377" \ - "\377\377\377\234\377\377\377\3wwy::<;;=\206::<\2;;=__a\377\377\377\377" \ - "\365\377\377\377\3\377\376\377\377\377\377\375\377\376\202\377\377\377" \ - "\11\373\373\363\241\321d\214\306>\213\310=\214\306>\214\305@\213\310" \ - "=\212\306@\217\304>\202\215\307=\14\214\306>\215\305>\214\306>\215\305" \ - ">\217\304@\215\307\77\215\307=\242\320c\367\375\361\376\376\377\377\376" \ - "\377\376\376\376\202\377\377\375\2\374\377\377\377\376\377\377\377\377" \ - "\377\211\377\377\377\1\376\376\376\203\377\377\377\3\376\376\376\204" \ - "\204\204::<\202;;=\1::<\202;;=\203::<\1SSU\204\377\377\377\1\376\376" \ - "\376\377\377\377\377\235\377\377\377\1;;=\203::<\1;;=\202::<\1;;=\202" \ - "::<\1\234\234\234\202\377\377\377\1\376\376\376\377\377\377\377\362\377" \ - "\377\377\1\377\377\375\202\377\377\377\32\377\376\377\370\373\364\243" \ - "\322b\214\306>\213\310\77\214\305@\215\305>\215\305@\214\306>\214\305" \ - "B\212\307<\215\307=\214\305B\214\306>\215\306A\212\306@\212\307>\214" \ - "\306>\212\307<\244\317c\370\373\364\377\377\377\377\375\376\377\377\375" \ - "\376\377\377\377\377\377\202\377\376\377\377\377\377\377\212\377\377" \ - "\377\1\376\376\376\204\377\377\377\6\301\301\301;;=::<;;=::<;;=\205:" \ - ":<\1\333\333\333\202\377\377\377\1\376\376\376\377\377\377\377\231\377" \ - "\377\377\1\376\376\376\203\377\377\377\1\301\301\303\204::<\1;;=\202" \ - "::<\1:9>\202::<\1\332\332\332\377\377\377\377\356\377\377\377\10\376" \ - "\376\377\377\377\375\377\377\377\377\377\375\377\377\377\377\376\377" \ - "\377\377\375\376\377\377\202\377\377\377\6\370\373\362\243\322b\211\307" \ - "B\213\310=\214\305@\214\306<\202\215\305@\4\214\306<\214\305@\214\306" \ - "<\215\307\77\202\214\306>\6\212\307>\214\306>\215\307\77\214\305@\244" \ - "\317c\367\375\361\377\377\377\377\230\377\377\377\2""99;;;=\210::<\1" \ - "\250\250\250\377\377\377\377\240\377\377\377\3\221\221\223::<;;=\207" \ - "::<\2SSU\376\376\376\377\377\377\377\355\377\377\377\6\376\376\377\377" \ - "\376\377\375\376\377\376\377\377\377\377\375\375\377\376\203\377\377" \ - "\377\27\377\377\375\372\373\366\241\321a\217\304@\212\307<\214\306>\215" \ - "\305>\215\305@\213\310=\212\306@\214\306>\214\305B\215\307\77\215\305" \ - ">\215\306A\212\307>\214\306>\215\307\77\214\306>\242\322b\370\373\362" \ - "\376\376\377\377\375\376\377\377\377\377\227\377\377\377\1yy{\211::<" \ - "\6lll\376\376\376\377\377\377\376\376\376\377\377\377\376\376\376\377" \ - "\377\377\377\224\377\377\377\202\376\376\376\7\377\377\377\376\376\376" \ - "\377\377\377\376\376\376\377\377\377__a;;=\202::<\4<<>;;=::<;;=\202:" \ - ":<\1\204\204\206\203\377\377\377\1\376\376\376\377\377\377\377\352\377" \ - "\377\377\7\377\377\375\375\376\377\376\377\377\376\377\375\377\374\377" \ - "\377\377\375\375\377\376\202\377\377\377\5\372\373\366\240\320b\215\307" \ - "\77\212\306@\215\305>\202\214\305@\20\215\305@\212\306@\214\305D\216" \ - "\306\77\214\306>\215\307\77\214\306>\212\306@\214\306>\215\307\77\215" \ - "\305@\242\320c\370\373\362\377\377\373\377\376\377\377\377\375\377\377" \ - "\377\377\221\377\377\377\3\376\376\376\377\377\377\376\376\376\203\377" \ - "\377\377\1\265\265\267\212::<\1\363\363\363\377\377\377\377\227\377\377" \ - "\377\1\376\376\376\202\377\377\377\1\376\376\376\203\377\377\377\1\345" \ - "\345\345\202::<\202;;=\1""99;\203::<\4;;=::<\301\301\301\376\376\376" \ - "\203\377\377\377\1\376\376\376\377\377\377\377\352\377\377\377\37\376" \ - "\377\377\376\377\375\377\375\376\375\377\376\377\377\375\377\377\377" \ - "\377\376\377\370\373\362\241\321a\215\307\77\215\307=\214\305@\214\306" \ - ">\212\307<\214\306>\214\306<\214\306>\216\306\77\215\305<\212\307>\213" \ - "\307A\215\305>\212\307>\215\307\77\214\306>\242\321a\373\374\364\377" \ - "\377\377\376\377\377\376\376\376\376\377\377\377\377\377\377\222\377" \ - "\377\377\3\376\376\376\377\377\377\376\376\376\202\377\377\377\1\347" \ - "\347\347\212::<\1\302\302\304\205\377\377\377\1\376\376\376\377\377\377" \ - "\377\222\377\377\377\1\376\376\376\202\377\377\377\1\376\376\376\202" \ - "\377\377\377\5\265\265\265::<;;=99;;;=\203::<\1;;=\202::<\1\363\363\363" \ - "\377\377\377\377\356\377\377\377\202\377\377\375\3\377\374\377\375\377" \ - "\376\376\377\377\202\377\377\377\25\370\373\364\243\322b\217\304@\212" \ - "\306@\214\305@\215\305>\212\307>\212\306@\214\305B\214\305@\214\305B" \ - "\214\306>\212\307>\212\310\77\214\306>\217\304@\214\306>\214\305@\242" \ - "\322b\370\373\362\377\377\377\202\377\376\377\1\377\377\375\377\377\377" \ - "\377\230\377\377\377\2\376\376\376TTT\211::<\3\221\221\223\377\377\377" \ - "\376\376\376\202\377\377\377\1\376\376\376\377\377\377\377\231\377\377" \ - "\377\2\204\204\204::<\202;;=\202::<\1;;=\203::<\2``b\376\376\376\377" \ - "\377\377\377\357\377\377\377\1\375\377\376\202\377\377\375\34\377\377" \ - "\377\376\376\376\373\373\363\243\322b\211\307B\212\307<\215\305>\214" \ - "\306>\212\307>\214\305@\217\304>\212\307<\214\306<\214\306>\215\307\77" \ - "\213\307A\214\306>\215\305@\215\307\77\212\307>\244\317c\370\373\362" \ - "\377\377\373\376\377\377\377\376\377\375\376\377\377\377\375\377\376" \ - "\377\377\377\377\377\225\377\377\377\1\376\376\376\202\377\377\377\1" \ - "\221\221\221\210::<\2;;=__a\202\377\377\377\1\376\376\376\377\377\377" \ - "\377\227\377\377\377\1\376\376\376\203\377\377\377\1SSU\202::<\1;;=\204" \ - "::<\202;;=\1\234\234\234\204\377\377\377\1\376\376\376\377\377\377\377" \ - "\352\377\377\377\3\377\376\377\377\377\377\375\377\376\202\377\377\377" \ - "\11\373\373\363\241\321d\214\306>\213\310=\214\306>\214\305@\213\310" \ - "=\212\306@\217\304>\202\215\307=\14\214\306>\215\305>\214\306>\215\305" \ - ">\217\304@\215\307\77\215\307=\242\320c\367\375\361\376\376\377\377\376" \ - "\377\376\376\376\202\377\377\375\2\374\377\377\377\376\377\377\377\377" \ - "\377\222\377\377\377\1\376\376\376\205\377\377\377\1\301\301\301\210" \ - "::<\4""99;;;=\364\364\366\376\376\376\377\377\377\377\233\377\377\377" \ - "\1\346\346\346\207::<\4;;=99;::<\316\316\316\203\377\377\377\1\376\376" \ - "\376\377\377\377\377\353\377\377\377\1\377\377\375\202\377\377\377\32" \ - "\377\376\377\370\373\364\243\322b\214\306>\213\310\77\214\305@\215\305" \ - ">\215\305@\214\306>\214\305B\212\307<\215\307=\214\305B\214\306>\215" \ - "\306A\212\306@\212\307>\214\306>\212\307<\244\317c\370\373\364\377\377" \ - "\377\377\375\376\377\377\375\376\377\377\377\377\377\202\377\376\377" \ - "\377\377\377\377\224\377\377\377\1\376\376\376\204\377\377\377\1\363" \ - "\363\363\210::<\3;;=::<\302\302\304\377\377\377\377\231\377\377\377\1" \ - "\376\376\376\202\377\377\377\1\266\266\270\203::<\203;;=\203::<\1:::" \ - "\377\377\377\377\351\377\377\377\10\376\376\377\377\377\375\377\377\377" \ - "\377\377\375\377\377\377\377\376\377\377\377\375\376\377\377\202\377" \ - "\377\377\6\370\373\362\243\322b\211\307B\213\310=\214\305@\214\306<\202" \ - "\215\305@\4\214\306<\214\305@\214\306<\215\307\77\202\214\306>\6\212" \ - "\307>\214\306>\215\307\77\214\305@\244\317c\367\375\361\377\377\377\377" \ - "\242\377\377\377\3__a::<;;=\207::<\1\221\221\221\377\377\377\377\234" \ - "\377\377\377\1\204\204\206\204::<\202;;=\203::<\1lll\203\377\377\377" \ - "\1\375\375\375\377\377\377\377\344\377\377\377\6\376\376\377\377\376" \ - "\377\375\376\377\376\377\377\377\377\375\375\377\376\203\377\377\377" \ - "\27\377\377\375\372\373\366\241\321a\217\304@\212\307<\214\306>\215\305" \ - ">\215\305@\213\310=\212\306@\214\306>\214\305B\215\307\77\215\305>\215" \ - "\306A\212\307>\214\306>\215\307\77\214\306>\242\322b\370\373\362\376" \ - "\376\377\377\375\376\377\377\377\377\241\377\377\377\2\221\221\223;;" \ - "=\202::<\202;;=\203::<\2;;=^^^\204\377\377\377\1\376\376\376\377\377" \ - "\377\377\224\377\377\377\1\376\376\376\202\377\377\377\1``b\202::<\1" \ - ";;=\206::<\1\234\234\234\205\377\377\377\1\376\376\376\377\377\377\377" \ - "\342\377\377\377\7\377\377\375\375\376\377\376\377\377\376\377\375\377" \ - "\374\377\377\377\375\375\377\376\202\377\377\377\5\372\373\366\240\320" \ - "b\215\307\77\212\306@\215\305>\202\214\305@\20\215\305@\212\306@\214" \ - "\305D\216\306\77\214\306>\215\307\77\214\306>\212\306@\214\306>\215\307" \ - "\77\215\305@\242\320c\370\373\362\377\377\373\377\376\377\377\377\375" \ - "\377\377\377\377\241\377\377\377\6\301\301\303::<;;=::<99;;;=\203::<" \ - "\6;;=:::\377\377\377\376\376\376\377\377\377\376\376\376\377\377\377" \ - "\377\224\377\377\377\1\376\376\376\202\377\377\377\2\363\363\363;;=\211" \ - "::<\1\316\316\316\203\377\377\377\1\376\376\376\202\377\377\377\1\376" \ - "\376\376\377\377\377\377\342\377\377\377\37\376\377\377\376\377\375\377" \ - "\375\376\375\377\376\377\377\375\377\377\377\377\376\377\370\373\362" \ - "\241\321a\215\307\77\215\307=\214\305@\214\306>\212\307<\214\306>\214" \ - "\306<\214\306>\216\306\77\215\305<\212\307>\213\307A\215\305>\212\307" \ - ">\215\307\77\214\306>\242\321a\373\374\364\377\377\377\376\377\377\376" \ - "\376\376\376\377\377\377\377\377\377\241\377\377\377\1\363\363\365\202" \ - "::<\1;;=\202::<\2""99;;;=\202::<\2;;=\316\316\316\377\377\377\377\231" \ - "\377\377\377\10\376\376\376\316\316\316::<;;=::<;;=99;;;=\204::<\202" \ - "\377\377\377\3\376\376\376\377\377\377\376\376\376\377\377\377\377\344" \ - "\377\377\377\202\377\377\375\3\377\374\377\375\377\376\376\377\377\202" \ - "\377\377\377\25\370\373\364\243\322b\217\304@\212\306@\214\305@\215\305" \ - ">\212\307>\212\306@\214\305B\214\305@\214\305B\214\306>\212\307>\212" \ - "\310\77\214\306>\217\304@\214\306>\214\305@\242\322b\370\373\362\377" \ - "\377\377\202\377\376\377\1\377\377\375\377\377\377\377\243\377\377\377" \ - "\1``b\203::<\203;;=\6::<<<>::<\234\234\234\377\377\377\376\376\376\377" \ - "\377\377\377\230\377\377\377\1\234\234\236\204::<\12;;=99;::<;;=::\214\306>\212\307>\214" \ - "\305@\217\304>\212\307<\214\306<\214\306>\215\307\77\213\307A\214\306" \ - ">\215\305@\215\307\77\212\307>\244\317c\370\373\362\377\377\373\376\377" \ - "\377\377\376\377\375\376\377\377\377\375\377\376\377\377\377\377\377" \ - "\242\377\377\377\2\222\222\222::<\202;;=\7""99;::<;;=::<99;;;=lln\202" \ - "\377\377\377\1\376\376\376\377\377\377\377\225\377\377\377\3\376\376" \ - "\376\377\377\377jjl\204;;=\2""99;;;=\202::<\2;;=\221\221\223\202\377" \ - "\377\377\1\376\376\376\202\377\377\377\1\376\376\376\377\377\377\377" \ - "\343\377\377\377\3\377\376\377\377\377\377\375\377\376\202\377\377\377" \ - "\11\373\373\363\241\321d\214\306>\213\310=\214\306>\214\305@\213\310" \ - "=\212\306@\217\304>\202\215\307=\14\214\306>\215\305>\214\306>\215\305" \ - ">\217\304@\215\307\77\215\307=\242\320c\367\375\361\376\376\377\377\376" \ - "\377\376\376\376\202\377\377\375\2\374\377\377\377\376\377\377\377\377" \ - "\377\242\377\377\377\2\264\264\264;;=\206::<\6;;=::\213\310\77\214\305@\215\305>\215\305@\214\306" \ - ">\214\305B\212\307<\215\307=\214\305B\214\306>\215\306A\212\306@\212" \ - "\307>\214\306>\212\307<\244\317c\370\373\364\377\377\377\377\375\376" \ - "\377\377\375\376\377\377\377\377\377\202\377\376\377\377\377\377\377" \ - "\243\377\377\377\2\346\346\346;;=\211::<\1\346\346\350\377\377\377\377" \ - "\230\377\377\377\3\346\346\350::<;;=\202::<\1;;=\205::<\1\346\346\346" \ - "\302\377\377\377\5\376\376\376\377\377\377\376\376\376\377\377\377\376" \ - "\376\376\377\377\377\377\233\377\377\377\10\376\376\377\377\377\375\377" \ - "\377\377\377\377\375\377\377\377\377\376\377\377\377\375\376\377\377" \ - "\202\377\377\377\6\370\373\362\243\322b\211\307B\213\310=\214\305@\214" \ - "\306<\202\215\305@\4\214\306<\214\305@\214\306<\215\307\77\202\214\306" \ - ">\6\212\307>\214\306>\215\307\77\214\305@\244\317c\367\375\361\345\377" \ - "\377\377\1\376\376\376\305\377\377\377\3FFF::<;;=\202::<\3;;=::<;;=\202" \ - "::<\1\301\301\303\377\377\377\377\230\377\377\377\4\301\301\30399;::" \ - "<;;=\204::<\3;;=::\215\305>\215\305@\213\310=\212\306@\214\306>" \ - "\214\305B\215\307\77\215\305>\215\306A\212\307>\214\306>\215\307\77\214" \ - "\306>\242\322b\370\373\362\376\376\377\377\375\376\341\377\377\377\5" \ - "\376\376\376\377\377\377\376\376\376\377\377\377\376\376\376\265\377" \ - "\377\377\3\376\376\376\377\377\377\376\376\376\212\377\377\377\3\376" \ - "\376\376\377\377\377lll\206::<\202;;=\2::<\234\234\236\377\377\377\377" \ - "\224\377\377\377\1\376\376\376\203\377\377\377\2\233\233\235;;=\203:" \ - ":<\2""99;;;=\202::<\2;;=xxz\213\377\377\377\1\376\376\376\265\377\377" \ - "\377\1\376\376\376\377\377\377\377\240\377\377\377\7\377\377\375\375" \ - "\376\377\376\377\377\376\377\375\377\374\377\377\377\375\375\377\376" \ - "\202\377\377\377\5\372\373\366\240\320b\215\307\77\212\306@\215\305>" \ - "\202\214\305@\20\215\305@\212\306@\214\305D\216\306\77\214\306>\215\307" \ - "\77\214\306>\212\306@\214\306>\215\307\77\215\305@\242\320c\370\373\362" \ - "\377\377\373\377\376\377\377\377\375\377\377\377\377\233\377\377\377" \ - "\3\376\376\376\377\377\377\376\376\376\213\377\377\377\6\376\376\376" \ - "\377\377\377\233\233\233;;=::<;;=\206::<\1lln\377\377\377\377\226\377" \ - "\377\377\3\376\376\376\377\377\377kkm\210::<\2;;=\234\234\236\214\377" \ - "\377\377\1\315\315\315\202\234\234\234\262\234\234\236\2\234\234\234" \ - "\265\265\265\377\377\377\377\240\377\377\377\37\376\377\377\376\377\375" \ - "\377\375\376\375\377\376\377\377\375\377\377\377\377\376\377\370\373" \ - "\362\241\321a\215\307\77\215\307=\214\305@\214\306>\212\307<\214\306" \ - ">\214\306<\214\306>\216\306\77\215\305<\212\307>\213\307A\215\305>\212" \ - "\307>\215\307\77\214\306>\242\321a\373\374\364\377\377\377\376\377\377" \ - "\376\376\376\376\377\377\344\377\377\377\4\376\376\376\347\347\347\234" \ - "\234\234\235\235\235\260\234\234\236\204\234\234\234\216\377\377\377" \ - "\1\301\301\301\202::<\1;;=\203::<\202;;=\2::\212\307>\212\306@\214\305B" \ - "\214\305@\214\305B\214\306>\212\307>\212\310\77\214\306>\217\304@\214" \ - "\306>\214\305@\242\322b\370\373\362\377\377\377\202\377\376\377\1\377" \ - "\377\375\346\377\377\377\2\316\316\316:::\263::<\4;;=:::\377\377\377" \ - "\376\376\376\214\377\377\377\3\346\346\346::<;;=\205::<\4;;=::<;;=\346" \ - "\346\346\377\377\377\377\226\377\377\377\2\362\362\362;;=\204::<\3""9" \ - "9;::<;;=\202::<\1\346\346\350\214\377\377\377\2\234\234\234;;=\264::" \ - "<\1kkm\377\377\377\377\240\377\377\377\1\375\377\376\202\377\377\375" \ - "\34\377\377\377\376\376\376\373\373\363\243\322b\211\307B\212\307<\215" \ - "\305>\214\306>\212\307>\214\305@\217\304>\212\307<\214\306<\214\306>" \ - "\215\307\77\213\307A\214\306>\215\305@\215\307\77\212\307>\244\317c\370" \ - "\373\362\377\377\373\376\377\377\377\376\377\375\376\377\377\377\375" \ - "\377\376\377\345\377\377\377\2\316\316\31699;\265::<\216\377\377\377" \ - "\2\376\376\376FFH\203::<\1;;=\203::<\3;;=99;\316\316\316\377\377\377" \ - "\377\226\377\377\377\1\317\317\317\206::<\202;;=\4""99;FFH\377\377\377" \ - "\376\376\376\213\377\377\377\1\234\234\236\202::<\1;;=\261::<\2;;=kk" \ - "m\205\377\377\377\1\376\376\376\377\377\377\377\231\377\377\377\3\377" \ - "\376\377\377\377\377\375\377\376\202\377\377\377\11\373\373\363\241\321" \ - "d\214\306>\213\310=\214\306>\214\305@\213\310=\212\306@\217\304>\202" \ - "\215\307=\14\214\306>\215\305>\214\306>\215\305>\217\304@\215\307\77" \ - "\215\307=\242\320c\367\375\361\376\376\377\377\376\377\376\376\376\202" \ - "\377\377\375\2\374\377\377\377\376\377\345\377\377\377\1\316\316\316" \ - "\264::<\202;;=\215\377\377\377\4\376\376\376\377\377\377lln99;\210::" \ - "<\2\234\234\234\376\376\376\377\377\377\377\225\377\377\377\5\234\234" \ - "\234::<;;=99;::<\202;;=\5::<;;=::\261::<\1kkm\377\377\377\377\237\377\377\377\1\377" \ - "\377\375\202\377\377\377\32\377\376\377\370\373\364\243\322b\214\306" \ - ">\213\310\77\214\305@\215\305>\215\305@\214\306>\214\305B\212\307<\215" \ - "\307=\214\305B\214\306>\215\306A\212\306@\212\307>\214\306>\212\307<" \ - "\244\317c\370\373\364\377\377\377\377\375\376\377\377\375\376\377\377" \ - "\377\377\377\202\377\376\377\346\377\377\377\1\316\316\316\266::<\217" \ - "\377\377\377\2\234\234\236;;=\206::<\3""99;;;=www\377\377\377\377\226" \ - "\377\377\377\3\204\204\206::<;;=\207::<\3\222\222\222\377\377\377\376" \ - "\376\376\213\377\377\377\1\234\234\236\265::<\1kkm\377\377\377\377\210" \ - "\377\377\377\7\376\376\376\377\377\377\377\377\375\376\377\375\376\377" \ - "\377\377\377\377\377\376\377\203\377\377\377\1\376\376\376\203\377\377" \ - "\377\1\376\377\377\203\377\377\377\16\377\377\375\377\377\377\377\376" \ - "\377\377\377\377\377\377\373\376\377\377\377\377\377\377\377\373\371" \ - "\372\364\242\322d\214\306<\215\307\77\214\305@\214\306<\202\215\305@" \ - "\4\214\306<\214\305@\214\306<\215\307\77\202\214\306>\6\212\307>\214" \ - "\306>\215\307\77\214\305@\244\317c\367\375\361\356\377\377\377\1\316" \ - "\316\316\266::<\214\377\377\377\1\376\376\376\202\377\377\377\1\266\266" \ - "\266\202::<\1;;=\203::<\1;;=\202::<\3__a\377\377\377\376\376\376\377" \ - "\377\377\377\224\377\377\377\2kkm;;=\202::<\202;;=\202::<\3;;=::<\265" \ - "\265\265\215\377\377\377\1\234\234\236\265::<\1kkm\377\377\377\377\214" \ - "\377\377\377\2\376\377\377\376\377\375\202\377\377\375\203\377\377\377" \ - "\204\377\377\375\205\377\377\377\1\376\376\377\202\377\377\377\6\377" \ - "\377\375\377\377\377\371\372\362\242\320c\214\305@\215\305@\202\214\306" \ - ">\20\215\305@\213\310=\212\306@\214\306>\214\305B\215\307\77\215\305" \ - ">\215\306A\212\307>\214\306>\215\307\77\214\306>\242\322b\370\373\362" \ - "\376\376\377\377\375\376\355\377\377\377\1\316\316\316\266::<\215\377" \ - "\377\377\4\376\376\376\377\377\377\315\315\315;;=\203::<\1;;=\203::<" \ - "\2;;=99;\377\377\377\377\226\377\377\377\203::<\1;;=\202::<\1;;=\203" \ - "::<\2\317\317\317\376\376\376\214\377\377\377\1\234\234\236\265::<\1" \ - "kkm\377\377\377\377\211\377\377\377\3\376\376\376\377\376\377\377\377" \ - "\377\203\377\376\377\204\377\377\377\1\376\376\376\202\377\377\377\1" \ - "\377\376\377\203\377\377\377\1\376\376\376\203\377\377\377\31\376\376" \ - "\377\377\376\377\371\372\365\241\322e\212\307<\216\306\77\212\311<\216" \ - "\303\77\212\307>\215\305@\212\306@\214\305D\216\306\77\214\306>\215\307" \ - "\77\214\306>\212\306@\214\306>\215\307\77\215\305@\242\320c\370\373\362" \ - "\377\377\373\377\376\377\377\377\375\355\377\377\377\1\316\316\316\266" \ - "::<\220\377\377\377\202::<\4;;=::<;;=::<\202;;=\3""99;;;=\346\346\346" \ - "\377\377\377\377\224\377\377\377\2\362\362\362;;=\202::<\7""99;::<;;" \ - "=88:;;=::<;;=\216\377\377\377\1\234\234\236\265::<\1kkm\377\377\377\377" \ - "\212\377\377\377\202\376\377\377\202\377\377\377\1\377\376\377\206\377" \ - "\377\377\1\376\376\376\202\377\377\377\1\376\376\376\203\377\377\377" \ - "\1\376\376\376\202\377\377\377\6\370\373\364\242\322b\214\306>\214\305" \ - "@\215\305>\214\305@\202\215\306A\20\214\306<\214\306>\216\306\77\215" \ - "\305<\212\307>\213\307A\215\305>\212\307>\215\307\77\214\306>\242\321" \ - "a\373\374\364\377\377\377\376\377\377\376\376\376\376\377\377\355\377" \ - "\377\377\1\316\316\316\266::<\216\377\377\377\6\376\376\376\377\377\377" \ - "SSU;;=99;;;=\206::<\1\316\316\316\377\377\377\377\224\377\377\377\2\316" \ - "\316\31699;\205::<\1;;=\202::<\1FFH\216\377\377\377\1\234\234\236\265" \ - "::<\1kkm\377\377\377\377\207\377\377\377\202\377\376\377\2\377\377\377" \ - "\377\377\375\203\377\377\377\1\376\377\375\202\377\377\375\203\377\377" \ - "\377\202\377\377\375\2\377\377\377\377\377\375\205\377\377\377\26\377" \ - "\377\375\371\372\362\243\322b\211\305A\215\305>\215\307\77\214\305@\214" \ - "\306>\215\305@\212\307>\214\305@\214\305B\214\306>\212\307>\212\310\77" \ - "\214\306>\217\304@\214\306>\214\305@\242\322b\370\373\362\377\377\377" \ - "\202\377\376\377\1\377\377\375\356\377\377\377\1\316\316\316\266::<\220" \ - "\377\377\377\3kkm::<;;=\202::<\6;;=::<;;=::<;;=\233\233\233\377\377\377" \ - "\377\223\377\377\377\2\376\376\376\265\265\265\205::<\1;;=\202::<\2""9" \ - "9;lln\216\377\377\377\1\234\234\236\265::<\1kkm\377\377\377\377\207\377" \ - "\377\377\3\376\377\375\375\377\376\377\377\377\202\377\376\377\3\377" \ - "\376\374\377\377\377\376\377\377\202\377\377\377\1\377\377\375\204\377" \ - "\377\377\2\375\377\376\377\377\375\202\377\377\377\1\377\377\375\202" \ - "\377\377\377\32\376\376\374\365\367\354\223\312K\215\305>\214\306<\211" \ - "\305\77\214\306>\212\307>\215\307\77\214\306>\214\306<\214\306>\215\307" \ - "\77\213\307A\214\306>\215\305@\215\307\77\212\307>\244\317c\370\373\362" \ - "\377\377\373\376\377\377\377\376\377\375\376\377\377\377\375\377\376" \ - "\377\355\377\377\377\1\316\316\316\266::<\217\377\377\377\5\376\376\376" \ - "\234\234\236;;=::<;;=\202::<\2""99;::<\202;;=\1\221\221\221\377\377\377" \ - "\377\224\377\377\377\1\235\235\235\211::<\2\221\221\223\376\376\376\215" \ - "\377\377\377\1\234\234\236\265::<\1kkm\377\377\377\377\207\377\377\377" \ - "\1\377\376\377\202\377\377\375\202\377\377\377\202\377\377\375\1\377" \ - "\377\377\202\376\377\377\1\377\377\377\202\377\377\375\5\376\376\377" \ - "\377\377\377\377\377\373\377\377\377\376\376\376\203\377\377\377\27\376" \ - "\376\376\377\377\375\376\377\372\347\365\333\225\311K\217\304>\214\305" \ - "B\215\307\77\212\306B\214\306>\215\306A\214\306>\215\305>\214\306>\215" \ - "\305>\217\304@\215\307\77\215\307=\242\320c\367\375\361\376\376\377\377" \ - "\376\377\376\376\376\202\377\377\375\2\374\377\377\377\376\377\355\377" \ - "\377\377\1\316\316\316\266::<\214\377\377\377\1\376\376\376\203\377\377" \ - "\377\3\250\250\252::<;;=\203::<\202;;=\202::<\1kkk\377\377\377\377\224" \ - "\377\377\377\4www;;=::<;;=\202::<\202;;=\202::<\1\234\234\236\216\377" \ - "\377\377\1\234\234\236\265::<\1kkm\377\377\377\377\207\377\377\377\15" \ - "\367\374\365\343\361\316\316\346\254\305\342\240\304\343\240\303\342" \ - "\236\305\342\237\312\346\251\345\356\317\365\373\357\376\377\377\376" \ - "\376\377\377\377\375\214\377\377\377\24\350\365\333\223\312K\216\306" \ - "\77\212\307>\215\304B\214\306>\215\307=\214\306>\215\306A\212\306@\212" \ - "\307>\214\306>\212\307<\244\317c\370\373\364\377\377\377\377\375\376" \ - "\377\377\375\376\377\377\377\377\377\202\377\376\377\356\377\377\377" \ - "\1\316\316\316\266::<\217\377\377\377\2\376\376\376\316\316\320\207:" \ - ":<\3;;=::\10\212\306@\212\307>\232\315W\277\337\224" \ - "\352\364\333\377\377\377\377\376\377\377\377\375\202\376\377\377\202" \ - "\377\377\377\2\377\376\377\377\377\375\202\377\377\377\17\377\377\375" \ - "\377\376\377\347\365\333\226\312L\215\306A\213\310=\212\306@\217\304" \ - ">\216\307<\214\305@\215\305<\214\305@\215\307=\244\317c\366\373\364\377" \ - "\377\377\377\276\377\377\377\6\346\346\346;;=99;;;=::<;;=\205::<\377" \ - "\377\377\377\224\377\377\377\1::<\202;;=\2::<;;=\203::<\4;;=::<\316\316" \ - "\316\376\376\376\377\377\377\377\274\377\377\377\14\377\375\377\377\377" \ - "\377\376\376\374\377\377\375\377\376\377\377\377\375\376\377\377\377" \ - "\377\377\376\377\377\377\376\377\324\353\265\231\316Z\202\214\306<\1" \ - "\215\305>\210\214\306>\202\215\305>\16\214\306>\213\307A\211\306;\233" \ - "\314V\324\353\265\377\377\377\377\376\377\377\377\375\375\377\376\376" \ - "\377\377\377\377\377\377\376\377\376\377\377\377\377\373\202\377\377" \ - "\377\6\376\376\377\350\365\333\222\312K\215\306A\217\304>\212\306@\202" \ - "\214\305@\6\213\310\77\212\307>\242\322d\370\373\364\377\377\377\377" \ - "\377\375\377\377\377\377\276\377\377\377\203::<\3;;=::<99;\202;;=\202" \ - "::<\1\346\346\350\377\377\377\377\222\377\377\377\2\376\376\376;;=\202" \ - "::<\202;;=\205::<\377\377\377\377\275\377\377\377\4\377\377\375\377\377" \ - "\377\377\377\373\377\376\374\202\376\377\377\12\377\377\375\377\377\377" \ - "\376\377\375\342\360\317\232\315V\214\306<\220\306=\215\306A\215\306" \ - "C\215\306A\210\214\306>\202\215\307\77\7\215\306A\214\306>\214\305@\213" \ - "\307A\214\305@\230\315W\341\361\315\203\377\377\377\2\376\376\374\374" \ - "\377\375\202\377\377\377\2\377\377\375\377\376\377\202\377\377\377\13" \ - "\352\364\331\221\311J\215\306A\213\310=\216\306\77\214\305@\214\306<" \ - "\242\322e\370\373\364\376\376\377\377\377\375\377\377\377\377\277\377" \ - "\377\377\1``b\202::<\2;;=99;\202;;=\4::<;;=::<\316\316\320\377\377\377" \ - "\377\222\377\377\377\4\316\316\316;;=::<99;\202::<\2;;=::<\202;;=\3:" \ - ":<\376\376\376\377\377\377\202\376\376\376\377\377\377\377\271\377\377" \ - "\377\17\376\377\377\376\376\374\377\376\374\376\377\377\377\377\377\377" \ - "\377\375\376\377\377\370\373\364\277\336\222\215\305<\214\305@\215\307" \ - "\77\212\307>\215\307\77\213\307A\211\214\306>\16\216\306A\214\305B\213" \ - "\307A\214\306>\215\305<\213\305=\215\306A\214\306<\215\305>\300\337\223" \ - "\370\373\362\376\376\377\377\377\375\376\377\377\204\377\377\377\16\377" \ - "\376\377\376\376\377\376\377\377\352\364\331\222\312K\215\306A\214\306" \ - "<\214\305@\243\321d\371\373\360\376\376\377\376\377\377\377\377\377\376" \ - "\377\377\377\377\377\377\273\377\377\377\4\376\376\376\377\377\377\376" \ - "\376\376lln\203::<\1;;=\20299;\1;;=\202::<\1\266\266\270\377\377\377" \ - "\377\222\377\377\377\5\316\316\316::<;;=::<;;=\205::<\3kkm\377\377\377" \ - "\376\376\376\377\377\377\377\274\377\377\377\14\377\377\375\376\377\377" \ - "\377\377\377\377\377\375\376\376\376\367\374\365\244\317c\214\305@\215" \ - "\307=\211\306=\213\307A\215\306A\202\212\306@\1\213\310<\210\214\306" \ - ">\202\212\307>\3\212\307<\214\306>\216\306\77\202\214\306>\12\215\305" \ - "<\215\307\77\212\306@\242\322b\371\374\365\377\377\375\376\376\374\376" \ - "\377\377\377\376\377\376\377\377\202\377\377\377\13\376\377\375\376\376" \ - "\377\377\377\377\350\365\333\225\311K\214\305B\242\320c\371\374\361\377" \ - "\377\377\376\377\377\377\376\377\377\377\377\377\300\377\377\377\7\221" \ - "\221\223::<99;::<;;=::<;;=\203::<\1\234\234\236\377\377\377\377\222\377" \ - "\377\377\2\250\250\25099;\206::<\3;;=::\216\306" \ - "\77\215\305>\215\305@\210\214\306>\37\215\305@\215\307\77\212\306@\215" \ - "\307\77\214\304\77\215\306A\212\307;\212\306@\214\306>\216\307B\214\306" \ - ">\222\312K\354\364\334\377\376\377\377\377\377\377\377\373\376\377\377" \ - "\377\375\376\376\377\375\377\377\377\377\376\377\377\377\377\376\376" \ - "\377\347\365\333\260\327z\371\374\363\375\377\376\376\377\377\377\376" \ - "\377\377\377\377\377\377\375\377\377\377\377\276\377\377\377\3\376\376" \ - "\376\234\234\23699;\203;;=\205::<\1\221\221\223\377\377\377\377\222\377" \ - "\377\377\2\234\234\234;;=\204::<\202;;=\3::<;;=\235\235\237\377\377\377" \ - "\377\276\377\377\377\202\377\377\375\15\376\377\377\367\374\365\223\312" \ - "K\214\306>\213\310\77\215\305@\214\306<\215\307=\214\305@\213\307A\211" \ - "\305\77\215\307\77\215\305>\210\214\306>\20\215\306A\213\305=\215\307" \ - "=\214\305@\215\306A\214\306>\213\304A\220\305\77\216\306\77\212\306@" \ - "\215\305@\213\307A\221\311L\367\375\363\376\377\377\377\377\377\202\377" \ - "\377\373\1\377\375\376\202\377\377\377\4\377\376\377\376\377\377\377" \ - "\376\377\376\377\377\203\377\377\377\3\377\376\377\376\376\377\374\377" \ - "\375\377\377\377\377\277\377\377\377\2\265\265\267<<>\20299;\7::<;;=" \ - "::<99;;;=::\214\305" \ - "@\210\214\306>\22\216\306A\215\307\77\213\305=\216\306\77\214\306>\212" \ - "\307>\213\310\77\214\305@\215\306C\214\306<\215\307=\215\305>\213\310" \ - "=\242\320d\372\372\362\376\377\375\377\375\377\377\377\375\202\376\377" \ - "\377\5\377\377\377\377\377\375\377\377\377\377\377\375\377\377\377\202" \ - "\377\376\377\5\376\377\375\376\377\377\377\377\377\377\375\376\377\377" \ - "\375\377\377\377\377\274\377\377\377\5\376\376\376\377\377\377\316\316" \ - "\320::<;;=\202::<\1;;=\202::<\3""99;::\214" \ - "\306<\214\306>\211\307>\231\214\306>\1\216\306\77\203\214\306>\2\214" \ - "\305@\266\334\207\202\377\377\377\7\377\376\377\377\377\377\377\376\377" \ - "\377\377\375\377\377\377\377\377\375\376\377\377\377\377\377\377\303" \ - "\377\377\377\1\376\376\376\202\377\377\377\1\316\316\316\206::<\6;;=" \ - "::<;;=FFH\377\377\377\376\376\376\205\377\377\377\1\376\376\376\377\377" \ - "\377\377\212\377\377\377\1lln\202::<\3;;=99;;;=\204::<\3\317\317\317" \ - "\377\377\377\376\376\376\377\377\377\377\273\377\377\377\10\377\375\377" \ - "\374\377\375\343\361\320\214\306>\215\306A\214\304=\212\307>\215\305" \ - ">\230\214\306>\20\214\306<\213\304\77\212\307>\212\306B\214\306<\212" \ - "\307>\220\304>\337\363\316\377\376\377\377\377\377\376\377\377\377\377" \ - "\377\376\376\377\377\377\377\376\376\376\376\377\377\377\377\377\377" \ - "\302\377\377\377\1\376\376\376\202\377\377\377\2\376\376\376\377\377" \ - "\377\204::<\1;;=\202::<\3;;=99;;;=\203\377\377\377\1\376\376\376\202" \ - "\377\377\377\1\376\376\376\377\377\377\377\213\377\377\377\2SSU;;=\202" \ - "::<\2;;=99;\204::<\1\315\315\315\203\377\377\377\1\376\376\376\377\377" \ - "\377\377\271\377\377\377\10\376\376\376\377\377\377\233\316W\214\305" \ - "@\212\306@\216\306=\214\305@\215\305@\230\214\306>\17\214\306<\215\306" \ - "C\211\306=\213\307A\214\304\77\212\306@\214\305B\234\313W\376\377\375" \ - "\377\377\377\376\377\375\377\377\375\376\377\377\376\376\377\376\377" \ - "\375\377\377\377\377\302\377\377\377\1\376\376\376\202\377\377\377\4" \ - "\376\376\376\377\377\377\376\376\376;;=\206::<\202;;=\3::<\377\377\377" \ - "\376\376\376\203\377\377\377\3\376\376\376\377\377\377\376\376\376\377" \ - "\377\377\377\212\377\377\377\3::<99;;;=\202::<\10;;=::<;;=99;;;=\363" \ - "\363\363\377\377\377\376\376\376\377\377\377\377\274\377\377\377\7\323" \ - "\354\265\214\305@\215\307\77\215\306A\216\305C\213\304\77\212\307<\230" \ - "\214\306>\20\215\307\77\215\304B\214\305@\214\306>\215\305>\215\307=" \ - "\212\307<\215\307\77\323\351\270\377\376\377\377\377\377\376\376\376" \ - "\376\377\375\376\376\376\376\377\377\377\376\374\377\377\377\377\302" \ - "\377\377\377\202\376\376\376\202\377\377\377\2\376\376\376FFH\210::<" \ - "\2;;=\316\316\316\202\377\377\377\1\376\376\376\377\377\377\377\215\377" \ - "\377\377\1\376\376\376\202;;=\4""99;;;=::<;;=\202::<\2;;=::<\377\377" \ - "\377\377\277\377\377\377\7\231\316X\220\304>\214\305@\215\307\77\214" \ - "\306<\214\311>\214\305@\231\214\306>\11\215\304B\214\306>\215\306A\214" \ - "\306<\215\306A\214\305B\215\307\77\234\315X\375\377\374\204\377\377\377" \ - "\2\376\377\377\377\376\377\377\377\377\377\304\377\377\377\202\376\376" \ - "\376\4\377\377\377jjl::<99;\202;;=\205::<\7\316\316\316\377\377\377\376" \ - "\376\376\377\377\377\376\376\376\377\377\377\376\376\376\377\377\377" \ - "\377\212\377\377\377\6\363\363\363::<99;;;=::<;;=\202::<\1;;=\202::<" \ - "\377\377\377\377\276\377\377\377\2\342\361\320\214\306<\202\215\305>" \ - "\4\212\307>\215\307=\211\306=\215\305>\230\214\306>\2\213\310=\214\306" \ - "<\202\214\305@\7\215\306A\214\306>\215\307=\214\304\77\211\310<\343\362" \ - "\321\377\377\375\202\377\376\377\2\377\377\375\376\376\376\377\377\377" \ - "\377\310\377\377\377\4kkm::<;;=::<\202;;=\202::<\3;;=::<\316\316\316" \ - "\202\377\377\377\1\376\376\376\377\377\377\377\215\377\377\377\3\316" \ - "\316\316::<;;=\202::<\1;;=\204::<\1__a\202\377\377\377\3\376\376\376" \ - "\377\377\377\376\376\376\377\377\377\377\271\377\377\377\4\270\333\207" \ - "\214\306>\214\305@\214\306>\203\214\305@\1\215\305>\230\214\306>\17\215" \ - "\306A\213\310=\212\307<\214\306>\214\306<\215\306A\214\306>\214\305@" \ - "\213\306E\267\332\206\377\377\375\376\377\377\377\377\375\377\377\377" \ - "\377\377\375\377\377\377\377\303\377\377\377\1\376\376\376\204\377\377" \ - "\377\6lln;;=::<99;::<;;=\204::<\1\250\250\250\204\377\377\377\1\376\376" \ - "\376\377\377\377\377\213\377\377\377\1\316\316\316\203::<\1;;=\205::" \ - "<\1lln\203\377\377\377\1\376\376\376\377\377\377\377\272\377\377\377" \ - "\10\232\315V\215\305@\212\306@\215\305>\214\306<\215\304D\215\305<\212" \ - "\306@\230\214\306>\3\217\304@\214\306<\215\306A\202\215\305@\7\214\306" \ - ">\214\305@\212\307>\215\305<\233\316W\376\376\377\376\377\375\203\377" \ - "\377\377\1\376\377\377\377\377\377\377\305\377\377\377\3\376\376\376" \ - "\377\377\377\234\234\236\203::<\2;;=99;\204::<\1\234\234\234\202\377" \ - "\377\377\1\376\376\376\377\377\377\377\215\377\377\377\5\316\316\320" \ - "::<;;=::<;;=\202::<\1;;=\202::<\1kkm\377\377\377\377\266\377\377\377" \ - "\10\375\377\374\376\377\377\376\376\376\377\377\375\377\377\377\376\377" \ - "\377\377\377\375\360\371\350\250\214\306>\4\214\305@\212\307>\360\371" \ - "\346\376\377\375\202\377\377\377\1\377\377\375\377\377\377\377\304\377" \ - "\377\377\1\376\376\376\203\377\377\377\1\234\234\234\211::<\1\234\234" \ - "\234\205\377\377\377\1\376\376\376\377\377\377\377\212\377\377\377\4" \ - "\316\316\320llnkkmlln\203kkm\1jjl\202kkm\1\221\221\223\377\377\377\377" \ - "\270\377\377\377\1\377\376\377\202\377\377\377\3\375\376\377\377\377" \ - "\375\341\361\315\251\214\306>\2\215\307\77\342\360\314\377\377\377\377" \ - "\310\377\377\377\202\376\376\376\202\377\377\377\2\266\266\266kkk\210" \ - "kkm\1\265\265\265\206\377\377\377\1\376\376\376\377\377\377\377\211\377" \ - "\377\377\1\376\376\376\203\377\377\377\3\376\376\376\377\377\377\376" \ - "\376\376\202\377\377\377\1\376\376\376\202\377\377\377\1\376\376\376" \ - "\377\377\377\377\264\377\377\377\1\377\376\377\205\377\377\377\2\375" \ - "\377\374\310\340\246\252\214\306>\1\310\340\246\377\377\377\377\307\377" \ - "\377\377\1\376\376\376\202\377\377\377\3\375\375\375\377\377\377\376" \ - "\376\376\211\377\377\377\7\376\376\376\377\377\377\376\376\376\377\377" \ - "\377\376\376\376\377\377\377\376\376\376\377\377\377\377\213\377\377" \ - "\377\1\376\376\376\204\377\377\377\1\376\376\376\206\377\377\377\1\376" \ - "\376\376\377\377\377\377\263\377\377\377\1\377\376\377\204\377\377\377" \ - "\3\376\376\377\376\377\375\304\342\234\251\214\306>\7\215\305@\305\343" \ - "\235\376\376\377\377\377\377\376\376\377\377\376\377\377\377\375\377" \ - "\377\377\377\306\377\377\377\1\376\376\376\217\377\377\377\3\376\376" \ - "\376\377\377\377\376\376\376\377\377\377\377\214\377\377\377\5\376\376" \ - "\376\377\377\377\376\376\376\377\377\377\376\376\376\203\377\377\377" \ - "\1\376\376\376\377\377\377\377\267\377\377\377\1\377\377\375\202\377" \ - "\377\377\3\377\376\377\376\377\375\305\342\237\251\214\306>\3\215\305" \ - "@\303\344\235\376\376\376\202\377\377\377\1\377\376\377\377\377\377\377" \ - "\305\377\377\377\1\376\376\376\203\377\377\377\1\376\376\376\214\377" \ - "\377\377\1\376\376\376\377\377\377\377\216\377\377\377\1\376\376\376" \ - "\203\377\377\377\1\376\376\376\206\377\377\377\1\376\376\376\377\377" \ - "\377\377\266\377\377\377\5\376\377\377\376\376\377\377\376\377\377\377" \ - "\377\305\342\242\251\214\306>\4\215\306A\302\341\236\377\377\375\376" \ - "\376\376\377\377\377\377\305\377\377\377\1\376\376\376\203\377\377\377" \ - "\1\376\376\376\214\377\377\377\1\376\376\376\377\377\377\377\231\377" \ - "\377\377\3\376\376\376\377\377\377\376\376\376\377\377\377\377\264\377" \ - "\377\377\2\376\376\376\377\376\377\202\376\377\377\202\377\377\377\1" \ - "\305\342\240\251\214\306>\7\214\305@\306\343\240\377\376\374\377\377" \ - "\377\376\377\377\377\377\377\376\376\376\377\377\377\377\325\377\377" \ - "\377\1\376\376\376\377\377\377\377\222\377\377\377\1\376\376\376\205" \ - "\377\377\377\1\376\376\376\377\377\377\377\265\377\377\377\4\377\377" \ - "\375\377\376\377\375\377\376\376\377\375\202\377\377\377\1\305\343\235" \ - "\251\214\306>\4\213\310\77\306\341\234\377\376\377\377\377\377\202\376" \ - "\377\375\377\377\377\377\311\377\377\377\1\377\377\375\215\377\377\377" \ - "\1\376\376\376\377\377\377\377\377\377\377\377\314\377\377\377\3\377" \ - "\377\375\377\377\377\376\377\375\203\377\377\377\11\376\377\377\345\360" \ - "\320\214\305@\214\306>\214\305@\214\304\77\214\306<\215\305>\212\307" \ - ">\231\214\306>\1\214\305@\202\215\307\77\205\214\306>\5\212\307>\214" \ - "\306>\342\360\315\377\377\377\376\376\376\202\377\377\377\1\377\377\375" \ - "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\244" \ - "\377\377\377\3\377\376\377\377\377\377\376\377\375\203\377\377\377\11" \ - "\376\377\377\362\371\347\214\306>\214\305B\215\310<\215\306A\214\305" \ - "@\215\307\77\214\305@\231\214\306>\4\215\307\77\213\305=\214\306>\215" \ - "\307\77\202\214\306>\5\215\307\77\214\306>\216\306\77\215\306A\360\367" \ - "\345\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ - "\251\377\377\377\2\377\376\377\377\377\375\203\377\377\377\13\377\377" \ - "\375\377\377\377\375\377\374\233\316W\214\305@\213\304\77\212\306@\215" \ - "\307\77\214\305@\215\306A\214\305@\230\214\306>\3\215\307\77\214\306" \ - ">\215\306A\203\214\305@\7\215\306A\214\305@\215\304B\232\315T\377\377" \ - "\375\376\377\377\377\377\375\377\377\377\377\377\377\377\377\377\377" \ - "\377\377\377\377\377\377\250\377\377\377\1\377\377\375\205\377\377\377" \ - "\11\377\376\377\267\333\204\213\307A\213\307C\215\307\77\213\304\77\215" \ - "\307\77\215\305<\212\306@\231\214\306>\1\215\307\77\203\214\305@\202" \ - "\214\306>\7\215\307\77\212\306@\267\333\204\377\376\377\376\377\377\377" \ - "\377\375\376\376\376\377\377\377\377\377\377\377\377\377\377\377\377" \ - "\377\377\377\377\247\377\377\377\17\377\377\375\377\377\377\377\377\375" \ - "\376\376\376\377\377\377\377\377\375\376\376\377\334\354\305\211\306" \ - "=\213\307A\213\305;\215\306A\214\306<\215\305>\213\307A\232\214\306>" \ - "\202\214\305@\11\214\306>\214\306<\214\306>\215\307\77\212\311=\333\355" \ - "\305\377\376\377\377\377\377\376\376\376\377\377\377\377\377\377\377" \ - "\377\377\377\377\377\377\377\377\377\252\377\377\377\3\377\377\375\377" \ - "\377\377\377\376\377\203\377\377\375\7\233\314V\215\307\77\215\305>\214" \ - "\306>\215\307\77\214\305@\212\307>\232\214\306>\14\214\305@\214\306>" \ - "\214\306<\215\307=\215\307\77\214\305@\232\315V\374\377\373\376\376\377" \ - "\377\377\375\377\377\377\376\376\376\377\377\377\377\377\377\377\377" \ - "\377\377\377\377\377\377\377\377\255\377\377\377\10\377\377\375\377\376" \ - "\377\324\353\267\214\304\77\215\305>\214\305@\212\307<\214\305@\232\214" \ - "\306>\2\215\307\77\215\306A\202\214\306>\4\215\307\77\213\304\77\215" \ - "\306E\316\346\254\202\377\377\377\3\377\377\375\376\376\377\376\377\377" \ - "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\247" \ - "\377\377\377\1\376\376\376\206\377\377\377\10\377\377\373\375\376\377" \ - "\232\315W\214\306>\215\307=\211\307>\215\306A\215\305>\232\214\306>\1" \ - "\214\305@\202\215\307\77\13\214\305@\215\306E\227\317P\377\377\377\377" \ - "\377\375\376\377\377\377\377\377\377\377\375\375\377\376\377\377\377" \ - "\377\377\375\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ - "\377\377\254\377\377\377\20\376\377\377\377\375\377\331\356\303\215\305" \ - "@\213\310\77\215\305>\216\306\77\213\307A\215\306A\214\306<\214\306>" \ - "\216\306\77\213\304\77\212\307<\214\306>\215\305@\210\214\306>\1\214" \ - "\305@\202\215\307\77\205\214\306>\10\214\305@\212\307>\215\305>\214\305" \ - "@\215\305>\214\305@\215\305>\331\356\305\377\377\377\377\377\377\377" \ - "\377\377\377\377\377\377\377\377\377\264\377\377\377\20\376\376\374\377" \ - "\377\375\376\376\374\261\330{\214\306>\216\306A\214\306>\213\307A\215" \ - "\305>\215\306A\215\307\77\213\304A\215\307\77\214\305@\214\306<\216\306" \ - "A\210\214\306>\4\215\307\77\213\305=\214\306>\215\307\77\202\214\306" \ - ">\12\215\307\77\214\306>\212\307>\220\305\77\212\307>\214\306>\213\310" \ - "=\214\306<\262\327z\376\377\377\377\377\377\377\377\377\377\377\377\377" \ - "\377\377\377\377\377\377\265\377\377\377\17\374\377\377\377\377\377\370" \ - "\373\362\241\321d\211\310<\215\305>\215\305@\216\306=\214\305@\214\306" \ - ">\215\307\77\214\306>\212\307<\212\306@\212\307<\210\214\306>\3\215\307" \ - "\77\214\306>\215\306A\203\214\305@\12\215\306A\214\305@\215\305>\212" \ - "\307>\213\307A\216\305C\215\307=\242\322e\371\372\364\375\377\376\377" \ - "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\264\377" \ - "\377\377\1\375\377\374\203\377\377\377\4\352\364\333\223\311O\212\306" \ - "@\215\305@\202\213\310\77\202\214\306>\4\216\307F\213\305=\215\307\77" \ - "\215\305@\211\214\306>\1\215\307\77\203\214\305@\202\214\306>\1\215\307" \ - "\77\202\214\305@\6\216\305C\215\307\77\225\311K\351\363\332\377\377\377" \ - "\376\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ - "\377\377\265\377\377\377\17\377\375\376\377\376\377\377\377\377\377\377" \ - "\375\352\365\327\223\313L\212\307<\215\305>\214\305@\215\307=\214\305" \ - "@\214\306<\213\310\77\213\304\77\220\305A\212\214\306>\202\214\305@\12" \ - "\214\306>\214\306<\214\306>\215\307\77\214\306>\213\310=\215\307=\225" \ - "\311K\347\365\334\377\377\375\377\377\377\377\377\377\377\377\377\377" \ - "\377\377\377\377\377\377\267\377\377\377\1\377\377\375\202\377\377\377" \ - "\13\377\376\377\376\377\377\353\363\334\245\320d\214\305B\214\305@\215" \ - "\306A\213\305=\214\306>\213\307A\213\310=\213\214\306>\5\214\305@\214" \ - "\306>\214\306<\215\307=\215\307\77\202\214\305@\5\214\306<\242\322e\351" \ - "\363\332\377\377\375\376\376\376\377\377\377\377\377\377\377\377\377" \ - "\377\377\377\377\377\377\377\267\377\377\377\1\376\376\374\202\377\377" \ - "\375\6\376\377\377\377\376\377\377\377\375\371\372\364\255\330|\217\304" \ - ">\202\212\306@\2\215\306A\214\303A\202\214\305@\211\214\306>\2\215\307" \ - "\77\215\306A\202\214\306>\6\215\307\77\213\304\77\215\306E\215\305>\262" \ - "\327z\371\372\364\203\377\377\377\2\376\377\377\377\377\375\377\377\377" \ - "\377\377\377\377\377\377\377\377\377\377\377\377\377\264\377\377\377" \ - "\1\376\376\376\202\377\377\377\2\377\377\375\377\376\377\203\377\377" \ - "\377\6\377\377\375\331\356\303\233\314W\215\310<\214\305@\215\307\77" \ - "\214\214\306>\1\214\305@\202\215\307\77\7\214\305@\215\306E\227\317P" \ - "\331\356\305\376\377\377\375\377\376\376\377\377\202\377\377\377\2\377" \ - "\377\375\376\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ - "\377\377\377\377\274\377\377\377\10\377\377\375\377\376\377\365\375\362" \ - "\307\342\237\234\315Z\212\306@\212\307>\214\305@\202\215\307\77\16\214" \ - "\306>\215\307\77\214\306>\215\306A\214\306>\213\310\77\214\306>\215\305" \ - "<\216\306A\213\310\77\212\307>\232\315T\307\341\242\370\373\362\377\377" \ - "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\304\377\377" \ - "\377\1\377\377\375\202\377\377\377\10\377\376\377\376\376\374\335\354" \ - "\303\270\333\207\222\311J\214\305@\215\306A\213\305=\202\214\306>\13" \ - "\215\307\77\216\306\77\215\305>\212\306@\212\307>\226\312K\270\333\211" \ - "\334\354\307\376\377\377\376\376\376\377\377\375\377\377\377\377\377" \ - "\377\377\377\377\377\377\377\377\377\377\377\306\377\377\377\2\376\377" \ - "\375\376\377\377\204\377\377\377\16\350\366\334\332\354\302\311\341\245" \ - "\306\341\234\305\342\237\304\341\237\305\342\240\305\342\237\334\355" \ - "\303\352\364\333\377\377\375\377\375\376\377\376\377\377\377\375\377" \ - "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\307\377" \ - "\377\377\15\376\376\376\377\376\377\377\377\375\377\377\373\376\377\377" \ - "\376\377\375\376\377\377\377\377\375\377\377\377\376\376\376\376\377" \ - "\377\376\377\375\377\377\377\202\377\376\377\204\377\377\377\1\376\376" \ - "\376\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ - "\307\377\377\377\3\376\377\377\377\377\377\376\376\376\202\377\377\377" \ - "\1\376\376\376\210\377\377\377\3\375\377\376\376\377\377\377\377\377" \ - "\203\377\376\377\4\376\377\375\376\377\377\377\377\377\377\376\377\377" \ - "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\304\377" \ - "\377\377\10\377\377\375\377\376\377\377\377\373\377\377\377\375\377\376" \ - "\376\377\377\376\376\376\377\376\377\202\376\377\377\1\377\377\377\202" \ - "\376\376\376\202\377\377\377\202\376\377\377\5\376\377\375\377\377\377" \ - "\376\376\374\377\377\377\377\377\375\377\377\377\377\377\377\377\377" \ - "\377\377\377\377\377\377\377\377\307\377\377\377\1\376\376\377\202\377" \ - "\377\377\2\377\377\375\376\376\377\202\377\377\377\2\376\377\375\377" \ - "\377\375\204\377\377\377\202\377\377\375\1\376\377\375\202\376\377\377" \ - "\202\377\377\375\202\377\377\377\1\377\376\377\377\377\377\377\377\377" \ - "\377\377\377\377\377\377\377\377\377\377\310\377\377\377\5\377\377\375" \ - "\377\376\377\377\377\375\376\376\377\377\376\377\207\377\377\377\202" \ - "\377\376\377\1\376\376\376\377\377\377\377\377\377\377\377\377\377\377" \ - "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ - "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ - "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ - "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ - "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ - "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ - "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ - "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ - "\377\377\377\377\377\377\377\377\377\377\377\377\377\261\377\377\377" \ - "\1\376\376\376\210\377\377\377\3\376\376\376\377\377\377\376\376\376" \ - "\331\377\377\377\1\376\376\376\204\377\377\377\1\376\376\376\257\377" \ - "\377\377\1\376\376\376\212\377\377\377\1\376\376\376\211\377\377\377" \ - "\1\376\376\376\221\377\377\377\1\376\376\376\203\377\377\377\1\376\376" \ - "\376\205\377\377\377\1\376\376\376\312\377\377\377\1\376\376\376\214" \ - "\377\377\377\1\376\376\376\202\377\377\377\6\377\376\375\377\377\377" \ - "\376\377\377\377\377\377\377\376\377\376\377\377\270\377\377\377\7\376" \ - "\377\377\377\376\377\376\377\377\377\377\375\377\377\377\377\375\377" \ - "\377\376\377\273\377\377\377\1\376\376\376\202\377\377\377\1\376\376" \ - "\376\302\377\377\377\1\376\376\376\305\377\377\377\1\376\376\376\241" \ - "\377\377\377\1\376\376\376\214\377\377\377\1\376\376\376\235\377\377" \ - "\377\1\376\376\376\202\377\377\377\1\376\376\376\202\377\377\377\1\376" \ - "\376\376\202\377\377\377\1\376\376\376\252\377\377\377\1\376\376\376" \ - "\212\377\377\377\3\376\376\376\377\377\377\376\376\376\202\377\377\377" \ - "\1\376\376\376\251\377\377\377\202\376\376\376\215\377\377\377\1\376" \ - "\376\376\202\377\377\377\1\376\376\376\205\377\377\377\1\376\376\376" \ - "\224\377\377\377\1\376\376\376\203\377\377\377\1\376\376\376\202\377" \ - "\377\377\1\376\376\376\232\377\377\377\1\376\376\376\202\377\377\377" \ - "\1\376\376\376\202\377\377\377\1\376\376\376\206\377\377\377\1\376\376" \ - "\376\243\377\377\377\1\376\376\376\204\377\377\377\1\376\376\376\202" \ - "\377\377\377\3\376\376\376\377\377\377\376\376\376\202\377\377\377\2" \ - "\376\376\376\377\377\377\202\377\377\375\3\377\377\377\376\377\377\377" \ - "\377\375\202\377\376\377\1\377\377\377\270\377\376\377\14\377\377\377" \ - "\377\376\377\377\376\374\377\377\375\375\376\377\376\377\377\377\377" \ - "\375\376\376\376\377\377\377\376\376\376\377\377\377\376\376\376\203" \ - "\377\377\377\1\376\376\376\266\377\377\377\1\376\376\376\203\377\377" \ - "\377\1\376\376\376\202\377\377\377\1\376\376\376\214\377\377\377\202" \ - "\376\376\376\207\377\377\377\1\376\376\376\272\377\377\377\1\376\376" \ - "\376\252\377\377\377\202\376\376\376\247\377\377\377\5\376\376\376\377" \ - "\377\377\376\376\376\377\377\377\376\376\376\202\377\377\377\1\376\376" \ - "\376\203\377\377\377\1\376\376\376\311\377\377\377\1\376\376\376\221" \ - "\377\377\377\1\376\376\376\203\377\377\377\1\376\376\376\302\377\377" \ - "\377\1\376\376\376\207\377\377\377\1\346\346\346\204\316\316\316\10\317" \ - "\317\317\315\315\315\316\316\316\363\363\365\377\377\377\376\376\376" \ - "\377\377\377\376\376\376\204\377\377\377\1\376\376\376\202\377\377\377" \ - "\1\376\376\376\234\377\377\377\1\376\376\376\262\377\377\377\1\376\376" \ - "\376\213\377\377\377\1\377\377\375\202\376\377\377\1\376\376\377\202" \ - "\377\377\377\2\377\376\377\377\377\375\270\276\317\331\1\377\376\377" \ - "\205\377\377\377\3\376\377\375\377\377\375\376\376\376\257\377\377\377" \ - "\1\376\376\376\210\377\377\377\202\376\376\376\210\377\377\377\1\376" \ - "\376\376\220\377\377\377\1\376\376\376\207\377\377\377\1\376\376\376" \ - "\243\377\377\377\1\376\376\376\203\377\377\377\3\376\376\376\377\377" \ - "\377\376\376\376\207\377\377\377\1\376\376\376\331\377\377\377\12\376" \ - "\376\376\377\377\377\235\235\235kkmllnkkmllnjjlkkm\346\346\346\202\377" \ - "\377\377\1\376\376\376\237\377\377\377\2\346\346\346\317\317\317\204" \ - "\316\316\316\2\317\317\317\346\346\346\234\377\377\377\1\376\376\376" \ - "\203\377\377\377\1\376\376\376\202\377\377\377\1\332\332\332\203\316" \ - "\316\316\1\317\317\317\202\316\316\316\213\377\377\377\5\346\346\346" \ - "\317\317\317\315\315\315\316\316\316\315\315\315\252\316\316\316\1\363" \ - "\363\363\205\377\377\377\1\376\376\376\212\377\377\377\1\376\376\376" \ - "\211\377\377\377\4\346\346\346\250\250\250\204\204\206``b\202::<\1;;" \ - "=\202::<\3;;=99;;;=\203::<\4lln\220\220\222\266\266\266\363\363\363\202" \ - "\376\376\376\240\377\377\377\1\346\346\346\202\316\316\316\10\317\317" \ - "\317\315\315\315\317\317\317\316\316\316\332\332\332\376\376\376\377" \ - "\377\377\376\376\376\203\377\377\377\1\376\376\376\241\377\377\377\6" \ - "\376\376\376\377\377\377\346\346\346\316\316\320\317\317\321\316\316" \ - "\320\203\316\316\316\2\347\347\347\376\376\376\205\377\377\377\1\376" \ - "\376\376\202\377\377\375\5\376\377\377\377\377\375\377\377\377\317\334" \ - "\344\37V\177\270\0>i\12\37U{\317\334\344\377\376\374\377\377\375\376" \ - "\377\377\377\376\374\376\377\377\376\376\376\377\377\377\363\363\363" \ - "\202\316\316\316\1\315\315\315\202\317\317\317\251\316\316\316\1\332" \ - "\332\332\202\377\377\377\1\376\376\376\203\377\377\377\202\376\376\376" \ - "\204\377\377\377\3\346\346\346\316\316\316\316\316\320\204\316\316\316" \ - "\2\346\346\346\376\376\376\212\377\377\377\1\347\347\347\206\316\316" \ - "\316\2\317\317\317\363\363\363\250\377\377\377\2\376\376\376\331\331" \ - "\331\206\316\316\316\1\332\332\332\202\377\377\377\1\376\376\376\204" \ - "\377\377\377\1\376\376\376\203\377\377\377\3\332\332\332\316\316\316" \ - "\316\316\320\250\316\316\316\1\363\363\363\205\377\377\377\1\376\376" \ - "\376\242\377\377\377\4\346\346\346::<;;=99;\204::<\1\204\204\206\237" \ - "\377\377\377\1\376\376\376\202\377\377\377\3\235\235\235::<;;=\202::" \ - "<\3;;=::<\235\235\235\202\377\377\377\1\376\376\376\232\377\377\377\1" \ - "\376\376\376\205\377\377\377\4kkm;;;99;;;=\202::<\1;;;\213\377\377\377" \ - "\4\234\234\234:::::<;;=\202::<\1;;;\250::<\1\316\316\316\202\377\377" \ - "\377\1\376\376\376\203\377\377\377\1\376\376\376\212\377\377\377\203" \ - "\376\376\376\203\377\377\377\3\346\346\346\250\250\250```\204::<\202" \ - ";;=\202::<\3;;=::<;;=\203::<\1;;=\202::<\5;;=::<```\265\265\265\362\362" \ - "\362\203\377\377\377\1\376\376\376\233\377\377\377\1\234\234\236\204" \ - "::<\5""99;;;=::<\333\333\335\376\376\376\203\377\377\377\1\376\376\376" \ - "\241\377\377\377\4\376\376\376\377\377\377\363\363\363FFH\202::<\1;;" \ - "=\203::<\1\234\234\234\210\377\377\377\6\376\377\377\377\377\375\375" \ - "\376\377\356\363\366\40Vz\0\77h\270\0=i\20\0>i\22Ip\356\363\367\376\377" \ - "\377\377\377\375\377\377\377\376\376\377\377\376\377\377\377\377\315" \ - "\315\315:::::<;;=::<99;;;;\250::<\1kkm\205\377\377\377\1\376\376\376" \ - "\203\377\377\377\4\376\376\376\377\377\377\376\376\376\234\234\234\203" \ - "::<\6;;=::<:::\234\234\234\377\377\377\376\376\376\211\377\377\377\3" \ - "\332\332\332:::;;=\202::<\202;;=\2::<\204\204\206\250\377\377\377\2\364" \ - "\364\364FFF\204::<\202:::\1\234\234\234\206\377\377\377\1\376\376\376" \ - "\204\377\377\377\2kkk;;=\251::<\1\316\316\316\202\377\377\377\1\376\376" \ - "\376\203\377\377\377\1\376\376\376\240\377\377\377\6\376\376\376\234" \ - "\234\236::<;;=::<;;=\203::<\2FFH\362\362\362\235\377\377\377\1\376\376" \ - "\376\203\377\377\377\3\234\234\236::<;;=\202::<\3;;=::<\234\234\236\203" \ - "\377\377\377\1\376\376\376\233\377\377\377\1\376\376\376\203\377\377" \ - "\377\7kkm::<;;=::<;;=::<;;=\213\377\377\377\4\235\235\235::<;;=99;\202" \ - ";;=\251::<\1\315\315\315\203\377\377\377\202\376\376\376\213\377\377" \ - "\377\1\376\376\376\202\377\377\377\6\376\376\376\377\377\377\315\315" \ - "\315\205\205\205::<;;=\213::<\4;;=::<;;=::<\203;;=\204::<\4FFF\204\204" \ - "\204\346\346\346\376\376\376\234\377\377\377\3\234\234\236::<;;=\202" \ - "::<\4;;=99;::<``b\244\377\377\377\1\376\376\376\203\377\377\377\1xxz" \ - "\202::<\10;;=99;;;=::<;;=\233\233\235\377\377\377\376\376\376\202\377" \ - "\377\377\1\376\376\376\203\377\377\377\4\375\377\376\377\376\373\377" \ - "\377\375\235\267\310\202\0>i\271\0=i\4\0\77j\237\266\306\377\376\377" \ - "\377\375\374\202\376\377\377\4\377\377\377\376\376\376\316\316\31699" \ - ";\202;;=\2::<;;=\251::<\1kkm\203\377\377\377\1\376\376\376\210\377\377" \ - "\377\4\235\235\235::<99;;;=\203::<\1\235\235\235\214\377\377\377\2ll" \ - "n99;\202;;=\1::<\203;;=\2\362\362\364\376\376\376\245\377\377\377\2\376" \ - "\376\376\250\250\250\204::<\4;;=::<:::\346\346\346\203\377\377\377\1" \ - "\376\376\376\205\377\377\377\3\376\376\376\377\377\377jjl\252::<\1\315" \ - "\315\315\203\377\377\377\202\376\376\376\242\377\377\377\3\362\362\364" \ - "GGI::<\202;;=\2""99;;;=\202::<\2""99;\235\235\235\237\377\377\377\3\376" \ - "\376\376\377\377\377\235\235\237\202::<\202;;=\202::<\3\235\235\237\377" \ - "\377\377\376\376\376\233\377\377\377\1\376\376\376\203\377\377\377\4" \ - "\376\376\376\377\377\377kkm;;=\202::<\5""99;;;=99;\377\377\377\376\376" \ - "\376\211\377\377\377\1\233\233\233\202::<\3;;=::<99;\251::<\1\317\317" \ - "\317\205\377\377\377\1\376\376\376\214\377\377\377\3\376\376\376\347" \ - "\347\347xxz\203::<\1;;=\202::<\1;;=\204::<\1;;=\203::<\1;;=\205::<\1" \ - ";;=\203::<\1;;=\203::<\2\234\234\236\362\362\362\233\377\377\377\2\233" \ - "\233\235;;=\204::<\1;;=\202::<\1\234\234\236\245\377\377\377\4\376\376" \ - "\376\302\302\304::<;;=\206::<\1\235\235\237\202\377\377\377\1\376\376" \ - "\376\203\377\377\377\7\375\376\377\377\377\377\377\377\375\376\377\377" \ - "\377\377\377\177\235\265\0\77k\271\0\77j\7\0\77k\0\77j~\236\265\377\376" \ - "\377\376\377\377\375\377\374\377\377\375\202\377\377\377\5\315\315\315" \ - ";;=::<99;;;=\252::<\3kkm\377\377\377\376\376\376\203\377\377\377\1\376" \ - "\376\376\203\377\377\377\1\376\376\376\202\377\377\377\3\233\233\233" \ - "::<;;=\202::<\3;;=::<\234\234\234\202\377\377\377\1\376\376\376\211\377" \ - "\377\377\4\264\264\264;;=::<;;=\204::<\3\247\247\251\377\377\377\376" \ - "\376\376\245\377\377\377\1SSS\203::<\1;;=\202::<\1\204\204\204\213\377" \ - "\377\377\4\376\376\376lln::<:9>\250::<\1\317\317\317\205\377\377\377" \ - "\1\376\376\376\241\377\377\377\1\265\265\267\204::<\1;;=\204::<\1FFF" \ - "\241\377\377\377\2\234\234\236;;=\204::<\2;;=\234\234\236\234\377\377" \ - "\377\3\376\376\376\377\377\377\376\376\376\204\377\377\377\1kkm\203:" \ - ":<\4;;=::<;;=\376\376\376\212\377\377\377\1\234\234\234\204::<\1;;=\251" \ - "::<\1\316\316\316\203\377\377\377\202\376\376\376\215\377\377\377\4\234" \ - "\234\234;;=::<;;=\202::<\1""99;\204::<\1;;=\203::<\1;;=\211::<\1""99" \ - ";\207::<\2FFF\301\301\301\232\377\377\377\2\234\234\23699;\210::<\1\333" \ - "\333\333\241\377\377\377\6\376\376\376\377\377\377\376\376\376\363\363" \ - "\363FFH;;=\205::<\3;;=::<\234\234\236\206\377\377\377\7\377\376\377\377" \ - "\377\377\377\377\375\375\376\377\377\376\377\201\235\263\0>g\272\0>i" \ - "\13\0>e\177\236\263\377\375\374\377\377\377\377\377\375\376\376\376\377" \ - "\376\377\377\377\377\316\316\316::<;;=\202::<\2""99;;;=\250::<\1kkm\204" \ - "\377\377\377\5\376\376\376\377\377\377\376\376\376\377\377\377\376\376" \ - "\376\202\377\377\377\2\376\376\376\234\234\234\206::<\1\234\234\234\215" \ - "\377\377\377\2RRT;;=\205::<\1SSU\246\377\377\377\2\316\316\316999\206" \ - "::<\1\316\316\316\202\377\377\377\3\376\376\376\377\377\377\376\376\376" \ - "\207\377\377\377\3jjl::<:9>\250::<\1\316\316\316\203\377\377\377\202" \ - "\376\376\376\242\377\377\377\2SSU99;\202;;=\204::<\4;;=99;::<\264\264" \ - "\266\240\377\377\377\1\234\234\234\206::<\1\234\234\234\243\377\377\377" \ - "\1kkm\206::<\213\377\377\377\2\234\234\236;;=\216::<\4""99;;;=::<;;=" \ - "\206::<\3;;=::<;;=\222::<\1\316\316\316\205\377\377\377\1\376\376\376" \ - "\207\377\377\377\1\376\376\376\202\377\377\377\2\346\346\350__a\202:" \ - ":<\3;;=::<;;=\204::<\1;;=\202::<\3;;=::<;;=\203::<\1;;=\202::<\2""99" \ - ";;;=\202::<\1;;=\204::<\7;;=::<;;=::<;;=\204\204\206\363\363\363\203" \ - "\377\377\377\3\376\376\376\377\377\377\376\376\376\222\377\377\377\4" \ - "\234\234\236::<;;=99;\204::<\3;;=::<__a\244\377\377\377\1xxx\205::<\1" \ - ";;=\203::<\1\234\234\236\213\377\377\377\3\177\236\263\0=i\0>i\211\0" \ - "=i\2\0>j\0=i\202\1>j\2\0\77k\0>j\232\0>i\2\0>j\0\77k\202\1>j\2\0=i\0" \ - ">j\211\0=i\3\0>i\0=i\177\236\263\206\377\377\377\6\316\316\316:::::<" \ - ";;=::<;;=\217::<\1;;=\203::<\1;;=\202::<\1;;=\222::<\1kkk\205\377\377" \ - "\377\1\376\376\376\206\377\377\377\1\234\234\236\206::<\1\234\234\236" \ - "\215\377\377\377\3\234\234\234;;=::<\202;;=\203::<\3\316\316\320\377" \ - "\377\377\376\376\376\240\377\377\377\1\376\376\376\202\377\377\377\3" \ - "xxz::<;;=\202::<\3;;=::<__a\215\377\377\377\1kkm\204::<\1;;=\202::<\1" \ - ";;=\242::<\1\316\316\316\205\377\377\377\1\376\376\376\240\377\377\377" \ - "\1\265\265\265\202::<\5;;=::<;;=::<;;=\204::<\2TTV\376\376\376\237\377" \ - "\377\377\1\234\234\234\206::<\1\234\234\234\243\377\377\377\1kkm\206" \ - "::<\213\377\377\377\3\234\234\23499;;;=\214::<\1""99;\207::<\1;;=\227" \ - "::<\1\316\316\316\204\377\377\377\3\376\376\376\377\377\377\376\376\376" \ - "\203\377\377\377\1\376\376\376\204\377\377\377\2\333\333\335FFH\214:" \ - ":<\16``b\221\221\223\251\251\251\315\315\315\316\316\316\363\363\363" \ - "\377\377\377\332\332\332\316\316\316\301\301\301\235\235\237jjlFFH;;" \ - "=\207::<\1;;=\202::<\3;;=__a\363\363\363\227\377\377\377\4\234\234\236" \ - "99;::<;;=\205::<\3;;=::<\233\233\233\240\377\377\377\12\376\376\376\377" \ - "\377\377\301\301\301;;=::<;;=::<;;=::<99;\203::<\1\234\234\236\213\377" \ - "\377\377\3\177\236\263\0=i\0>i\211\0=i\7\1>j\0=i\1>j\0=i\0>g\3>h\2=g" \ - "\230\0=i\7\2=g\3>h\0>g\0=i\1>j\0=i\1>j\211\0=i\3\0>i\0=i\177\236\263" \ - "\206\377\377\377\2\317\317\317:::\221::<\202;;=\202::<\3;;=::<99;\203" \ - "::<\2;;=99;\220::<\1kkk\214\377\377\377\1\234\234\236\206::<\1\234\234" \ - "\236\213\377\377\377\3\376\376\376\377\377\377\363\363\363\204::<\4;" \ - ";=::<;;=xxz\202\377\377\377\1\376\376\376\236\377\377\377\1\376\376\376" \ - "\202\377\377\377\3\346\346\346::<;;=\202::<\4;;=99;;;=\266\266\270\215" \ - "\377\377\377\1kkm\203::<\1;;=\202::<\1;;=\243::<\1\316\316\316\204\377" \ - "\377\377\3\376\376\376\377\377\377\376\376\376\232\377\377\377\1\376" \ - "\376\376\204\377\377\377\1kkm\202;;=\202::<\202;;=\2::<;;=\204::<\3\317" \ - "\317\317\377\377\377\376\376\376\235\377\377\377\1\234\234\234\206::" \ - "<\1\234\234\234\243\377\377\377\1kkm\206::<\212\377\377\377\1\376\376" \ - "\376\224\377\377\377\1lln\203::<\1;;=\202::<\1\234\234\236\234\377\377" \ - "\377\1\376\376\376\204\377\377\377\4\376\376\376\265\265\267::<;;=\202" \ - "::<\1;;=\202::<\1;;=\203::<\5__a\266\266\270\363\363\363\377\377\377" \ - "\376\376\376\204\377\377\377\1\376\376\376\203\377\377\377\1\376\376" \ - "\376\202\377\377\377\4\301\301\303\204\204\206;;=::<\203;;=\202::<\2" \ - ";;=::<\202;;=\3GGI\332\332\334\376\376\376\203\377\377\377\1\376\376" \ - "\376\221\377\377\377\2\235\235\237::<\202;;=\202::<\1;;=\202::<\4""9" \ - "9;::<;;=\331\331\331\240\377\377\377\2\363\363\363GGI\203::<\2;;=::<" \ - "\203;;=\202::<\1\234\234\236\213\377\377\377\3\177\236\263\0=i\0>i\210" \ - "\0=i\10\0\77k\0=i\1>j\0>i\0\77j\0=i\0>i\0>j\230\0>i\10\0>j\0>i\0=i\0" \ - "\77j\0>i\1>j\0=i\0\77k\210\0=i\3\0>i\0=i\177\236\263\206\377\377\377" \ - "\1\376\376\376\217\377\377\377\1\376\376\376\203\377\377\377\1\315\315" \ - "\317\204::<\3;;=::i\211\0=i\202\0>i\5\0j\0=i\1>j" \ - "\0>i\230\0=i\5\0>i\1>j\0=i\1>j\0i\211\0=i\3\0>i\0=i\177\236" \ - "\263\212\377\377\377\3\376\376\376\377\377\377\376\376\376\212\377\377" \ - "\377\1\376\376\376\202\377\377\377\10\316\316\320::<;;=::<;;=99;::::<99;::<99;\202;;=\203::<\1" \ - "\234\234\236\213\377\377\377\3\177\236\263\0=i\0>i\210\0=i\7\2=g\0>i" \ - "\0>j\0\77j\0=i\0\77j\0=h\232\1>j\7\0=h\0\77j\0=i\0\77j\0>j\0>i\2=g\210" \ - "\0=i\3\0>i\0=i\177\236\263\213\377\377\377\1\376\376\376\216\377\377" \ - "\377\1\317\317\321\202::<\6;;=::<;;=::i\210\0=i\10\0\77j\0>j\0\77k\0=i\3>h\2=" \ - "g\1>j\0\77k\230\0=i\10\0\77k\1>j\2=g\3>h\0=i\0\77k\0>j\0\77j\210\0=i" \ - "\3\0>i\0=i\177\236\263\232\377\377\377\12\316\316\316;;=::<;;=::<;;=" \ - "::i\210\0=i\10\0>i\0=i\0>i\0\77k\0>j\2=g\1\77h\0>l\230\0>i\10\0>l\1\77" \ - "h\2=g\0>j\0\77k\0>i\0=i\0>i\210\0=i\3\0>i\0=i\177\236\263\205\377\377" \ - "\377\1\376\376\376\202\377\377\377\1\376\376\376\221\377\377\377\3\316" \ - "\316\316::<;;=\204::<\1kkm\225\377\377\377\202\376\376\376\211\377\377" \ - "\377\1\234\234\236\206::<\1\234\234\236\217\377\377\377\3\376\376\376" \ - "TTV99;\202::<\4""99;;;=::i\210\0=i\7\0>j\2=g\0>g\0>j\40V|o\224\256\177\236\262\232" \ - "\177\236\263\7\177\236\262o\224\256\40V|\0>j\0>g\2=g\0>j\210\0=i\3\0" \ - ">i\0=i\177\236\263\232\377\377\377\3\316\316\316::<;;=\203::<\2;;=kk" \ - "m\232\377\377\377\1\376\376\376\205\377\377\377\1\234\234\236\206::<" \ - "\1\234\234\236\220\377\377\377\2\233\233\235;;=\202::<\1<<>\203::<\1" \ - "\346\346\346\237\377\377\377\1\204\204\204\206::<\2SSU\376\376\376\217" \ - "\377\377\377\1kkm\203::<\4;;=::<;;=\316\316\320\304\377\377\377\1\376" \ - "\376\376\202\377\377\377\2\234\234\236;;=\202::<\4;;=::<;;=\234\234\234" \ - "\203\377\377\377\1\346\346\346\205::<\3;;=FFH\363\363\365\203\377\377" \ - "\377\1\376\376\376\230\377\377\377\1\234\234\234\206::<\1\234\234\234" \ - "\243\377\377\377\1kkm\206::<\237\377\377\377\1kkm\206::<\1\234\234\236" \ - "\235\377\377\377\2\316\316\316;;=\202::<\6;;=::<;;=::<:::\265\265\265" \ - "\237\377\377\377\7\376\376\376\363\363\363___::<;;=::<;;=\203::<\2GG" \ - "I\363\363\363\204\377\377\377\1\376\376\376\214\377\377\377\1\234\234" \ - "\234\203::<\202;;=\5::<\266\266\266GGI99;;;=\202::<\1;;=\202::<\1\332" \ - "\332\332\206\377\377\377\1\376\376\376\211\377\377\377\1\376\376\376" \ - "\207\377\377\377\2\363\363\363FFH\206::<\3FFH\301\301\30399;\202::<\202" \ - ";;=\2::<\234\234\236\206\377\377\377\7\377\377\375\377\377\377\377\377" \ - "\375\376\377\377\376\376\376\200\237\263\0\77i\211\0>i\7\0>g\1>j\0>g" \ - "_\210\236\377\377\377\376\377\377\377\376\377\231\377\377\377\10\377" \ - "\377\375\376\377\375\377\377\377\377\377\375`\210\242\3>h\0\77j\1\77" \ - "h\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316\316\206::<" \ - "\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236\220\377\377" \ - "\377\1\363\363\363\204::<\202;;=\2""99;\205\205\207\207\377\377\377\1" \ - "\376\376\376\224\377\377\377\4\376\376\376\377\377\377\363\363\363FF" \ - "H\202::<\5;;=99;;;=::<\265\265\265\220\377\377\377\1kkm\206::<\1\316" \ - "\316\316\305\377\377\377\5\376\376\376\364\364\364FFH::<;;=\202::<\4" \ - ";;=FFH\363\363\363\377\377\377\202\376\376\376\6\377\377\377xxz::<;;" \ - "=::<;;=\202::<\1\234\234\236\206\377\377\377\202\376\376\376\224\377" \ - "\377\377\1\234\234\234\206::<\1\234\234\234\243\377\377\377\1kkm\206" \ - "::<\237\377\377\377\1kkm\206::<\1\234\234\236\225\377\377\377\1\376\376" \ - "\376\207\377\377\377\2SSS;;=\202::<\1;;=\203::<\1\234\234\234\202\377" \ - "\377\377\3\376\376\376\377\377\377\376\376\376\232\377\377\377\1\376" \ - "\376\376\202\377\377\377\4\332\332\332FFH::<;;=\202::<\1;;=\202::<\1" \ - "\222\222\224\205\377\377\377\1\376\376\376\213\377\377\377\3\234\234" \ - "\234::<;;=\202::<\5""99;;;=\315\315\315\250\250\252;;=\206::<\2``b\376" \ - "\376\376\202\377\377\377\1\376\376\376\216\377\377\377\1\376\376\376" \ - "\205\377\377\377\2xxx;;=\202::<\1;;=\203::<\2\300\300\300\317\317\321" \ - "\203::<\1;;=\202::<\1\234\234\236\207\377\377\377\1\377\376\377\202\377" \ - "\377\377\4\377\376\377\201\235\263\0=j\3>j\210\0=i\5\1>j\0=j\37V\177" \ - "\377\376\377\376\376\376\202\377\377\377\1\376\377\377\230\377\377\377" \ - "\10\376\377\377\377\377\375\374\377\377\377\376\374\376\377\377#W\177" \ - "\0>g\0\77i\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316\316" \ - "\206::<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236\220\377" \ - "\377\377\2\376\376\376\204\204\206\205::<\3;;=FFH\362\362\362\204\377" \ - "\377\377\202\376\376\376\2\377\377\377\376\376\376\224\377\377\377\3" \ - "\376\376\376\265\265\265;;=\203::<\4;;=99;FFH\363\363\363\220\377\377" \ - "\377\1kkm\206::<\1\316\316\316\306\377\377\377\4\265\265\26599;;;=::" \ - "<\202;;=\2""99;\222\222\224\204\377\377\377\12\376\376\376\316\316\320" \ - ";;=::<;;=99;;;=99;SSU\376\376\376\202\377\377\377\3\376\376\376\377\377" \ - "\377\376\376\376\226\377\377\377\1\234\234\234\206::<\1\234\234\234\243" \ - "\377\377\377\1kkm\206::<\237\377\377\377\1kkm\206::<\1\234\234\236\234" \ - "\377\377\377\11\234\234\234::<;;=99;;;=99;::<;;=kkm\241\377\377\377\1" \ - "\376\376\376\202\377\377\377\1\301\301\303\203::<\6;;=99;::<;;=::<\346" \ - "\346\350\203\377\377\377\1\376\376\376\214\377\377\377\1\234\234\234" \ - "\203::<\202;;=\10""99;\316\316\316\377\377\377kkm::<;;=::<;;=\203::<" \ - "\1\235\235\237\203\377\377\377\1\376\376\376\214\377\377\377\1\376\376" \ - "\376\205\377\377\377\3\302\302\304::<;;=\202::<\7""99;;;=99;xxz\377\377" \ - "\377\315\315\315;;=\203::<\3:9>::<\234\234\236\206\377\377\377\3\376" \ - "\377\377\377\377\375\377\377\377\202\377\377\375\3|\237\265\0\77k\0>" \ - "g\210\0=i\10\0@h\3j\210\0=i\3\0>i\0=i\177" \ - "\236\263\232\377\377\377\1\316\316\316\206::<\1kkm\240\377\377\377\1" \ - "\234\234\236\206::<\1\234\234\236\215\377\377\377\1\376\376\376\203\377" \ - "\377\377\2\332\332\334;;=\206::<\2\266\266\266\376\376\376\202\377\377" \ - "\377\1\376\376\376\202\377\377\377\1\376\376\376\222\377\377\377\1\376" \ - "\376\376\203\377\377\377\1SSS\203::<\4""99;::<;;=\221\221\223\221\377" \ - "\377\377\1kkm\206::<\1\316\316\316\306\377\377\377\4RRT;;=::<;;=\202" \ - "::<\2;;=\345\345\345\202\377\377\377\1\376\376\376\203\377\377\377\2" \ - "__a;;=\202::<\1;;=\202::<\1\264\264\264\206\377\377\377\1\376\376\376" \ - "\224\377\377\377\1\234\234\234\206::<\1\234\234\234\243\377\377\377\1" \ - "kkm\206::<\237\377\377\377\1kkm\206::<\1\234\234\236\226\377\377\377" \ - "\1\376\376\376\204\377\377\377\2\363\363\363FFH\203::<\1;;=\202::<\2" \ - "FFH\346\346\346\204\377\377\377\1\376\376\376\233\377\377\377\1\376\376" \ - "\376\203\377\377\377\3\376\376\376xxz99;\202::<\1""99;\202::<\4;;=\204" \ - "\204\206\377\377\377\376\376\376\202\377\377\377\1\376\376\376\213\377" \ - "\377\377\1\234\234\234\202::<\10;;=99;;;=::<\317\317\317\376\376\376" \ - "\363\363\363GGI\203::<\1;;=\203::<\3\331\331\331\377\377\377\376\376" \ - "\376\202\377\377\377\1\376\376\376\217\377\377\377\5\363\363\363GGI;" \ - ";=::<;;=\202::<\7""99;FFH\363\363\363\377\377\377\316\316\316::<;;=\202" \ - "::<\3:9>::<\234\234\236\207\377\377\377\7\376\377\377\376\376\376\377" \ - "\377\377\377\377\375\377\377\377\377\375\374\376\377\377\210\377\377" \ - "\377\10\376\376\374\376\377\377\354\364\366\377\377\375\376\377\377\377" \ - "\376\374\377\377\375\376\377\377\230\377\377\377\10\377\377\375\376\377" \ - "\377\377\376\375\375\376\377\376\377\377\301\317\330\0>g\0>j\210\0=i" \ - "\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316\316\206::<\1kkm\240" \ - "\377\377\377\1\234\234\236\206::<\1\234\234\236\220\377\377\377\5\376" \ - "\376\376\377\377\377kkm::<;;=\202::<\3""99;::<^^`\204\377\377\377\1\376" \ - "\376\376\227\377\377\377\1\316\316\316\202::<\203;;=\202::<\1\347\347" \ - "\347\221\377\377\377\1kkm\206::<\1\316\316\316\303\377\377\377\12\376" \ - "\376\376\377\377\377\301\301\301;;=::<;;=::<99;::<\204\204\206\204\377" \ - "\377\377\4\376\376\376\377\377\377\376\376\376\266\266\266\202::<\5;" \ - ";=::<;;=::<``b\203\377\377\377\1\376\376\376\227\377\377\377\1\234\234" \ - "\234\206::<\1\234\234\234\243\377\377\377\1kkm\206::<\237\377\377\377" \ - "\1kkm\206::<\1\234\234\236\233\377\377\377\1\265\265\267\204::<\4""9" \ - "9;;;=::<\234\234\234\203\377\377\377\3\376\376\376\377\377\377\376\376" \ - "\376\231\377\377\377\5\376\376\376\377\377\377\376\376\376\377\377\377" \ - "\376\376\376\202\377\377\377\5\363\363\363GGI99;::<;;=\202::<\3;;=::" \ - "<\346\346\346\204\377\377\377\1\376\376\376\212\377\377\377\3\234\234" \ - "\234::<99;\202;;=\202::<\1\315\315\315\202\377\377\377\3\301\301\303" \ - ";;=99;\202;;=\5::<;;=::<``b\376\376\376\202\377\377\377\1\376\376\376" \ - "\215\377\377\377\6\376\376\376\377\377\377\376\376\376xxz::<;;=\203:" \ - ":<\202;;=\1\300\300\302\202\377\377\377\3\316\316\316;;=99;\202::<\3" \ - ";:\77::<\234\234\236\206\377\377\377\2\377\377\375\376\377\375\202\376" \ - "\377\377\4\377\377\375\377\377\377\377\376\377\377\377\375\211\377\377" \ - "\377\1\376\376\374\202\377\377\377\3\377\376\377\377\377\377\375\376" \ - "\377\231\377\377\377\202\376\377\377\5\377\376\377\376\377\377\377\377" \ - "\375\277\320\332\0\77j\211\0=i\3\0>i\0=i\177\236\263\232\377\377\377" \ - "\1\316\316\316\206::<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234" \ - "\234\236\213\377\377\377\3\376\376\376\377\377\377\376\376\376\204\377" \ - "\377\377\1\265\265\265\202::<\1;;=\204::<\1\315\315\317\204\377\377\377" \ - "\1\376\376\376\202\377\377\377\1\376\376\376\220\377\377\377\1\376\376" \ - "\376\202\377\377\377\3\204\204\204::<;;=\204::<\2yy{\376\376\376\221" \ - "\377\377\377\1kkm\206::<\1\316\316\316\305\377\377\377\4kkm;;=::<;;=" \ - "\203::<\1\316\316\316\210\377\377\377\1TTV\206::<\2\317\317\321\376\376" \ - "\376\231\377\377\377\1\234\234\234\206::<\1\234\234\234\243\377\377\377" \ - "\1kkm\206::<\237\377\377\377\1kkm\206::<\1\234\234\236\233\377\377\377" \ - "\1TTV\202::<\7;;=::<;;=::i\0=i\177\236\263\232\377\377" \ - "\377\1\316\316\316\206::<\1kkm\240\377\377\377\1\234\234\236\206::<\1" \ - "\234\234\236\221\377\377\377\4\376\376\376\377\377\377SSU;;=\202::<\4" \ - ";;=99;;;=\204\204\206\203\377\377\377\1\376\376\376\226\377\377\377\11" \ - "\363\363\36399;;;=::<;;=::<;;=::<\316\316\316\202\377\377\377\1\376\376" \ - "\376\217\377\377\377\1kkm\206::<\1\316\316\316\304\377\377\377\1\316" \ - "\316\316\206::<\1kkk\211\377\377\377\2\235\235\23599;\202;;=\6::<;;=" \ - "::99;\202::<\3;;" \ - "=::<\234\234\236\211\377\377\377\4\377\375\376\376\377\377\254\334\363" \ - "Z\266\347\211[\267\350\6\\\266\350X\267\347\326\354\367\377\376\377\376" \ - "\377\377\377\377\375\232\377\377\377\3\377\377\373\375\377\376\376\377" \ - "\377\202\377\377\375\3\276\320\336\0>g\0>i\210\0=i\3\0>i\0=i\177\236" \ - "\263\232\377\377\377\1\316\316\316\206::<\1kkm\240\377\377\377\1\234" \ - "\234\236\206::<\1\234\234\236\223\377\377\377\1\235\235\237\204::<\4" \ - "<<>::<;;=\363\363\363\206\377\377\377\1\376\376\376\222\377\377\377\2" \ - "\234\234\234;;=\205::<\1SSU\204\377\377\377\1\376\376\376\216\377\377" \ - "\377\1kkm\206::<\1\316\316\316\304\377\377\377\1\204\204\204\203::<\1" \ - "99;\202::<\1\265\265\265\211\377\377\377\2\363\363\363FFH\205::<\2;;" \ - "=\346\346\346\231\377\377\377\1\234\234\234\206::<\1\234\234\234\243" \ - "\377\377\377\1kkm\206::<\237\377\377\377\1kkm\206::<\1\234\234\236\232" \ - "\377\377\377\1\222\222\222\202::<\1;;=\202::<\3;;=FFH\362\362\364\251" \ - "\377\377\377\1\235\235\235\203::<\7;;=::<;;=;;;\331\331\331\377\377\377" \ - "\376\376\376\214\377\377\377\2\234\234\234;;=\205::<\1\316\316\316\202" \ - "\377\377\377\3\376\376\376\377\377\377\301\301\301\205::<\4;;=::<__a" \ - "\376\376\376\216\377\377\377\4\376\376\376yyy::<;;=\205::<\1\316\316" \ - "\320\204\377\377\377\2\316\316\31699;\203::<\3""99;::<\234\234\236\207" \ - "\377\377\377\2\376\377\377\376\376\374\202\377\376\377\3\254\332\362" \ - "Y\267\352[\267\350\210Y\270\350\7[\267\350Y\267\352\326\356\370\376\376" \ - "\377\377\376\377\377\375\377\376\377\377\231\377\377\377\10\377\377\375" \ - "\376\377\377\377\377\377\377\376\377\377\377\375\276\317\331\1>j\0>j" \ - "\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316\316\206::<\1" \ - "kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236\220\377\377\377" \ - "\1\376\376\376\202\377\377\377\4\363\363\365;;=::<;;=\204::<\1\234\234" \ - "\234\231\377\377\377\1SSS\202::<\1;;=\203::<\1\265\265\267\223\377\377" \ - "\377\1kkm\206::<\1\316\316\316\300\377\377\377\1\376\376\376\202\377" \ - "\377\377\1\346\346\350\203::<\4;;=::<;;=SSU\213\377\377\377\1\204\204" \ - "\204\203::<\1;;=\202::<\1\204\204\206\202\377\377\377\1\376\376\376\226" \ - "\377\377\377\1\234\234\234\206::<\1\234\234\234\243\377\377\377\1kkm" \ - "\206::<\237\377\377\377\1kkm\206::<\1\234\234\236\227\377\377\377\1\376" \ - "\376\376\202\377\377\377\3TTV::<;;=\203::<\2;;=\205\205\205\252\377\377" \ - "\377\1\347\347\347\202::<\202;;=\203::<\1\235\235\237\204\377\377\377" \ - "\1\376\376\376\211\377\377\377\1\234\234\234\206::<\1\316\316\316\205" \ - "\377\377\377\1\205\205\205\202::<\6;;=::<;;=::<;;=\234\234\236\213\377" \ - "\377\377\1\376\376\376\202\377\377\377\1\302\302\302\202;;=\203::<\3" \ - ";;=::<\221\221\221\202\377\377\377\1\376\376\376\202\377\377\377\1\316" \ - "\316\316\206::<\1\234\234\236\213\377\377\377\2\255\333\363Y\270\350" \ - "\211[\267\350\3Y\270\350[\267\350\326\354\371\242\377\377\377\3\276\317" \ - "\331\0=i\0>i\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316" \ - "\316\206::<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236\224" \ - "\377\377\377\4\204\204\204;;=::<;;=\203::<\1TTT\204\377\377\377\1\376" \ - "\376\376\223\377\377\377\1\300\300\300\203::<\5;;=::<;;=FFF\363\363\363" \ - "\223\377\377\377\1kkm\203::<\4;;=::<;;=\316\316\320\277\377\377\377\14" \ - "\376\376\376\377\377\377\376\376\376\377\377\377\204\204\206::<;;=::" \ - "<99;<<>99;\265\265\267\213\377\377\377\3\346\346\346::<;;=\202::<\1;" \ - ";=\202::<\2\347\347\347\376\376\376\227\377\377\377\1\234\234\234\206" \ - "::<\1\234\234\234\243\377\377\377\1kkm\206::<\237\377\377\377\1kkm\206" \ - "::<\1\234\234\236\226\377\377\377\4\376\376\376\377\377\377\376\376\376" \ - "\346\346\350\202;;=\203::<\3""99;<<>\301\301\301\253\377\377\377\1aa" \ - "c\202::<\1;;=\202::<\2;;=jjl\205\377\377\377\1\376\376\376\210\377\377" \ - "\377\1\234\234\234\206::<\1\316\316\316\202\377\377\377\1\376\376\376" \ - "\202\377\377\377\3\362\362\362SSU;;=\205::<\2;;=\332\332\332\210\377" \ - "\377\377\1\376\376\376\203\377\377\377\2\363\363\363FFH\202::<\202;;" \ - "=\5::<;;=SSS\363\363\363\376\376\376\204\377\377\377\1\316\316\316\206" \ - "::<\1\234\234\236\213\377\377\377\2\255\333\363Y\270\350\211[\267\350" \ - "\3Y\270\350[\267\350\326\354\371\242\377\377\377\3\276\317\331\0=i\0" \ - ">i\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316\316\206::" \ - "<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236\224\377\377" \ - "\377\1\332\332\332\207::<\1\301\301\301\227\377\377\377\1lll\204::<\3" \ - ";;=::<\221\221\221\202\377\377\377\3\376\376\376\377\377\377\376\376" \ - "\376\217\377\377\377\1kkm\204::<\3;;=99;\316\316\316\241\377\377\377" \ - "\1\376\376\376\234\377\377\377\10\376\376\376\377\377\377\376\376\376" \ - "\377\377\377\363\363\363FFH;;=::<\202;;=\3::i\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316" \ - "\316\316\206::<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236" \ - "\225\377\377\377\1__a\204;;=\5""99;::99;\202::<\4;;=::<;;=\331\331\331\215\377\377\377\1\234\234\234" \ - "\206::<\1\316\316\316\207\377\377\377\1\222\222\224\202::<\3;;=99;<<" \ - ">\202::<\4\234\234\236\376\376\376\377\377\377\376\376\376\203\377\377" \ - "\377\1\376\376\376\203\377\377\377\6\302\302\304;;=99;;;=::<;;=\202:" \ - ":<\1\234\234\234\202\377\377\377\1\376\376\376\204\377\377\377\1\316" \ - "\316\316\206::<\1\234\234\236\213\377\377\377\2\255\333\363Y\270\350" \ - "\211[\267\350\3Y\270\350[\267\350\326\354\371\242\377\377\377\3\276\317" \ - "\331\0=i\0>i\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316" \ - "\316\206::<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236\225" \ - "\377\377\377\2\265\265\265;;=\202::<\2""99;;;=\202::<\2\347\347\347\376" \ - "\376\376\215\377\377\377\3\376\376\376\377\377\377\376\376\376\204\377" \ - "\377\377\3\221\221\223;;=99;\204::<\3xxz\377\377\377\376\376\376\202" \ - "\377\377\377\202\376\376\376\217\377\377\377\1kkm\202::<\5;;=99;;;=9" \ - "9;\317\317\317\233\377\377\377\1\376\376\376\237\377\377\377\1\376\376" \ - "\376\204\377\377\377\3\376\376\376\377\377\377GGI\202::<\5;;=::<;;=:" \ - ":<\346\346\346\213\377\377\377\1\376\376\376\202\377\377\377\2``b99;" \ - "\202;;=\203::<\3\247\247\247\377\377\377\376\376\376\225\377\377\377" \ - "\1\234\234\234\206::<\1\234\234\234\243\377\377\377\1kkm\206::<\237\377" \ - "\377\377\1kkm\206::<\1\234\234\236\231\377\377\377\10kkm::<;;=::<;;=" \ - "99;::<\235\235\237\255\377\377\377\202::<\1;;=\204::<\1\301\301\301\215" \ - "\377\377\377\1\234\234\234\206::<\1\316\316\316\206\377\377\377\5\376" \ - "\376\376\364\364\364TTV::<99;\202;;=\203::<\4\332\332\334\376\376\376" \ - "\377\377\377\376\376\376\203\377\377\377\6\376\376\376\377\377\377\363" \ - "\363\363FFH::<;;=\204::<\1__a\210\377\377\377\1\316\316\316\206::<\1" \ - "\234\234\236\213\377\377\377\2\255\333\363Y\270\350\211[\267\350\3Y\270" \ - "\350[\267\350\326\354\371\242\377\377\377\3\276\317\331\0=i\0>i\210\0" \ - "=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316\316\206::<\1kkm\240" \ - "\377\377\377\1\234\234\236\206::<\1\234\234\236\224\377\377\377\5\376" \ - "\376\376\377\377\377GGI::<;;=\203::<\4;;=\220\220\222\377\377\377\376" \ - "\376\376\214\377\377\377\1\376\376\376\203\377\377\377\10\376\376\376" \ - "\377\377\377\363\363\363FFH::<;;=99;;;=\202::<\1\316\316\320\202\377" \ - "\377\377\1\376\376\376\204\377\377\377\1\376\376\376\215\377\377\377" \ - "\1kkm\206::<\1\316\316\316\277\377\377\377\3\376\376\376\377\377\377" \ - "\265\265\267\204::<\3;;=::<\205\205\205\213\377\377\377\1\376\376\376" \ - "\202\377\377\377\2\376\376\376\265\265\265\202::<\5""99;<<>::<;;=SSU" \ - "\202\377\377\377\1\376\376\376\224\377\377\377\1\234\234\234\206::<\1" \ - "\234\234\234\243\377\377\377\1kkm\206::<\237\377\377\377\1kkm\206::<" \ - "\1\234\234\236\230\377\377\377\2\376\376\376SSU\204::<\3;;=::<\266\266" \ - "\266\253\377\377\377\3\376\376\376\377\377\377^^`\206::<\1\234\234\234" \ - "\202\377\377\377\1\376\376\376\212\377\377\377\1\234\234\234\206::<\1" \ - "\316\316\316\205\377\377\377\6\376\376\376\377\377\377\376\376\376\315" \ - "\315\317::<;;=\202::<\4;;=99;::<``b\210\377\377\377\4xxz99;<<>::<\202" \ - ";;=\202::<\1\332\332\332\203\377\377\377\1\376\376\376\204\377\377\377" \ - "\1\316\316\316\206::<\1\234\234\236\213\377\377\377\2\255\333\363Y\270" \ - "\350\211[\267\350\3Y\270\350[\267\350\326\354\371\242\377\377\377\3\276" \ - "\317\331\0=i\0>i\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316" \ - "\316\316\206::<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236" \ - "\226\377\377\377\1\234\234\234\206::<\2FFH\376\376\376\214\377\377\377" \ - "\1\376\376\376\202\377\377\377\1\376\376\376\203\377\377\377\3\265\265" \ - "\265;;=99;\202;;=\202::<\1SSU\202\377\377\377\1\376\376\376\223\377\377" \ - "\377\1kkm\203::<\4""99;::<;;=\316\316\320\275\377\377\377\202\376\376" \ - "\376\4\377\377\377\376\376\376SSU;;=\202::<\4;;=::<;;=\332\332\332\215" \ - "\377\377\377\5\376\376\376\377\377\377\376\376\376SSU;;=\204::<\2;;=" \ - "\264\264\264\226\377\377\377\1\234\234\234\206::<\1\234\234\234\243\377" \ - "\377\377\1kkm\206::<\237\377\377\377\1kkm\206::<\1\234\234\236\231\377" \ - "\377\377\207::<\1\316\316\316\254\377\377\377\2\376\376\376lln\202::" \ - "<\1;;=\202::<\4;;=\233\233\233\377\377\377\376\376\376\202\377\377\377" \ - "\1\376\376\376\210\377\377\377\1\234\234\234\206::<\1\316\316\316\203" \ - "\377\377\377\202\376\376\376\204\377\377\377\1\234\234\234\207::<\1\234" \ - "\234\236\205\377\377\377\4\376\376\376\300\300\302::<;;=\205::<\2\234" \ - "\234\234\376\376\376\202\377\377\377\1\376\376\376\205\377\377\377\1" \ - "\316\316\316\206::<\1\234\234\236\213\377\377\377\2\255\333\363Y\270" \ - "\350\211[\267\350\3Y\270\350[\267\350\326\354\371\242\377\377\377\3\276" \ - "\317\331\0=i\0>i\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316" \ - "\316\316\206::<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236" \ - "\226\377\377\377\1\347\347\347\204::<\5;;=99;;;=\265\265\265\376\376" \ - "\376\222\377\377\377\2___99;\202::<\4;;=::<;;=\265\265\265\207\377\377" \ - "\377\1\376\376\376\216\377\377\377\1kkm\203::<\1;;=\202::<\1;;=\233:" \ - ":<\5""99;;;=::<:::\234\234\234\240\377\377\377\2\316\316\316;;=\204:" \ - ":<\2;;=kkm\221\377\377\377\1\234\234\236\203::<\1;;=\202::<\3kkk\377" \ - "\377\377\376\376\376\224\377\377\377\1\234\234\234\206::<\1\234\234\234" \ - "\243\377\377\377\1kkm\206::<\237\377\377\377\1kkm\206::<\1\234\234\236" \ - "\231\377\377\377\207::<\1\316\316\316\255\377\377\377\2\221\221\221;" \ - ";=\205::<\1\204\204\204\203\377\377\377\1\376\376\376\211\377\377\377" \ - "\1\234\234\234\206::<\1\316\316\316\210\377\377\377\3\376\376\376\377" \ - "\377\377``b\202::<\7;;=::<;;=::<;;=\332\332\332\376\376\376\202\377\377" \ - "\377\3\376\376\376\363\363\363GGI\203::<\4;;=::<;;=__a\206\377\377\377" \ - "\1\376\376\376\203\377\377\377\1\316\316\316\206::<\1\234\234\236\213" \ - "\377\377\377\2\255\333\363Y\270\350\211[\267\350\3Y\270\350[\267\350" \ - "\326\354\371\242\377\377\377\3\276\317\331\0=i\0>i\210\0=i\3\0>i\0=i" \ - "\177\236\263\232\377\377\377\1\316\316\316\206::<\1kkm\240\377\377\377" \ - "\1\234\234\236\206::<\1\234\234\236\227\377\377\377\1\204\204\206\204" \ - "::<\3;;=::i\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316\316" \ - "\206::<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236\227\377" \ - "\377\377\1\315\315\315\205::<\3;;=::<\332\332\334\221\377\377\377\1\204" \ - "\204\206\205::<\2;;=\205\205\205\227\377\377\377\1kkm\203::<\3;;=::<" \ - ";;=\234::<\1:9>\203::<\1\234\234\236\237\377\377\377\1\331\331\331\202" \ - ";;=\204::<\1SSU\217\377\377\377\5\376\376\376\377\377\377\376\376\376" \ - "\377\377\377\204\204\204\204::<\3;;=99;yyy\203\377\377\377\1\376\376" \ - "\376\221\377\377\377\1\234\234\234\206::<\1\234\234\234\235\377\377\377" \ - "\1\376\376\376\205\377\377\377\1kkm\206::<\237\377\377\377\1kkm\206:" \ - ":<\1\234\234\236\231\377\377\377\203::<\1;;=\203::<\202\377\377\377\1" \ - "\376\376\376\253\377\377\377\2\233\233\235;;=\205::<\3kkm\377\377\377" \ - "\376\376\376\202\377\377\377\1\376\376\376\210\377\377\377\1\234\234" \ - "\234\206::<\1\316\316\316\213\377\377\377\1\234\234\236\202;;=\1""99" \ - ";\203::<\5;;=\235\235\235\377\377\377\376\376\376\302\302\302\207::<" \ - "\1\251\251\251\213\377\377\377\1\316\316\316\206::<\1\234\234\236\213" \ - "\377\377\377\2\255\333\363Y\270\350\211[\267\350\3Y\270\350[\267\350" \ - "\326\354\371\242\377\377\377\3\276\317\331\0=i\0>i\210\0=i\3\0>i\0=i" \ - "\177\236\263\232\377\377\377\1\316\316\316\206::<\1kkm\240\377\377\377" \ - "\1\234\234\236\206::<\1\234\234\236\223\377\377\377\1\376\376\376\204" \ - "\377\377\377\1^^`\202::<\202;;=\3::<<<>\204\204\206\213\377\377\377\1" \ - "\376\376\376\204\377\377\377\1\363\363\363\205::<\3;;=::<\346\346\346" \ - "\227\377\377\377\1kkm\204::<\3;;=::<;;=\234::<\1;;=\202::<\1\234\234" \ - "\236\237\377\377\377\4\204\204\20499;::<;;=\203::<\3\266\266\270\377" \ - "\377\377\376\376\376\221\377\377\377\5\346\346\346;;=::<;;=::<\202;;" \ - "=\4::<\346\346\350\377\377\377\376\376\376\202\377\377\377\1\376\376" \ - "\376\217\377\377\377\1\234\234\234\206::<\1\234\234\234\237\377\377\377" \ - "\202\376\376\376\202\377\377\377\1kkm\206::<\237\377\377\377\1kkm\206" \ - "::<\1\234\234\236\224\377\377\377\6\376\376\376\377\377\377\376\376\376" \ - "\377\377\377\376\376\376;;=\206::<\1\331\331\331\255\377\377\377\1\234" \ - "\234\236\202::<\1;;=\203::<\2kkm\376\376\376\202\377\377\377\1\376\376" \ - "\376\211\377\377\377\1\234\234\234\206::<\1\316\316\316\212\377\377\377" \ - "\3\376\376\376\377\377\377___\204::<\7;;=99;::<\332\332\332\363\363\365" \ - "FFH;;=\204::<\3;;=kkm\376\376\376\213\377\377\377\1\316\316\316\206:" \ - ":<\1\234\234\236\213\377\377\377\2\255\333\363Y\270\350\211[\267\350" \ - "\3Y\270\350[\267\350\326\354\371\242\377\377\377\3\276\317\331\0=i\0" \ - ">i\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316\316\206::" \ - "<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236\224\377\377" \ - "\377\1\376\376\376\203\377\377\377\4\265\265\267::<;;=::<\202;;=\3::" \ - "i\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316\316\206" \ - "::<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236\231\377\377" \ - "\377\10FFH::<;;=99;;;=::<;;=\265\265\265\216\377\377\377\4\376\376\376" \ - "TTV99;;;=\202::<\202;;=\1\301\301\301\230\377\377\377\1kkm\202::<\1;" \ - ";=\204::<\3;;=::<;;=\232::<\5;;=::<\234\234\234\377\377\377\376\376\376" \ - "\232\377\377\377\3\376\376\376\377\377\377\221\221\221\202::<\1""99;" \ - "\203::<\5\234\234\236\377\377\377\376\376\376\377\377\377\376\376\376" \ - "\216\377\377\377\1\376\376\376\202\377\377\377\2\316\316\320::<\202;" \ - ";=\204::<\2\363\363\363\376\376\376\202\377\377\377\1\376\376\376\217" \ - "\377\377\377\1\234\234\234\206::<\1\234\234\234\243\377\377\377\1kkm" \ - "\206::<\237\377\377\377\1kkm\206::<\1\234\234\236\224\377\377\377\1\376" \ - "\376\376\204\377\377\377\1""99;\202::<\1;;=\203::<\1\316\316\316\252" \ - "\377\377\377\10\376\376\376\377\377\377\376\376\376kkm;;=::<;;=99;\202" \ - "::<\1\234\234\236\215\377\377\377\1\234\234\234\206::<\1\316\316\316" \ - "\215\377\377\377\5\247\247\247;;=99;::<;;=\210::<\5""99;::<\250\250\252" \ - "\377\377\377\376\376\376\213\377\377\377\1\316\316\316\206::<\1\234\234" \ - "\236\213\377\377\377\2\255\333\363Y\270\350\211[\267\350\3Y\270\350[" \ - "\267\350\326\354\371\242\377\377\377\3\276\317\331\0=i\0>i\210\0=i\3" \ - "\0>i\0=i\177\236\263\232\377\377\377\1\316\316\316\206::<\1kkm\240\377" \ - "\377\377\1\234\234\236\206::<\1\234\234\236\223\377\377\377\3\376\376" \ - "\376\377\377\377\376\376\376\203\377\377\377\1\234\234\236\202::<\1;" \ - ";=\202::<\2""99;SSU\214\377\377\377\5\376\376\376\377\377\377\301\301" \ - "\301;;=<<>\202::<\3;;=::i\210\0=i\3\0>i\0=i\177\236\263" \ - "\232\377\377\377\1\316\316\316\206::<\1kkm\240\377\377\377\1\234\234" \ - "\236\206::<\1\234\234\236\224\377\377\377\1\376\376\376\204\377\377\377" \ - "\2\346\346\34699;\202::<\2;;=::<\202;;=\1\315\315\315\212\377\377\377" \ - "\1\376\376\376\202\377\377\377\1yy{\203::<\4;;=99;;;=\250\250\250\202" \ - "\377\377\377\1\376\376\376\226\377\377\377\1kkm\206::<\1\317\317\317" \ - "\240\377\377\377\1\376\376\376\234\377\377\377\1\234\234\234\202::<\2" \ - "99;;;=\202::<\1\204\204\206\203\377\377\377\1\376\376\376\220\377\377" \ - "\377\1\376\376\376\202\377\377\377\2\264\264\264::<\202;;=\203::<\3G" \ - "GI\364\364\364\376\376\376\202\377\377\377\1\376\376\376\216\377\377" \ - "\377\1\234\234\234\206::<\1\234\234\234\241\377\377\377\3\376\376\376" \ - "\377\377\377kkm\206::<\237\377\377\377\1kkm\206::<\1\234\234\236\225" \ - "\377\377\377\202\376\376\376\202\377\377\377\12kkm::<;;=99;::<;;=::<" \ - "\204\204\204\377\377\377\376\376\376\251\377\377\377\4\376\376\376\377" \ - "\377\377::<99;\202;;=\203::<\1\316\316\320\215\377\377\377\1\234\234" \ - "\234\206::<\1\316\316\316\216\377\377\377\5\346\346\350GGI;;=::<;;=\202" \ - "::<\2""99;;;=\202::<\3;;=GGI\346\346\350\216\377\377\377\1\316\316\316" \ - "\206::<\1\234\234\236\213\377\377\377\2\255\333\363Y\270\350\211[\267" \ - "\350\3Y\270\350[\267\350\326\354\371\242\377\377\377\3\276\317\331\0" \ - "=i\0>i\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316\316\206" \ - "::<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236\231\377\377" \ - "\377\2\376\376\376\205\205\205\202::<\5""99;;;=::<;;=\205\205\207\213" \ - "\377\377\377\12\376\376\376\346\346\346::<;;=99;::<99;;;=FFH\363\363" \ - "\363\231\377\377\377\1kkm\202::<\2;;=::<\202;;=\3\316\316\316\377\377" \ - "\377\376\376\376\234\377\377\377\1\376\376\376\236\377\377\377\1SSS\204" \ - "::<\3;;=99;\347\347\351\204\377\377\377\1\376\376\376\215\377\377\377" \ - "\1\376\376\376\205\377\377\377\1SSU\203::<\4;;=99;::<\265\265\265\202" \ - "\377\377\377\1\376\376\376\217\377\377\377\1\234\234\234\206::<\1\234" \ - "\234\234\242\377\377\377\2\376\376\376SSU\206::<\237\377\377\377\1kk" \ - "m\206::<\1\234\234\236\231\377\377\377\4\221\221\223;;=::<;;=\202::<" \ - "\3;;=___\376\376\376\253\377\377\377\1\332\332\332\204::<\1;;=\202::" \ - "<\1\346\346\350\203\377\377\377\1\376\376\376\211\377\377\377\1\234\234" \ - "\234\206::<\1\316\316\316\217\377\377\377\1\250\250\252\204::<\202;;" \ - "=\2::<;;=\202::<\1\265\265\267\217\377\377\377\1\316\316\316\206::<\1" \ - "\234\234\236\213\377\377\377\2\255\333\363Y\270\350\211[\267\350\3Y\270" \ - "\350[\267\350\326\354\371\242\377\377\377\3\276\317\331\0=i\0>i\210\0" \ - "=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316\316\206::<\1kkm\240" \ - "\377\377\377\1\234\234\236\206::<\1\234\234\236\232\377\377\377\1\316" \ - "\316\316\203::<\2""99;<<>\202::<\1\346\346\350\213\377\377\377\4\221" \ - "\221\223;;=::<;;=\203::<\1\204\204\206\232\377\377\377\1kkm\203::<\1" \ - ";;=\202::<\1\316\316\316\274\377\377\377\2\265\265\267;;=\205::<\1xx" \ - "x\231\377\377\377\1\250\250\250\206::<\1TTV\222\377\377\377\1\234\234" \ - "\234\204::<\3;;=::<\235\235\235\203\377\377\377\1\376\376\376\237\377" \ - "\377\377\202;;=\203::<\3;;=::<\376\376\376\236\377\377\377\1kkm\206:" \ - ":<\1\234\234\236\225\377\377\377\1\376\376\376\203\377\377\377\1\265" \ - "\265\267\204::<\1;;=\202::<\1\363\363\363\253\377\377\377\1\250\250\250" \ - "\204::<\3;;=::j\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316\316" \ - "\206::<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236\233\377" \ - "\377\377\1``b\205::<\2;;=\235\235\237\210\377\377\377\1\376\376\376\202" \ - "\377\377\377\2FFH;;=\205::<\1\346\346\346\202\377\377\377\1\376\376\376" \ - "\227\377\377\377\1kkm\206::<\1\316\316\316\266\377\377\377\1\376\376" \ - "\376\205\377\377\377\5__a::<;;=::<;;=\202::<\1SSU\202kkm\1lln\203kkm" \ - "\1lln\222kkm\4__a;;=99;;;=\204::<\3\301\301\301\377\377\377\376\376\376" \ - "\215\377\377\377\202\376\376\376\1\235\235\235\204::<\3""99;;;=\221\221" \ - "\221\243\377\377\377\203::<\1;;=\202::<\1""99;\237\377\377\377\1kkm\206" \ - "::<\1\234\234\236\231\377\377\377\1\332\332\332\202::<\3;;=::<99;\202" \ - ";;=\1\264\264\264\210\377\377\377\1\376\376\376\232\377\377\377\1\376" \ - "\376\376\206\377\377\377\2\376\376\376xxx\202::<\1;;=\203::<\1xxz\216" \ - "\377\377\377\1\234\234\234\206::<\1\316\316\316\220\377\377\377\3\363" \ - "\363\365FFH;;=\202::<\1;;=\202::<\2FFH\363\363\363\220\377\377\377\1" \ - "\316\316\316\206::<\1\234\234\236\213\377\377\377\2\255\333\363Y\270" \ - "\350\211[\267\350\10X\267\347Y\267\352\326\354\371\377\377\377\376\376" \ - "\376\377\376\377\377\377\377\377\376\377\234\377\377\377\2\376\376\374" \ - "\277\320\330\212\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316" \ - "\316\206::<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236\233" \ - "\377\377\377\1\265\265\267\203::<\4""99;;;=::9" \ - "9;::<;;=::<99;\203::<\2;;=99;\202::<\1;;=\224::<\1;;=\202::<\1;;=\203" \ - "::<\1kkm\203\377\377\377\1\376\376\376\215\377\377\377\1\300\300\300" \ - "\202::<\11;;=::<99;;;=jjl\377\377\377\376\376\376\377\377\377\376\376" \ - "\376\236\377\377\377\1\346\346\350\206::<\1__a\237\377\377\377\1kkm\206" \ - "::<\1\234\234\236\231\377\377\377\2\376\376\376SSU\206::<\2yy{\376\376" \ - "\376\206\377\377\377\1\376\376\376\234\377\377\377\1\376\376\376\205" \ - "\377\377\377\4\363\363\363::<<<>99;\202::<\3;;=::<\265\265\267\203\377" \ - "\377\377\3\376\376\376\377\377\377\376\376\376\210\377\377\377\1\234" \ - "\234\234\206::<\1\316\316\316\221\377\377\377\4\301\301\30199;::<;;=" \ - "\202::<\6;;=\301\301\301\377\377\377\376\376\376\377\377\377\376\376" \ - "\376\215\377\377\377\1\316\316\316\206::<\1\234\234\236\213\377\377\377" \ - "\2\255\333\363Y\270\350\211[\267\350\6Y\270\350Y\267\352\325\353\370" \ - "\377\377\377\376\377\375\377\375\377\234\377\377\377\5\376\376\376\377" \ - "\377\377\377\377\375\276\317\327\2\77k\211\0=i\3\0>i\0=i\177\236\263" \ - "\232\377\377\377\1\316\316\316\206::<\1kkm\240\377\377\377\1\234\234" \ - "\236\206::<\1\234\234\236\234\377\377\377\1GGI\203::<\1;;=\202::<\2\301" \ - "\301\301\376\376\376\204\377\377\377\1\376\376\376\203\377\377\377\3" \ - "lln::<;;=\202::<\202;;=\4\301\301\303\376\376\376\377\377\377\376\376" \ - "\376\230\377\377\377\1kkm\206::<\1\316\316\316\265\377\377\377\1\376" \ - "\376\376\205\377\377\377\3kkm::<;;=\202::<\2""99;<<>\202::<\3;;=::<;" \ - ";=\202::<\1;;=\222::<\4""99;;;=::<;;=\203::<\1;;=\202::<\3\316\316\316" \ - "\377\377\377\376\376\376\215\377\377\377\3\376\376\376\316\316\316;;" \ - "=\203::<\3;;=::\204::<\3\346" \ - "\346\346\377\377\377\376\376\376\202\377\377\377\1\376\376\376\211\377" \ - "\377\377\1\234\234\234\206::<\1\316\316\316\220\377\377\377\14\376\376" \ - "\376\377\377\377yy{::<99;;;=::j\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316" \ - "\316\206::<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236\234" \ - "\377\377\377\1\234\234\234\206::<\3jjj\377\377\377\376\376\376\204\377" \ - "\377\377\4\376\376\376\377\377\377\332\332\33299;\203::<\3;;=::j\210\0=i\3\0>i\0=i\177" \ - "\236\263\232\377\377\377\1\316\316\316\206::<\1kkm\240\377\377\377\1" \ - "\234\234\236\206::<\1\234\234\236\233\377\377\377\2\376\376\376\347\347" \ - "\347\202::<\2;;=::<\203;;=\1\346\346\346\207\377\377\377\5\204\204\204" \ - "<<>99;::<;;=\202::<\2\251\251\251\376\376\376\205\377\377\377\1\376\376" \ - "\376\225\377\377\377\1kkm\206::<\1\316\316\316\264\377\377\377\1\376" \ - "\376\376\205\377\377\377\3\204\204\206::<;;=\203::<\1;;=\205::<\1;;=" \ - "\225::<\3;;=::<;;=\202::<\1;;=\202::<\1;;=\202::<\1\347\347\347\220\377" \ - "\377\377\2SSU;;=\203::<\3;;=::<\265\265\265\237\377\377\377\7\376\376" \ - "\376\377\377\377lln99;::<;;=99;\202::<\1\265\265\267\237\377\377\377" \ - "\1kkm\206::<\1\234\234\236\225\377\377\377\1\376\376\376\204\377\377" \ - "\377\3\376\376\376SSU;;=\204::<\3;;=FFH\346\346\346\202\377\377\377\1" \ - "\376\376\376\237\377\377\377\1\376\376\376\204\377\377\377\2\265\265" \ - "\267;;=\202::<\1;;=\203::<\1\265\265\265\217\377\377\377\1\234\234\234" \ - "\206::<\1\316\316\316\223\377\377\377\4\301\301\301::<:::\302\302\302" \ - "\223\377\377\377\1\316\316\316\206::<\1\234\234\236\213\377\377\377\2" \ - "\255\333\363Y\270\350\212[\267\350\2Y\270\350\332\354\370\202\377\377" \ - "\377\3\376\376\376\376\377\377\377\376\373\235\377\377\377\1\276\317" \ - "\331\202\0>i\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316" \ - "\316\206::<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236\235" \ - "\377\377\377\1\204\204\204\206::<\1\221\221\223\206\377\377\377\2\363" \ - "\363\363GGI\202::<\5""99;;;=::i\210\0=i\3\0>i\0=i\177\236" \ - "\263\232\377\377\377\1\316\316\316\206::<\1kkm\240\377\377\377\1\234" \ - "\234\236\206::<\1\234\234\236\235\377\377\377\1\316\316\316\206::<\1" \ - "FFH\203\377\377\377\1\376\376\376\202\377\377\377\1\250\250\250\203:" \ - ":<\1;;=\202::<\1\204\204\206\203\377\377\377\1\376\376\376\231\377\377" \ - "\377\1kkm\206::<\1\316\316\316\271\377\377\377\1\234\234\236\204::<\4" \ - ";;=::j\0>i\210\0=i\3\0>i\0=i\177\236\263\232" \ - "\377\377\377\1\316\316\316\206::<\1kkm\240\377\377\377\1\234\234\236" \ - "\206::<\1\234\234\236\236\377\377\377\2__a;;=\204::<\5;;=\265\265\265" \ - "\376\376\376\377\377\377\376\376\376\202\377\377\377\1SSU\204::<\3;;" \ - "=::<\346\346\350\235\377\377\377\1kkm\206::<\1\316\316\316\270\377\377" \ - "\377\2\363\363\365GGI\205::<\3;;=\333\333\333\376\376\376\237\377\377" \ - "\377\10FFH::<;;=::<;;=99;;;=\233\233\235\217\377\377\377\5\346\346\346" \ - "::<;;=::<;;=\203::<\1\234\234\234\210\377\377\377\1\376\376\376\217\377" \ - "\377\377\1\376\376\376\206\377\377\377\1TTT\205::<\3;;=\221\221\221\376" \ - "\376\376\237\377\377\377\1kkm\206::<\1\234\234\236\234\377\377\377\12" \ - "\233\233\233::<;;=::<;;=::<;;=::l\0\77j\210\0=i\3\0>i\0=" \ - "i\177\236\263\232\377\377\377\1\316\316\316\206::<\1kkm\240\377\377\377" \ - "\1\234\234\236\206::<\1\234\234\236\236\377\377\377\1\265\265\265\204" \ - "::<\3;;=::<__a\204\377\377\377\1\317\317\321\206::<\1kkk\236\377\377" \ - "\377\1kkm\206::<\1\316\316\316\267\377\377\377\3\376\376\376\250\250" \ - "\25299;\202;;=\203::<\1kkm\233\377\377\377\1\376\376\376\205\377\377" \ - "\377\10\234\234\236;;=::<;;=::<;;=99;GGI\204\377\377\377\3\376\376\376" \ - "\377\377\377\376\376\376\210\377\377\377\5\376\376\376__a::<;;=99;\203" \ - ";;=\2FFH\363\363\363\204\377\377\377\3\376\376\376\377\377\377\376\376" \ - "\376\224\377\377\377\5\376\376\376\377\377\377\301\301\301:::;;=\202" \ - "::<\202;;=\4::<\332\332\332\377\377\377\376\376\376\236\377\377\377\1" \ - "kkm\206::<\1\234\234\236\233\377\377\377\3\376\376\376\364\364\364FF" \ - "H\205::<\4;;=99;xxx\376\376\376\203\377\377\377\1\376\376\376\203\377" \ - "\377\377\1\376\376\376\202\377\377\377\1\376\376\376\224\377\377\377" \ - "\4\376\376\376\377\377\377\362\362\362GGI\202::<\6;;=::<;;=::<99;\250" \ - "\250\252\221\377\377\377\1\234\234\234\206::<\1\316\316\316\252\377\377" \ - "\377\1\316\316\316\206::<\1\234\234\236\213\377\377\377\2\255\333\363" \ - "Y\270\350\211[\267\350\7Y\267\352X\267\347[\266\353\301\344\367\377\377" \ - "\377\376\376\376\376\377\377\211\377\377\377\6\377\376\377\377\377\377" \ - "\377\375\376\377\377\377\377\377\375\377\376\377\202\377\377\377\210" \ - "\377\376\377\10\377\377\375\376\377\377\377\377\377\376\377\375\237\266" \ - "\306\0=i\2=g\0>e\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316" \ - "\316\316\206::<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234\236" \ - "\237\377\377\377\1EEG\202::<\202;;=\11""99;;;=\332\332\332\377\377\377" \ - "\376\376\376\377\377\377xxz::<;;=\204::<\1\302\302\302\236\377\377\377" \ - "\1kkm\206::<\1\316\316\316\266\377\377\377\4\376\376\376\377\377\377" \ - "SSU;;=\202::<\1;;=\202::<\1\316\316\320\235\377\377\377\15\376\376\376" \ - "\377\377\377\376\376\376\377\377\377\363\363\365::<;;=99;;;=::<;;=::" \ - "<\265\265\265\215\377\377\377\3\376\376\376\377\377\377\266\266\270\202" \ - "::<\1;;=\203::<\2;;=\204\204\206\205\377\377\377\3\376\376\376\377\377" \ - "\377\376\376\376\213\377\377\377\1\376\376\376\205\377\377\377\1\376" \ - "\376\376\202\377\377\377\2\363\363\363SSU\203::<\4;;=99;;;=SSU\241\377" \ - "\377\377\1kkm\206::<\1\234\234\236\235\377\377\377\3\265\265\265;;=9" \ - "9;\202::<\1;;=\203::<\1\204\204\206\206\377\377\377\1\376\376\376\216" \ - "\377\377\377\3\376\376\376\377\377\377\376\376\376\206\377\377\377\6" \ - "\376\376\376\377\377\377\362\362\364``b::<;;=\202::<\1;;=\202::<\2aa" \ - "c\376\376\376\221\377\377\377\1\234\234\234\206::<\1\316\316\316\252" \ - "\377\377\377\1\316\316\316\206::<\1\234\234\236\213\377\377\377\2\255" \ - "\333\363Y\270\350\211[\267\350\10X\267\347[\267\346[\265\347[\267\346" \ - "\230\320\361\327\360\367\325\356\365\331\355\370\210\326\354\371\10\325" \ - "\355\367\323\355\372\366\373\377\377\376\374\376\377\375\276\320\332" \ - "\277\320\330\301\317\330\210\276\317\331\10\276\317\327\276\320\334\301" \ - "\316\327_\207\241\0>i\0=l\0\77k\0>i\210\0=i\3\0>i\0=i\177\236\263\232" \ - "\377\377\377\1\316\316\316\206::<\1kkm\240\377\377\377\1\234\234\236" \ - "\206::<\1\234\234\236\237\377\377\377\3\222\222\224::<;;=\202::<\3;;" \ - "=99;\205\205\207\202\377\377\377\2\346\346\346;;=\202::<\1;;=\202::<" \ - "\1SSU\237\377\377\377\1kkm\206::<\1\316\316\316\267\377\377\377\5\265" \ - "\265\26799;;;=::<;;=\202::<\1TTV\243\377\377\377\1\204\204\206\205::" \ - "<\2;;=SSU\206\377\377\377\1\376\376\376\210\377\377\377\3\376\376\376" \ - "GGI;;=\202::<\5;;=::<;;=::<\301\301\303\203\377\377\377\1\376\376\376" \ - "\214\377\377\377\1\376\376\376\202\377\377\377\1\376\376\376\202\377" \ - "\377\377\1\376\376\376\204\377\377\377\3\204\204\206;;=::<\202;;=\203" \ - "::<\1\265\265\265\241\377\377\377\1kkm\206::<\1\234\234\236\236\377\377" \ - "\377\12kkk::<99;;;=::<99;;;=::<;;=\204\204\206\210\377\377\377\202\376" \ - "\376\376\213\377\377\377\1\376\376\376\202\377\377\377\1\376\376\376" \ - "\202\377\377\377\1\376\376\376\202\377\377\377\2\364\364\366__a\206:" \ - ":<\3;;=::<\332\332\332\222\377\377\377\1\234\234\234\206::<\1\316\316" \ - "\316\252\377\377\377\1\316\316\316\206::<\1\234\234\236\213\377\377\377" \ - "\2\255\333\363Y\270\350\211[\267\350\3\\\266\350X\270\352\\\266\352\202" \ - "[\267\350\3X\267\347Y\270\350Z\266\347\210Y\270\350\10[\267\350[\265" \ - "\351\327\355\372\376\377\377\377\377\375\0>j\0>i\1\77h\210\0>i\10\0\77" \ - "k\0>g\2=g\0=i\0\77j\0j\210\0=i\3\0>i\0=i\177\236\263\232\377" \ - "\377\377\1\316\316\316\206::<\1kkm\240\377\377\377\1\234\234\236\206" \ - "::<\1\234\234\236\236\377\377\377\2\376\376\376\346\346\346\202::<\10" \ - ";;=::<99;;;=::<\363\363\363\377\377\377\234\234\236\202::<\6;;=::<;;" \ - "=::<\250\250\250\376\376\376\236\377\377\377\1kkm\206::<\1\316\316\316" \ - "\267\377\377\377\10kkm;;=::<;;=99;::<;;=\264\264\266\236\377\377\377" \ - "\1\376\376\376\204\377\377\377\2\346\346\346;;=\202::<\202;;=\202::<" \ - "\2\316\316\320\376\376\376\203\377\377\377\1\376\376\376\205\377\377" \ - "\377\3\376\376\376\377\377\377\376\376\376\202\377\377\377\3\234\234" \ - "\234::<;;=\202::<\6;;=::<;;=GGI\332\332\332\376\376\376\224\377\377\377" \ - "\1\376\376\376\203\377\377\377\2\266\266\266;;=\202::<\6;;=::<;;=::<" \ - "SSU\376\376\376\241\377\377\377\1kkm\206::<\1\234\234\236\236\377\377" \ - "\377\2\363\363\363GGI\203::<\1;;=\203::<\3""99;\204\204\204\363\363\363" \ - "\225\377\377\377\1\376\376\376\204\377\377\377\4\376\376\376\346\346" \ - "\346``b::<\202;;=\3::<99;<<>\202::<\1\250\250\250\223\377\377\377\1\234" \ - "\234\234\206::<\1\316\316\316\252\377\377\377\1\316\316\316\206::<\1" \ - "\234\234\236\213\377\377\377\2\255\333\363Y\270\350\211[\267\350\10Y" \ - "\270\350X\270\353Y\267\352X\266\351X\271\346[\267\350\\\266\353[\267" \ - "\350\210Y\270\350\7X\267\345]\267\351\323\355\372\377\376\377\376\377" \ - "\377\4=h\0>g\211\0=i\10\2=i\0@j\0>i\1>j\0>i\1\77h\0>g\0>j\210\0=i\3\0" \ - ">i\0=i\177\236\263\232\377\377\377\1\316\316\316\206::<\1kkm\240\377" \ - "\377\377\1\234\234\236\206::<\1\234\234\236\237\377\377\377\6\376\376" \ - "\376yy{::<;;=::<;;=\202::<\4\251\251\251\376\376\376SSU;;=\203::<\3;" \ - ";=FFH\363\363\363\237\377\377\377\1kkm\206::<\1\316\316\316\264\377\377" \ - "\377\5\376\376\376\377\377\377\315\315\317::<;;=\204::<\2FFH\376\376" \ - "\376\237\377\377\377\1\376\376\376\203\377\377\377\3\376\376\376kkm;" \ - ";=\204::<\6""99;lln\377\377\377\376\376\376\377\377\377\376\376\376\202" \ - "\377\377\377\3\376\376\376\377\377\377\376\376\376\205\377\377\377\10" \ - "\376\376\376\377\377\377SSU::<99;;;=99;;;=\202::<\2FFF\332\332\332\203" \ - "\377\377\377\1\376\376\376\212\377\377\377\1\376\376\376\210\377\377" \ - "\377\1\265\265\265\206::<\3""99;::<\265\265\265\203\377\377\377\1\376" \ - "\376\376\236\377\377\377\1kkm\206::<\1\234\234\236\233\377\377\377\1" \ - "\376\376\376\203\377\377\377\1\331\331\331\204::<\3""99;;;=99;\202;;" \ - "=\2^^^\332\332\332\202\377\377\377\1\376\376\376\216\377\377\377\1\376" \ - "\376\376\206\377\377\377\5\376\376\376\316\316\316FFH::<;;=\204::<\7" \ - "99;::<\204\204\204\377\377\377\376\376\376\377\377\377\376\376\376\220" \ - "\377\377\377\1\234\234\234\206::<\1\316\316\316\252\377\377\377\1\316" \ - "\316\316\206::<\1\234\234\236\213\377\377\377\2\255\333\363Y\270\350" \ - "\213[\267\350\6Y\270\350[\266\353[\267\350]\267\351X\266\351X\270\350" \ - "\210[\267\350\10X\266\351Z\266\351\326\354\367\377\376\377\376\377\372" \ - "\0>j\0>i\1>j\210\0=i\10\1\77h\0=h\0>i\1\77h\0>j\0=i\0>i\1>j\210\0=i\3" \ - "\0>i\0=i\177\236\263\232\377\377\377\1\316\316\316\206::<\1kkm\240\377" \ - "\377\377\1\234\234\236\206::<\1\234\234\236\237\377\377\377\2\376\376" \ - "\376\316\316\316\203::<\1;;=\202::<\4SSU\265\265\267;;=99;\202::<\5;" \ - ";=99;\204\204\204\377\377\377\376\376\376\236\377\377\377\1kkm\206::" \ - "<\1\316\316\316\263\377\377\377\1\376\376\376\202\377\377\377\1xxz\202" \ - "::<\1;;=\202::<\3""99;\234\234\236\376\376\376\236\377\377\377\1\375" \ - "\375\375\202\377\377\377\1\376\376\376\202\377\377\377\5\317\317\317" \ - "99;::<;;=::<\202;;=\2::<\332\332\332\210\377\377\377\3\376\376\376\377" \ - "\377\377\376\376\376\204\377\377\377\2\316\316\316;;=\206::<\3;;=::<" \ - "\250\250\252\217\377\377\377\1\376\376\376\204\377\377\377\2\363\363" \ - "\363\222\222\224\202::<\2;;=::<\202;;=\3""99;;;=kkm\205\377\377\377\1" \ - "\376\376\376\235\377\377\377\1kkm\206::<\1\234\234\236\235\377\377\377" \ - "\1\376\376\376\202\377\377\377\2\266\266\26699;\202::<\3;;=::<;;=\202" \ - "::<\3;;=FFH\234\234\234\202\377\377\377\1\376\376\376\223\377\377\377" \ - "\2\364\364\364\204\204\206\202::<\1;;=\202::<\1;;=\202::<\3""99;``b\376" \ - "\376\376\224\377\377\377\1\234\234\234\206::<\1\316\316\316\252\377\377" \ - "\377\1\316\316\316\206::<\1\234\234\236\213\377\377\377\2\255\333\363" \ - "Y\270\350\211[\267\350\10Y\271\353Z\266\347\\\267\344[\267\346X\267\347" \ - "[\267\350X\270\353Z\266\347\210Y\270\350\10Y\267\352\\\267\346\325\355" \ - "\371\377\377\377\376\377\377\0>g\0\77k\0>i\210\0\77j\10\0>i\3>h\0=i\0" \ - "\77i\0=j\0>g\0=j\0=f\210\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1" \ - "\316\316\316\206::<\1kkm\240\377\377\377\1\234\234\236\206::<\1\234\234" \ - "\236\234\377\377\377\3\376\376\376\377\377\377\376\376\376\202\377\377" \ - "\377\2SSU;;=\202::<\202;;=\3::j\0=i\1>j\210\0>i\10\0\77j\1\77h\0>j\0>g\3>j\0\77i\0=j\0>i\210" \ - "\0=i\3\0>i\0=i\177\236\263\232\377\377\377\1\316\316\316\206::<\1kkm" \ - "\240\377\377\377\1\234\234\236\206::<\1\234\234\236\241\377\377\377\6" \ - "\266\266\270::<;;=::<99;::<\202;;=\205::<\2kkm\376\376\376\240\377\377" \ - "\377\1kkm\206::<\1\316\316\316\265\377\377\377\4\205\205\205;;=::<;;" \ - "=\203::<\3\204\204\206\377\377\377\376\376\376\245\377\377\377\1\265" \ - "\265\267\207::<\2\346\346\346\376\376\376\216\377\377\377\4\376\376\376" \ - "lll::<;;=\202::<\13;;=::<;;=::<;;=::g\1\1>k\220\0=i\15\0>g\1>j\0>" \ - "i\0\77j\1>j\0=i\0\77j\0>j\0=i\199;\203::<\1;;=\202::<\2""99;;;=\203::<\1\204\204\206" \ - "\206\377\377\377\1\376\376\376\221\377\377\377\10\234\234\234;;=::<9" \ - "9;;;=::<99;\316\316\316\252\377\377\377\4\317\317\317;;=88:;;=\202::" \ - "<\3;;=\234\234\234\376\376\376\205\377\377\377\1\377\375\377\202\377" \ - "\377\375\6\377\376\377\377\377\375\253\333\362Y\270\350X\267\347Z\266" \ - "\347\202Y\270\350\1[\267\350\202Z\266\347\2[\267\350Z\266\347\220[\267" \ - "\350\5[\267\352Z\266\351\327\355\372\377\375\376\377\376\377\202\1>j" \ - "\1\1>k\220\0>i\202\0=i\14\0\77k\0>i\0=i\1>j\0=i\0=j\0\77k\0=i\177\236" \ - "\263\377\377\377\376\377\377\375\376\377\224\377\377\377\1\376\376\376" \ - "\202\377\377\377\1\316\316\316\203::<\202;;=\3""99;kkm\376\376\376\234" \ - "\377\377\377\1\376\376\376\202\377\377\377\1\233\233\233\202::<\7;;=" \ - "::<;;=::<\234\234\236\377\377\377\376\376\376\233\377\377\377\3\376\376" \ - "\376\377\377\377\376\376\376\202\377\377\377\4\221\221\221;;=99;;;=\202" \ - "::<\202;;=\203::<\1SSU\203\377\377\377\1\376\376\376\233\377\377\377" \ - "\10\376\376\376\377\377\377\376\376\376kkm::<;;=::<;;=\202::<\1;;=\202" \ - "::<\1;;=\240::<\1kkk\207\377\377\377\1\376\376\376\203\377\377\377\3" \ - "\375\375\375\377\377\377\376\376\376\202\377\377\377\2\233\233\235::" \ - "<\202;;=\203::<\1xxz\251\377\377\377\1\235\235\237\202::<\1;;=\203::" \ - "<\3GGI\363\363\363\376\376\376\217\377\377\377\2\363\363\363yyy\204:" \ - ":<\1;;=\203::<\1;;=\206::<\1""99;\203::<\1;;=\203::<\6;;=99;;;=::<;;" \ - "=99;\202;;=\3""99;GGI\301\301\301\206\377\377\377\1\376\376\376\232\377" \ - "\377\377\1\376\376\376\204\377\377\377\1lln\202::<\1;;=\202::<\2;;=\234" \ - "\234\236\241\377\377\377\1\376\376\376\202\377\377\377\2\332\332\334" \ - "__a\211::<\1;;=\205::<\1;;=\202::<\1;;=\202::<\4;;=::<99;;;=\202::<\1" \ - ";;=\202::<\1;;=\203::<\2FFH\265\265\267\206\377\377\377\3\376\376\376" \ - "\377\377\377\376\376\376\220\377\377\377\3\234\234\236::<;;=\203::<\2" \ - ";;=\316\316\316\252\377\377\377\2\315\315\31599;\203::<\5;;=::<\234\234" \ - "\234\377\377\377\376\376\376\205\377\377\377\7\377\377\375\375\377\376" \ - "\377\377\377\375\376\377\255\333\365Z\266\345[\267\350\202Y\270\350\1" \ - "X\267\347\202Y\267\352\3Z\266\351Z\266\347Y\270\350\221[\267\350\2[\267" \ - "\352\323\355\372\202\376\377\377\1\0=j\222\0=i\204\0>i\14\1\77h\0>g\0" \ - "=f\1>j\0\77i\0>i\177\237\266\377\377\375\377\376\375\377\377\377\376" \ - "\377\377\377\376\377\225\377\377\377\2\316\316\316::<\202;;=\202::<\4" \ - ";;=kkm\377\377\377\376\376\376\235\377\377\377\2\376\376\376\235\235" \ - "\235\202::<\1;;=\202::<\2;;=\234\234\236\242\377\377\377\3\346\346\346" \ - "::<;;=\210::<\2\235\235\237\376\376\376\234\377\377\377\1\376\376\376" \ - "\204\377\377\377\1lln\202::<\3;;=::<;;=\203::<\2;;=99;\240::<\1kkk\210" \ - "\377\377\377\11\376\376\376\377\377\377\376\376\376\377\377\377\376\376" \ - "\376\377\377\377\376\376\376\364\364\366GGI\205::<\6;;=\316\316\316\377" \ - "\377\377\376\376\376\377\377\377\376\376\376\245\377\377\377\11\345\345" \ - "\345;;=::<;;=::<;;=::<;;=\234\234\236\222\377\377\377\7\234\234\234;" \ - ";=::<;;=99;;;=99;\203::<\1;;=\202::<\203;;=\2::<;;=\202::<\1;;=\202:" \ - ":<\1;;=\202::<\12;;=::<;;=99;::<``b\332\332\332\376\376\376\377\377\377" \ - "\376\376\376\202\377\377\377\5\376\376\376\377\377\377\376\376\376\377" \ - "\377\377\376\376\376\232\377\377\377\5\376\376\376\377\377\377\376\376" \ - "\376kkm;;=\202::<\1;;=\202::<\1\234\234\236\236\377\377\377\1\376\376" \ - "\376\207\377\377\377\2\234\234\236;;=\202::<\1;;=\204::<\1;;=\211::<" \ - "\1;;=\202::<\1;;=\202::<\1;;=\202::<\1;;=\203::<\3;;=kkm\346\346\346" \ - "\203\377\377\377\1\376\376\376\204\377\377\377\1\376\376\376\221\377" \ - "\377\377\2\234\234\236;;=\202::<\1;;=\202::<\1\316\316\316\252\377\377" \ - "\377\4\316\316\316;;=99;;;=\203::<\1\234\234\234\210\377\377\377\7\376" \ - "\377\377\377\375\376\377\377\375\256\332\363Y\270\350Y\267\352[\267\352" \ - "\202[\267\350\5X\270\350X\270\352Y\267\352Y\270\350X\267\347\220[\267" \ - "\350\5X\267\347[\267\350\325\355\367\377\377\373\377\377\375\202\0\77" \ - "j\1\0>g\220\0>i\1\0\77j\203\0>i\202\0=i\6\1>j\0>i\0\77h\0>g\177\236\263" \ - "\377\377\375\203\377\377\377\1\377\376\377\222\377\377\377\1\376\376" \ - "\376\202\377\377\377\1\316\316\316\203::<\1;;=\202::<\2kkm\376\376\376" \ - "\233\377\377\377\1\376\376\376\203\377\377\377\5\234\234\234::<;;=::" \ - "<;;=\202::<\1\234\234\236\235\377\377\377\202\376\376\376\202\377\377" \ - "\377\5\376\376\376\377\377\377xxz99;;;=\204::<\4;;=::<;;=\362\362\362" \ - "\237\377\377\377\5\376\376\376\377\377\377\376\376\376kkm;;=\207::<\2" \ - "99;;;=\240::<\1lll\205\377\377\377\1\376\376\376\203\377\377\377\1\376" \ - "\376\376\202\377\377\377\1\376\376\376\202\377\377\377\4\265\265\267" \ - ";;=::<;;=\202::<\2;;=__a\205\377\377\377\1\376\376\376\245\377\377\377" \ - "\3\204\204\206::<;;=\204::<\2SSU\376\376\376\215\377\377\377\1\376\376" \ - "\376\204\377\377\377\2\316\316\316__a\206::<\1;;=\214::<\5;;=::<;;=:" \ - ":<;;=\203::<\2\234\234\234\363\363\363\204\377\377\377\1\376\376\376" \ - "\243\377\377\377\1lln\206::<\2\233\233\235\376\376\376\233\377\377\377" \ - "\1\376\376\376\202\377\377\377\1\376\376\376\207\377\377\377\3\345\345" \ - "\345lln;;=\204::<\5;;=99;::<99;;;=\205::<\1;;=\203::<\3""99;;;=99;\206" \ - "::<\2TTV\265\265\265\234\377\377\377\10\234\234\234;;=::<;;=::<;;=::" \ - "<\316\316\316\252\377\377\377\1\315\315\315\206::<\4\235\235\235\376" \ - "\376\376\377\377\377\376\376\376\205\377\377\377\12\377\377\373\377\377" \ - "\377\377\377\375\267\340\366[\270\344Z\266\351[\267\352Z\266\351[\265" \ - "\347[\267\350\202Y\270\350\2\\\270\351Z\266\347\220[\267\350\10X\267" \ - "\347X\266\351\325\355\371\377\376\377\377\377\377\0\77k\0=h\3>j\220\0" \ - "\77j\16\1>j\0=i\1>j\0=i\0\77j\0>i\0=h\0\77j\0\77h\1g\0\77h\221\0=i\1\0>g\202\1\77h\1\0=i\202\0>i\11\0\77j\0>g\0>" \ - "j\0\77m\336\347\354\376\377\377\377\376\377\376\377\377\377\377\375\222" \ - "\377\377\377\1\376\376\376\203\377\377\377\1\316\316\316\202::<\1;;=" \ - "\203::<\2kkm\376\376\376\233\377\377\377\1\376\376\376\202\377\377\377" \ - "\3\376\376\376\234\234\234;;=\202::<\6""99;::<;;=\234\234\236\377\377" \ - "\377\376\376\376\237\377\377\377\1\376\376\376\202\377\377\377\1SSS\202" \ - ";;=\1""99;\204;;=\3\331\331\331\377\377\377\376\376\376\234\377\377\377" \ - "\3\376\376\376\377\377\377\376\376\376\202\377\377\377\3lll::<;;=\202" \ - "::<\202;;=\203::<\1;;=\240::<\1kkk\204\377\377\377\1\376\376\376\211" \ - "\377\377\377\3\302\302\302;;;999\202::<\3;;=::g\0" \ - "\77m\220\0=i\6\0\77j\0>i\0=h\0\77j\0=i\0\77j\202\0>g\2\1\77h\240\266" \ - "\304\204\377\377\377\2\376\376\376\377\377\375\223\377\377\377\14\376" \ - "\376\376\377\377\377\315\315\315;;=::<:::;;;:::;;;kkk\377\377\377\376" \ - "\376\376\233\377\377\377\1\376\376\376\202\377\377\377\10\235\235\235" \ - "99;::<999;;;:::;;;\233\233\233\234\377\377\377\1\376\376\376\207\377" \ - "\377\377\1\265\265\265\202::<\1;;=\203::<\1kkk\203\377\377\377\1\376" \ - "\376\376\240\377\377\377\2kkk:::\202::<\3;;=99;;;=\244::<\1kkk\205\377" \ - "\377\377\1\376\376\376\210\377\377\377\1\346\346\346\206\316\316\316" \ - "\3\332\332\332\377\377\377\377\377\375\253\377\377\377\2\346\346\346" \ - "\316\316\316\202\316\316\320\203\316\316\316\1\315\315\315\225\377\377" \ - "\377\202\376\376\376\202\377\377\377\4\316\316\320\234\234\236kkmSSU" \ - "\205::<\1;;=\203::<\5kkm\204\204\206\264\264\266\346\346\350\376\376" \ - "\376\214\377\377\377\1\376\376\376\202\377\377\377\202\376\376\376\231" \ - "\377\377\377\1\376\376\376\203\377\377\377\2\331\331\331\317\317\317" \ - "\205\316\316\316\1\347\347\347\243\377\377\377\1\376\376\376\211\377" \ - "\377\377\5\376\376\377\347\347\351\265\265\267\204\204\206lln\212::<" \ - "\4``bxxz\234\234\236\332\332\332\207\377\377\377\1\376\376\376\210\377" \ - "\377\377\1\376\376\376\222\377\377\377\1\346\346\346\203\316\316\320" \ - "\4\316\316\316\316\316\320\315\315\315\364\364\364\251\377\377\377\2" \ - "\376\376\376\364\364\364\205\316\316\316\2\316\316\320\346\346\346\210" \ - "\377\377\377\16\377\376\377\377\377\375\376\377\377\377\377\377\377\375" \ - "\377\326\354\371\241\326\366\206\310\352\200\312\357\202\312\362\204" \ - "\310\357\204\312\356\203\311\355\205\311\360\220\204\312\356\10\203\311" \ - "\355\201\311\361\342\360\371\376\377\377\377\377\375>n\222Bm\215@n\220" \ - "\220@n\217\3@l\217An\217Bo\220\202An\217\5@m\214Dm\213l\223\260\277\320" \ - "\332\376\377\377\202\377\377\377\1\377\377\375\202\377\377\377\1\376" \ - "\377\377\225\377\377\377\3\363\363\363\317\317\321\316\316\320\204\316" \ - "\316\316\1\332\332\332\240\377\377\377\1\346\346\346\202\316\316\320" \ - "\204\316\316\316\1\347\347\347\243\377\377\377\3\376\376\376\363\363" \ - "\363lln\202kkm\1lln\202kkm\1\301\301\301\240\377\377\377\1\376\376\376" \ - "\203\377\377\377\2\331\331\331\317\317\317\202\316\316\316\202\317\317" \ - "\317\245\316\316\316\2\332\332\332\376\376\376\351\377\377\377\5\332" \ - "\332\332\315\315\315\316\316\316\315\315\315\363\363\363\361\377\377" \ - "\377\202\316\316\316\1\317\317\317\202\316\316\316\2\315\315\315\363" \ - "\363\363\377\377\377\377\377\377\377\377\377\377\377\377\334\377\377" \ - "\377\1\376\376\376\375\377\377\377\1\376\376\376\377\377\377\377\377" \ - "\377\377\377\377\377\377\377\340\377\377\377\1\376\376\376\370\377\377" \ - "\377\1\376\376\376\377\377\377\377\377\377\377\377\377\377\377\377\342" \ - "\377\377\377\1\376\376\376\377\377\377\377\377\377\377\377\377\377\377" \ - "\377\377\377\377\377\334\377\377\377\1\376\376\376\362\377\377\377\1" \ - "\376\376\376\377\377\377\377\377\377\377\377\377\377\377\377\346\377" \ - "\377\377\1\376\376\376\363\377\377\377\1\376\376\376\377\377\377\377" \ - "\377\377\377\377\377\377\377\377\342\377\377\377\1\376\376\376\373\377" \ - "\377\377\1\376\376\376\377\377\377\377\377\377\377\377\377\377\377\377" \ - "\340\377\377\377\3\376\376\376\377\377\377\376\376\376\377\377\377\377" \ - "\377\377\377\377\377\377\377\377\377\377\377\377\243\377\377\377\3\376" \ - "\376\376\377\377\377\376\376\376\203\377\377\377\1\376\376\376\233\377" \ - "\377\377\1\376\376\376\205\377\377\377\1\376\376\376\214\377\377\377" \ - "\1\376\376\376\205\377\377\377\1\376\376\376\260\377\377\377\3\376\376" \ - "\376\377\377\377\376\376\376\300\377\377\377\1\376\376\376\306\377\377" \ - "\377\1\376\376\376\233\377\377\377\4\376\377\377\376\376\376\377\376" \ - "\377\377\377\377\203\376\377\375\203\377\377\377\3\377\377\375\376\377" \ - "\375\376\377\377\265\377\377\377\4\377\377\375\377\376\377\376\377\377" \ - "\377\377\375\202\377\376\377\210\377\377\377\7\377\377\375\376\377\377" \ - "\377\377\377\375\377\376\376\377\377\377\376\377\376\377\377\211\377" \ - "\377\377\4\376\377\375\377\377\377\376\376\376\377\377\375\202\377\377" \ - "\377\2\377\377\375\376\376\376\220\377\377\377\1\376\377\375\202\377" \ - "\377\375\5\377\376\377\377\377\373\377\377\377\375\377\376\377\377\375" \ - "\210\377\377\377\1\377\376\377\202\377\377\375\202\377\377\377\3\376" \ - "\377\377\377\377\375\377\376\377\213\377\377\377\3\376\377\377\376\377" \ - "\375\377\377\375\203\377\377\377\203\376\377\375\4\377\377\377\377\376" \ - "\377\376\376\376\376\377\377\233\377\377\377\3\376\377\377\376\377\375" \ - "\377\377\375\203\377\377\377\203\376\377\375\4\377\377\377\377\376\377" \ - "\376\376\376\376\377\377\210\377\377\377\1\377\376\377\203\377\377\377" \ - "\4\376\377\377\377\377\375\377\376\377\376\377\373\211\377\377\377\4" \ - "\376\377\377\376\376\374\377\376\377\377\375\376\226\377\377\377\5\376" \ - "\377\377\375\377\374\377\377\375\376\375\377\377\377\375\210\377\377" \ - "\377\1\377\377\375\202\376\377\377\1\377\377\373\242\377\377\377\1\376" \ - "\376\376\212\377\377\377\1\376\376\376\207\377\377\377\1\376\376\376" \ - "\237\377\377\377\1\376\376\376\203\377\377\377\1\376\376\376\214\377" \ - "\377\377\1\376\376\376\204\377\377\377\202\376\376\376\257\377\377\377" \ - "\1\376\376\376\202\377\377\377\1\376\376\376\202\377\377\377\1\376\376" \ - "\376\246\377\377\377\1\376\376\376\224\377\377\377\1\376\376\376\250" \ - "\377\377\377\1\376\376\376\202\377\377\377\1\376\376\376\236\377\377" \ - "\377\3\376\376\376\377\377\377\376\376\376\230\377\377\377\4\377\377" \ - "\373\376\377\377\376\376\376\377\376\377\203\377\377\377\1\377\377\375" \ - "\202\377\377\377\1\377\376\377\202\377\377\375\3\377\377\377\377\377" \ - "\375\376\376\374\260\377\377\377\2\377\377\375\376\376\376\203\377\376" \ - "\377\214\377\377\377\7\376\377\377\377\376\377\377\377\375\377\377\377" \ - "\377\376\377\375\377\376\377\377\375\210\377\377\377\7\377\376\374\377" \ - "\377\375\377\376\377\377\377\375\376\376\376\377\377\377\376\376\376" \ - "\221\377\377\377\1\377\376\377\203\377\377\377\202\377\377\375\212\377" \ - "\377\377\2\377\377\375\377\377\377\202\377\377\375\214\377\377\377\3" \ - "\376\376\374\377\377\375\377\377\377\202\377\377\375\1\377\376\377\202" \ - "\377\377\377\1\377\377\375\203\377\377\377\4\377\376\377\376\376\376" \ - "\376\377\377\377\377\373\230\377\377\377\3\376\376\374\377\377\375\377" \ - "\377\377\202\377\377\375\1\377\376\377\202\377\377\377\1\377\377\375" \ - "\203\377\377\377\4\377\376\377\376\376\376\376\377\377\377\377\373\213" \ - "\377\377\377\1\377\376\374\214\377\377\377\2\377\377\375\377\376\377" \ - "\202\377\377\375\3\376\377\377\377\377\377\377\377\373\221\377\377\377" \ - "\3\376\377\375\376\377\377\377\376\377\204\377\377\377\1\377\377\375" \ - "\212\377\377\377\5\377\376\377\377\377\375\377\377\377\376\377\375\376" \ - "\377\373\243\377\377\377\1\376\376\376\205\377\377\377\1\376\376\376" \ - "\204\377\377\377\1\376\376\376\242\377\377\377\1\376\376\376\205\377" \ - "\377\377\1\376\376\376\213\377\377\377\1\376\376\376\206\377\377\377" \ - "\1\376\376\376\263\377\377\377\3\376\376\376\377\377\377\376\376\376" \ - "\270\377\377\377\1\376\376\376\312\377\377\377\1\376\376\376\234\377" \ - "\377\377\1\377\377\375\202\376\377\377\7\377\376\377\377\377\377\376" \ - "\377\377\377\376\377\377\377\375\377\377\377\376\377\377\202\377\376" \ - "\377\2\376\377\375\376\377\377\262\377\377\377\10\377\377\375\376\377" \ - "\377\377\376\377\377\377\373\377\377\377\377\376\377\376\377\375\377" \ - "\377\375\211\377\377\377\3\376\377\377\377\376\377\377\377\375\202\377" \ - "\377\377\2\376\377\377\376\376\376\210\377\377\377\202\377\376\377\4" \ - "\374\377\377\376\377\377\377\376\377\377\377\375\222\377\377\377\4\377" \ - "\376\375\376\377\377\377\377\377\376\377\377\202\377\376\377\202\377" \ - "\377\375\210\377\377\377\4\377\377\375\377\377\377\377\377\375\377\377" \ - "\377\202\377\376\377\2\377\377\377\376\377\377\212\377\377\377\2\376" \ - "\377\377\376\377\375\202\377\376\377\7\376\377\377\377\377\377\377\377" \ - "\375\377\376\377\376\377\377\377\377\377\377\376\377\202\376\377\377" \ - "\1\377\377\375\232\377\377\377\2\376\377\377\376\377\375\202\377\376" \ - "\377\7\376\377\377\377\377\377\377\377\375\377\376\377\376\377\377\377" \ - "\377\377\377\376\377\202\376\377\377\1\377\377\375\210\377\377\377\1" \ - "\377\377\375\202\377\377\377\4\377\377\375\377\376\377\377\377\377\376" \ - "\377\377\211\377\377\377\7\375\376\377\377\377\375\377\376\377\376\376" \ - "\377\376\377\375\375\377\376\377\377\375\222\377\377\377\6\376\377\377" \ - "\377\376\377\377\377\377\377\377\375\377\376\377\376\377\377\213\377" \ - "\377\377\202\377\376\377\3\377\377\375\376\377\377\376\377\375\236\377" \ - "\377\377\1\376\376\376\203\377\377\377\1\376\376\376\202\377\377\377" \ - "\1\376\376\376\203\377\377\377\2\376\376\376\377\377\377\202\376\376" \ - "\376\202\377\377\377\1\376\376\376\202\377\377\377\1\376\376\376\204" \ - "\377\377\377\1\376\376\376\235\377\377\377\1\376\376\376\217\377\377" \ - "\377\1\376\376\376\206\377\377\377\1\376\376\376\260\377\377\377\3\376" \ - "\376\376\377\377\377\376\376\376\241\377\377\377\202\376\376\376\204" \ - "\377\377\377\1\376\376\376\222\377\377\377\1\376\376\376\205\377\377" \ - "\377\1\376\376\376\246\377\377\377\1\376\376\376\233\377\377\377\3\376" \ - "\376\376\377\377\377\376\376\376\234\377\377\377\15\376\376\376\377\377" \ - "\377\377\376\377\377\377\375\375\377\376\377\377\377\376\377\375\377" \ - "\377\377\375\376\377\377\377\377\377\377\375\376\377\377\377\377\377" \ - "\202\377\376\377\260\377\377\377\7\377\376\377\376\377\377\377\377\377" \ - "\376\377\377\377\377\377\377\377\375\376\377\377\212\377\377\377\1\376" \ - "\376\374\203\377\377\377\3\376\376\377\377\377\375\376\377\377\210\377" \ - "\377\377\10\376\377\377\377\376\377\374\377\373\376\377\373\377\376\377" \ - "\376\376\376\377\377\377\376\377\375\220\377\377\377\2\377\376\377\377" \ - "\377\377\202\377\377\375\202\377\377\377\2\376\376\374\376\377\377\210" \ - "\377\377\377\1\376\377\377\202\377\377\377\5\376\377\377\377\377\377" \ - "\376\376\376\377\377\377\376\377\375\210\377\377\377\202\377\376\377" \ - "\15\377\377\377\376\377\377\377\377\375\377\377\377\375\376\377\377\377" \ - "\377\376\377\375\377\377\377\375\377\376\377\377\375\377\376\377\377" \ - "\377\377\376\376\376\231\377\377\377\202\377\376\377\15\377\377\377\376" \ - "\377\377\377\377\375\377\377\377\375\376\377\377\377\377\376\377\375" \ - "\377\377\377\375\377\376\377\377\375\377\376\377\377\377\377\376\376" \ - "\376\211\377\377\377\4\377\376\377\377\377\377\376\377\375\376\377\377" \ - "\202\377\377\377\2\376\377\377\376\377\375\210\377\377\377\1\376\377" \ - "\375\202\376\376\376\202\377\377\377\2\377\377\375\375\376\377\221\377" \ - "\377\377\10\377\377\375\377\377\377\376\376\374\376\377\373\376\376\376" \ - "\377\376\377\376\377\377\377\377\375\210\377\377\377\6\376\376\376\377" \ - "\377\377\377\377\375\377\377\377\374\375\377\377\377\375\242\377\377" \ - "\377\1\376\376\376\214\377\377\377\1\376\376\376\204\377\377\377\3\376" \ - "\376\376\377\377\377\376\376\376\235\377\377\377\1\376\376\376\203\377" \ - "\377\377\202\376\376\376\212\377\377\377\1\376\376\376\202\377\377\377" \ - "\202\376\376\376\264\377\377\377\5\376\376\376\377\377\377\376\376\376" \ - "\377\377\377\376\376\376\242\377\377\377\3\376\376\376\377\377\377\376" \ - "\376\376\202\377\377\377\1\376\376\376\223\377\377\377\1\376\376\376" \ - "\244\377\377\377\1\376\376\376\203\377\377\377\1\376\376\376\233\377" \ - "\377\377\1\376\376\376\202\377\377\377\1\376\376\376\234\377\377\377" \ - "\1\375\377\372\202\377\377\377\3\376\376\376\377\377\375\377\377\377" \ - "\202\376\377\377\204\377\377\377\4\376\377\377\377\377\377\377\376\377" \ - "\375\377\372\260\377\377\377\202\377\377\375\2\377\377\377\376\375\377" \ - "\202\377\377\377\1\375\377\376\212\377\377\377\6\377\377\375\377\377" \ - "\377\376\377\375\377\377\375\377\376\377\377\376\375\212\377\377\377" \ - "\1\377\376\377\202\377\377\377\4\377\375\376\377\377\377\377\377\373" \ - "\376\375\377\221\377\377\377\203\376\376\376\4\377\377\375\376\376\374" \ - "\377\376\377\376\376\374\210\377\377\377\5\377\376\377\377\377\375\377" \ - "\376\377\376\376\376\376\377\375\202\377\377\377\1\376\376\376\210\377" \ - "\377\377\4\375\377\372\377\376\377\377\377\377\376\377\377\204\377\377" \ - "\377\202\376\377\377\3\377\377\377\377\377\375\376\376\376\202\377\377" \ - "\377\1\375\377\372\230\377\377\377\4\375\377\372\377\376\377\377\377" \ - "\377\376\377\377\204\377\377\377\202\376\377\377\3\377\377\377\377\377" \ - "\375\376\376\376\202\377\377\377\1\375\377\372\210\377\377\377\3\376" \ - "\377\377\377\377\377\376\376\376\202\376\377\377\202\377\377\377\1\376" \ - "\377\375\210\377\377\377\7\376\376\377\377\377\375\376\377\375\376\376" \ - "\376\377\376\377\377\377\377\376\377\377\221\377\377\377\5\376\376\376" \ - "\376\377\377\377\377\377\375\375\375\377\376\377\202\377\377\377\1\377" \ - "\377\375\211\377\377\377\7\377\376\377\376\376\374\376\377\377\377\377" \ - "\377\377\376\377\377\377\375\377\377\373\233\377\377\377\1\376\376\376" \ - "\205\377\377\377\1\376\376\376\203\377\377\377\1\376\376\376\203\377" \ - "\377\377\1\376\376\376\204\377\377\377\3\376\376\376\377\377\377\376" \ - "\376\376\204\377\377\377\1\376\376\376\237\377\377\377\1\376\376\376" \ - "\212\377\377\377\1\376\376\376\213\377\377\377\1\376\376\376\255\377" \ - "\377\377\1\376\376\376\247\377\377\377\1\376\376\376\202\377\377\377" \ - "\1\376\376\376\224\377\377\377\1\376\376\376\247\377\377\377\1\376\376" \ - "\376\236\377\377\377\1\376\376\376\203\377\377\377\1\376\376\376\232" \ - "\377\377\377\10\377\376\377\377\377\375\377\377\377\376\377\377\376\376" \ - "\376\377\376\377\377\377\375\377\376\377\202\377\377\375\1\377\376\377" \ - "\202\377\377\377\3\377\376\377\377\375\376\377\376\377\260\377\377\377" \ - "\2\377\376\377\377\377\377\202\377\376\377\4\377\377\375\376\376\374" \ - "\377\375\377\377\376\377\210\377\377\377\3\376\376\374\377\376\377\376" \ - "\376\376\204\377\377\377\1\376\377\375\210\377\377\377\4\375\377\374" \ - "\377\377\377\377\375\376\377\376\377\203\377\377\377\1\377\377\375\220" \ - "\377\377\377\3\376\377\377\377\377\375\376\377\377\202\377\377\377\3" \ - "\377\376\377\373\377\377\376\377\377\211\377\377\377\202\376\377\375" \ - "\1\377\377\375\203\377\377\377\1\377\376\377\210\377\377\377\3\377\376" \ - "\377\377\375\376\377\376\377\202\377\377\377\1\377\376\377\202\377\377" \ - "\375\10\377\376\377\377\377\375\377\376\377\376\376\376\376\377\377\377" \ - "\377\377\377\377\375\377\376\377\230\377\377\377\3\377\376\377\377\375" \ - "\376\377\376\377\202\377\377\377\1\377\376\377\202\377\377\375\10\377" \ - "\376\377\377\377\375\377\376\377\376\376\376\376\377\377\377\377\377" \ - "\377\377\375\377\376\377\210\377\377\377\2\377\377\375\375\376\371\202" \ - "\377\376\377\3\377\377\377\377\377\375\377\376\377\212\377\377\377\1" \ - "\377\375\376\202\377\377\377\4\377\377\375\376\376\376\376\377\377\377" \ - "\376\377\220\377\377\377\2\376\377\377\376\376\377\202\377\377\377\2" \ - "\376\377\375\375\377\374\212\377\377\377\10\373\377\376\377\377\377\377" \ - "\377\375\376\376\374\377\377\375\377\376\377\377\377\377\376\377\377" \ - "\235\377\377\377\1\376\376\376\202\377\377\377\7\316\316\320\250\250" \ - "\252\221\221\223llnjjlGGI99;\204::<\7TTVkkmyy{\234\234\236\265\265\267" \ - "\332\332\332\376\376\376\237\377\377\377\3\376\376\376\377\377\377\376" \ - "\376\376\222\377\377\377\1\376\376\376\205\377\377\377\3\376\376\376" \ - "\377\377\377\376\376\376\255\377\377\377\1\376\376\376\246\377\377\377" \ - "\1\376\376\376\227\377\377\377\1\376\376\376\252\377\377\377\1\376\376" \ - "\376\233\377\377\377\1\376\376\376\236\377\377\377\17\305\344\240\303" \ - "\342\237\304\343\240\304\343\237\307\342\237\303\342\236\305\342\240" \ - "\303\342\236\305\342\237\304\343\240\304\343\237\304\341\237\304\343" \ - "\237\323\352\266\376\377\375\250\377\377\377\210\305\342\240\10\305\342" \ - "\237\303\342\234\304\343\237\306\341\236\304\343\240\322\352\270\376" \ - "\377\377\375\377\376\211\377\377\377\5\377\376\377\376\376\376\377\376" \ - "\377\360\371\350\305\342\237\202\304\341\236\210\305\342\240\5\304\341" \ - "\236\327\356\302\376\377\377\377\377\373\376\377\375\202\377\377\375" \ - "\1\377\376\377\220\377\377\377\202\377\377\375\2\376\377\377\377\377" \ - "\377\202\377\377\375\2\304\343\237\306\341\236\210\305\342\240\5\307" \ - "\342\237\303\342\236\304\341\236\341\357\314\377\377\375\213\377\377" \ - "\377\17\376\377\375\323\352\266\304\343\237\304\341\237\304\343\237\304" \ - "\343\240\305\342\237\303\342\236\305\342\240\303\342\236\307\342\237" \ - "\304\343\237\304\343\240\303\342\237\305\344\240\231\377\377\377\17\376" \ - "\377\375\323\352\266\304\343\237\304\341\237\304\343\237\304\343\240" \ - "\305\342\237\303\342\236\305\342\240\303\342\236\307\342\237\304\343" \ - "\237\304\343\240\303\342\237\305\344\240\211\377\377\377\10\360\367\347" \ - "\306\343\241\303\342\237\307\342\237\303\342\237\304\343\235\307\341" \ - "\240\304\343\240\210\305\342\240\7\315\347\252\376\377\375\377\375\376" \ - "\376\377\375\377\377\377\377\377\373\376\377\377\221\377\377\377\10\377" \ - "\377\375\376\377\375\323\352\266\307\341\240\307\342\237\305\342\240" \ - "\307\340\236\306\341\236\210\305\342\240\4\304\343\237\311\335\236\377" \ - "\377\377\377\376\377\203\377\377\377\1\376\377\377\230\377\377\377\1" \ - "\376\376\376\203\377\377\377\3\346\346\346\251\251\251jjl\202;;=\210" \ - "::<\1;;=\202::<\2;;=99;\203::<\5FFHxxx\265\265\265\363\363\363\376\376" \ - "\376\234\377\377\377\2\376\376\376\346\346\346\214\234\234\234\1\235" \ - "\235\235\203\234\234\234\3\235\235\235\234\234\234\250\250\250\203\316" \ - "\316\316\1\346\346\346\263\377\377\377\202\250\250\250\245\377\377\377" \ - "\1\316\316\316\222\234\234\234\1\302\302\302\203\316\316\316\1\363\363" \ - "\363\247\377\377\377\3\316\316\316\234\234\234\235\235\235\240\234\234" \ - "\234\1\316\316\316\231\377\377\377\6\215\305>\216\306A\215\305@\213\310" \ - "=\215\305>\212\307>\202\214\305@\6\214\306>\212\306@\214\306<\215\304" \ - "B\214\306>\252\323m\251\377\377\377\210\214\306>\10\215\305@\215\307" \ - "\77\212\307>\217\304@\214\305@\251\323m\377\377\377\377\377\375\213\377" \ - "\377\377\5\377\375\377\341\363\315\215\305>\212\307>\215\305@\210\214" \ - "\306>\6\215\306A\220\305\77\350\365\333\377\377\377\376\377\377\377\376" \ - "\377\202\376\377\377\225\377\377\377\3\377\376\377\214\306>\215\306A" \ - "\210\214\306>\6\215\305>\212\310\77\215\305@\307\341\240\376\377\377" \ - "\377\376\377\213\377\377\377\6\252\323m\214\306>\215\304B\214\306<\212" \ - "\306@\214\306>\202\214\305@\6\212\307>\215\305>\213\310=\215\305@\216" \ - "\306A\215\305>\232\377\377\377\6\252\323m\214\306>\215\304B\214\306<" \ - "\212\306@\214\306>\202\214\305@\6\212\307>\215\305>\213\310=\215\305" \ - "@\216\306A\215\305>\211\377\377\377\4\376\377\377\242\321a\213\307A\215" \ - "\305>\202\214\306>\2\215\305@\215\307\77\210\214\306>\7\215\305<\332" \ - "\354\304\377\377\377\376\377\375\376\376\376\377\376\377\376\376\376" \ - "\221\377\377\377\10\377\376\377\342\362\316\215\305>\213\310\77\212\305" \ - "D\212\307<\216\306\77\211\307>\211\214\306>\4\304\343\240\373\377\376" \ - "\377\377\377\375\377\376\202\377\377\377\1\377\377\375\225\377\377\377" \ - "\1\376\376\376\204\377\377\377\6\265\265\267__a99;;;=::<;;=\202::<\1" \ - ";;=\202::<\1;;=\202::<\1;;=\203::<\1;;=\203::<\3;;=::<99;\202::<\2xx" \ - "z\301\301\301\202\377\377\377\1\376\376\376\202\377\377\377\1\376\376" \ - "\376\206\377\377\377\1\376\376\376\217\377\377\377\1\316\316\316\205" \ - "::<\202;;=\221::<\4TTVwwy\250\250\252\346\346\350\255\377\377\377\1\316" \ - "\316\320\202::<\1\316\316\316\244\377\377\377\1\234\234\236\204::<\1" \ - ";;=\205::<\3;;=::<;;=\206::<\1;;=\204::<\6SSUkkm\204\204\206\250\250" \ - "\250\316\316\316\376\376\376\206\377\377\377\1\376\376\376\231\377\377" \ - "\377\1\234\234\234\206::<\3;;=::<;;=\222::<\1;;=\204::<\3;;=::<\234\234" \ - "\236\231\377\377\377\3\214\305@\214\306>\214\305@\207\214\306>\4\214" \ - "\305@\215\305>\214\306>\252\324p\251\377\377\377\215\214\306>\1\250\325" \ - "p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\210\214\306>" \ - "\15\212\306@\215\307\77\233\316W\365\374\364\377\376\375\376\377\377" \ - "\377\376\377\377\377\375\377\377\377\377\377\375\376\376\376\377\377" \ - "\377\376\376\374\202\377\377\377\1\376\376\376\216\377\377\377\213\214" \ - "\306>\3\215\305>\214\306>\305\342\240\215\377\377\377\4\252\324p\214" \ - "\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\232" \ - "\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3\214" \ - "\305@\214\306>\214\305@\212\377\377\377\7\350\364\334\215\305>\212\307" \ - "<\214\305@\215\304B\215\305@\213\310\77\210\214\306>\10\214\305@\225" \ - "\311J\370\373\362\377\376\377\376\377\377\377\377\375\377\377\377\376" \ - "\377\377\210\377\377\377\40\376\377\377\376\377\375\377\376\377\377\377" \ - "\377\375\376\377\377\377\375\377\376\377\376\377\377\370\373\364\233" \ - "\314W\215\307\77\214\304=\212\306@\215\307\77\213\305=\215\307\77\214" \ - "\306>\217\304@\215\306A\212\307>\214\306<\215\306A\214\306>\211\307@" \ - "\242\321a\377\377\377\377\376\377\376\377\377\377\376\377\377\377\377" \ - "\376\377\377\377\376\377\223\377\377\377\7\376\376\376\377\377\377\376" \ - "\376\376\377\377\377\363\363\365\234\234\236FFH\202::<\10;;=99;;;=::" \ - "<;;=::<99;;;=\203::<\1;;=\203::<\2;;=99;\204::<\11""99;;;=::<;;=::<;" \ - ";=TTV\265\265\265\363\363\363\203\377\377\377\1\376\376\376\207\377\377" \ - "\377\1\376\376\376\215\377\377\377\1\316\316\316\205::<\3;;=::<;;=\202" \ - "::<\1;;=\214::<\3;;=99;;;=\202::<\4lln\316\316\316\376\376\376\377\377" \ - "\377\202\376\376\376\246\377\377\377\2\376\376\376xxz\202::<\2xxx\376" \ - "\376\376\243\377\377\377\1\234\234\236\204::<\202;;=\205::<\1;;=\204" \ - "::<\1;;=\202::<\1""99;\206::<\1;;=\202::<\6;;=kkk\250\250\250\346\346" \ - "\346\377\377\377\376\376\376\205\377\377\377\1\376\376\376\225\377\377" \ - "\377\1\234\234\234\204::<\1;;=\202::<\4;;=::<99;;;=\225::<\3;;=::<\234" \ - "\234\236\231\377\377\377\3\214\305@\214\306>\214\305@\207\214\306>\4" \ - "\214\305@\215\305>\214\306>\252\324p\251\377\377\377\215\214\306>\1\250" \ - "\325p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\210\214\306" \ - ">\4\215\306A\213\304\77\215\305@\262\327x\202\377\377\377\1\376\377\375" \ - "\203\377\377\375\204\377\377\377\1\376\376\376\217\377\377\377\213\214" \ - "\306>\3\215\305>\214\306>\305\342\240\215\377\377\377\4\252\324p\214" \ - "\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\232" \ - "\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3\214" \ - "\305@\214\306>\214\305@\212\377\377\377\7\376\376\376\305\342\237\212" \ - "\307>\214\306>\212\307<\214\306>\212\307>\210\214\306>\3\214\306<\215" \ - "\306A\300\337\221\202\377\377\377\3\377\376\377\376\376\376\377\377\375" \ - "\210\377\377\377\1\377\375\377\202\377\377\377\2\376\376\377\376\377" \ - "\375\202\377\376\377\30\377\377\377\277\340\221\215\306A\213\305=\215" \ - "\305>\212\306B\214\306>\216\306\77\214\306<\212\307>\215\307=\213\305" \ - ";\215\307\77\216\305C\214\306>\214\305@\216\306\77\347\365\333\377\376" \ - "\377\377\377\375\376\377\377\377\376\374\377\377\377\377\377\375\222" \ - "\377\377\377\1\376\376\376\204\377\377\377\12\265\265\267FFH;;=::<;;" \ - "=99;::<;;=::<;;=\202::<\4<<>99;::<;;=\202::<\1;;=\203::<\1<<>\204::<" \ - "\5<<>99;;;=99;;;=\202::<\4:::SSS\266\266\266\376\376\376\203\377\377" \ - "\377\1\376\376\376\204\377\377\377\1\376\376\376\216\377\377\377\1\316" \ - "\316\316\204::<\3;;=::<;;=\204::<\1;;=\214::<\1;;=\202::<\1;;=\202::" \ - "<\2yyy\363\363\363\202\377\377\377\1\376\376\376\245\377\377\377\3\346" \ - "\346\346::<;;=\202::<\1\347\347\347\202\377\377\377\1\376\376\376\240" \ - "\377\377\377\1\234\234\236\203::<\4;;=99;::<;;=\202::<\7;;=::<;;=99;" \ - ";;=::<;;=\203::<\202;;=\210::<\1""99;\202::<\4;;=xxz\317\317\317\376" \ - "\376\376\202\377\377\377\1\376\376\376\227\377\377\377\1\234\234\234" \ - "\204::<\1""99;\203;;=\224::<\1;;=\204::<\2<<>\234\234\236\231\377\377" \ - "\377\3\214\305@\214\306>\214\305@\207\214\306>\4\214\305@\215\305>\214" \ - "\306>\252\324p\251\377\377\377\215\214\306>\1\250\325p\216\377\377\377" \ - "\1\342\361\320\202\214\306>\1\214\305@\210\214\306>\10\215\305>\214\306" \ - ">\213\307A\214\306>\315\345\253\377\377\375\377\376\377\376\377\377\226" \ - "\377\377\377\213\214\306>\3\215\305>\214\306>\305\342\240\215\377\377" \ - "\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3\214\305@\214" \ - "\306>\214\305@\232\377\377\377\4\252\324p\214\306>\215\305>\214\305@" \ - "\207\214\306>\3\214\305@\214\306>\214\305@\211\377\377\377\7\377\377" \ - "\375\377\376\377\376\376\376\241\321a\212\307>\211\305\77\215\306A\211" \ - "\214\306>\4\213\310\77\214\305@\213\305=\342\361\320\202\377\376\377" \ - "\2\377\377\375\377\376\377\210\377\377\377\1\377\376\377\202\377\377" \ - "\377\30\377\377\375\376\377\377\377\377\375\376\377\377\351\366\334\214" \ - "\305B\211\306;\215\307\77\214\306>\212\306@\215\305>\215\305@\212\307" \ - ">\214\305@\212\306B\214\306>\213\305=\213\310\77\215\305>\215\307\77" \ - "\314\345\253\377\375\377\377\376\374\376\377\377\203\377\377\377\1\377" \ - "\376\374\225\377\377\377\2\345\345\345kkm\205::<\202;;=\203::<\1;;=\203" \ - "::<\1;;=\202::<\202;;=\202::<\1;;=\210::<\2;;=99;\205::<\2```\331\331" \ - "\331\211\377\377\377\1\376\376\376\214\377\377\377\1\316\316\316\206" \ - "::<\5""99;::<;;=::<99;\212::<\1;;=\202::<\1;;=\204::<\4;;=::\214\305@" \ - "\207\214\306>\4\214\305@\215\305>\214\306>\252\324p\251\377\377\377\215" \ - "\214\306>\1\250\325p\216\377\377\377\1\342\361\320\202\214\306>\1\214" \ - "\305@\210\214\306>\10\215\305@\212\307>\214\305@\215\306A\214\305@\352" \ - "\364\334\376\376\377\377\377\373\202\377\377\377\3\376\376\376\377\377" \ - "\377\377\377\375\202\377\377\377\1\376\376\374\216\377\377\377\213\214" \ - "\306>\3\215\305>\214\306>\305\342\240\215\377\377\377\4\252\324p\214" \ - "\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\232" \ - "\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3\214" \ - "\305@\214\306>\214\305@\211\377\377\377\1\376\377\377\202\377\377\375" \ - "\5\347\364\332\215\307\77\215\306C\214\307;\216\306\77\210\214\306>\10" \ - "\214\305@\214\305D\215\307\77\233\314V\371\374\363\376\377\377\377\377" \ - "\377\377\377\375\210\377\377\377\20\375\377\374\377\376\377\376\376\377" \ - "\376\377\377\377\376\377\376\377\375\376\377\377\244\317d\212\307>\215" \ - "\306A\215\305@\214\305@\211\306=\215\307=\215\306A\214\305@\204\214\306" \ - ">\14\211\305A\212\307>\251\324k\377\376\377\377\375\376\376\377\377\377" \ - "\377\377\377\377\375\377\377\377\377\377\375\377\377\377\377\377\375" \ - "\217\377\377\377\1\376\376\376\203\377\377\377\2\265\265\267FFH\205:" \ - ":<\1;;=\203::<\202;;=\7:::TTT\203\203\203\235\235\235\316\316\316\332" \ - "\332\332\377\377\377\202\376\376\376\202\377\377\377\5\316\316\316\317" \ - "\317\317\234\234\234yyyFFF\202::<\1;;=\202::<\3""99;;;=99;\204::<\2;" \ - ";=\233\233\233\206\377\377\377\1\376\376\376\216\377\377\377\1\316\316" \ - "\316\204::<\1;;=\205::<\1;;=\212::<\3""99;::<;;=\202::<\2;;=99;\204:" \ - ":<\2;;=\265\265\265\245\377\377\377\4\346\346\346::<99;;;=\202::<\4""9" \ - "9;\347\347\347\377\377\377\376\376\376\240\377\377\377\1\234\234\236" \ - "\205::<\1;;=\203::<\202;;=\1""99;\203;;=\2::<;;=\203::<\1;;=\202::<\2" \ - ";;=::<\202;;=\7::<;;=99;::<;;=99;;;=\202::<\3;;=xxx\362\362\362\227\377" \ - "\377\377\1\234\234\234\205::<\202;;=\4::<;;=::<;;=\223::<\2;;=99;\202" \ - ";;=\1\234\234\236\231\377\377\377\3\214\305@\214\306>\214\305@\207\214" \ - "\306>\4\214\305@\215\305>\214\306>\252\324p\251\377\377\377\215\214\306" \ - ">\1\250\325p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\210" \ - "\214\306>\12\212\307>\215\306A\214\305@\215\307\77\213\306:\226\312N" \ - "\372\374\361\375\376\377\377\377\375\377\377\373\224\377\377\377\213" \ - "\214\306>\3\215\305>\214\306>\305\342\240\215\377\377\377\4\252\324p" \ - "\214\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305" \ - "@\232\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>" \ - "\3\214\305@\214\306>\214\305@\211\377\377\377\10\376\377\377\376\376" \ - "\377\376\377\377\377\375\376\307\342\237\214\306<\215\306A\214\305@\210" \ - "\214\306>\5\215\307\77\213\305=\216\306A\213\310\77\277\337\223\202\377" \ - "\377\375\1\377\376\377\210\377\377\377\14\376\377\375\376\376\376\377" \ - "\376\377\377\377\375\377\376\377\377\377\377\303\342\236\215\307\77\216" \ - "\306A\215\305>\214\306<\215\306A\203\214\306>\20\215\307\77\212\307>" \ - "\215\305@\216\306\77\214\305@\216\307<\223\312K\356\372\346\377\377\377" \ - "\376\377\377\375\377\376\377\377\377\377\376\377\377\377\375\377\377" \ - "\377\377\377\375\216\377\377\377\1\376\376\376\203\377\377\377\2\375" \ - "\375\375\205\205\207\202::<\202;;=\3::<;;=::<\202;;=\6::<:::SSS\250\250" \ - "\250\346\346\346\376\376\376\216\377\377\377\3\332\332\332\220\220\220" \ - "SSS\202::<\4;;=99;::<;;=\202::<\1""99;\202;;=\2__a\332\332\334\223\377" \ - "\377\377\1\316\316\316\204::<\6;;=RRT\235\235\237\235\235\235\233\233" \ - "\233\234\234\234\212\234\234\236\5xxzkkm__a99;;;=\204::<\202;;=\1""9" \ - "9;\202::<\1\316\316\316\244\377\377\377\4\204\204\206;;=::<;;=\202::" \ - "<\2;;=\220\220\222\203\377\377\377\1\376\376\376\236\377\377\377\1\234" \ - "\234\236\203::<\3;;=::\214\305" \ - "@\207\214\306>\4\214\305@\215\305>\214\306>\252\324p\251\377\377\377" \ - "\215\214\306>\1\250\325p\216\377\377\377\1\342\361\320\202\214\306>\1" \ - "\214\305@\210\214\306>\7\212\306@\214\306<\217\307@\214\304\77\214\311" \ - ">\214\306>\251\323m\202\376\377\377\4\376\376\374\377\377\375\377\377" \ - "\377\376\376\376\202\377\377\377\1\376\376\376\216\377\377\377\213\214" \ - "\306>\3\215\305>\214\306>\305\342\240\215\377\377\377\4\252\324p\214" \ - "\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\232" \ - "\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3\214" \ - "\305@\214\306>\214\305@\212\377\377\377\7\377\377\375\377\376\377\376" \ - "\377\377\377\376\377\251\323o\211\307>\214\305@\210\214\306>\7\212\307" \ - ">\215\305>\214\305@\214\306>\215\307\77\347\365\334\377\376\377\211\377" \ - "\377\377\2\377\376\377\375\377\374\203\377\376\377\15\352\364\333\212" \ - "\306@\215\306A\214\306>\215\307\77\213\310\77\214\306>\216\306A\215\306" \ - "A\214\306<\212\307>\213\310=\212\307>\202\214\305@\4\214\306>\314\345" \ - "\253\377\376\377\376\377\377\202\377\377\375\6\377\376\377\375\376\377" \ - "\377\377\377\377\376\377\376\377\375\377\376\377\217\377\377\377\3\376" \ - "\376\376\362\362\362lln\20299;\1;;=\204::<\202;;=\6::<\204\204\204\317" \ - "\317\317\376\376\376\377\377\377\376\376\376\206\377\377\377\1\376\376" \ - "\376\213\377\377\377\2\301\301\301kkm\211::<\6;;=FFH\301\301\301\376" \ - "\376\376\377\377\377\376\376\376\217\377\377\377\1\316\316\316\204::" \ - "<\3;;=kkm\376\376\376\221\377\377\377\3\316\316\316\204\204\204FFF\202" \ - "::<\1;;=\202::<\202;;=\2FFH\363\363\363\242\377\377\377\5\364\364\364" \ - "::<;;=99;;;=\203::<\3GGI\363\363\363\376\376\376\240\377\377\377\1\234" \ - "\234\236\205::<\1\234\234\236\210\377\377\377\1\376\376\376\204\377\377" \ - "\377\1\376\376\376\202\377\377\377\6\362\362\362\316\316\316\265\265" \ - "\265\234\234\234kkmFFH\202::<\2;;=99;\205::<\1;;=\202::<\1\221\221\221" \ - "\225\377\377\377\1\234\234\234\205::<\1\234\234\236\202\377\377\377\1" \ - "\376\376\376\225\377\377\377\1\375\375\375\235\377\377\377\3\214\305" \ - "@\214\306>\214\305@\207\214\306>\4\214\305@\215\305>\214\306>\252\324" \ - "p\251\377\377\377\215\214\306>\1\250\325p\216\377\377\377\1\342\361\320" \ - "\202\214\306>\1\214\305@\210\214\306>\4\215\307\77\214\306>\214\304\77" \ - "\214\306>\202\214\305@\6\215\307\77\307\341\240\376\377\375\376\377\377" \ - "\376\376\374\377\377\373\202\377\377\377\202\377\377\375\216\377\377" \ - "\377\213\214\306>\3\215\305>\214\306>\305\342\240\215\377\377\377\4\252" \ - "\324p\214\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214" \ - "\305@\232\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306" \ - ">\3\214\305@\214\306>\214\305@\212\377\377\377\7\377\376\377\376\376" \ - "\377\377\377\377\376\376\377\361\372\347\222\312K\215\305>\210\214\306" \ - ">\10\214\305@\215\306A\214\305@\214\306<\213\304A\243\322b\376\376\374" \ - "\376\377\375\211\377\377\377\24\377\377\373\377\377\377\376\377\377\377" \ - "\377\375\242\320c\215\307=\214\306>\213\310\77\213\304A\212\306@\215" \ - "\307\77\215\305@\214\306>\215\307\77\212\306@\215\305>\215\307\77\213" \ - "\310\77\213\306:\253\325q\202\377\377\377\11\377\377\375\377\376\377" \ - "\377\377\377\377\377\375\376\377\375\377\377\375\377\375\377\376\377" \ - "\377\377\377\375\214\377\377\377\7\376\376\376\377\377\377\376\376\376" \ - "\363\363\363__a::<;;=\203::<\202;;=\202::<\4xxz\347\347\351\377\377\377" \ - "\376\376\376\210\377\377\377\1\376\376\376\204\377\377\377\2\376\376" \ - "\376\377\377\377\203\376\376\376\205\377\377\377\2\316\316\320kkm\202" \ - "::<\3;;=::<;;=\202::<\202;;=\2:::\250\250\250\202\377\377\377\1\376\376" \ - "\376\216\377\377\377\1\316\316\316\205::<\1kkm\203\377\377\377\1\376" \ - "\376\376\215\377\377\377\1\376\376\376\202\377\377\377\3\363\363\363" \ - "xxx::<\202;;=\203::<\2;;=xxz\242\377\377\377\1\234\234\234\202::<\1;" \ - ";=\202::<\1;;=\202::<\1\234\234\234\241\377\377\377\1\234\234\236\202" \ - "::<\10;;=::<;;=\234\234\236\377\377\377\376\376\376\377\377\377\376\376" \ - "\376\216\377\377\377\1\376\376\376\203\377\377\377\3\332\332\332\221" \ - "\221\223FFH\205::<\2;;=::<\202;;=\2::<\204\204\204\224\377\377\377\1" \ - "\234\234\234\205::<\3\234\234\236\377\377\377\376\376\376\264\377\377" \ - "\377\3\214\305@\214\306>\214\305@\207\214\306>\4\214\305@\215\305>\214" \ - "\306>\252\324p\251\377\377\377\215\214\306>\1\250\325p\216\377\377\377" \ - "\1\342\361\320\202\214\306>\1\214\305@\210\214\306>\5\216\306\77\212" \ - "\307>\215\307=\212\306@\214\306>\202\215\305>\5\215\305@\345\356\317" \ - "\376\377\375\376\377\377\377\377\375\202\377\377\377\1\377\377\375\217" \ - "\377\377\377\213\214\306>\3\215\305>\214\306>\305\342\240\215\377\377" \ - "\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3\214\305@\214" \ - "\306>\214\305@\232\377\377\377\4\252\324p\214\306>\215\305>\214\305@" \ - "\207\214\306>\3\214\305@\214\306>\214\305@\211\377\377\377\4\376\377" \ - "\377\377\377\377\377\377\375\376\377\377\202\377\377\377\2\315\347\252" \ - "\212\306@\210\214\306>\10\216\306A\212\306@\212\307>\215\305<\213\310" \ - "\77\215\305>\307\341\240\376\377\377\212\377\377\377\10\375\377\374\377" \ - "\377\377\305\342\237\215\305@\212\306@\216\306\77\215\307=\215\305>\202" \ - "\214\306>\24\213\307A\213\310=\215\304B\214\306>\212\306@\215\304B\212" \ - "\307>\225\311K\370\373\362\377\377\377\376\377\375\377\377\375\377\377" \ - "\377\374\377\375\376\376\376\377\377\377\377\377\375\377\376\377\376" \ - "\377\377\377\377\375\211\377\377\377\1\376\376\376\205\377\377\377\1" \ - "___\204::<\1;;=\203::<\2SSS\316\316\316\235\377\377\377\2\317\317\317" \ - "``b\207::<\3;;=::<\204\204\206\220\377\377\377\1\316\316\316\205::<\1" \ - "kkm\226\377\377\377\3\204\204\206::<;;=\205::<\1\316\316\316\232\377" \ - "\377\377\1\376\376\376\205\377\377\377\2\364\364\364FFF\202;;=\202::" \ - "<\6;;=99;;;=::\214\305@\207\214\306>\4\214\305@\215" \ - "\305>\214\306>\252\324p\251\377\377\377\215\214\306>\1\250\325p\216\377" \ - "\377\377\1\342\361\320\202\214\306>\1\214\305@\220\214\306>\2\222\313" \ - "J\366\373\364\202\377\376\377\4\377\377\373\376\376\374\376\377\377\377" \ - "\376\377\216\377\377\377\213\214\306>\3\215\305>\214\306>\305\342\240" \ - "\215\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3" \ - "\214\305@\214\306>\214\305@\232\377\377\377\4\252\324p\214\306>\215\305" \ - ">\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\211\377\377\377" \ - "-\377\377\375\376\377\377\377\377\377\376\376\374\376\377\377\377\376" \ - "\377\376\377\377\252\324p\212\306@\215\305>\212\307<\215\305@\215\305" \ - "<\214\305B\215\305@\214\306<\212\307>\215\305>\214\306>\211\306=\215" \ - "\305>\212\307>\214\306<\350\364\334\374\377\377\377\376\377\376\376\376" \ - "\374\377\375\377\377\377\376\377\375\377\377\375\377\376\377\377\377" \ - "\375\377\377\377\377\376\377\357\367\350\223\312K\213\310\77\215\305" \ - ">\214\306>\215\305>\213\310\77\212\306@\214\306>\215\305@\202\214\306" \ - ">\10\214\305@\216\306=\212\307>\215\305>\333\355\303\376\376\374\377" \ - "\377\377\377\377\375\223\377\377\377\1\376\376\376\203\377\377\377\1" \ - "\203\203\203\206::<\4;;=::<\204\204\206\363\363\363\230\377\377\377\1" \ - "\376\376\376\207\377\377\377\1\235\235\237\202::<\1;;=\203::<\5;;=99" \ - ";;;=\204\204\204\376\376\376\216\377\377\377\1\316\316\316\205::<\1k" \ - "km\227\377\377\377\12\204\204\206::<;;=::<99;;;=::<\204\204\204\377\377" \ - "\377\376\376\376\232\377\377\377\1\376\376\376\203\377\377\377\2\234" \ - "\234\234;;=\203::<\1;;=\204::<\3<<>\250\250\250\376\376\376\237\377\377" \ - "\377\1\234\234\236\205::<\1\234\234\234\231\377\377\377\10\376\376\376" \ - "\377\377\377\265\265\265FFH::<;;=::<;;=\203::<\2;;=\204\204\204\222\377" \ - "\377\377\1\234\234\234\205::<\1\234\234\236\266\377\377\377\3\214\305" \ - "@\214\306>\214\305@\207\214\306>\4\214\305@\215\305>\214\306>\252\324" \ - "p\251\377\377\377\215\214\306>\1\250\325p\216\377\377\377\1\342\361\320" \ - "\202\214\306>\1\214\305@\220\214\306>\4\216\306\77\250\322n\376\377\375" \ - "\376\377\373\222\377\377\377\213\214\306>\3\215\305>\214\306>\305\342" \ - "\240\215\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306" \ - ">\3\214\305@\214\306>\214\305@\232\377\377\377\4\252\324p\214\306>\215" \ - "\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\211\377\377" \ - "\377\13\376\376\377\376\377\377\377\376\377\376\376\374\374\377\377\377" \ - "\377\375\377\376\377\356\372\346\225\311K\214\306>\213\310=\203\214\306" \ - ">\2\213\310\77\214\306>\202\214\305@\7\214\306<\213\307A\214\304\77\214" \ - "\305B\212\307>\244\317d\377\376\377\202\377\377\377\1\377\375\377\202" \ - "\377\377\377\25\376\377\377\377\376\377\377\377\377\374\377\375\376\376" \ - "\374\253\324n\214\306<\215\307\77\215\305>\211\307@\216\305C\214\305" \ - "@\215\307\77\214\305@\214\306<\212\307<\211\306=\214\306>\214\305@\213" \ - "\307A\263\327}\202\376\377\377\3\377\377\377\377\375\376\377\377\375" \ - "\221\377\377\377\1\376\376\376\203\377\377\377\1\250\250\250\204::<\1" \ - ";;=\202::<\2;;=\264\264\264\202\377\377\377\1\376\376\376\232\377\377" \ - "\377\1\376\376\376\205\377\377\377\2\332\332\332SSS\202::<\1;;=\204:" \ - ":<\4xxx\364\364\364\377\377\377\376\376\376\214\377\377\377\1\316\316" \ - "\316\205::<\1kkm\227\377\377\377\2\363\363\363SSU\202::<\4;;=99;::<;" \ - ";;\202\377\377\377\1\376\376\376\226\377\377\377\1\376\376\376\204\377" \ - "\377\377\11\376\376\376\363\363\363FFH99;;;=::<;;=99;;;=\203::<\4""9" \ - "9;SSU\377\377\377\376\376\376\236\377\377\377\1\234\234\236\205::<\1" \ - "\234\234\234\225\377\377\377\1\376\376\376\204\377\377\377\10\376\376" \ - "\376\377\377\377\363\363\363yyy::<;;=99;;;=\204::<\1\266\266\266\221" \ - "\377\377\377\1\234\234\234\205::<\1\234\234\236\266\377\377\377\3\214" \ - "\305@\214\306>\214\305@\207\214\306>\4\214\305@\215\305>\214\306>\252" \ - "\324p\251\377\377\377\215\214\306>\1\250\325p\216\377\377\377\1\342\361" \ - "\320\202\214\306>\1\214\305@\220\214\306>\4\214\306<\213\307A\275\335" \ - "\222\376\377\377\203\377\377\377\1\377\377\375\216\377\377\377\213\214" \ - "\306>\3\215\305>\214\306>\305\342\240\215\377\377\377\4\252\324p\214" \ - "\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\232" \ - "\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3\214" \ - "\305@\214\306>\214\305@\211\377\377\377\4\377\376\377\376\376\377\377" \ - "\377\377\377\377\375\202\376\377\377\5\377\375\376\377\376\377\315\346" \ - "\255\212\307>\214\305@\202\215\306A\22\214\305@\212\307<\214\305B\214" \ - "\306>\213\307A\214\306>\213\305=\214\306>\215\305>\213\307A\211\310<" \ - "\313\347\254\377\377\375\377\375\377\376\377\377\376\377\373\376\377" \ - "\377\377\376\377\202\376\377\377\10\377\377\377\315\346\254\212\307>" \ - "\212\306@\215\306A\216\306A\212\307>\214\306<\202\215\306A\10\215\306" \ - "C\214\305B\215\307\77\214\306<\214\305@\213\310<\222\310L\372\373\363" \ - "\225\377\377\377\1\376\376\376\202\377\377\377\6\376\376\376\333\333" \ - "\333::<;;=::<;;=\202::<\3;;=FFH\315\315\315\205\377\377\377\1\376\376" \ - "\376\225\377\377\377\202\376\376\376\202\377\377\377\1\376\376\376\202" \ - "\377\377\377\1\376\376\376\202\377\377\377\2\363\363\363xxx\204::<\2" \ - ";;=\203\203\203\220\377\377\377\1\316\316\316\205::<\1kkm\230\377\377" \ - "\377\3\266\266\27099;;;=\204::<\1\316\316\316\230\377\377\377\1\376\376" \ - "\376\202\377\377\377\1\376\376\376\202\377\377\377\3\265\265\267::<;" \ - ";=\204::<\202;;=\202::<\202;;=\1\265\265\265\237\377\377\377\1\234\234" \ - "\236\205::<\1\234\234\234\236\377\377\377\5\234\234\234::<;;=::<;;=\202" \ - "::<\3;;=FFH\332\332\332\220\377\377\377\1\234\234\234\205::<\1\234\234" \ - "\236\266\377\377\377\3\214\305@\214\306>\214\305@\207\214\306>\4\214" \ - "\305@\215\305>\214\306>\252\324p\251\377\377\377\215\214\306>\1\250\325" \ - "p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\220\214\306>" \ - "\4\215\307\77\214\304\77\213\310\77\333\355\303\202\377\377\377\1\376" \ - "\377\375\217\377\377\377\213\214\306>\3\215\305>\214\306>\305\342\240" \ - "\215\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3" \ - "\214\305@\214\306>\214\305@\232\377\377\377\4\252\324p\214\306>\215\305" \ - ">\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\213\377\377\377" \ - "\5\377\377\373\377\376\377\377\377\377\375\377\374\376\377\377\202\376" \ - "\376\376\22\260\331{\212\307>\214\306>\215\305>\215\305@\215\307\77\215" \ - "\307=\214\305@\214\306>\215\306A\214\306>\213\307C\214\306>\214\304;" \ - "\213\307A\222\312K\357\370\345\377\377\375\202\377\377\377\15\377\375" \ - "\376\377\377\375\376\376\376\377\377\375\361\367\351\222\311J\213\310" \ - "\77\214\305B\215\310<\213\305=\216\306\77\212\307<\214\305B\202\214\306" \ - ">\6\216\306\77\215\305@\215\306A\214\305@\215\305<\333\356\301\202\377" \ - "\376\377\3\377\377\375\377\377\377\377\376\377\225\377\377\377\1``b\202" \ - "::<\6;;=::<;;=::\214\305@\207\214\306>\4\214\305@\215" \ - "\305>\214\306>\252\324p\251\377\377\377\215\214\306>\1\250\325p\216\377" \ - "\377\377\1\342\361\320\202\214\306>\1\214\305@\220\214\306>\10\216\306" \ - "\77\215\306A\214\305@\224\310J\360\371\350\377\377\377\377\376\377\376" \ - "\377\377\216\377\377\377\213\214\306>\3\215\305>\214\306>\305\342\240" \ - "\215\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3" \ - "\214\305@\214\306>\214\305@\232\377\377\377\4\252\324p\214\306>\215\305" \ - ">\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\212\377\377\377" \ - "\1\377\377\375\202\377\377\377\2\377\376\377\377\377\377\202\376\377" \ - "\377\25\377\377\375\370\373\362\223\312K\212\307>\215\305>\216\306A\212" \ - "\307<\214\305B\215\307\77\214\305@\214\306>\214\305@\212\306@\215\307" \ - "=\216\306A\215\305>\214\306<\252\324n\376\377\377\376\376\376\377\376" \ - "\377\202\377\377\375\4\377\376\377\376\376\377\252\324n\215\306A\202" \ - "\214\306>\21\214\305@\215\307\77\215\305>\212\307>\214\306<\213\304A" \ - "\215\307=\214\304=\215\307\77\212\307>\214\306>\277\337\226\377\376\377" \ - "\376\377\375\377\377\375\377\377\377\376\376\376\225\377\377\377\3\234" \ - "\234\236::<;;=\204::<\4;;=\265\265\267\377\377\377\376\376\376\204\377" \ - "\377\377\202\376\376\376\202\377\377\377\1\376\376\376\225\377\377\377" \ - "\1\376\376\376\203\377\377\377\1\376\376\376\202\377\377\377\1\376\376" \ - "\376\202\377\377\377\3\250\250\250::<\204\204\206\205\377\377\377\1\376" \ - "\376\376\214\377\377\377\1\316\316\316\205::<\1kkm\226\377\377\377\1" \ - "\376\376\376\202\377\377\377\2kkm99;\202::<\4;;=::<\204\204\206\376\376" \ - "\376\202\377\377\377\1\376\376\376\224\377\377\377\1\376\376\376\203" \ - "\377\377\377\2\376\376\376\265\265\265\202::<\1;;=\202::<\3;;=\316\316" \ - "\320\316\316\316\204::<\3;;=::<\266\266\266\236\377\377\377\1\234\234" \ - "\236\205::<\1\234\234\234\226\377\377\377\202\376\376\376\2\377\377\377" \ - "\376\376\376\205\377\377\377\4\376\376\376\251\251\253;;=99;\202::<\4" \ - "<<>99;::<\250\250\252\217\377\377\377\1\234\234\234\205::<\1\234\234" \ - "\236\266\377\377\377\3\214\305@\214\306>\214\305@\207\214\306>\4\214" \ - "\305@\215\305>\214\306>\252\324p\251\377\377\377\215\214\306>\1\250\325" \ - "p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\220\214\306>" \ - "\202\214\305@\6\212\306@\215\307\77\243\321d\377\377\375\377\375\377" \ - "\376\377\377\216\377\377\377\213\214\306>\3\215\305>\214\306>\305\342" \ - "\240\215\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306" \ - ">\3\214\305@\214\306>\214\305@\232\377\377\377\4\252\324p\214\306>\215" \ - "\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\211\377\377" \ - "\377\2\376\377\377\377\377\375\202\377\377\377\1\376\376\376\202\377" \ - "\377\377\6\376\377\372\376\377\377\377\376\377\331\357\301\213\304\77" \ - "\215\307=\202\214\305@\25\214\305B\214\306<\215\305@\212\307<\214\306" \ - ">\216\306=\212\307>\212\306B\214\305@\215\306E\212\306@\313\347\255\376" \ - "\377\375\376\376\377\376\377\377\377\376\377\377\377\377\333\355\305" \ - "\212\307>\216\306\77\215\307\77\202\214\306>\1\215\307\77\202\214\306" \ - ">\13\215\305<\212\306@\212\307<\215\307\77\211\306=\213\307A\233\314" \ - "V\370\373\362\377\377\375\377\377\377\376\377\377\202\377\377\375\2\374" \ - "\377\377\377\375\376\222\377\377\377\3\363\363\363GGI::<\202;;=\202:" \ - ":<\2;;=\234\234\234\214\377\377\377\1\376\376\376\221\377\377\377\1\376" \ - "\376\376\202\377\377\377\3\376\376\376\377\377\377\376\376\376\206\377" \ - "\377\377\3\376\376\376\377\377\377\316\316\316\203\377\377\377\1\376" \ - "\376\376\203\377\377\377\1\376\376\376\213\377\377\377\1\316\316\316" \ - "\205::<\1kkm\227\377\377\377\5\376\376\376\377\377\377\235\235\237::" \ - "<;;=\203::<\2lln\376\376\376\203\377\377\377\1\376\376\376\224\377\377" \ - "\377\13\376\376\376\377\377\377\376\376\376\377\377\377RRR::<99;::<;" \ - ";=::\214\305@\207\214\306" \ - ">\4\214\305@\215\305>\214\306>\252\324p\251\377\377\377\215\214\306>" \ - "\1\250\325p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\221" \ - "\214\306>\5\213\307A\216\306\77\212\307<\214\306>\277\337\223\220\377" \ - "\377\377\213\214\306>\3\215\305>\214\306>\305\342\240\215\377\377\377" \ - "\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306" \ - ">\214\305@\232\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207" \ - "\214\306>\3\214\305@\214\306>\214\305@\211\377\377\377\4\376\377\377" \ - "\377\377\375\377\375\377\377\377\377\202\377\377\375\202\377\376\377" \ - "\202\376\377\377\22\377\376\377\262\331~\213\304\77\213\310\77\216\306" \ - "A\212\307<\215\306A\214\304=\213\310\77\214\305@\215\304B\214\305B\214" \ - "\306<\212\307>\212\307<\216\306A\221\312I\370\373\362\203\377\377\377" \ - "\13\370\373\364\226\310K\214\306>\212\307>\215\304B\214\306>\215\306" \ - "A\213\304\77\215\306A\214\306>\215\305@\202\212\306@\13\215\307\77\213" \ - "\310=\220\303@\336\362\315\377\376\377\377\377\377\374\377\377\377\376" \ - "\377\377\377\377\376\376\374\376\377\375\223\377\377\377\1\204\204\206" \ - "\203::<\4""99;;;=::\214\305@\207\214\306>\4\214\305@\215\305>\214" \ - "\306>\252\324p\251\377\377\377\215\214\306>\1\250\325p\216\377\377\377" \ - "\1\342\361\320\202\214\306>\1\214\305@\220\214\306>\10\215\304B\214\306" \ - "<\214\305@\215\305@\212\306@\215\305>\323\354\265\377\376\377\216\377" \ - "\377\377\213\214\306>\3\215\305>\214\306>\305\342\240\215\377\377\377" \ - "\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306" \ - ">\214\305@\232\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207" \ - "\214\306>\3\214\305@\214\306>\214\305@\212\377\377\377\3\375\377\376" \ - "\377\377\377\377\377\375\202\377\377\377\26\377\377\375\375\377\374\376" \ - "\377\377\377\376\377\377\377\375\365\375\362\225\311K\212\306@\214\306" \ - ">\214\305@\212\306@\216\306=\211\306;\215\306A\214\306>\215\307\77\217" \ - "\304@\214\306>\212\307>\215\305@\214\305@\262\327z\203\377\377\377\13" \ - "\260\331{\213\310\77\214\305B\214\305@\215\305@\215\307\77\212\307<\216" \ - "\306A\213\305;\214\305@\215\305>\202\214\306>\11\215\305@\214\306<\276" \ - "\340\224\377\376\375\377\377\375\376\377\377\377\376\375\376\377\375" \ - "\377\376\377\202\377\377\377\1\376\377\375\221\377\377\377\1\346\346" \ - "\346\206::<\2:::\346\346\346\202\377\377\377\1\376\376\376\276\377\377" \ - "\377\1\316\316\316\205::<\1kkm\216\377\377\377\1\376\376\376\202\377" \ - "\377\377\1\376\376\376\207\377\377\377\3\234\234\236::<;;=\203::<\1k" \ - "km\226\377\377\377\1\376\376\376\204\377\377\377\2\376\376\376lln\205" \ - "::<\1``b\204\377\377\377\1SSS\205::<\1kkm\235\377\377\377\1\234\234\236" \ - "\205::<\1\234\234\234\242\377\377\377\2\316\316\316:::\202::<\5;;=::" \ - "<;;=FFH\363\363\363\206\377\377\377\1\376\376\376\206\377\377\377\1\234" \ - "\234\234\205::<\1\234\234\236\266\377\377\377\3\214\305@\214\306>\214" \ - "\305@\207\214\306>\4\214\305@\215\305>\214\306>\252\324p\251\377\377" \ - "\377\215\214\306>\1\250\325p\216\377\377\377\1\342\361\320\202\214\306" \ - ">\1\214\305@\210\214\306>\27\215\306A\212\307>\215\305>\215\305@\215" \ - "\307=\217\304B\214\306<\214\305@\215\307\77\215\305@\215\307\77\214\305" \ - "@\216\306\77\211\310<\226\312L\347\364\332\377\377\377\377\376\377\377" \ - "\377\375\374\377\377\377\376\377\376\376\376\376\377\377\207\377\377" \ - "\377\213\214\306>\3\215\305>\214\306>\305\342\240\215\377\377\377\4\252" \ - "\324p\214\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214" \ - "\305@\232\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306" \ - ">\3\214\305@\214\306>\214\305@\221\377\377\377\1\377\377\375\203\377" \ - "\377\377\5\333\355\303\214\306>\212\307<\216\306A\214\305@\202\214\306" \ - ">\15\215\305@\214\306>\212\306@\213\310\77\215\305>\216\306A\211\306" \ - "=\212\306@\212\307<\334\354\305\377\377\375\335\354\303\212\307>\210" \ - "\214\306>\10\216\306A\212\307;\215\306A\216\306A\214\305@\241\321a\371" \ - "\374\361\375\376\377\223\377\377\377\1\376\376\376\204\377\377\377\2" \ - "\376\376\376\234\234\234\203::<\1""99;\202::<\1\234\234\234\302\377\377" \ - "\377\1\316\316\316\205::<\1kkm\217\377\377\377\1\376\376\376\202\377" \ - "\377\377\3\376\376\376\377\377\377\376\376\376\202\377\377\377\3\376" \ - "\376\376\377\377\377xxz\202::<\5""99;::<;;=xxz\376\376\377\232\377\377" \ - "\377\3\317\317\31799;;;=\202::<\5;;=::<\265\265\265\377\377\377\376\376" \ - "\376\202\377\377\377\2\265\265\265;;=\202::<\203;;=\1\332\332\332\203" \ - "\377\377\377\1\376\376\376\230\377\377\377\1\234\234\236\205::<\1\234" \ - "\234\234\242\377\377\377\4\376\376\376\204\204\204::<;;=\202::<\3;;=" \ - "::<\266\266\266\207\377\377\377\1\376\376\376\205\377\377\377\1\234\234" \ - "\234\205::<\1\234\234\236\266\377\377\377\3\214\305@\214\306>\214\305" \ - "@\207\214\306>\4\214\305@\215\305>\214\306>\252\324p\251\377\377\377" \ - "\215\214\306>\1\250\325p\216\377\377\377\1\342\361\320\202\214\306>\1" \ - "\214\305@\211\214\306>\27\216\306A\214\306>\212\306@\214\306<\213\310" \ - "\77\215\305@\215\307\77\213\305=\216\306\77\212\307;\212\306@\215\305" \ - ">\215\306A\212\307>\245\320d\367\375\361\376\377\377\377\376\377\377" \ - "\377\377\376\376\377\377\376\377\375\377\376\377\377\375\206\377\377" \ - "\377\213\214\306>\3\215\305>\214\306>\305\342\240\215\377\377\377\4\252" \ - "\324p\214\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214" \ - "\305@\232\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306" \ - ">\3\214\305@\214\306>\214\305@\221\377\377\377\6\376\376\376\377\376" \ - "\377\377\377\377\375\377\376\376\377\377\270\333\207\203\214\306>\17" \ - "\211\306=\212\307<\214\306<\214\305@\215\307\77\214\305@\216\305C\214" \ - "\306>\212\310A\215\305@\216\306\77\223\312K\360\371\346\222\311I\214" \ - "\305@\210\214\306>\10\214\305@\212\307>\214\305@\216\306A\215\307=\350" \ - "\364\334\375\377\376\377\376\377\225\377\377\377\7\376\376\376\377\377" \ - "\377\376\376\376\377\377\377SSS::<;;=\203::<\5FFH\364\364\364\376\376" \ - "\376\377\377\377\376\376\376\277\377\377\377\1\316\316\316\205::<\1k" \ - "km\222\377\377\377\1\376\376\376\204\377\377\377\3\376\376\376\377\377" \ - "\377SSU\205::<\1\234\234\236\202\377\377\377\1\376\376\376\202\377\377" \ - "\377\1\376\376\376\220\377\377\377\1\376\376\376\204\377\377\377\2kk" \ - "m;;=\202::<\5;;=::\214\305@\207\214\306>\4\214\305" \ - "@\215\305>\214\306>\252\324p\251\377\377\377\215\214\306>\1\250\325p" \ - "\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\211\214\306>\27" \ - "\214\304=\215\305>\213\307A\212\306@\214\305B\215\305<\213\310=\215\307" \ - "\77\215\304B\214\306<\213\307A\215\305>\216\306A\212\306@\212\307>\270" \ - "\332\204\377\376\377\377\377\377\377\376\377\376\376\374\377\377\373" \ - "\377\376\377\377\377\375\206\377\377\377\213\214\306>\3\215\305>\214" \ - "\306>\305\342\240\215\377\377\377\4\252\324p\214\306>\215\305>\214\305" \ - "@\207\214\306>\3\214\305@\214\306>\214\305@\232\377\377\377\4\252\324" \ - "p\214\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305" \ - "@\223\377\377\377\1\377\377\375\202\377\377\377\2\371\372\364\232\315" \ - "W\202\214\305@\4\214\306<\215\307\77\214\305B\215\306C\202\215\306A\1" \ - "\214\306<\202\212\307>\6\215\305@\212\307>\215\305>\212\306B\216\306" \ - "A\212\307>\210\214\306>\10\214\305B\215\307\77\214\306<\214\306>\304" \ - "\341\237\377\377\377\377\376\377\377\377\375\220\377\377\377\1\376\376" \ - "\376\203\377\377\377\1\376\376\376\203\377\377\377\10\301\301\301::<" \ - ";;=99;;;=::<99;\234\234\236\207\377\377\377\1\376\376\376\273\377\377" \ - "\377\1\316\316\316\205::<\1kkm\216\377\377\377\1\376\376\376\202\377" \ - "\377\377\1\376\376\376\204\377\377\377\3\376\376\376\377\377\377\315" \ - "\315\315\202;;=\203::<\6;;=\265\265\267\377\377\377\376\376\376\377\377" \ - "\377\376\376\376\225\377\377\377\2\376\376\376\317\317\317\203::<\4;" \ - ";=::<;;=\264\264\264\206\377\377\377\10\234\234\234;;=::<;;=99;;;=::" \ - "<\346\346\346\233\377\377\377\1\234\234\236\205::<\1\234\234\234\237" \ - "\377\377\377\1\376\376\376\204\377\377\377\1\204\204\206\202::<\6;;=" \ - "99;;;=::<\346\346\346\376\376\376\204\377\377\377\3\376\376\376\377\377" \ - "\377\376\376\376\204\377\377\377\1\234\234\234\205::<\1\234\234\236\266" \ - "\377\377\377\3\214\305@\214\306>\214\305@\207\214\306>\4\214\305@\215" \ - "\305>\214\306>\252\324p\251\377\377\377\215\214\306>\1\250\325p\216\377" \ - "\377\377\1\342\361\320\202\214\306>\1\214\305@\210\214\306>\22\215\307" \ - "\77\212\307>\216\306A\212\304<\215\307\77\215\305@\216\306\77\213\307" \ - "A\214\306>\214\305@\215\307\77\213\310=\212\307>\214\306>\214\306<\214" \ - "\306>\216\306\77\324\353\267\202\376\376\376\3\377\377\377\376\376\377" \ - "\376\377\375\207\377\377\377\213\214\306>\3\215\305>\214\306>\305\342" \ - "\240\215\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306" \ - ">\3\214\305@\214\306>\214\305@\232\377\377\377\4\252\324p\214\306>\215" \ - "\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\221\377\377" \ - "\377\3\376\377\377\377\377\377\376\377\375\202\377\377\377\7\377\376" \ - "\377\341\363\315\215\305@\214\305@\215\306A\215\305@\216\306\77\202\214" \ - "\306>\12\214\305B\212\307<\213\304A\213\310=\216\306A\211\306;\213\310" \ - "=\214\305@\212\307>\215\305>\210\214\306>\10\215\307\77\214\304=\212" \ - "\307>\243\322b\377\377\377\376\377\377\377\376\377\377\377\375\226\377" \ - "\377\377\4\376\376\376\377\377\377\204\204\206;;=\203::<\3""99;;;=\364" \ - "\364\364\205\377\377\377\1\376\376\376\275\377\377\377\1\316\316\316" \ - "\205::<\1kkm\217\377\377\377\202\376\376\376\202\377\377\377\1\376\376" \ - "\376\203\377\377\377\4\376\376\376xxz;;=99;\202;;=\4::<;;=\346\346\346" \ - "\376\376\376\204\377\377\377\1\376\376\376\224\377\377\377\1xxz\203:" \ - ":<\3;;=::\214\305" \ - "@\207\214\306>\4\214\305@\215\305>\214\306>\252\324p\251\377\377\377" \ - "\215\214\306>\1\250\325p\216\377\377\377\1\342\361\320\202\214\306>\1" \ - "\214\305@\210\214\306>\7\213\305=\214\306<\210\306\77\216\306\77\215" \ - "\307=\214\306>\215\307\77\202\214\306>\14\215\307\77\214\305B\214\306" \ - "<\212\307<\214\305@\216\306\77\215\305>\214\305@\224\313L\352\364\331" \ - "\374\377\377\377\376\377\211\377\377\377\213\214\306>\3\215\305>\214" \ - "\306>\305\342\240\215\377\377\377\4\252\324p\214\306>\215\305>\214\305" \ - "@\207\214\306>\3\214\305@\214\306>\214\305@\232\377\377\377\4\252\324" \ - "p\214\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305" \ - "@\222\377\377\377\1\376\377\377\202\377\377\377\24\376\376\374\376\377" \ - "\375\377\375\377\277\337\224\214\306>\212\307>\215\307\77\214\304=\215" \ - "\307=\213\304A\214\306<\212\307>\215\307\77\214\305@\213\304\77\215\307" \ - "\77\215\305@\214\304=\215\305<\215\306A\210\214\306>\1\212\307>\202\215" \ - "\306A\4\350\365\333\377\375\376\377\376\377\375\376\377\226\377\377\377" \ - "\1\376\376\376\202\377\377\377\3TTV::<99;\202;;=\4::<\203\203\203\377" \ - "\377\377\376\376\376\302\377\377\377\1\316\316\316\205::<\1kkm\222\377" \ - "\377\377\1\376\376\376\204\377\377\377\3\300\300\302;;=::<\202;;=\202" \ - "::<\2```\376\376\376\227\377\377\377\7\376\376\376\377\377\377\346\346" \ - "\346;;=99;::<;;=\202::<\3\251\251\251\377\377\377\376\376\376\206\377" \ - "\377\377\1\234\234\234\202::<\1;;=\202::<\2;;=\346\346\346\232\377\377" \ - "\377\1\234\234\236\205::<\1\234\234\234\235\377\377\377\1\376\376\376" \ - "\207\377\377\377\11SSU::<;;=99;<<>::\214\305@\207\214\306>\4\214\305@\215\305>\214\306>\252" \ - "\324p\251\377\377\377\215\214\306>\1\250\325p\216\377\377\377\1\342\361" \ - "\320\202\214\306>\1\214\305@\210\214\306>\25\213\307A\216\306A\232\315" \ - "W\215\306C\212\306@\214\305@\212\307;\216\306A\215\305>\215\307\77\214" \ - "\305@\215\307\77\214\306>\214\305@\212\306B\213\307C\214\306>\215\305" \ - "@\232\315V\372\374\367\376\376\376\202\377\377\375\1\376\376\376\206" \ - "\377\377\377\213\214\306>\3\215\305>\214\306>\305\342\240\215\377\377" \ - "\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3\214\305@\214" \ - "\306>\214\305@\232\377\377\377\4\252\324p\214\306>\215\305>\214\305@" \ - "\207\214\306>\3\214\305@\214\306>\214\305@\221\377\377\377\5\377\376" \ - "\377\376\377\377\377\375\376\377\376\377\376\377\377\202\377\377\377" \ - "\10\370\373\362\233\314V\213\307A\211\306=\215\307\77\212\307<\212\306" \ - "@\215\305<\202\214\306>\7\215\307=\215\306A\214\305@\212\307>\216\306" \ - "A\212\306@\215\307=\210\214\306>\10\212\307>\212\307<\313\347\254\376" \ - "\377\377\377\377\377\377\376\377\376\377\377\377\377\375\223\377\377" \ - "\377\1\376\376\376\203\377\377\377\1\332\332\332\202::<\1;;=\203::<\1" \ - "\302\302\302\203\377\377\377\5\376\376\376\377\377\377\376\376\376\377" \ - "\377\377\376\376\376\274\377\377\377\1\316\316\316\205::<\1kkm\217\377" \ - "\377\377\1\376\376\376\206\377\377\377\3\332\332\334FFH;;=\205::<\1\265" \ - "\265\265\202\377\377\377\1\376\376\376\224\377\377\377\1\376\376\376" \ - "\202\377\377\377\1\205\205\207\202::<\1;;=\202::<\2GGI\363\363\363\202" \ - "\377\377\377\1\376\376\376\205\377\377\377\1\363\363\363\202::<\1;;=" \ - "\202::<\2""99;\234\234\234\203\377\377\377\1\376\376\376\226\377\377" \ - "\377\1\234\234\236\205::<\1\234\234\234\234\377\377\377\1\376\376\376" \ - "\210\377\377\377\3\222\222\222::<99;\202;;=\5""99;GGI\376\376\376\377" \ - "\377\377\376\376\376\211\377\377\377\1\234\234\234\205::<\1\234\234\236" \ - "\266\377\377\377\3\214\305@\214\306>\214\305@\207\214\306>\4\214\305" \ - "@\215\305>\214\306>\252\324p\251\377\377\377\215\214\306>\1\250\325p" \ - "\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\210\214\306>\10" \ - "\213\307A\214\306>\331\356\303\232\315W\215\305>\215\306A\214\305B\214" \ - "\306>\202\214\305@\7\213\310=\214\306>\215\304B\215\306A\211\306;\213" \ - "\310\77\214\305@\202\215\307\77\2\257\326{\376\377\373\202\377\377\377" \ - "\1\377\377\375\206\377\377\377\213\214\306>\3\215\305>\214\306>\305\342" \ - "\240\215\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306" \ - ">\3\214\305@\214\306>\214\305@\232\377\377\377\4\252\324p\214\306>\215" \ - "\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\221\377\377" \ - "\377\6\377\377\373\377\377\375\377\377\377\376\376\377\377\376\377\373" \ - "\377\374\202\377\376\377\4\336\362\315\220\303@\213\310=\215\307\77\202" \ - "\212\306@\1\215\305@\202\214\306>\7\213\305=\214\306>\213\305=\214\305" \ - "@\213\310\77\212\306@\213\307A\210\214\306>\10\215\307\77\252\324p\377" \ - "\377\375\376\377\377\377\377\375\377\377\377\377\376\377\377\377\375" \ - "\220\377\377\377\1\376\376\376\203\377\377\377\1\376\376\376\202\377" \ - "\377\377\1\265\265\265\204::<\5;;=::<\363\363\363\377\377\377\376\376" \ - "\376\302\377\377\377\1\316\316\316\205::<\1kkm\225\377\377\377\2\317" \ - "\317\317FFH\206::<\1SSU\204\377\377\377\1\376\376\376\225\377\377\377" \ - "\2\346\346\346;;=\203::<\3;;=::<\234\234\236\202\377\377\377\1\376\376" \ - "\376\207\377\377\377\2\204\204\206;;=\204::<\2FFF\362\362\362\231\377" \ - "\377\377\1\234\234\236\205::<\1\234\234\234\245\377\377\377\1\301\301" \ - "\301\202::<\6;;=::<;;=::<\347\347\347\376\376\376\212\377\377\377\1\234" \ - "\234\234\205::<\1\234\234\236\266\377\377\377\3\214\305@\214\306>\214" \ - "\305@\207\214\306>\4\214\305@\215\305>\214\306>\252\324p\251\377\377" \ - "\377\215\214\306>\1\250\325p\216\377\377\377\1\342\361\320\202\214\306" \ - ">\1\214\305@\210\214\306>\27\214\305@\215\305<\342\362\315\353\365\334" \ - "\223\312K\215\305<\212\306@\215\305<\212\307>\215\306A\214\306>\212\307" \ - ">\215\307\77\215\304B\215\307\77\215\305@\214\306>\215\305>\214\305@" \ - "\215\305<\315\345\253\377\377\375\376\377\377\207\377\377\377\213\214" \ - "\306>\3\215\305>\214\306>\305\342\240\215\377\377\377\4\252\324p\214" \ - "\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\232" \ - "\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3\214" \ - "\305@\214\306>\214\305@\221\377\377\377\14\376\377\377\376\376\377\377" \ - "\377\377\377\377\373\376\377\375\377\376\377\376\377\377\377\377\377" \ - "\377\376\375\276\340\224\214\306<\215\305@\202\214\306>\12\215\305>\214" \ - "\305@\215\305@\214\305@\213\310\77\214\306>\216\306\77\211\305\77\215" \ - "\307=\214\305@\210\214\306>\4\223\312K\360\367\347\377\377\377\377\377" \ - "\375\232\377\377\377\2\376\376\376\234\234\236\204::<\2;;=___\234\377" \ - "\377\377\1\376\376\376\203\377\377\377\1\376\376\376\244\377\377\377" \ - "\1\316\316\316\205::<\1kkm\202\377\377\377\1\376\376\376\216\377\377" \ - "\377\4\376\376\376\377\377\377\347\347\347\204\204\204\203::<\6;;=::" \ - "<;;=::<;;=\301\301\303\226\377\377\377\1\376\376\376\203\377\377\377" \ - "\1\203\203\205\202;;=\5::<;;=::\214\305@\207\214\306>\4" \ - "\214\305@\215\305>\214\306>\252\324p\251\377\377\377\215\214\306>\1\250" \ - "\325p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\210\214\306" \ - ">\40\213\307A\215\305>\341\360\317\377\375\376\324\353\267\215\304B\214" \ - "\306>\215\307=\214\305@\212\307>\212\307<\215\305<\215\306A\214\306>" \ - "\214\306<\212\306@\214\305@\215\307\77\216\306=\212\306B\214\306>\352" \ - "\364\333\377\376\377\377\377\377\377\376\377\377\377\377\377\377\375" \ - "\376\377\373\375\376\377\377\376\377\214\306>\215\307\77\211\214\306" \ - ">\3\215\305>\214\306>\305\342\240\215\377\377\377\4\252\324p\214\306" \ - ">\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\232\377" \ - "\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3\214\305" \ - "@\214\306>\214\305@\232\377\377\377\7\374\377\375\242\321a\216\306A\212" \ - "\307>\214\306>\215\307\77\212\307<\210\214\306>\16\215\307\77\214\307" \ - ";\213\304\77\216\306A\214\305B\215\307\77\215\305>\212\307>\320\345\254" \ - "\374\377\377\377\376\377\377\377\375\377\376\377\375\377\372\223\377" \ - "\377\377\1\376\376\376\203\377\377\377\3\376\376\376\377\377\377kkm\203" \ - "::<\3<<>::<\221\221\221\305\377\377\377\1\316\316\316\204::<\2;;=jjl" \ - "\217\377\377\377\16\316\316\316\300\300\300\234\234\234__a::<;;=::<;" \ - ";=::<99;;;=::<;;=\204\204\206\232\377\377\377\1\362\362\362\202;;=\202" \ - "::<\3""99;::<\235\235\235\212\377\377\377\12\376\376\376\377\377\377" \ - "\205\205\20799;;;=::<;;=::\214\305" \ - "@\207\214\306>\4\214\305@\215\305>\214\306>\252\324p\251\377\377\377" \ - "\215\214\306>\1\250\325p\216\377\377\377\1\342\361\320\202\214\306>\1" \ - "\214\305@\210\214\306>\202\214\306<\32\342\361\322\377\377\377\377\377" \ - "\375\266\334\205\212\306B\215\307\77\212\306@\220\306=\214\306>\215\307" \ - "\77\214\305B\213\305=\216\306\77\215\307\77\215\305<\212\306B\215\306" \ - "A\215\305@\216\306=\232\315V\371\373\360\377\377\375\377\377\377\375" \ - "\376\377\377\375\377\376\376\377\202\377\377\377\2\214\305@\212\307>" \ - "\211\214\306>\3\215\305>\214\306>\305\342\240\215\377\377\377\4\252\324" \ - "p\214\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305" \ - "@\232\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>" \ - "\3\214\305@\214\306>\214\305@\233\377\377\377\5\347\365\334\211\306=" \ - "\215\305>\216\306=\214\305@\211\214\306>\2\215\304B\212\307>\202\214" \ - "\306>\14\215\306A\214\306<\215\305@\252\324p\374\377\377\377\377\377" \ - "\377\375\376\377\376\377\376\376\377\377\377\375\377\377\377\377\375" \ - "\377\222\377\377\377\1\376\376\376\203\377\377\377\4\376\376\376lln:" \ - ":<;;=\203::<\2\235\235\235\376\376\376\304\377\377\377\1\316\316\316" \ - "\205::<\202;;=\2::<;;=\202::<\1;;=\211::<\202;;=\204::<\1""99;\202::" \ - "<\5;;=::<;;=__a\376\376\376\224\377\377\377\1\376\376\376\205\377\377" \ - "\377\1\235\235\235\206::<\3\346\346\346\377\377\377\376\376\376\207\377" \ - "\377\377\5\376\376\376\377\377\377\376\376\376\346\346\350;;=\203::<" \ - "\3;;=::<\265\265\265\230\377\377\377\1\234\234\236\205::<\1\234\234\234" \ - "\246\377\377\377\1lln\202::<\4""99;;;=99;\234\234\234\213\377\377\377" \ - "\1\234\234\234\203::<\7;;=::<;;=::<;;=::<;;=\222::<\7;;=99;;;=::<;;=" \ - "::<\316\316\316\231\377\377\377\3\214\305@\214\306>\214\305@\207\214" \ - "\306>\4\214\305@\215\305>\214\306>\252\324p\251\377\377\377\215\214\306" \ - ">\1\250\325p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\210" \ - "\214\306>\13\216\306A\213\310\77\343\361\320\377\377\375\375\377\376" \ - "\371\374\361\242\320c\213\310\77\216\306\77\214\306>\215\306A\202\214" \ - "\305@\2\216\306A\213\305=\204\214\306>\11\213\307A\216\306A\212\307>" \ - "\260\331y\377\376\377\376\377\375\377\377\373\376\377\377\377\377\377" \ - "\202\377\376\377\2\212\311=\215\306A\211\214\306>\3\215\305>\214\306" \ - ">\305\342\240\215\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207" \ - "\214\306>\3\214\305@\214\306>\214\305@\232\377\377\377\4\252\324p\214" \ - "\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\231" \ - "\377\377\377\6\377\376\377\377\377\373\377\376\377\305\342\240\212\310" \ - "\77\214\304=\202\215\305@\210\214\306>\4\215\305>\213\305=\212\306@\215" \ - "\306A\202\214\306>\10\222\312M\370\373\362\377\376\377\377\375\376\377" \ - "\376\377\377\377\377\376\377\375\377\377\377\202\377\376\377\221\377" \ - "\377\377\1\376\376\376\205\377\377\377\2::<;;=\202::<\202;;=\3\300\300" \ - "\300\377\377\377\376\376\376\235\377\377\377\1\376\376\376\245\377\377" \ - "\377\1\316\316\316\207::<\5;;=::<;;=::<;;=\210::<\202;;=\2""99;;;=\202" \ - "::<\3;;=::<;;=\202::<\3;;=xxz\363\363\363\225\377\377\377\3\376\376\376" \ - "\377\377\377\376\376\376\202\377\377\377\3\363\363\363FFH::<\202;;=\202" \ - "::<\1\204\204\206\205\377\377\377\1\376\376\376\205\377\377\377\1\376" \ - "\376\376\202\377\377\377\1kkm\202::<\1;;=\202::<\1SSU\230\377\377\377" \ - "\1\234\234\236\205::<\1\234\234\234\244\377\377\377\3\376\376\376\377" \ - "\377\377xxz\202::<\1;;=\202::<\3xxx\377\377\377\376\376\376\211\377\377" \ - "\377\1\234\234\234\203::<\1;;=\202::<\1;;=\224::<\5;;=99;;;=::<;;=\202" \ - "::<\1\316\316\316\231\377\377\377\3\214\305@\214\306>\214\305@\207\214" \ - "\306>\4\214\305@\215\305>\214\306>\252\324p\251\377\377\377\215\214\306" \ - ">\1\250\325p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\210" \ - "\214\306>\3\214\305@\214\306<\343\361\316\202\377\377\377\26\377\376" \ - "\374\353\365\335\223\312K\211\305\77\215\307=\215\306C\211\306;\214\306" \ - ">\215\305@\215\307\77\214\305@\213\307A\214\306>\212\307<\216\306\77" \ - "\212\306B\215\305>\212\306@\304\341\236\377\376\377\375\377\376\377\377" \ - "\375\203\377\377\377\2\212\306@\214\306<\211\214\306>\3\215\305>\214" \ - "\306>\305\342\240\215\377\377\377\4\252\324p\214\306>\215\305>\214\305" \ - "@\207\214\306>\3\214\305@\214\306>\214\305@\232\377\377\377\4\252\324" \ - "p\214\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305" \ - "@\231\377\377\377\2\377\377\373\376\377\377\202\377\377\377\4\241\321" \ - "c\215\306A\215\305>\213\310\77\210\214\306>\20\215\305@\215\307=\213" \ - "\310\77\214\304;\216\306\77\213\310\77\333\355\303\377\375\376\377\377" \ - "\375\377\376\377\377\377\377\375\377\374\376\377\377\377\377\377\377" \ - "\377\375\376\376\376\222\377\377\377\1\376\376\376\204\377\377\377\206" \ - "::<\2\316\316\316\376\376\376\234\377\377\377\1\376\376\376\247\377\377" \ - "\377\1\316\316\316\204::<\1;;=\205::<\1;;=\212::<\4""99;;;=::<;;=\203" \ - "::<\1;;=\202::<\1\233\233\233\234\377\377\377\3\235\235\23799;;;=\203" \ - "::<\2;;=\346\346\346\203\377\377\377\1\376\376\376\204\377\377\377\3" \ - "\376\376\376\377\377\377\376\376\376\203\377\377\377\4\316\316\320;;" \ - "=::<;;=\202::<\2;;=\264\264\264\227\377\377\377\1\234\234\236\205::<" \ - "\1\234\234\234\246\377\377\377\2\234\234\236;;=\203::<\2;;=kkk\213\377" \ - "\377\377\1\234\234\234\204::<\3;;=::<;;=\225::<\2;;=99;\202::<\3;;=:" \ - "::\316\316\316\231\377\377\377\3\214\305@\214\306>\214\305@\207\214\306" \ - ">\4\214\305@\215\305>\214\306>\252\324p\251\377\377\377\215\214\306>" \ - "\1\250\325p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\210" \ - "\214\306>\14\215\307\77\215\305@\340\361\315\376\376\376\377\376\377" \ - "\377\377\375\377\377\377\323\353\267\212\307>\215\305@\214\305@\214\311" \ - "@\202\214\306>\22\212\307>\215\305@\214\306>\212\306@\214\305@\215\305" \ - ">\215\307=\214\306>\214\304=\215\307\77\341\362\316\377\376\377\377\377" \ - "\377\376\376\376\377\377\375\375\376\377\217\307@\212\306@\211\214\306" \ - ">\3\215\305>\214\306>\305\342\240\215\377\377\377\4\252\324p\214\306" \ - ">\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\232\377" \ - "\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3\214\305" \ - "@\214\306>\214\305@\232\377\377\377\7\377\376\377\376\377\377\377\377" \ - "\377\352\364\331\212\307<\215\307=\212\307>\211\214\306>\13\212\306@" \ - "\214\306<\216\306A\214\305@\252\322q\376\376\377\376\377\373\377\376" \ - "\377\376\376\377\377\377\375\376\377\377\203\377\377\377\1\376\377\375" \ - "\227\377\377\377\202::<\202;;=\3::<;;=\316\316\316\233\377\377\377\1" \ - "\375\375\375\251\377\377\377\1\316\316\316\211::<\1;;=\213::<\3;;=::" \ - "<;;=\204::<\3""99;\205\205\207\346\346\346\233\377\377\377\4\376\376" \ - "\376\364\364\364FFH;;=\202::<\202;;=\1\204\204\204\215\377\377\377\1" \ - "\376\376\376\202\377\377\377\7kkm::<99;::<;;=99;TTV\227\377\377\377\1" \ - "\234\234\236\205::<\1\234\234\234\246\377\377\377\1\234\234\236\202:" \ - ":<\202;;=\2::\214\305@\207\214\306>\4\214\305@\215\305>\214\306>\252\324p\251" \ - "\377\377\377\215\214\306>\1\250\325p\216\377\377\377\1\342\361\320\202" \ - "\214\306>\1\214\305@\210\214\306>\202\214\305@\15\341\362\316\377\377" \ - "\375\376\377\375\377\377\377\373\377\374\377\376\377\271\332\211\212" \ - "\307>\212\307<\214\305B\214\305@\216\306\77\212\307>\202\215\307\77\11" \ - "\214\305B\215\306A\212\311=\214\303A\214\306>\215\306A\212\307>\225\311" \ - "K\371\372\362\202\377\377\375\202\377\377\377\2\214\305@\215\306A\211" \ - "\214\306>\3\215\305>\214\306>\305\342\240\215\377\377\377\4\252\324p" \ - "\214\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305" \ - "@\232\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>" \ - "\3\214\305@\214\306>\214\305@\231\377\377\377\10\376\377\377\377\376" \ - "\377\377\377\375\377\375\376\331\356\303\214\306>\214\305B\215\307\77" \ - "\210\214\306>\12\215\305>\212\306B\215\304B\214\306>\215\307=\224\310" \ - "J\364\370\351\376\376\374\375\377\372\377\377\375\203\377\377\377\3\377" \ - "\376\377\377\377\377\376\377\375\221\377\377\377\3\376\376\376\377\377" \ - "\377\376\376\376\203\377\377\377\7::<;;=99;::<;;=::<\315\315\315\232" \ - "\377\377\377\1\376\376\376\203\377\377\377\1\376\376\376\246\377\377" \ - "\377\1\316\316\316\204::<\1;;=\202::<\1;;=\203::<\1;;=\210::<\1;;=\202" \ - "::<\1;;=\202::<\4``b\233\233\235\347\347\351\376\376\376\235\377\377" \ - "\377\2\265\265\265;;=\202::<\1;;=\202::<\1\332\332\332\216\377\377\377" \ - "\3\376\376\376\377\377\377\302\302\302\206::<\1\315\315\315\226\377\377" \ - "\377\1\234\234\236\205::<\1\234\234\234\245\377\377\377\2\376\376\376" \ - "\235\235\237\205::<\1jjj\203\377\377\377\3\376\376\376\377\377\377\376" \ - "\376\376\205\377\377\377\1\234\234\234\204::<\2;;=kkm\202\234\234\236" \ - "\1\233\233\235\223\234\234\234\202\235\235\235\1\233\233\233\203\234" \ - "\234\234\1\346\346\346\231\377\377\377\3\214\305@\214\306>\214\305@\207" \ - "\214\306>\4\214\305@\215\305>\214\306>\252\324p\251\377\377\377\215\214" \ - "\306>\1\250\325p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305" \ - "@\210\214\306>\17\212\307>\216\306A\342\360\315\376\377\377\376\376\374" \ - "\375\377\376\377\376\377\377\376\374\377\377\375\242\320d\215\307=\214" \ - "\306>\214\305@\215\305@\212\306@\202\214\305@\17\215\305@\212\307>\215" \ - "\307\77\214\306<\215\306A\213\304\77\215\306A\215\307\77\252\324n\377" \ - "\377\377\375\377\376\377\376\377\377\377\375\212\307<\215\305@\211\214" \ - "\306>\3\215\305>\214\306>\305\342\240\215\377\377\377\4\252\324p\214" \ - "\306>\215\305>\214\305@\207\214\306>\3\214\305@\214\306>\214\305@\232" \ - "\377\377\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3\214" \ - "\305@\214\306>\214\305@\232\377\377\377\6\376\377\375\377\375\377\367" \ - "\375\363\223\312H\216\306\77\215\305>\212\214\306>\2\215\305@\214\306" \ - ">\202\212\307>\3\214\305@\247\324o\377\376\377\202\377\377\377\2\377" \ - "\376\377\377\377\375\233\377\377\377\2::<;;=\204::<\2\316\316\316\376" \ - "\376\376\236\377\377\377\3\316\316\316;;;:::\230::<\213\377\377\377\1" \ - "\316\316\316\224::<\6kkmlln\205\205\207\234\234\236\301\301\303\363\363" \ - "\363\202\377\377\377\1\376\376\376\202\377\377\377\3\376\376\376\377" \ - "\377\377\376\376\376\231\377\377\377\1SSS\204::<\2;;=lln\213\377\377" \ - "\377\1\376\376\376\205\377\377\377\2\376\376\376TTV\205::<\1lll\226\377" \ - "\377\377\1\234\234\236\205::<\1\234\234\234\246\377\377\377\2\233\233" \ - "\235;;=\204::<\2kkk\376\376\376\203\377\377\377\1\376\376\376\206\377" \ - "\377\377\1\234\234\234\205::<\1\234\234\236\266\377\377\377\3\214\305" \ - "@\214\306>\214\305@\207\214\306>\4\214\305@\215\305>\214\306>\252\324" \ - "p\251\377\377\377\215\214\306>\1\250\325p\216\377\377\377\1\342\361\320" \ - "\202\214\306>\1\214\305@\210\214\306>\3\212\307>\215\305>\342\362\315" \ - "\202\377\377\377\22\377\376\377\376\377\377\377\377\375\376\377\377\363" \ - "\367\346\225\311K\211\307@\216\306\77\212\307>\215\305@\214\306<\212" \ - "\307>\214\305@\214\306>\212\306@\215\306C\214\304\77\215\307\77\202\214" \ - "\306>\7\212\306@\307\341\240\377\376\377\376\377\372\377\377\377\212" \ - "\307>\215\305>\211\214\306>\3\215\305>\214\306>\305\342\240\215\377\377" \ - "\377\4\252\324p\214\306>\215\305>\214\305@\207\214\306>\3\214\305@\214" \ - "\306>\214\305@\232\377\377\377\4\252\324p\214\306>\215\305>\214\305@" \ - "\207\214\306>\3\214\305@\214\306>\214\305@\231\377\377\377\4\377\376" \ - "\377\376\377\375\376\377\377\257\330z\202\214\305@\1\215\307\77\211\214" \ - "\306>\14\212\307>\215\307\77\214\305@\215\305@\212\307>\215\307=\214" \ - "\305B\313\347\252\377\377\377\377\375\377\377\376\377\376\376\376\202" \ - "\376\377\375\231\377\377\377\4GGI;;=::<;;=\202::<\1\233\233\235\237\377" \ - "\377\377\3\316\316\316::<;;=\230::<\213\377\377\377\1\316\316\316\205" \ - "::<\1kkm\202\377\377\377\2\376\376\376\250\250\250\206::<\2FFH\346\346" \ - "\346\210\377\377\377\1\376\376\376\237\377\377\377\1\264\264\266\203" \ - ";;=\4::<;;=;;;\316\316\316\222\377\377\377\1\265\265\265\204::<\3;;=" \ - "::<\316\316\316\203\377\377\377\1\376\376\376\221\377\377\377\1\234\234" \ - "\236\205::<\1\234\234\234\245\377\377\377\2\376\376\376\235\235\237\205" \ - "::<\1lll\213\377\377\377\1\234\234\234\205::<\1\234\234\236\266\377\377" \ - "\377\3\214\305@\214\306>\214\305@\207\214\306>\4\214\305@\215\305>\214" \ - "\306>\252\324p\251\377\377\377\215\214\306>\1\250\325p\216\377\377\377" \ - "\1\342\361\320\202\214\306>\1\214\305@\211\214\306>\2\214\305@\343\361" \ - "\316\205\377\377\377\10\376\377\375\377\377\377\333\355\303\215\305@" \ - "\214\306>\214\306<\214\305@\215\305>\202\214\305@\207\214\306>\6\212" \ - "\306@\214\307;\330\355\304\377\376\377\377\377\377\215\305>\212\214\306" \ - ">\3\215\305>\214\306>\305\342\240\215\377\377\377\17\251\323q\214\306" \ - ">\215\307\77\214\305B\215\307\77\213\305=\215\307\77\214\305@\212\307" \ - ">\215\305@\213\310\77\214\305@\215\305<\214\306>\376\377\377\230\377" \ - "\377\377\6\376\377\377\253\323p\215\305@\213\307A\214\306<\212\306B\202" \ - "\214\306>\4\214\305@\214\306>\212\307>\214\305@\202\214\306>\2\214\305" \ - "@\376\377\375\220\377\377\377\1\377\377\375\202\377\377\377\16\376\377" \ - "\375\377\376\377\377\375\376\374\377\377\377\377\375\376\377\375\377" \ - "\377\377\336\355\304\214\306>\215\306A\214\306>\215\306A\212\306@\216" \ - "\306A\202\214\305@\4\215\307\77\214\306>\215\307\77\214\306>\202\214" \ - "\305@\16\214\306>\215\307\77\214\306>\215\307\77\214\305@\214\305B\222" \ - "\313H\361\370\346\376\377\377\377\377\377\377\376\377\377\377\377\374" \ - "\377\377\377\376\377\230\377\377\377\1kkm\202::<\1""99;\202::<\1\235" \ - "\235\237\233\377\377\377\1\376\376\376\203\377\377\377\1\316\316\316" \ - "\224::<\1;;=\205::<\213\377\377\377\1\316\316\316\205::<\1kkm\204\377" \ - "\377\377\3wwy::<;;=\202::<\4""99;;;=``b\363\363\363\206\377\377\377\1" \ - "\376\376\376\235\377\377\377\4\376\376\376\377\377\377\376\376\376TT" \ - "V\205::<\1lln\223\377\377\377\10\376\376\376SSU;;=::<;;=99;::\214\305@\207\214\306>\4\214\305@\215" \ - "\305>\214\306>\252\324p\251\377\377\377\215\214\306>\1\250\325p\216\377" \ - "\377\377\1\342\361\320\202\214\306>\1\214\305@\211\214\306>\2\214\305" \ - "@\343\361\316\205\377\377\377\7\377\375\377\377\377\375\376\377\377\276" \ - "\337\220\213\310\77\213\304A\216\306=\207\214\306>\3\215\307\77\214\306" \ - ">\212\307>\202\215\305>\5\223\312J\361\371\344\377\375\377\212\307<\214" \ - "\305@\211\214\306>\3\215\305>\214\306>\305\342\240\214\377\377\377\14" \ - "\376\376\374\252\324n\214\306>\213\305=\215\307\77\214\305@\215\306A" \ - "\214\306>\215\307\77\213\310\77\215\305@\212\307>\202\214\306>\1\214" \ - "\305@\232\377\377\377\3\247\324m\215\305>\214\305@\202\214\306>\1\215" \ - "\307=\202\214\305@\6\214\306<\215\307=\214\305B\215\307\77\214\306>\214" \ - "\305@\224\377\377\377\15\377\377\375\376\376\376\377\377\377\377\376" \ - "\377\376\377\375\377\377\375\372\373\366\222\312M\216\306A\215\305<\214" \ - "\306>\212\307>\215\305<\202\214\306>\2\215\307\77\213\305=\204\214\306" \ - ">\1\214\305@\203\214\306>\14\215\307\77\214\305@\213\304\77\214\305B" \ - "\253\324n\376\376\377\376\377\377\377\376\377\377\377\377\376\377\375" \ - "\377\377\375\376\377\375\227\377\377\377\3lln::<;;=\203::<\2kkm\376\376" \ - "\376\236\377\377\377\2\316\316\316;;=\226::<\3;;=::\214\305" \ - "@\207\214\306>\4\214\305@\215\305>\214\306>\252\324p\251\377\377\377" \ - "\215\214\306>\1\250\325p\216\377\377\377\1\342\361\320\202\214\306>\1" \ - "\214\305@\211\214\306>\2\214\305@\343\361\316\205\377\377\377\2\377\377" \ - "\375\377\375\377\202\377\377\377\1\242\322b\202\214\305@\2\214\305B\215" \ - "\307\77\205\214\306>\12\215\307\77\214\306>\215\306A\214\306>\212\306" \ - "@\215\307=\241\321c\377\377\377\215\304B\212\307>\211\214\306>\3\215" \ - "\305>\214\306>\305\342\240\214\377\377\377\5\376\377\375\251\323o\215" \ - "\307\77\214\306>\215\307\77\202\214\305@\2\214\306>\215\307\77\202\214" \ - "\306>\5\213\310\77\215\305>\214\305@\214\306>\377\376\377\230\377\377" \ - "\377\12\377\376\377\247\326p\213\304\77\215\307\77\214\305B\214\306<" \ - "\214\306>\215\307\77\214\305@\214\306>\202\215\307\77\3\214\306>\215" \ - "\306A\216\306\77\223\377\377\377\5\376\377\372\377\377\375\376\376\376" \ - "\377\377\377\377\377\375\202\377\376\377\4\250\325p\212\307<\214\305" \ - "@\215\307\77\202\214\305@\3\214\307;\215\307=\214\306>\202\214\305@\202" \ - "\214\306>\1\215\307\77\207\214\306>\202\214\305@\5\212\307>\307\341\240" \ - "\376\376\374\377\377\377\377\376\377\202\377\377\377\1\376\376\374\227" \ - "\377\377\377\7\234\234\236;;=99;<<>99;::<;;=\237\377\377\377\1\316\316" \ - "\316\223::<\7;;=99;;;=99;::<;;=kkm\213\377\377\377\1\316\316\316\205" \ - "::<\2mmo\376\376\377\204\377\377\377\12\332\332\332FFH;;=::<;;=99;<<" \ - ">::<\266\266\270\376\376\376\203\377\377\377\1\376\376\376\202\377\377" \ - "\377\1\376\376\376\230\377\377\377\3\376\376\376\377\377\377\376\376" \ - "\376\202\377\377\377\1kkm\205::<\202;;=\224::<\10;;=::<;;=::<;;=88:;" \ - ";=\205\205\205\224\377\377\377\1\234\234\236\205::<\1\234\234\234\246" \ - "\377\377\377\3SSU;;=::<\203;;=\1\234\234\234\206\377\377\377\1\376\376" \ - "\376\204\377\377\377\1\234\234\234\205::<\1\234\234\236\266\377\377\377" \ - "\3\214\305@\214\306>\214\305@\207\214\306>\4\214\305@\215\305>\214\306" \ - ">\252\324p\251\377\377\377\215\214\306>\1\250\325p\216\377\377\377\1" \ - "\342\361\320\202\214\306>\1\214\305@\211\214\306>\2\214\305@\343\361" \ - "\316\205\377\377\377\10\376\376\374\376\377\375\377\375\377\377\377\377" \ - "\367\372\357\224\313L\214\305B\215\305<\203\214\306>\202\215\307\77\204" \ - "\214\306>\6\215\306A\213\307A\214\306>\212\306@\277\337\223\215\305>" \ - "\212\214\306>\3\215\305>\214\306>\305\342\240\214\377\377\377\2\376\377" \ - "\377\251\322r\202\215\307\77\1\214\305B\202\214\306>\202\215\307\77\7" \ - "\214\306>\215\307\77\214\306>\214\304\77\212\306@\215\307\77\377\376" \ - "\377\230\377\377\377\7\377\377\375\215\305@\214\306>\214\305@\214\306" \ - ">\216\306\77\214\306<\203\214\305@\6\215\306C\215\307=\214\305@\215\306" \ - "A\233\314V\377\377\375\220\377\377\377\5\376\376\376\377\377\377\377" \ - "\376\377\377\375\377\377\377\375\202\376\377\377\21\377\376\377\314\346" \ - "\251\212\306B\215\307=\212\307>\216\306\77\215\306C\212\307>\215\306" \ - "C\214\305@\215\307\77\213\304\77\215\306A\214\306>\214\305@\215\307\77" \ - "\215\306A\203\214\306>\1\215\307\77\202\214\306>\202\215\307\77\10\214" \ - "\306>\214\305@\350\364\334\377\377\375\377\376\377\377\377\377\376\376" \ - "\376\377\376\377\222\377\377\377\1\376\376\376\204\377\377\377\1\301" \ - "\301\301\202::<\2""99;;;=\202::<\1\316\316\316\233\377\377\377\1\376" \ - "\376\376\202\377\377\377\2\316\316\316;;;\222::<\7""99;;;=::<;;=::<9" \ - "9;\204\204\206\213\377\377\377\1\316\316\316\205::<\1jjl\202\377\377" \ - "\377\202\376\376\376\202\377\377\377\1\265\265\267\202::<\202;;=\202" \ - "::<\2FFH\332\332\332\205\377\377\377\1\376\376\376\234\377\377\377\2" \ - "\376\376\376\317\317\317\202::<\1;;=\204::<\3;;=::<;;=\222::<\2""99;" \ - ";;=\202::<\1;;=\203::<\3\346\346\346\377\377\377\376\376\376\221\377" \ - "\377\377\1\234\234\236\205::<\1\234\234\234\246\377\377\377\1;;=\203" \ - "::<\4;;=::<\316\316\316\376\376\376\203\377\377\377\1\376\376\376\206" \ - "\377\377\377\1\234\234\234\205::<\1\234\234\236\266\377\377\377\3\214" \ - "\305@\214\306>\214\305@\207\214\306>\4\214\305@\215\305>\214\306>\252" \ - "\324p\251\377\377\377\215\214\306>\1\250\325p\216\377\377\377\1\342\361" \ - "\320\202\214\306>\1\214\305@\211\214\306>\2\214\305@\343\361\316\205" \ - "\377\377\377\203\376\377\377\202\377\376\377\2\341\361\315\214\305@\203" \ - "\215\307\77\202\214\306>\1\215\307\77\203\214\306>\10\214\305@\215\307" \ - "\77\214\306>\212\307>\216\306A\213\305;\214\305@\215\305<\211\214\306" \ - ">\3\215\305>\214\306>\305\342\240\214\377\377\377\2\376\377\377\252\324" \ - "p\202\214\306>\3\214\305B\214\306<\215\307\77\203\214\306>\6\214\306" \ - "<\214\307;\217\307@\212\307>\214\305@\376\377\377\231\377\377\377\10" \ - "\215\307=\214\305B\213\304A\216\310@\214\304\77\215\307=\214\305@\215" \ - "\307\77\203\214\306>\3\215\307\77\214\306>\247\324o\222\377\377\377\3" \ - "\377\377\375\377\377\377\377\375\376\203\377\377\377\20\360\371\346\223" \ - "\312K\216\306\77\213\304A\215\306A\213\305=\215\305@\212\307>\215\305" \ - "<\214\305B\214\305@\214\306>\214\306<\214\306>\215\307\77\213\305=\204" \ - "\214\306>\202\215\307\77\203\214\306>\10\215\306A\212\307<\243\321d\377" \ - "\377\373\375\377\376\377\376\377\377\377\377\376\376\374\223\377\377" \ - "\377\5\375\375\375\377\377\377\376\376\376\377\377\377\346\346\346\202" \ - "::<\1;;=\203::<\1\221\221\221\235\377\377\377\3\376\376\376\377\377\377" \ - "\376\376\376\222\377\377\377\1__a\204::<\2;;=\234\234\234\213\377\377" \ - "\377\1\316\316\316\205::<\3jjl\377\377\377\376\376\376\205\377\377\377" \ - "\2\204\204\206;;=\204::<\3;;=RRT\363\363\363\237\377\377\377\1\376\376" \ - "\376\202\377\377\377\2jjl;;=\206::<\4;;=::<99;;;=\223::<\1;;=\205::<" \ - "\1\204\204\206\203\377\377\377\1\376\376\376\217\377\377\377\1\234\234" \ - "\236\205::<\1\234\234\234\245\377\377\377\3\315\315\315;;=99;\202::<" \ - "\5""99;;;=\346\346\346\377\377\377\376\376\376\211\377\377\377\1\234" \ - "\234\234\205::<\1\234\234\236\266\377\377\377\3\214\305@\214\306>\214" \ - "\305@\207\214\306>\4\214\305@\215\305>\214\306>\252\324p\251\377\377" \ - "\377\215\214\306>\1\250\325p\216\377\377\377\1\342\361\320\202\214\306" \ - ">\1\214\305@\211\214\306>\2\214\305@\343\361\316\207\377\377\377\202" \ - "\377\377\375\4\376\377\377\377\377\375\303\342\237\212\306@\202\214\305" \ - "@\206\214\306>\7\216\306\77\213\305;\214\305@\216\306A\214\306>\215\307" \ - "\77\213\307A\212\214\306>\3\215\305>\214\306>\305\342\240\215\377\377" \ - "\377\17\252\323k\215\306A\214\306>\215\307\77\214\306>\215\307\77\214" \ - "\305@\214\306>\213\304A\215\306C\214\305@\213\304A\213\310=\214\306<" \ - "\342\357\321\230\377\377\377\6\360\371\346\214\305B\212\307<\215\307" \ - "=\213\305=\215\307\77\202\214\305@\7\215\306A\214\306>\214\306<\214\305" \ - "@\214\306>\214\305@\252\324p\222\377\377\377\11\377\376\377\376\377\377" \ - "\377\377\377\377\377\375\376\376\374\377\377\377\253\323p\215\307\77" \ - "\211\306;\202\215\306A\6\214\306>\214\306<\215\305>\216\305C\215\307" \ - "\77\213\304\77\202\215\307\77\2\215\307=\213\305;\202\215\307\77\2\214" \ - "\306>\215\307\77\205\214\306>\5\215\307\77\212\306@\214\306>\215\307" \ - "\77\304\341\236\202\377\377\377\2\376\376\377\374\377\377\230\377\377" \ - "\377\7SSU;;=99;::<;;=::\214\305@\207\214\306>\4\214\305@\215\305>\214\306" \ - ">\252\324p\251\377\377\377\215\214\306>\1\250\325p\216\377\377\377\1" \ - "\342\361\320\202\214\306>\1\214\305@\211\214\306>\2\214\305@\343\361" \ - "\316\206\377\377\377\13\377\376\377\377\377\377\376\377\375\377\377\377" \ - "\377\376\377\376\377\377\253\324l\214\305B\213\304\77\214\305@\215\307" \ - "\77\203\214\306>\11\214\305@\214\306<\216\306=\214\306>\212\306@\215" \ - "\306C\214\304;\212\307>\214\305@\211\214\306>\3\215\305>\214\306>\305" \ - "\342\240\215\377\377\377\1\261\330\177\202\214\306>\2\214\306<\215\306" \ - "A\203\214\306>\7\215\307\77\214\306>\214\306<\215\307=\214\306>\215\306" \ - "C\323\353\267\230\377\377\377\4\340\361\315\215\305@\215\306A\214\305" \ - "@\202\214\306>\2\213\305=\215\306A\202\214\305@\5\214\306>\215\307\77" \ - "\214\306>\214\305@\260\330x\221\377\377\377\3\376\376\376\377\377\373" \ - "\375\377\376\202\377\377\377\25\376\377\377\314\345\253\214\305@\213" \ - "\304\77\216\306\77\212\307>\215\305@\214\306>\214\305@\215\305>\214\305" \ - "@\214\306>\214\306<\214\305@\215\306A\214\305@\215\306C\214\306>\214" \ - "\305@\214\306>\215\307\77\207\214\306>\7\212\306@\220\306=\215\306C\350" \ - "\364\336\376\377\373\377\377\375\376\377\377\230\377\377\377\1\221\221" \ - "\223\203::<\1;;=\202::<\1\265\265\265\230\377\377\377\1\376\376\376\227" \ - "\377\377\377\1\316\316\316\202::<\1;;=\203::<\1\363\363\363\213\377\377" \ - "\377\1\316\316\316\205::<\1kkm\204\377\377\377\1\376\376\376\203\377" \ - "\377\377\2\346\346\346FFH\206::<\2\234\234\236\376\376\376\237\377\377" \ - "\377\1\205\205\205\206::<\3;;=::<;;=\223::<\1;;=\203::<\202;;=\204::" \ - "<\2\234\234\234\376\376\376\221\377\377\377\1\234\234\236\205::<\1\234" \ - "\234\234\245\377\377\377\1RRR\204::<\2""99;yy{\203\377\377\377\1\376" \ - "\376\376\202\377\377\377\202\376\376\376\204\377\377\377\1\234\234\234" \ - "\205::<\1\234\234\236\266\377\377\377\3\214\305@\214\306>\214\305@\207" \ - "\214\306>\4\214\305@\215\305>\214\306>\252\324p\251\377\377\377\215\214" \ - "\306>\1\250\325p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305" \ - "@\211\214\306>\2\214\305@\343\361\316\205\377\377\377\30\377\377\375" \ - "\377\377\377\375\377\376\377\377\377\377\376\377\377\377\377\376\377" \ - "\377\371\372\365\222\313H\214\305B\214\305@\215\307\77\214\306>\215\307" \ - "\77\214\306>\214\305@\212\306B\214\305@\212\307>\216\306\77\212\307>" \ - "\215\307\77\214\306<\214\305@\211\214\306>\3\215\305>\214\306>\305\342" \ - "\240\214\377\377\377\20\377\376\377\301\345\237\215\305>\215\306A\213" \ - "\304\77\215\306C\214\306>\214\306<\216\306\77\214\306>\214\305B\215\307" \ - "\77\214\306>\215\307\77\214\305@\271\332\211\230\377\377\377\10\307\341" \ - "\240\215\305>\214\305@\214\306>\215\305<\212\307>\214\305B\214\306<\202" \ - "\214\306>\5\215\305<\214\305B\215\307\77\214\306>\303\344\235\222\377" \ - "\377\377\6\376\376\377\377\377\375\376\377\377\377\376\377\352\364\333" \ - "\215\305@\202\215\307\77\16\214\306>\215\307\77\214\306>\215\307\77\214" \ - "\306<\216\306A\213\310\77\214\305D\215\3108\214\305@\215\305>\223\312" \ - "K\236\323a\215\307\77\207\214\306>\202\214\305@\10\214\306>\215\307\77" \ - "\212\307>\212\307<\241\321c\377\376\377\377\375\376\377\375\377\230\377" \ - "\377\377\3\332\332\332:::;;=\204::<\1SSU\203\377\377\377\1\376\376\376" \ - "\247\377\377\377\1\376\376\376\204\377\377\377\1\221\221\221\202::<\1" \ - ";:\77\202::<\1RRT\214\377\377\377\1\316\316\316\205::<\1kkm\211\377\377" \ - "\377\2\316\316\316;;=\202::<\5;;=::<;;=::<\316\316\316\210\377\377\377" \ - "\1\376\376\376\215\377\377\377\1\376\376\376\207\377\377\377\2\346\346" \ - "\350::<\202;;=\202::<\2:::xxx\230\234\234\234\3\235\235\235\234\234\234" \ - "kkm\203::<\4;;=::\214\305@\204\214\306>\2\213\307A\213\310\77\204\214\306>\1\252\324" \ - "p\232\377\377\377\1\377\377\375\216\377\377\377\215\214\306>\1\250\325" \ - "p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\211\214\306>" \ - "\2\214\305@\343\361\316\215\377\377\377\10\352\363\336\214\306>\212\306" \ - "B\215\307\77\212\307<\215\305>\214\305@\215\307\77\221\214\306>\3\215" \ - "\305>\214\306>\305\342\240\214\377\377\377\30\377\376\377\313\347\254" \ - "\215\307\77\214\304=\215\307\77\212\306@\215\307\77\215\306A\214\305" \ - "@\214\306>\215\307\77\214\306>\215\307\77\214\305@\214\305B\222\313H" \ - "\377\376\377\377\375\376\377\376\377\377\377\377\377\376\377\377\377" \ - "\373\376\377\377\377\376\377\211\377\377\377\26\377\377\375\377\376\377" \ - "\377\377\377\376\377\377\377\377\375\376\377\375\377\377\377\241\323" \ - "b\215\304D\214\307;\215\307\77\214\305B\215\307\77\214\306<\215\306A" \ - "\212\307>\215\305@\214\306>\213\310=\215\305@\215\306A\323\352\264\221" \ - "\377\377\377\11\376\377\377\376\376\374\376\377\377\377\376\374\377\376" \ - "\377\242\320c\215\307\77\215\306A\214\306>\202\214\305@\203\214\306>" \ - "\25\214\305@\215\306A\214\305@\215\307\77\214\306>\215\307=\315\345\253" \ - "\361\370\346\215\307\77\214\306>\212\306@\216\306A\214\306>\215\305>" \ - "\215\305@\214\305@\212\307>\215\305@\212\306@\215\305<\215\305@\202\214" \ - "\306>\12\277\337\223\377\377\377\376\377\375\377\376\377\377\377\375" \ - "\376\377\377\377\377\377\376\376\376\377\377\377\377\377\375\222\377" \ - "\377\377\1___\202::<\202;;=\202::<\1\266\266\266\250\377\377\377\1\376" \ - "\376\376\202\377\377\377\1\376\376\376\203\377\377\377\1SSU\203::<\3" \ - ";;=::<\221\221\223\214\377\377\377\1\316\316\316\205::<\1kkm\210\377" \ - "\377\377\3\376\376\376\377\377\377\233\233\233\203::<\5;;=::<;;=FFH\364" \ - "\364\364\210\377\377\377\1\376\376\376\213\377\377\377\2\376\376\376" \ - "\377\377\377\202\376\376\376\205\377\377\377\1\204\204\206\202::<\1;" \ - ";=\202::<\3FFF\363\363\363\376\376\376\231\377\377\377\3\346\346\346" \ - "::<;;=\204::<\3\234\234\234\377\377\377\376\376\376\217\377\377\377\1" \ - "\234\234\236\205::<\1\234\234\234\234\377\377\377\1\376\376\376\207\377" \ - "\377\377\3\205\205\207::<;;=\204::<\1\346\346\350\214\377\377\377\1\234" \ - "\234\234\205::<\1\234\234\236\266\377\377\377\3\214\305@\214\306>\214" \ - "\305@\205\214\306>\7\214\306<\214\306>\215\307\77\214\305@\214\306>\252" \ - "\324p\376\377\375\230\377\377\377\203\377\376\377\203\377\377\377\1\376" \ - "\376\377\211\377\377\377\215\214\306>\1\250\325p\216\377\377\377\1\342" \ - "\361\320\202\214\306>\1\214\305@\211\214\306>\2\214\305@\343\361\316" \ - "\215\377\377\377\2\376\377\375\313\347\254\203\214\306>\3\214\305@\216" \ - "\306\77\211\306=\221\214\306>\3\215\305>\214\306>\305\342\240\214\377" \ - "\377\377\11\375\376\377\343\361\316\215\305>\215\307\77\213\304A\215" \ - "\307\77\215\305>\214\306<\214\305@\203\214\306>\14\215\307\77\214\305" \ - "@\213\304\77\214\305B\322\353\264\377\377\377\377\377\375\377\377\377" \ - "\377\376\377\376\377\377\377\377\377\376\377\377\210\377\377\377\13\377" \ - "\377\375\377\377\377\376\377\375\377\376\377\376\376\374\377\377\375" \ - "\377\377\377\350\364\334\215\304D\215\305>\215\307\77\202\214\305@\202" \ - "\214\306>\10\214\305@\215\306A\214\306<\215\306C\214\304=\215\307=\212" \ - "\307<\351\366\332\222\377\377\377\14\377\377\375\377\377\377\377\377" \ - "\375\304\343\237\214\306>\212\307>\217\307@\214\305@\215\307\77\214\306" \ - ">\214\305@\215\306A\202\214\306>\5\214\306<\215\305>\211\307>\216\306" \ - "=\251\323o\202\376\377\377\31\304\341\241\212\306@\215\306A\212\307>" \ - "\215\307\77\214\306<\216\305C\212\307<\216\306A\214\306<\215\307\77\215" \ - "\305>\212\307>\216\306A\214\305@\216\306A\341\361\315\377\376\377\377" \ - "\377\375\376\377\377\377\376\377\376\376\376\377\377\377\377\376\377" \ - "\376\377\375\222\377\377\377\1\265\265\265\202;;=\204::<\2SSU\364\364" \ - "\364\203\377\377\377\1\376\376\376\245\377\377\377\1\376\376\376\203" \ - "\377\377\377\1\316\316\316\203::<\1;;=\202::<\1\302\302\302\214\377\377" \ - "\377\1\316\316\316\205::<\1kkm\213\377\377\377\1lln\204::<\3;;=::<__" \ - "a\202\377\377\377\1\376\376\376\206\377\377\377\1\376\376\376\213\377" \ - "\377\377\1\376\376\376\202\377\377\377\1\376\376\376\203\377\377\377" \ - "\3\346\346\346::<;;=\204::<\1\234\234\234\234\377\377\377\1\204\204\206" \ - "\202;;=\202::<\2;;=SSU\221\377\377\377\1\234\234\236\205::<\1\234\234" \ - "\234\235\377\377\377\1\376\376\376\202\377\377\377\1\376\376\376\202" \ - "\377\377\377\2\346\346\346::<\202;;=\4""99;;;=::\214\305@\204\214\306>\10\214\305@\215\306A\215\305@\213\305=\214\306" \ - ">\215\307\77\252\324p\376\377\377\230\377\377\377\1\376\376\376\205\377" \ - "\377\377\2\376\377\377\376\377\375\210\377\377\377\215\214\306>\1\250" \ - "\325p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\211\214\306" \ - ">\2\214\305@\343\361\316\215\377\377\377\10\377\377\375\377\375\376\262" \ - "\331|\214\305@\215\306A\214\306>\214\305B\215\307\77\221\214\306>\3\215" \ - "\305>\214\306>\305\342\240\214\377\377\377\10\376\377\375\377\377\377" \ - "\214\304\77\212\307>\216\306A\214\306>\215\305@\215\307\77\206\214\306" \ - ">\202\214\305@\3\233\316X\376\376\377\376\377\373\202\377\377\377\3\377" \ - "\375\376\377\377\375\377\376\377\210\377\377\377\12\377\376\377\376\377" \ - "\375\377\375\376\376\376\374\377\377\377\377\377\375\377\377\377\257" \ - "\330x\214\307;\215\307\77\202\214\305@\2\215\307\77\213\305=\202\214" \ - "\306>\1\215\305>\202\214\306>\5\216\306\77\215\306A\215\305@\376\377" \ - "\375\377\376\377\220\377\377\377\11\377\377\375\377\377\377\376\377\377" \ - "\350\364\334\212\307>\213\310\77\216\306\77\212\307>\214\305@\202\214" \ - "\306>%\215\306A\214\306>\213\305=\214\306>\215\307\77\215\305@\211\307" \ - ">\223\311M\363\367\350\376\377\375\377\377\377\377\377\375\242\320d\212" \ - "\307<\215\306A\214\305@\212\306@\215\306A\214\306>\212\307>\215\307\77" \ - "\217\304@\211\310<\215\305>\213\310\77\212\307>\214\306>\234\315W\367" \ - "\372\363\376\377\377\377\376\377\377\377\375\377\377\377\376\376\376" \ - "\377\377\375\377\377\377\376\377\375\222\377\377\377\1RRR\202::<\203" \ - ";;=\2::<\234\234\236\204\377\377\377\1\376\376\376\246\377\377\377\3" \ - "\376\376\376\377\377\377kkk\202::<\4;;=99;;;=FFH\215\377\377\377\1\316" \ - "\316\316\205::<\1kkm\211\377\377\377\5\376\376\376\377\377\377\363\363" \ - "\363SSU;;=\202::<\202;;=\2""99;\222\222\222\207\377\377\377\3\376\376" \ - "\376\377\377\377\376\376\376\214\377\377\377\1\376\376\376\204\377\377" \ - "\377\3\204\204\204;;=99;\202;;=\3::\214\305@\204\214\306>\2\214\305@\214\306>\203\215\306A\2\215\307\77" \ - "\251\323q\231\377\377\377\203\377\377\375\202\377\377\377\1\377\375\376" \ - "\202\377\376\377\210\377\377\377\215\214\306>\1\250\325p\216\377\377" \ - "\377\1\342\361\320\202\214\306>\1\214\305@\211\214\306>\2\214\305@\343" \ - "\361\316\215\377\377\377\7\376\376\376\377\377\375\366\373\364\233\316" \ - "X\215\305@\215\307=\215\305>\222\214\306>\3\215\305>\214\306>\305\342" \ - "\240\216\377\377\377\6\243\322b\214\306>\215\305@\215\307\77\215\305" \ - "@\215\306A\203\214\306>\1\215\307\77\202\214\306>\202\215\307\77\2\214" \ - "\306>\315\346\254\202\377\377\377\4\377\376\375\376\377\375\376\376\377" \ - "\377\376\377\212\377\377\377\7\377\377\375\377\376\377\377\377\373\377" \ - "\377\375\327\356\304\214\306>\215\307\77\202\214\305@\203\214\306>\12" \ - "\215\307\77\214\306>\214\305@\216\306\77\214\306<\214\304\77\212\307" \ - ">\260\331{\376\377\375\377\376\377\220\377\377\377\13\376\377\377\377" \ - "\377\375\370\373\362\233\315Z\216\306A\214\305@\212\307>\215\306A\214" \ - "\306>\214\305@\215\306A\202\214\306>\6\215\307\77\214\305@\214\305B\214" \ - "\306>\215\307=\313\347\254\202\377\377\377\23\377\376\377\377\377\375" \ - "\350\364\334\212\307>\220\306=\214\305@\216\306=\214\306>\214\305@\214" \ - "\306>\212\306@\215\305>\212\306@\215\307\77\212\307>\215\307\77\214\305" \ - "@\212\306@\277\340\221\202\377\377\377\1\377\377\375\203\377\377\377" \ - "\2\377\376\377\377\377\375\220\377\377\377\4\376\376\376\377\377\377" \ - "\265\265\265::<\202;;=\5""99;::<;;=99;\317\317\317\250\377\377\377\1" \ - "\376\376\376\202\377\377\377\2\316\316\31699;\202::<\202;;=\2::<\221" \ - "\221\223\215\377\377\377\1\316\316\316\205::<\1kkm\207\377\377\377\1" \ - "\376\376\376\204\377\377\377\1\332\332\334\203::<\5;;=::<;;=99;\302\302" \ - "\302\202\377\377\377\1\376\376\376\216\377\377\377\1\376\376\376\202" \ - "\377\377\377\1\376\376\376\204\377\377\377\4\362\362\362FFH::<;;=\202" \ - "::<\2;;=\221\221\223\204\377\377\377\202\376\376\376\224\377\377\377" \ - "\1\376\376\376\203\377\377\377\1kkm\202;;=\203::<\1SSU\220\377\377\377" \ - "\1\234\234\236\205::<\1\234\234\234\240\377\377\377\3\376\376\376\377" \ - "\377\377\315\315\315\203::<\1;;=\202::<\1SSU\216\377\377\377\1\234\234" \ - "\234\205::<\1\234\234\236\266\377\377\377\3\214\305@\214\306>\214\305" \ - "@\204\214\306>\3\215\306A\214\306<\215\307=\202\214\305@\3\214\306>\253" \ - "\324n\377\377\375\230\377\377\377\2\375\376\377\376\376\376\203\377\377" \ - "\377\1\377\377\375\212\377\377\377\215\214\306>\1\250\325p\216\377\377" \ - "\377\1\342\361\320\202\214\306>\1\214\305@\211\214\306>\2\214\305@\343" \ - "\361\316\220\377\377\377\5\350\365\333\214\306>\214\305@\214\306>\215" \ - "\306A\221\214\306>\3\215\305>\214\306>\305\342\240\215\377\377\377\7" \ - "\377\377\375\277\337\224\212\306@\215\305@\212\307>\215\306A\215\307" \ - "\77\203\214\306>\202\215\307\77\203\214\306>\3\214\306<\214\306>\351" \ - "\363\330\202\377\377\377\3\376\376\376\374\377\377\376\377\377\211\377" \ - "\377\377\1\376\377\377\202\377\377\377\7\375\376\377\351\365\337\223" \ - "\311M\215\307=\214\305B\214\305@\215\307\77\202\214\306>\12\215\306A" \ - "\214\305@\214\306>\212\307>\215\306A\214\306>\215\307=\213\310\77\316" \ - "\345\255\376\377\377\221\377\377\377\7\376\377\377\377\377\375\300\337" \ - "\223\216\306A\213\305=\215\307=\215\305>\202\214\306>\1\215\307\77\203" \ - "\214\306>\202\214\305@\5\215\307\77\213\307A\251\322r\377\377\377\377" \ - "\377\375\202\377\377\377\14\377\376\377\377\377\377\305\342\237\212\307" \ - "<\220\305\77\214\306>\212\306@\215\306A\214\306<\214\305@\214\306<\216" \ - "\305C\202\214\306>\7\215\305<\214\306>\215\305>\214\305@\342\362\316" \ - "\377\377\377\377\377\375\202\377\377\377\3\376\377\377\377\376\377\376" \ - "\376\376\221\377\377\377\3\376\376\376\377\377\377___\205::<\4;;=FFH" \ - "\363\363\363\377\377\377\202\376\376\376\246\377\377\377\3\363\363\363" \ - "SSU;;=\204::<\4;;=\345\345\345\377\377\377\376\376\376\213\377\377\377" \ - "\1\316\316\316\205::<\1kkm\211\377\377\377\1\376\376\376\203\377\377" \ - "\377\4\264\264\266;;=99;::<\202;;=\3::\214\305@\204\214\306>\2\212\306@\213\310" \ - "\77\202\214\305@\3\215\307\77\214\306<\251\323o\231\377\377\377\4\377" \ - "\376\377\377\377\375\377\377\377\376\376\377\214\377\377\377\215\214" \ - "\306>\1\250\325p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305" \ - "@\211\214\306>\2\214\305@\343\361\316\215\377\377\377\1\377\377\375\203" \ - "\377\377\377\4\323\353\267\212\307<\214\306<\212\306B\221\214\306>\3" \ - "\215\305>\214\306>\305\342\240\214\377\377\377\7\376\377\377\377\376" \ - "\377\350\365\331\215\307\77\215\305>\214\306>\212\307>\202\214\306>\1" \ - "\215\307\77\205\214\306>\11\215\307\77\213\304A\212\307>\222\312M\343" \ - "\361\316\376\376\377\377\376\377\377\377\377\377\375\377\210\377\377" \ - "\377\1\377\376\377\202\377\377\375\12\377\376\377\350\364\334\220\313" \ - "K\216\306=\215\305<\215\307\77\214\306>\213\305=\214\306>\215\306A\202" \ - "\214\306>\1\214\305@\202\212\307>\6\214\305@\215\306C\215\305>\360\370" \ - "\351\377\377\373\376\377\377\221\377\377\377\7\345\360\322\215\305@\214" \ - "\305@\215\307=\214\304=\213\310=\215\305>\202\214\306>\2\213\305=\215" \ - "\307\77\202\214\305@\7\215\307\77\214\307;\214\305@\363\367\346\376\377" \ - "\377\377\377\373\377\376\377\202\377\377\377\30\376\377\375\377\376\377" \ - "\241\321a\216\306\77\212\306@\213\310=\215\305@\213\307A\217\304>\215" \ - "\305@\214\306<\216\306A\215\306A\212\307>\214\306<\214\306>\212\307<" \ - "\233\314W\366\373\365\377\377\375\377\377\377\377\376\377\373\377\377" \ - "\377\376\377\224\377\377\377\1\317\317\317\205::<\4;;=::<``b\362\362" \ - "\362\247\377\377\377\2\376\376\376\221\221\221\206::<\3\204\204\206\377" \ - "\377\377\376\376\376\214\377\377\377\1\316\316\316\205::<\1kkm\212\377" \ - "\377\377\6\376\376\376\377\377\377\376\376\376\377\377\377\203\203\203" \ - ";;=\205::<\3``b\363\363\363\376\376\376\216\377\377\377\1\376\376\376" \ - "\206\377\377\377\3\363\363\363FFH;;=\203::<\2;;=\203\203\203\203\377" \ - "\377\377\3\376\376\376\377\377\377\376\376\376\225\377\377\377\1\376" \ - "\376\376\204\377\377\377\3kkk::<<<>\202::<\2;;=kkm\217\377\377\377\1" \ - "\234\234\236\205::<\1\234\234\234\236\377\377\377\4\376\376\376\377\377" \ - "\377\376\376\376kkk\202::<\5;;=::<99;;;=TTV\202\377\377\377\1\376\376" \ - "\376\214\377\377\377\1\234\234\234\205::<\1\234\234\236\266\377\377\377" \ - "\3\214\305@\214\306>\214\305@\204\214\306>\10\214\306<\214\306>\214\305" \ - "@\214\306>\215\307\77\214\306>\252\324r\376\377\377\230\377\377\377\1" \ - "\377\377\375\202\377\377\377\2\377\377\375\376\376\374\203\377\376\377" \ - "\210\377\377\377\215\214\306>\1\250\325p\216\377\377\377\1\342\361\320" \ - "\202\214\306>\1\214\305@\211\214\306>\2\214\305@\343\361\316\215\377" \ - "\377\377\10\375\377\374\377\376\377\375\377\376\376\376\377\377\377\377" \ - "\270\333\207\214\305@\215\307\77\221\214\306>\3\215\305>\214\306>\305" \ - "\342\240\214\377\377\377\12\375\376\377\377\376\377\376\377\377\234\313" \ - "Y\215\306A\214\305@\212\307>\214\305@\214\306>\215\307\77\206\214\306" \ - ">\7\215\307\77\214\306>\215\305@\213\310\77\304\343\240\371\372\364\376" \ - "\377\377\212\377\377\377\10\376\377\377\377\376\377\315\345\251\223\311" \ - "M\214\306>\216\306\77\214\305B\214\306<\202\214\306>\15\215\306A\214" \ - "\305@\214\306>\215\307\77\214\305@\214\306<\214\305@\215\307\77\213\304" \ - "A\263\330{\377\377\377\376\376\376\377\377\375\220\377\377\377\7\370" \ - "\373\364\232\315V\216\306=\212\311=\214\306>\216\306A\213\307A\202\214" \ - "\305@\202\214\306>\202\214\305@\10\215\307\77\215\305>\215\304D\304\341" \ - "\237\376\377\377\377\376\377\376\376\377\377\377\375\202\377\376\377" \ - "\24\376\377\377\377\377\373\350\365\333\215\305>\214\306<\214\306>\212" \ - "\306@\215\307\77\213\305=\215\305@\215\307\77\214\306>\215\305>\215\306" \ - "A\211\305A\215\305@\214\305B\213\310=\262\327z\374\377\377\202\377\377" \ - "\377\2\377\377\375\373\377\376\225\377\377\377\1\221\221\223\203::<\6" \ - ";;=99;;;=::<``b\362\362\362\246\377\377\377\2\265\265\265:::\202::<\1" \ - ";;=\203::<\1\346\346\350\216\377\377\377\1\316\316\316\205::<\1kkm\216" \ - "\377\377\377\6\363\363\363__a::<;;=::<;;=\202::<\1\204\204\204\204\377" \ - "\377\377\1\376\376\376\221\377\377\377\1\234\234\234\204::<\3;;=::<\347" \ - "\347\347\202\377\377\377\1\376\376\376\205\377\377\377\1\376\376\376" \ - "\225\377\377\377\3\376\376\376\377\377\377\265\265\265\202::<\202;;=" \ - "\3::<;;=\316\316\316\216\377\377\377\1\234\234\236\205::<\1\234\234\234" \ - "\240\377\377\377\2\204\204\204:::\206::<\1\301\301\303\217\377\377\377" \ - "\1\234\234\234\205::<\1\234\234\236\266\377\377\377\3\214\305@\214\306" \ - ">\214\305@\205\214\306>\7\214\305@\216\306A\215\307=\213\304\77\213\307" \ - "A\242\321a\345\356\317\230\342\362\316\7\341\361\315\342\361\322\342" \ - "\361\320\343\361\315\345\360\322\365\373\357\376\377\377\211\377\377" \ - "\377\215\214\306>\1\250\325p\216\377\377\377\1\342\361\320\202\214\306" \ - ">\1\214\305@\211\214\306>\2\214\305@\343\361\316\216\377\377\377\7\376" \ - "\377\375\377\377\375\377\377\377\377\376\377\371\374\365\242\322d\215" \ - "\306A\221\214\306>\3\215\305>\214\306>\305\342\240\214\377\377\377\10" \ - "\377\377\375\377\377\377\377\377\373\312\346\253\215\307=\212\307>\214" \ - "\305B\216\306=\206\214\306>\202\214\305@\10\214\306>\212\307>\216\306" \ - "\77\214\306>\212\307>\233\316W\306\340\237\361\370\346\210\377\377\377" \ - "\12\361\370\350\314\345\253\233\314W\214\306>\213\310\77\215\305<\214" \ - "\305@\212\307<\215\306A\214\305@\203\214\306>\202\214\305@\202\214\306" \ - ">\4\216\306A\212\306@\213\310\77\333\356\301\202\377\377\377\1\377\377" \ - "\375\220\377\377\377\26\270\332\204\215\306A\212\306B\214\306>\213\307" \ - "A\215\305@\214\306<\214\306>\215\306A\214\306<\215\307\77\214\305B\215" \ - "\307\77\214\307;\215\304D\241\323b\377\377\375\376\377\377\377\377\377" \ - "\377\377\373\377\377\377\376\377\377\202\377\377\375\16\377\377\377\376" \ - "\377\377\277\337\224\214\305@\215\306A\214\306>\215\305>\212\310\77\214" \ - "\305@\215\307\77\212\307>\214\305B\216\306=\215\306A\202\214\306<\6\214" \ - "\306>\213\307C\331\356\305\377\376\377\377\377\373\376\376\376\227\377" \ - "\377\377\3__a::<;:\77\205::<\2__a\363\363\363\203\377\377\377\1\376\376" \ - "\376\213\377\377\377\1\376\376\376\203\377\377\377\3\376\376\376\377" \ - "\377\377\376\376\376\213\377\377\377\1\376\376\376\202\377\377\377\1" \ - "\265\265\267\205::<\3;;=:::\234\234\234\217\377\377\377\1\316\316\316" \ - "\205::<\1kkm\217\377\377\377\4\332\332\332GGI::<;;=\204::<\1\250\250" \ - "\252\225\377\377\377\1FFH\205::<\1\204\204\204\242\377\377\377\1TTV\205" \ - "::<\4lln\376\376\376\377\377\377\376\376\376\203\377\377\377\1\376\376" \ - "\376\207\377\377\377\1\234\234\236\205::<\1\235\235\237\221\377\377\377" \ - "\1\376\376\376\202\377\377\377\1\376\376\376\202\377\377\377\202\376" \ - "\376\376\205\377\377\377\3\363\363\365\204\204\206;;=\204::<\3;;=:::" \ - "xxx\220\377\377\377\1\234\234\234\203::<\3;;=::<\234\234\234\204\377" \ - "\377\377\1\376\376\376\261\377\377\377\3\214\305@\214\306>\214\305@\250" \ - "\214\306>\2\215\307\77\342\362\316\212\377\377\377\215\214\306>\1\250" \ - "\325p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\211\214\306" \ - ">\2\214\305@\343\361\316\216\377\377\377\11\375\376\377\377\376\377\377" \ - "\377\375\376\377\377\377\376\377\351\365\335\223\311M\212\307<\214\306" \ - ">\202\216\306A\4\212\307<\215\306A\215\305>\215\307\77\211\214\306>\3" \ - "\215\305>\214\306>\305\342\240\214\377\377\377\20\377\376\377\377\377" \ - "\375\377\376\377\365\374\364\223\312J\217\304>\215\307\77\212\307;\215" \ - "\306A\214\305B\214\305@\215\307\77\214\306<\213\310\77\214\305@\215\305" \ - ">\210\214\306>\10\234\315Z\257\327~\304\343\235\306\340\237\307\341\240" \ - "\304\343\237\257\327\177\241\321a\210\214\306>\20\217\304>\215\306A\212" \ - "\306@\212\307>\213\305;\216\306A\213\305=\215\306C\211\310<\216\306A" \ - "\214\306>\234\314V\377\377\377\375\377\374\376\377\377\377\376\377\211" \ - "\377\377\377\7\377\376\377\376\377\375\376\377\377\376\377\375\377\376" \ - "\377\377\377\377\333\355\303\210\214\306>\10\215\306A\214\305@\216\306" \ - "=\214\306>\215\307\77\214\305@\215\307\77\352\364\334\211\377\377\377" \ - "\6\377\376\377\367\375\363\232\315V\215\307\77\214\306>\214\305@\212" \ - "\214\306>\6\212\307>\223\311M\366\373\364\377\376\377\377\377\377\376" \ - "\377\373\221\377\377\377\1\376\376\376\204\377\377\377\2\346\346\346" \ - "FFH\203::<\1""99;\203::<\2__a\332\332\332\211\377\377\377\1\376\376\376" \ - "\203\377\377\377\1\376\376\376\205\377\377\377\1\376\376\376\206\377" \ - "\377\377\1\376\376\376\207\377\377\377\1\265\265\267\202::<\1;;=\204" \ - "::<\2```\376\376\376\217\377\377\377\1\316\316\316\205::<\1kkm\216\377" \ - "\377\377\4\376\376\376\377\377\377\301\301\301;;=\205::<\2;;=\331\331" \ - "\331\202\377\377\377\3\376\376\376\377\377\377\376\376\376\216\377\377" \ - "\377\1\265\265\267\205::<\3;;=\332\332\332\376\376\376\241\377\377\377" \ - "\1\266\266\270\205::<\2""99;\316\316\320\215\377\377\377\1\234\234\236" \ - "\203::<\5;;=::<\234\234\234\377\377\377\376\376\376\220\377\377\377\1" \ - "\376\376\376\206\377\377\377\1\376\376\376\203\377\377\377\2\346\346" \ - "\346``b\202::<\2""99;;;=\203::<\4FFF\363\363\363\377\377\377\376\376" \ - "\376\216\377\377\377\1\234\234\234\204::<\3;;=\234\234\234\376\376\376" \ - "\265\377\377\377\3\214\305@\214\306>\214\305@\250\214\306>\2\215\307" \ - "\77\342\362\316\212\377\377\377\215\214\306>\1\250\325p\216\377\377\377" \ - "\1\342\361\320\202\214\306>\1\214\305@\211\214\306>\2\214\305@\343\361" \ - "\316\215\377\377\377\16\377\376\377\376\377\377\377\376\377\377\377\377" \ - "\376\377\377\377\376\377\375\377\374\323\353\267\215\305<\215\306C\215" \ - "\305<\213\306:\213\310\77\212\306@\202\214\305@\211\214\306>\3\215\305" \ - ">\214\306>\305\342\240\215\377\377\377\4\376\377\377\377\377\375\377" \ - "\376\377\305\342\242\202\214\305@\5\216\306A\214\306>\215\307=\215\307" \ - "\77\213\304A\202\214\305@\2\214\306>\212\306@\210\214\306>\7\214\306" \ - "<\215\307=\215\307\77\213\305=\214\306>\215\307\77\213\305=\211\214\306" \ - ">\11\215\306A\215\305>\212\307;\213\304\77\215\306A\211\306=\215\306" \ - "A\212\307<\216\306A\202\215\307\77\4\343\361\320\376\377\375\377\377" \ - "\375\376\376\377\212\377\377\377\1\377\376\377\202\377\377\377\4\377" \ - "\376\377\376\377\377\367\375\363\225\311J\210\214\306>\10\215\307=\213" \ - "\310\77\214\305@\216\306\77\214\305@\212\307>\307\341\240\376\377\375" \ - "\210\377\377\377\5\377\376\377\374\377\375\377\376\377\343\361\320\212" \ - "\306@\202\214\306>\1\213\310\77\210\214\306>\10\215\306A\215\305>\214" \ - "\305@\260\327z\377\376\374\374\377\377\377\377\377\377\376\377\226\377" \ - "\377\377\1\332\332\332\210::<\2GGI\250\250\250\223\377\377\377\3\376" \ - "\376\376\377\377\377\376\376\376\202\377\377\377\1\376\376\376\202\377" \ - "\377\377\1\376\376\376\204\377\377\377\2\250\250\252;;=\204::<\202;;" \ - "=\2EEG\331\331\331\220\377\377\377\1\316\316\316\205::<\1kkm\221\377" \ - "\377\377\5\222\222\224::<;;=::<;;=\202::<\5SSU\364\364\364\376\376\376" \ - "\377\377\377\376\376\376\216\377\377\377\2\376\376\376TTV\203::<\4;;" \ - "=99;lln\376\376\376\243\377\377\377\1TTV\204::<\5;;=\204\204\206\376" \ - "\376\376\377\377\377\376\376\376\212\377\377\377\1\234\234\236\202::" \ - "<\1;;=\202::<\1\234\234\234\215\377\377\377\1\376\376\376\202\377\377" \ - "\377\1\376\376\376\212\377\377\377\6\376\376\376\250\250\252FFH99;::" \ - "<;;=\205::<\1\316\316\316\221\377\377\377\1\234\234\234\203::<\3;;=:" \ - ":<\234\234\236\266\377\377\377\3\214\305@\214\306>\214\305@\250\214\306" \ - ">\2\215\307\77\342\362\316\212\377\377\377\215\214\306>\1\250\325p\216" \ - "\377\377\377\1\342\361\320\202\214\306>\1\214\305@\211\214\306>\2\214" \ - "\305@\343\361\316\215\377\377\377\3\377\376\377\376\377\375\376\377\377" \ - "\202\377\377\377\13\377\377\375\377\376\377\376\376\374\271\332\211\215" \ - "\306A\211\306;\216\306A\212\307>\213\307A\215\306A\212\307>\211\214\306" \ - ">\3\215\305>\214\306>\305\342\240\214\377\377\377\20\376\377\375\377" \ - "\377\377\377\377\375\377\377\377\371\370\364\233\316U\214\306>\214\305" \ - "@\215\306A\214\306>\214\305@\215\307=\214\306>\215\305@\215\304B\213" \ - "\310=\210\214\306>\3\215\305@\214\306>\213\305=\202\213\310\77\3\214" \ - "\306>\215\307\77\215\305@\210\214\306>\20\212\306@\212\307;\216\306\77" \ - "\215\307\77\212\306@\214\306<\215\305>\215\307\77\220\305\77\211\307" \ - ">\263\330{\377\376\377\377\377\375\376\377\377\377\377\377\376\376\376" \ - "\211\377\377\377\7\377\377\373\377\377\377\377\375\376\377\377\377\377" \ - "\377\375\257\330|\213\310\77\211\214\306>\6\215\306C\211\306=\214\305" \ - "@\214\306>\242\322e\377\377\375\212\377\377\377\7\376\377\377\377\377" \ - "\375\377\375\376\277\337\224\216\307B\212\307>\214\305@\210\214\306>" \ - "\2\214\305@\216\306\77\202\212\307>\4\332\360\302\376\376\374\376\376" \ - "\376\377\376\377\227\377\377\377\1\266\266\266\202::<\1;;=\202::<\2;" \ - ";=::<\202;;=\2kkm\346\346\350\202\377\377\377\1\376\376\376\207\377\377" \ - "\377\1\376\376\376\203\377\377\377\5\376\376\376\377\377\377\376\376" \ - "\376\377\377\377\376\376\376\202\377\377\377\3\376\376\376\377\377\377" \ - "\376\376\376\204\377\377\377\2\364\364\364yy{\203::<\2;;=99;\203::<\3" \ - "\265\265\267\377\377\377\376\376\376\217\377\377\377\1\316\316\316\205" \ - "::<\1kkm\222\377\377\377\1kkm\203::<\1;;=\202::<\5kkm\377\377\377\376" \ - "\376\376\377\377\377\376\376\376\212\377\377\377\5\376\376\376\377\377" \ - "\377\376\376\376\265\265\267;;=\204::<\2;;=\315\315\315\244\377\377\377" \ - "\11\234\234\234::<99;;;=::<;;=::<\347\347\347\376\376\376\213\377\377" \ - "\377\1\234\234\236\204::<\2;;=\233\233\233\217\377\377\377\1\376\376" \ - "\376\206\377\377\377\6\376\376\376\377\377\377\376\376\376\377\377\377" \ - "\265\265\265TTT\202::<\202;;=\203::<\3;;=::<\266\266\270\202\377\377" \ - "\377\1\376\376\376\217\377\377\377\1\234\234\234\204::<\4;;=\235\235" \ - "\237\377\377\377\376\376\376\224\377\377\377\1\376\376\376\203\377\377" \ - "\377\1\376\376\376\233\377\377\377\3\214\305@\214\306>\214\305@\250\214" \ - "\306>\2\215\307\77\342\362\316\212\377\377\377\215\214\306>\1\250\325" \ - "p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\211\214\306>" \ - "\2\214\305@\343\361\316\215\377\377\377\202\377\377\375\16\377\377\377" \ - "\377\377\375\377\377\377\376\377\375\376\376\374\377\376\377\375\377" \ - "\376\241\322_\215\306A\212\306B\215\305>\215\307\77\214\306<\214\305" \ - "B\211\214\306>\3\215\305>\214\306>\305\342\240\214\377\377\377\1\377" \ - "\376\377\202\377\377\375\15\376\377\377\377\375\376\340\361\317\214\306" \ - ">\212\307>\214\306>\215\307\77\214\306>\212\307<\215\307\77\215\305>" \ - "\216\306=\213\305=\210\214\306>\1\212\307>\202\214\305@\202\214\306>" \ - "\3\214\305@\215\306A\212\307>\210\214\306>\20\212\307>\213\304\77\214" \ - "\306>\211\310<\214\306>\216\306A\212\306@\215\305@\214\306>\223\313N" \ - "\367\372\363\376\377\377\377\377\377\377\376\377\376\377\373\377\376" \ - "\377\212\377\377\377\202\376\377\377\3\377\375\376\324\353\265\215\306" \ - "A\211\214\306>\7\215\305>\213\305=\215\307\77\215\306A\212\307>\351\363" \ - "\333\377\377\375\211\377\377\377\10\377\376\377\375\377\376\376\377\377" \ - "\377\376\377\370\373\362\233\314W\215\307\77\215\305<\210\214\306>\1" \ - "\215\307\77\202\214\306>\4\214\306<\225\310O\360\366\350\377\376\377" \ - "\221\377\377\377\3\376\376\376\377\377\377\376\376\376\205\377\377\377" \ - "\1\266\266\266\202::<\4;;=99;::<;;=\202::<\4;;=::<\204\204\206\346\346" \ - "\350\207\377\377\377\1\376\376\376\206\377\377\377\202\376\376\376\202" \ - "\377\377\377\1\376\376\376\203\377\377\377\1\376\376\376\202\377\377" \ - "\377\3\251\251\251FFF99;\202::<\1""99;\202::<\5;;=::<\234\234\236\377" \ - "\377\377\376\376\376\220\377\377\377\1\316\316\316\205::<\1kkm\222\377" \ - "\377\377\11\363\363\363GGI99;::<99;;;=::<;;=\234\234\234\214\377\377" \ - "\377\1\376\376\376\203\377\377\377\1SSU\202::<\1;;=\202::<\1kkm\245\377" \ - "\377\377\5\362\362\362GGI;;=::<;;=\202::<\1\204\204\206\206\377\377\377" \ - "\1\376\376\376\205\377\377\377\1\234\234\236\203::<\3""99;::<\234\234" \ - "\234\223\377\377\377\1\376\376\376\203\377\377\377\3\331\331\331\222" \ - "\222\222SSU\203::<\2;;=::<\202;;=\4::<;;=::<\265\265\267\202\377\377" \ - "\377\1\376\376\376\203\377\377\377\1\376\376\376\214\377\377\377\1\234" \ - "\234\234\205::<\1\234\234\236\203\377\377\377\1\376\376\376\223\377\377" \ - "\377\1\376\376\376\236\377\377\377\3\214\305@\214\306>\214\305@\250\214" \ - "\306>\2\215\307\77\342\362\316\212\377\377\377\215\214\306>\1\250\325" \ - "p\216\377\377\377\1\342\361\320\202\214\306>\1\214\305@\211\214\306>" \ - "\2\214\305@\343\361\316\216\377\377\377\17\377\376\377\377\377\377\376" \ - "\376\376\377\376\377\377\377\375\376\377\377\375\377\376\377\377\377" \ - "\363\367\350\222\312K\214\305@\213\310\77\214\304\77\215\307\77\216\306" \ - "A\211\214\306>\3\215\305>\214\306>\305\342\240\214\377\377\377\14\377" \ - "\376\377\376\377\375\376\377\377\377\376\377\376\377\377\376\377\375" \ - "\307\342\237\214\305@\214\306<\215\304D\214\306>\214\305D\202\212\307" \ - "<\2\212\307>\213\307A\210\214\306>\3\215\307\77\214\306>\215\307\77\202" \ - "\214\305@\213\214\306>\12\213\305;\215\306A\212\306@\214\306>\213\307" \ - "C\212\307>\215\305>\212\307>\215\305>\333\356\301\202\377\377\377\3\377" \ - "\377\375\377\377\377\377\376\377\211\377\377\377\10\376\377\375\377\377" \ - "\375\376\377\375\374\377\375\362\371\347\225\311M\215\307\77\215\305" \ - "<\210\214\306>\2\214\305@\216\306=\202\212\306@\2\305\342\237\377\375" \ - "\376\212\377\377\377\1\376\376\374\203\377\377\377\4\376\376\376\337" \ - "\363\316\215\306C\215\305<\211\214\306>\1\215\307\77\202\214\305@\4\214" \ - "\306<\253\324n\375\377\374\377\377\375\224\377\377\377\1\376\376\376" \ - "\204\377\377\377\2\301\301\301FFH\202::<\2;;=99;\202;;=\2::<;;=\202:" \ - ":<\2\204\204\206\316\316\320\207\377\377\377\1\376\376\376\203\377\377" \ - "\377\1\376\376\376\206\377\377\377\6\376\376\376\377\377\377\364\364" \ - "\364\265\265\267SSU::<\202;;=\202::<\5;;=::<;;=::<\204\204\204\223\377" \ - "\377\377\1\316\316\316\205::<\1kkm\223\377\377\377\11\315\315\315;;=" \ - "::<;;=::<;;=::<99;\302\302\302\216\377\377\377\5\301\301\303::<;;=::" \ - "<;;=\202::<\2\316\316\316\377\377\377\202\376\376\376\241\377\377\377" \ - "\14\376\376\376\377\377\377\234\234\234;;=::<;;=::<;;=::<\347\347\351" \ - "\377\377\377\376\376\376\211\377\377\377\1\234\234\236\203::<\3;;=::" \ - "<\234\234\236\216\377\377\377\202\376\376\376\1\377\377\377\202\316\316" \ - "\316\6\250\250\250\234\234\234jjjFFF;;=99;\202;;=\2::<;;=\202::<\5<<" \ - ">99;;;=::<\265\265\267\204\377\377\377\1\376\376\376\217\377\377\377" \ - "\1\234\234\234\204::<\2;;=\234\234\236\202\377\377\377\1\376\376\376" \ - "\223\377\377\377\1\376\376\376\202\377\377\377\1\376\376\376\234\377" \ - "\377\377\3\214\305@\214\306>\214\305@\250\214\306>\2\215\307\77\342\362" \ - "\316\212\377\377\377\215\214\306>\1\250\325p\216\377\377\377\1\342\361" \ - "\320\202\214\306>\1\214\305@\211\214\306>\2\214\305@\343\361\316\215" \ - "\377\377\377\202\377\376\377\16\377\377\375\376\377\377\377\377\377\377" \ - "\377\375\377\376\377\376\376\376\377\376\377\377\377\377\333\354\302" \ - "\212\307>\213\310\77\214\306<\213\310=\215\305@\211\214\306>\3\215\305" \ - ">\214\306>\305\342\240\214\377\377\377\1\377\376\377\202\376\377\377" \ - "\202\377\377\375\13\376\377\377\377\375\376\271\333\205\215\305>\214" \ - "\306>\212\307>\214\306>\215\306A\214\306>\212\306@\214\305@\210\214\306" \ - ">\3\214\305@\215\307\77\214\306>\202\212\307>\3\214\306>\215\307\77\215" \ - "\306A\210\214\306>\4\216\306A\211\306=\214\306<\216\306A\202\212\307" \ - ">\202\215\306A\10\322\352\270\377\377\375\376\376\374\377\377\377\376" \ - "\377\377\377\376\377\377\377\375\376\377\377\210\377\377\377\10\377\377" \ - "\375\377\377\377\377\376\377\374\376\373\250\325n\216\306\77\212\307" \ - ">\214\305B\210\214\306>\202\212\307>\6\214\305@\242\322d\376\376\374" \ - "\377\377\375\375\377\376\377\376\377\210\377\377\377\10\376\377\377\377" \ - "\377\375\377\375\376\377\377\375\375\376\377\376\377\375\270\333\207" \ - "\211\310<\210\214\306>\10\214\304=\216\307B\214\306>\212\307>\216\306" \ - "A\215\307\77\313\350\250\376\376\377\221\377\377\377\1\376\376\376\203" \ - "\377\377\377\1\376\376\376\204\377\377\377\7\332\332\332RRT;;=::<;;=" \ - "::<;;=\202::<\1;;=\203::<\3RRT\221\221\223\317\317\321\214\377\377\377" \ - "\11\376\376\376\377\377\377\364\364\364\301\301\301\204\204\206EEG;;" \ - "=99;;;=\204::<\1""99;\202::<\1\251\251\251\207\377\377\377\1\376\376" \ - "\376\214\377\377\377\1\316\316\316\205::<\1kkm\224\377\377\377\1\247" \ - "\247\247\203::<\5;;=::<;;=FFH\345\345\345\214\377\377\377\2\376\376\376" \ - "kkm\205::<\1SSU\202\377\377\377\1\376\376\376\244\377\377\377\2\363\363" \ - "\363FFH\204::<\2;;=\221\221\223\213\377\377\377\1\234\234\236\204::<" \ - "\4;;=SSUkkmlln\213kkm\5;;=::<;;=::<;;=\204::<\2;;=99;\202;;=\2::<;;=" \ - "\202::<\7;;=99;::\214\305@\250\214\306>\2\215" \ - "\307\77\342\362\316\212\377\377\377\215\214\306>\1\250\325p\216\377\377" \ - "\377\1\342\361\320\202\214\306>\1\214\305@\211\214\306>\2\214\305@\343" \ - "\361\316\215\377\377\377\1\377\376\377\202\377\377\375\202\377\377\377" \ - "\202\377\376\377\11\377\377\375\377\377\377\376\377\377\377\376\377\276" \ - "\336\223\214\306<\213\310\77\214\304=\215\306A\211\214\306>\3\215\305" \ - ">\214\306>\305\342\240\214\377\377\377\20\377\377\375\376\377\375\376" \ - "\376\376\377\376\377\375\377\376\377\375\377\376\377\377\376\377\375" \ - "\270\333\207\217\305<\212\307>\214\305@\216\306\77\213\305=\214\305@" \ - "\216\306=\211\214\306>\2\215\306A\215\305@\202\216\306\77\3\215\305@" \ - "\214\305@\215\307\77\210\214\306>\13\213\305=\215\306A\215\305>\212\306" \ - "@\215\305>\215\306A\220\305A\323\352\266\376\377\375\377\376\377\377" \ - "\377\375\202\377\377\377\3\376\377\377\377\375\377\376\377\375\213\377" \ - "\377\377\5\316\347\256\212\307>\213\305;\216\306A\212\307<\210\214\306" \ - ">\10\212\307>\216\306\77\215\305>\350\364\336\377\376\377\376\376\374" \ - "\377\377\377\377\376\377\210\377\377\377\1\377\376\377\202\377\377\377" \ - "\5\377\376\377\376\377\375\377\376\377\370\373\360\225\311K\210\214\306" \ - ">\10\216\306=\214\305@\215\310<\212\307>\214\306>\214\305@\223\312J\356" \ - "\371\350\231\377\377\377\4\376\376\376\377\377\377\363\363\363xxz\202" \ - "::<\1""99;\202::<\1;;=\203::<\202;;=\203::<\4__a\205\205\205\234\234" \ - "\234\250\250\250\205\316\316\316\4\250\250\250\234\234\234xxx___\202" \ - "::<\3""99;;;=99;\203::<\1;;=\203::<\2FFH\265\265\265\205\377\377\377" \ - "\1\376\376\376\217\377\377\377\1\316\316\316\205::<\1kkm\225\377\377" \ - "\377\3xxx::<;;=\204::<\1```\213\377\377\377\4\376\376\376\317\317\317" \ - "::<;;=\204::<\1\266\266\270\203\377\377\377\1\376\376\376\241\377\377" \ - "\377\1\377\377\375\202\377\377\377\1\204\204\206\202::<\1;;=\202::<\2" \ - "GGI\363\363\363\212\377\377\377\1\234\234\236\203::<\1;;=\202::<\1;;" \ - "=\221::<\1;;=\207::<\1;;=\202::<\1;;=\202::<\2``b\346\346\350\210\377" \ - "\377\377\1\376\376\376\215\377\377\377\1\234\234\234\207::<\3;;=::<;" \ - ";=\221::<\1;;=\203::<\1;;=\202::<\1\316\316\320\231\377\377\377\3\214" \ - "\305@\214\306>\214\305@\250\214\306>\2\215\307\77\342\362\316\212\377" \ - "\377\377\215\214\306>\1\250\325p\216\377\377\377\1\342\361\320\202\214" \ - "\306>\1\214\305@\211\214\306>\2\214\305@\343\361\316\215\377\377\377" \ - "\7\377\377\375\376\377\375\377\377\377\377\376\377\376\376\374\376\377" \ - "\377\377\377\377\202\376\377\377\202\377\377\375\4\377\377\377\242\320" \ - "d\211\306=\215\305@\212\214\306>\3\215\305>\214\306>\305\342\240\214" \ - "\377\377\377\6\377\376\377\377\377\377\377\377\375\377\375\377\376\377" \ - "\372\375\376\377\202\377\377\377\10\376\377\377\304\343\240\215\305@" \ - "\214\306>\216\306A\215\307\77\212\307>\215\307\77\212\214\306>\3\215" \ - "\307\77\214\306>\214\305@\202\215\307\77\211\214\306>\12\215\306C\212" \ - "\307<\215\307\77\215\305@\213\310\77\215\306A\323\352\266\377\376\377" \ - "\377\377\377\376\377\377\204\377\377\377\2\377\377\375\377\376\377\210" \ - "\377\377\377\10\376\377\377\377\376\377\361\370\346\225\311K\212\307" \ - ">\215\306A\214\305@\215\305>\210\214\306>\3\214\305@\214\306>\307\341" \ - "\240\203\376\377\377\2\377\377\375\376\377\377\210\377\377\377\5\376" \ - "\377\377\377\376\372\376\377\375\376\376\376\377\377\377\202\377\376" \ - "\377\1\334\355\301\210\214\306>\10\215\306A\213\310\77\215\305@\214\306" \ - ">\214\306<\215\306A\214\306>\254\322o\232\377\377\377\6\376\376\376\377" \ - "\377\377\376\376\376\302\302\302FFH;;=\206::<\1;;=\202::<\202;;=\203" \ - "::<\1;;=\204::<\3;;=::<;;=\202::<\1;;=\202::<\1;;=\203::<\2;;=::<\202" \ - ";;=\2__a\332\332\332\226\377\377\377\3\316\316\316::<;;=\203::<\1kkm" \ - "\222\377\377\377\7\376\376\376\377\377\377\376\376\376\363\363\363__" \ - "a::<;;=\204::<\1\203\203\203\202\377\377\377\2\376\376\376\377\377\377" \ - "\202\376\376\376\205\377\377\377\1kkm\202::<\1;;=\202::<\5TTV\377\377" \ - "\377\376\376\376\377\377\377\376\376\376\245\377\377\377\2\347\347\347" \ - "99;\202::<\1;;=\202::<\1\235\235\237\206\377\377\377\1\376\376\376\202" \ - "\377\377\377\2\376\376\376\234\234\234\224::<\1;;=\202::<\3""99;::<;" \ - ";=\204::<\1;;=\204::<\3;;=GGI\250\250\252\230\377\377\377\2\234\234\236" \ - ";;=\232::<\10;;=99;;;=::<;;=::<:::\316\316\316\230\377\377\377\10\377" \ - "\376\377\212\306@\214\305@\213\310=\214\306<\215\306A\214\307;\215\306" \ - "A\240\214\306>\10\214\305@\212\307<\214\306<\214\305@\212\306@\342\360" \ - "\315\376\377\377\377\376\377\210\377\377\377\212\214\306>\4\216\306\77" \ - "\212\306B\214\306>\250\325n\202\377\376\377\210\377\377\377\1\377\376" \ - "\377\202\377\377\377\5\376\377\375\342\362\316\214\305B\215\305@\214" \ - "\306<\210\214\306>\202\212\307>\5\343\361\320\377\377\377\377\377\375" \ - "\376\377\377\377\376\377\223\377\377\377\6\377\376\377\377\377\375\371" \ - "\372\364\223\312J\212\306@\215\305@\210\214\306>\10\214\305@\215\305" \ - ">\212\307>\304\343\240\377\377\375\377\377\377\377\377\375\377\376\377" \ - "\220\377\377\377\11\376\377\377\377\377\377\333\355\303\226\310K\213" \ - "\310\77\214\306>\215\305@\215\306A\214\305@\203\214\306>\7\215\305>\215" \ - "\305@\214\305@\212\307>\215\305>\215\307\77\215\306A\202\214\306<\5\215" \ - "\306A\213\305=\215\305@\215\307\77\213\305;\202\215\305@\13\215\307\77" \ - "\213\310\77\214\305@\215\307\77\212\307>\215\305>\214\306>\212\306@\235" \ - "\315U\347\365\334\377\376\377\220\377\377\377\15\376\376\376\377\377" \ - "\375\377\377\377\244\317c\213\307A\214\306<\213\307A\215\305>\215\305" \ - "<\215\307\77\214\306<\215\307\77\214\305@\202\215\307\77\12\214\305@" \ - "\215\306A\215\305@\234\315W\367\375\363\377\376\377\376\377\377\377\377" \ - "\375\376\377\377\377\376\377\220\377\377\377\10\260\331{\215\307=\212" \ - "\307>\213\307A\214\306>\215\305@\215\307\77\215\305>\210\214\306>\3\314" \ - "\345\253\377\377\377\376\377\375\202\377\376\377\2\377\377\377\376\377" \ - "\377\222\377\377\377\3\376\376\376\377\377\377\376\376\376\202\377\377" \ - "\377\3\364\364\364\220\220\220;;=\211::<\2;;=::<\202;;=\2::<;;=\202:" \ - ":<\4;;=::<;;=99;\203::<\2;;=99;\206::<\2GGI\247\247\251\203\377\377\377" \ - "\1\376\376\376\222\377\377\377\6\376\376\376\377\377\377\316\316\316" \ - ";;=99;;;=\202::<\2lln\376\376\376\202\377\377\377\1\376\376\376\221\377" \ - "\377\377\4\376\376\376\333\333\333FFH;;=\202::<\1;;=\202::<\1\265\265" \ - "\265\202\377\377\377\1\376\376\376\202\377\377\377\5\376\376\376\377" \ - "\377\377\376\376\376\377\377\377\316\316\320\202::<\2;;=99;\202;;=\1" \ - "\264\264\266\202\377\377\377\1\376\376\376\244\377\377\377\1\376\376" \ - "\376\202\377\377\377\1\205\205\207\204::<\3;;=FFH\363\363\363\206\377" \ - "\377\377\1\376\376\376\202\377\377\377\3\233\233\233::<;;=\220::<\3""9" \ - "9;;;=99;\202::<\1;;=\203::<\1;;=\204::<\7;;=::\215\307\77" \ - "\214\306>\215\306A\240\214\306>\7\214\306<\214\306>\216\306\77\214\306" \ - ">\214\305@\343\361\320\377\377\375\211\377\377\377\210\214\306>\10\213" \ - "\307A\212\306@\215\305@\212\307<\215\307\77\247\324o\375\377\376\376" \ - "\377\377\211\377\377\377\7\376\377\375\377\377\377\377\377\375\342\360" \ - "\315\214\305@\213\305=\215\307\77\210\214\306>\10\215\305>\215\307\77" \ - "\343\361\316\376\376\376\377\376\377\376\377\377\377\377\375\376\377" \ - "\372\220\377\377\377\10\376\377\377\377\376\377\377\377\375\377\376\374" \ - "\376\377\375\343\362\321\212\307>\214\307;\210\214\306>\4\215\307=\215" \ - "\304B\213\307A\305\342\240\203\377\377\377\1\376\377\377\222\377\377" \ - "\377\21\377\376\377\367\374\365\267\332\206\215\306A\212\306@\214\306" \ - "<\214\306>\215\306A\215\307\77\214\306>\214\305@\212\306B\212\306@\212" \ - "\307<\215\307\77\214\306>\214\305@\202\215\305@\5\214\305@\214\306>\214" \ - "\305@\212\307>\215\306A\202\214\305@\11\214\307;\214\306>\215\306A\214" \ - "\305@\215\305>\212\306@\222\311I\306\343\240\366\373\364\224\377\377" \ - "\377\6\303\342\237\217\304@\214\306<\214\306>\215\306C\212\306B\204\214" \ - "\305@\1\215\306A\202\214\305@\11\215\306A\214\306<\214\306>\341\361\314" \ - "\377\377\377\376\377\375\377\377\377\377\375\377\377\377\375\221\377" \ - "\377\377\10\370\373\364\224\307N\215\305@\215\305>\212\307<\215\306A" \ - "\212\307<\215\306A\210\214\306>\10\215\307=\346\364\332\376\377\375\376" \ - "\377\373\377\377\377\376\376\377\377\376\377\377\377\375\230\377\377" \ - "\377\5\346\346\350\204\204\206GGI::<;;=\202::<\5;;=::<;;=::<;;=\202:" \ - ":<\3;;=::<;;=\202::<\5;;=99;;;=::<;;=\207::<\3FFH\234\234\234\363\363" \ - "\363\203\377\377\377\1\376\376\376\222\377\377\377\1\376\376\376\202" \ - "\377\377\377\4\316\316\316::<;;=99;\202;;=\1kkm\202\377\377\377\1\376" \ - "\376\376\220\377\377\377\1\376\376\376\202\377\377\377\5\376\376\376" \ - "\266\266\26699;;;=::<\202;;=\3::\215\307\77\212\307>\216\306\77\241\214\306" \ - ">\1\215\306C\202\215\305@\5\212\306@\215\307=\343\361\320\377\377\377" \ - "\377\376\377\210\377\377\377\210\214\306>\10\215\305<\215\307\77\216" \ - "\306\77\214\306>\216\305C\252\324r\377\377\377\377\377\373\211\377\377" \ - "\377\7\375\377\376\377\377\377\377\375\376\343\361\316\215\307=\212\307" \ - ">\215\305>\210\214\306>\10\214\305@\215\305<\342\362\316\377\377\375" \ - "\377\376\377\375\377\374\376\376\377\376\377\377\222\377\377\377\1\375" \ - "\377\372\202\377\377\377\3\377\376\377\304\341\237\215\307\77\210\214" \ - "\306>\10\212\307;\215\307\77\213\305=\305\342\240\377\377\377\377\376" \ - "\374\377\377\375\376\377\377\221\377\377\377\22\377\376\377\377\377\375" \ - "\376\377\377\377\375\376\361\367\351\270\334\204\214\306>\215\307\77" \ - "\214\305@\212\306@\213\307A\212\306@\213\310\77\214\306>\215\304B\214" \ - "\306>\212\307<\214\306>\202\216\306A\6\214\306>\213\310\77\214\305@\215" \ - "\305<\215\305>\215\307=\202\213\310\77\10\215\306A\214\306>\215\306A" \ - "\222\311I\300\336\226\361\370\346\376\376\376\377\377\377\202\377\376" \ - "\377\1\376\377\373\217\377\377\377\10\377\377\375\347\365\333\214\307" \ - ";\211\305A\213\304\77\215\307\77\215\305<\213\310\77\202\214\306>\1\215" \ - "\307\77\203\214\306>\4\215\307\77\214\306>\215\306A\275\337\223\202\377" \ - "\377\377\5\377\376\377\377\377\377\376\377\375\377\376\377\376\377\377" \ - "\220\377\377\377\10\375\377\376\331\357\301\215\307\77\215\305>\216\305" \ - "C\211\306=\220\305A\211\307@\210\214\306>\10\214\305@\246\321e\377\377" \ - "\377\377\376\377\376\377\377\377\377\375\376\377\377\377\376\377\227" \ - "\377\377\377\1\376\376\376\202\377\377\377\3\363\363\363\266\266\270" \ - "__a\207::<\202;;=\203::<\2;;=99;\202;;=\2""99;::<\202;;=\1::<\203;;=" \ - "\3^^^\250\250\250\363\363\363\203\377\377\377\1\376\376\376\202\377\377" \ - "\377\1\376\376\376\224\377\377\377\4\316\316\316999::<;;=\202::<\1ll" \ - "l\205\377\377\377\1\376\376\376\217\377\377\377\6\376\376\376\377\377" \ - "\377\376\376\376\204\204\204::<;;=\203::<\3:::TTT\363\363\363\206\377" \ - "\377\377\10\347\347\347;;;99;::<;;=::<:::\234\234\236\253\377\377\377" \ - "\3\376\376\376lln;;=\202::<\3;;=999SSS\202\377\377\377\1\376\376\376" \ - "\203\377\377\377\4\376\376\376\377\377\377\376\376\376\234\234\234\223" \ - "::<\1""99;\202::<\1;;=\203::<\5kkmxxz\235\235\237\301\301\301\346\346" \ - "\346\207\377\377\377\1\376\376\376\202\377\377\377\1\376\376\376\221" \ - "\377\377\377\1\376\376\376\202\377\377\377\3\235\235\235::<;;=\232::" \ - "<\2;;=99;\202::<\3;;=::<\316\316\316\230\377\377\377\10\373\377\376\216" \ - "\306A\214\306<\213\304A\212\306@\214\305@\214\304\77\215\307\77\240\214" \ - "\306>\6\214\306<\215\306A\215\305@\216\310@\217\304@\341\361\314\212" \ - "\377\377\377\210\214\306>\7\215\307\77\213\310\77\213\305=\215\307\77" \ - "\214\304\77\253\323r\374\377\373\211\377\377\377\1\377\376\377\203\377" \ - "\377\377\3\342\362\315\215\305@\215\307=\211\214\306>\10\214\306<\215" \ - "\304B\341\363\313\374\377\375\376\376\377\377\377\377\377\375\376\377" \ - "\377\375\221\377\377\377\7\376\377\375\376\376\377\377\377\377\375\377" \ - "\374\377\377\377\377\377\375\253\323p\210\214\306>\5\215\307\77\215\305" \ - ">\217\304@\305\342\237\376\377\375\202\377\377\377\1\377\377\375\220" \ - "\377\377\377\1\376\377\377\202\377\376\377\202\376\377\375\202\377\377" \ - "\377\5\360\370\351\311\347\247\245\320e\215\305>\212\307>\202\214\306" \ - ">\5\215\306A\212\307>\215\305@\214\306>\214\306<\202\214\306>\2\214\306" \ - "<\214\306>\202\216\306A\14\214\306>\215\306A\215\305<\214\306>\213\305" \ - "=\255\331x\323\353\267\366\374\362\377\377\377\377\377\375\377\377\377" \ - "\376\377\377\217\377\377\377\2\376\376\376\377\377\377\202\377\377\375" \ - "\11\244\317d\214\306>\213\307A\214\306>\214\305@\214\306>\215\306A\214" \ - "\306<\215\307\77\202\214\306>\202\214\305@\13\215\305<\215\305@\230\316" \ - "V\370\373\360\376\377\375\377\377\377\377\376\377\376\376\376\377\377" \ - "\375\377\376\377\376\377\377\220\377\377\377\10\376\376\376\377\376\377" \ - "\262\327x\214\306>\216\306A\215\307=\215\305<\215\306A\211\214\306>\6" \ - "\215\306C\307\341\240\376\377\373\376\377\377\376\377\375\376\376\374" \ - "\236\377\377\377\4\346\346\350\266\266\270\204\204\206SSU\202::<\1;;" \ - "=\202::<\1;;=\202::<\202;;=\3""99;::<;;=\203::<\4GGIxxz\247\247\247\347" \ - "\347\347\212\377\377\377\1\376\376\376\223\377\377\377\1\364\364\364" \ - "\205\316\316\316\1\332\332\332\203\377\377\377\202\376\376\376\221\377" \ - "\377\377\1\376\376\376\202\377\377\377\202\316\316\316\203\316\316\320" \ - "\3\316\316\316\317\317\317\346\346\346\206\377\377\377\5\346\346\346" \ - "\316\316\316\317\317\317\316\316\316\315\315\315\202\316\316\316\1\363" \ - "\363\363\250\377\377\377\1\376\376\376\203\377\377\377\3\346\346\346" \ - "\315\315\315\317\317\317\202\316\316\320\3\317\317\317\315\315\315\363" \ - "\363\363\202\377\377\377\202\376\376\376\204\377\377\377\3\346\346\346" \ - "\316\316\316\316\316\320\224\316\316\316\1\315\315\315\203\377\377\377" \ - "\1\376\376\376\215\377\377\377\1\376\376\376\225\377\377\377\2\346\346" \ - "\346\317\317\317\232\316\316\316\1\317\317\317\203\316\316\316\4\317" \ - "\317\317\315\315\315\316\316\316\363\363\363\231\377\377\377\3\340\361" \ - "\317\342\360\317\342\362\316\202\343\361\316\2\342\360\315\343\361\316" \ - "\240\342\361\320\10\342\362\316\342\361\320\343\363\317\341\360\317\342" \ - "\361\320\370\373\364\376\377\375\376\377\377\210\377\377\377\210\342" \ - "\361\320\7\341\360\317\342\362\316\343\361\316\342\360\314\342\361\320" \ - "\350\364\336\377\376\374\211\377\377\377\10\377\376\377\377\377\375\377" \ - "\377\377\377\377\375\370\373\362\341\360\321\340\357\316\342\362\316" \ - "\210\342\361\320\3\342\362\316\342\361\320\371\373\360\203\377\377\377" \ - "\202\377\376\377\220\377\377\377\4\377\377\375\376\376\376\377\376\377" \ - "\376\377\375\203\377\377\377\1\365\375\362\210\342\361\320\4\341\360" \ - "\321\342\361\322\343\363\317\360\367\345\224\377\377\377\7\376\377\377" \ - "\376\377\375\377\377\375\377\376\377\377\377\375\377\375\376\377\376" \ - "\377\202\377\377\377\30\376\376\377\364\370\351\333\354\277\277\337\224" \ - "\247\324k\224\313K\214\305@\214\306>\212\306@\214\306>\214\305B\215\306" \ - "C\215\307\77\212\306@\214\306>\215\307\77\241\321c\257\330|\304\342\242" \ - "\341\361\315\377\377\377\377\376\377\376\377\373\377\377\377\202\377" \ - "\377\375\1\377\376\377\203\377\377\377\1\376\377\377\212\377\377\377" \ - "\1\376\376\376\203\377\377\377\13\376\376\374\372\372\370\342\361\320" \ - "\343\361\316\342\362\316\341\360\317\342\361\320\341\360\317\342\362" \ - "\316\342\361\322\342\361\320\202\341\361\315\6\342\361\320\341\360\317" \ - "\343\361\315\343\361\320\356\371\350\377\376\377\203\377\377\377\1\376" \ - "\377\375\202\377\377\377\1\376\377\375\222\377\377\377\6\366\373\364" \ - "\342\361\320\342\362\316\342\360\317\341\362\316\343\361\320\210\342" \ - "\361\320\10\341\362\316\341\361\315\352\364\334\377\377\377\377\376\377" \ - "\377\377\377\376\377\377\376\377\375\222\377\377\377\202\376\376\376" \ - "\202\377\377\377\1\376\376\376\202\377\377\377\1\376\376\376\202\377" \ - "\377\377\3\376\376\376\377\377\377\375\375\375\202\377\377\377\5\363" \ - "\363\363\316\316\316\264\264\264\235\235\235\233\233\233\202kkk\202k" \ - "km\3llnkkmyy{\202\234\234\236\6\316\316\320\346\346\346\377\377\377\376" \ - "\376\376\377\377\377\376\376\376\204\377\377\377\1\376\376\376\204\377" \ - "\377\377\1\376\376\376\240\377\377\377\1\376\376\376\231\377\377\377" \ - "\1\375\375\375\203\377\377\377\1\376\376\376\214\377\377\377\1\376\376" \ - "\376\202\377\377\377\1\376\376\376\242\377\377\377\1\376\376\376\206" \ - "\377\377\377\3\376\376\376\377\377\377\376\376\376\204\377\377\377\1" \ - "\376\376\376\202\377\377\377\202\376\376\376\225\377\377\377\3\376\376" \ - "\376\377\377\377\376\376\376\202\377\377\377\3\376\376\376\377\377\377" \ - "\376\376\376\214\377\377\377\3\376\376\376\377\377\377\376\376\376\265" \ - "\377\377\377\1\375\375\375\234\377\377\377\7\376\377\377\377\376\377" \ - "\376\377\377\376\376\374\377\376\377\377\377\377\377\377\375\240\377" \ - "\377\377\1\377\377\375\202\377\377\377\5\377\376\377\376\376\376\377" \ - "\376\377\376\376\377\377\377\375\221\377\377\377\7\375\376\377\377\377" \ - "\377\377\376\377\377\377\375\376\377\377\377\377\373\377\376\377\210" \ - "\377\377\377\5\377\376\377\377\377\377\376\376\374\376\377\377\377\377" \ - "\377\202\377\377\375\1\376\377\377\210\377\377\377\6\376\377\377\375" \ - "\376\377\377\376\377\377\377\377\376\377\377\377\377\377\202\377\377" \ - "\375\224\377\377\377\202\377\376\377\2\374\377\377\377\376\377\210\377" \ - "\377\377\3\376\377\377\376\376\376\376\377\377\202\377\377\377\3\375" \ - "\377\376\377\377\377\377\376\377\220\377\377\377\202\377\376\377\2\376" \ - "\377\377\375\376\377\202\377\377\377\4\377\377\375\377\376\377\377\377" \ - "\377\377\377\375\202\376\377\377\7\377\377\377\377\376\377\377\377\377" \ - "\376\377\375\370\373\364\344\357\315\342\361\320\202\342\362\315\14\340" \ - "\357\316\345\360\316\376\377\373\376\376\376\377\377\377\377\375\376" \ - "\377\377\375\377\377\377\375\377\376\377\377\377\377\376\377\377\377" \ - "\375\202\376\377\375\5\376\377\377\377\377\377\377\377\375\376\376\376" \ - "\377\376\377\214\377\377\377\1\376\376\376\202\377\377\377\5\377\377" \ - "\375\376\375\377\377\377\377\376\376\377\377\377\375\204\377\377\377" \ - "\1\377\377\375\205\377\377\377\202\377\376\377\2\377\377\377\377\377" \ - "\375\202\377\377\377\202\376\377\377\222\377\377\377\5\377\377\375\377" \ - "\377\377\377\377\375\377\377\377\377\377\375\202\377\377\377\1\377\376" \ - "\372\212\377\377\377\1\377\375\377\202\377\377\377\3\377\376\377\377" \ - "\377\377\377\377\375\225\377\377\377\1\376\376\376\211\377\377\377\1" \ - "\376\376\376\204\377\377\377\1\376\376\376\205\377\377\377\1\376\376" \ - "\376\206\377\377\377\3\376\376\376\377\377\377\376\376\376\206\377\377" \ - "\377\1\376\376\376\233\377\377\377\1\376\376\376\203\377\377\377\5\376" \ - "\376\376\377\377\377\376\376\376\377\377\377\376\376\376\223\377\377" \ - "\377\3\376\376\376\377\377\377\376\376\376\205\377\377\377\3\376\376" \ - "\376\377\377\377\376\376\376\203\377\377\377\3\376\376\376\377\377\377" \ - "\376\376\376\203\377\377\377\1\376\376\376\205\377\377\377\1\376\376" \ - "\376\246\377\377\377\3\376\376\376\377\377\377\376\376\376\220\377\377" \ - "\377\1\376\376\376\246\377\377\377\1\376\376\376\225\377\377\377\1\376" \ - "\376\376\202\377\377\377\1\376\376\376\240\377\377\377\1\376\376\376" \ - "\230\377\377\377\6\377\377\375\377\377\377\377\376\377\376\377\375\374" \ - "\377\377\376\375\377\242\377\377\377\202\377\376\377\6\376\376\376\375" \ - "\376\377\377\377\377\377\377\375\377\377\377\376\377\375\220\377\377" \ - "\377\7\377\377\375\377\377\377\377\377\375\377\375\376\376\377\375\376" \ - "\377\377\376\376\376\212\377\377\377\4\377\376\377\377\377\375\377\377" \ - "\377\377\377\375\203\377\376\377\210\377\377\377\5\377\377\375\377\377" \ - "\377\377\375\376\377\376\377\377\377\375\202\377\377\377\1\376\377\377" \ - "\221\377\377\377\1\375\376\377\203\377\377\375\2\376\377\375\377\375" \ - "\376\211\377\377\377\204\377\376\377\4\377\377\377\376\377\375\377\377" \ - "\375\377\376\377\221\377\377\377\5\376\377\377\376\376\376\377\377\373" \ - "\376\376\377\376\377\377\202\377\377\377\2\377\376\377\377\377\375\202" \ - "\377\377\377\7\377\377\375\377\376\377\376\376\377\377\377\377\376\377" \ - "\377\376\377\375\376\377\377\202\377\377\377\203\376\377\377\2\377\377" \ - "\377\376\376\374\202\377\376\377\13\376\376\376\377\377\375\377\377\377" \ - "\377\375\376\376\377\377\377\377\377\376\376\377\377\376\377\376\376" \ - "\374\376\377\377\377\377\375\221\377\377\377\203\377\377\375\4\377\377" \ - "\377\377\377\375\377\376\377\376\376\376\210\377\377\377\1\377\377\373" \ - "\203\377\377\377\1\377\377\375\202\376\377\377\222\377\377\377\1\377" \ - "\377\375\202\377\376\377\3\377\377\377\377\376\377\377\376\374\202\376" \ - "\377\377\210\377\377\377\4\377\377\375\377\377\377\376\377\375\377\375" \ - "\377\202\376\377\377\1\377\376\375\227\377\377\377\1\376\376\376\207" \ - "\377\377\377\1\376\376\376\217\377\377\377\1\376\376\376\205\377\377" \ - "\377\1\376\376\376\204\377\377\377\1\376\376\376\233\377\377\377\1\376" \ - "\376\376\211\377\377\377\1\376\376\376\222\377\377\377\1\376\376\376" \ - "\206\377\377\377\1\376\376\376\207\377\377\377\1\376\376\376\262\377" \ - "\377\377\1\376\376\376\212\377\377\377\1\376\376\376\202\377\377\377" \ - "\1\376\376\376\202\377\377\377\1\376\376\376\225\377\377\377\1\376\376" \ - "\376\306\377\377\377\1\376\376\376\235\377\377\377\7\377\376\377\376" \ - "\377\377\377\377\377\377\377\375\376\375\377\377\377\375\377\376\377" \ - "\241\377\377\377\1\376\377\377\203\377\377\377\3\377\377\375\377\375" \ - "\376\377\376\377\221\377\377\377\202\376\377\377\5\377\377\377\377\377" \ - "\375\377\377\377\377\376\377\377\377\375\211\377\377\377\203\377\377" \ - "\375\202\377\377\377\202\376\377\377\1\377\377\375\212\377\377\377\202" \ - "\376\377\375\3\376\377\377\377\377\375\377\376\377\223\377\377\377\6" \ - "\377\377\375\377\376\377\374\377\377\377\377\377\377\376\377\376\377" \ - "\375\210\377\377\377\3\377\377\375\376\377\377\377\377\375\202\377\377" \ - "\377\1\377\377\375\223\377\377\377\4\376\376\376\377\377\375\376\376" \ - "\376\377\376\377\202\377\377\375\1\376\376\376\206\377\377\377\1\377" \ - "\377\375\215\377\377\377\1\377\377\375\202\377\377\377\5\376\377\377" \ - "\377\377\377\376\376\374\377\377\377\377\376\377\202\377\377\377\1\376" \ - "\376\376\221\377\377\377\7\376\377\375\377\375\377\377\377\377\376\377" \ - "\377\377\377\377\377\377\373\377\376\377\202\377\377\377\1\377\377\375" \ - "\202\377\377\377\1\377\377\375\204\377\377\377\6\376\376\377\377\377" \ - "\375\376\377\377\377\377\375\377\376\377\375\377\374\222\377\377\377" \ - "\3\376\377\375\377\377\377\376\377\375\203\376\377\377\1\377\376\377" \ - "\211\377\377\377\7\377\377\373\377\376\377\377\377\375\377\377\377\377" \ - "\376\377\376\376\376\376\377\377") - - diff --git a/meta-agl/recipes-core/psplash/files/psplash-quit.service b/meta-agl/recipes-core/psplash/files/psplash-quit.service deleted file mode 100644 index 14bd4994b..000000000 --- a/meta-agl/recipes-core/psplash/files/psplash-quit.service +++ /dev/null @@ -1,11 +0,0 @@ -[Unit] -Description=Terminate Psplash Boot Screen -After=psplash-start.service - -[Service] -Type=oneshot -ExecStart=/usr/bin/psplash-write QUIT -TimeoutSec=20 - -[Install] -WantedBy=multi-user.target diff --git a/meta-agl/recipes-core/psplash/files/psplash-start.service b/meta-agl/recipes-core/psplash/files/psplash-start.service deleted file mode 100644 index d3b6940d0..000000000 --- a/meta-agl/recipes-core/psplash/files/psplash-start.service +++ /dev/null @@ -1,12 +0,0 @@ -[Unit] -Description=Start Psplash Boot Screen -Wants=systemd-vconsole-setup.service -After=systemd-vconsole-setup.service systemd-udev-trigger.service systemd-udevd.service -DefaultDependencies=no - -[Service] -ExecStartPre=/bin/sh -c "if [ -e /sys/class/graphics/fbcon/cursor_blink ]; then echo 0 > /sys/class/graphics/fbcon/cursor_blink; fi" -ExecStart=/bin/bash -c "/usr/bin/psplash-anim -n -a 90" - -[Install] -WantedBy=sysinit.target diff --git a/meta-agl/recipes-core/psplash/psplash_git.bbappend b/meta-agl/recipes-core/psplash/psplash_git.bbappend deleted file mode 100644 index bdc196b6f..000000000 --- a/meta-agl/recipes-core/psplash/psplash_git.bbappend +++ /dev/null @@ -1,27 +0,0 @@ -FILESEXTRAPATHS_prepend := "${THISDIR}/files:" - -SRC_URI += "file://psplash-colors.h \ - file://psplash-start.service \ - file://psplash-quit.service \ - file://psplash-anim \ - " - -SPLASH_IMAGES="file://psplash-poky-img.h;outsuffix=default" - -inherit systemd - -SYSTEMD_PACKAGES = "${@bb.utils.contains('DISTRO_FEATURES', 'systemd', '${PN}', '', d)}" -SYSTEMD_SERVICE_${PN} = "${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'psplash-start.service psplash-quit.service', '', d)}" - -do_configure_append () { - cd ${S} - cp ../psplash-colors.h ./ -} - -do_install_append () { - if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)}; then - install -d ${D}${systemd_unitdir}/system - install -m 644 ${WORKDIR}/*.service ${D}/${systemd_unitdir}/system - fi - install -m 755 ${WORKDIR}/psplash-anim ${D}/${bindir} -} diff --git a/meta-agl/recipes-core/systemd/.appends.core b/meta-agl/recipes-core/systemd/.appends.core deleted file mode 100644 index e69de29bb..000000000 diff --git a/meta-agl/recipes-core/systemd/systemd/0001-Switch-Smack-label-earlier.patch b/meta-agl/recipes-core/systemd/systemd/0001-Switch-Smack-label-earlier.patch deleted file mode 100644 index 46445be73..000000000 --- a/meta-agl/recipes-core/systemd/systemd/0001-Switch-Smack-label-earlier.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 6cc74075797edb6f698cb7f312bb1c3d8cc6cb28 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jos=C3=A9=20Bollo?= -Date: Thu, 12 Oct 2017 17:17:56 +0200 -Subject: [PATCH] Switch Smack label earlier -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Switching label after removing capability isn't -possible. - -Change-Id: Ib7dac8f071f36119520ed3205d743c1e3df3cd5e -Signed-off-by: José Bollo ---- - src/core/execute.c | 14 +++++++------- - 1 file changed, 7 insertions(+), 7 deletions(-) - -diff --git a/src/core/execute.c b/src/core/execute.c -index d72e5bf08..0abffd569 100644 ---- a/src/core/execute.c -+++ b/src/core/execute.c -@@ -2707,6 +2707,13 @@ static int exec_child( - } - } - -+ r = setup_smack(context, command); -+ if (r < 0) { -+ *exit_status = EXIT_SMACK_PROCESS_LABEL; -+ *error_message = strdup("Failed to set SMACK process label"); -+ return r; -+ } -+ - if (!cap_test_all(context->capability_bounding_set)) { - r = capability_bounding_set_drop(context->capability_bounding_set, false); - if (r < 0) { -@@ -2775,13 +2782,6 @@ static int exec_child( - } - #endif - -- r = setup_smack(context, command); -- if (r < 0) { -- *exit_status = EXIT_SMACK_PROCESS_LABEL; -- *error_message = strdup("Failed to set SMACK process label"); -- return r; -- } -- - #ifdef HAVE_APPARMOR - if (context->apparmor_profile && mac_apparmor_use()) { - r = aa_change_onexec(context->apparmor_profile); --- -2.14.3 - diff --git a/meta-agl/recipes-core/systemd/systemd/e2fsck.conf b/meta-agl/recipes-core/systemd/systemd/e2fsck.conf deleted file mode 100644 index b774f9ebf..000000000 --- a/meta-agl/recipes-core/systemd/systemd/e2fsck.conf +++ /dev/null @@ -1,3 +0,0 @@ -[options] -# This will prevent e2fsck from stopping boot just because the clock is wrong -broken_system_clock = 1 diff --git a/meta-agl/recipes-core/systemd/systemd/wired.network b/meta-agl/recipes-core/systemd/systemd/wired.network deleted file mode 100644 index 3559b0155..000000000 --- a/meta-agl/recipes-core/systemd/systemd/wired.network +++ /dev/null @@ -1,5 +0,0 @@ -[Match] -Name=eth* en* - -[Network] -DHCP=yes diff --git a/meta-agl/recipes-core/systemd/systemd_%.bbappend b/meta-agl/recipes-core/systemd/systemd_%.bbappend deleted file mode 100644 index f64ca8c8a..000000000 --- a/meta-agl/recipes-core/systemd/systemd_%.bbappend +++ /dev/null @@ -1,26 +0,0 @@ -FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" - -SRC_URI += "\ - file://e2fsck.conf \ - ${@bb.utils.contains('VIRTUAL-RUNTIME_net_manager','systemd','file://wired.network','',d)} \ -" - -# enable networkd/resolved support -PACKAGECONFIG_append_pn-systemd = " \ - ${@bb.utils.contains('VIRTUAL-RUNTIME_net_manager','systemd','networkd resolved','',d)} \ -" - -do_install_append() { - # Install /etc/e2fsck.conf to avoid boot stuck by wrong clock time - install -m 644 -p -D ${WORKDIR}/e2fsck.conf ${D}${sysconfdir}/e2fsck.conf - - if ${@bb.utils.contains('VIRTUAL-RUNTIME_net_manager','systemd','true','false',d)}; then - # Install DHCP configuration for Ethernet adapters - install -m 644 ${WORKDIR}/wired.network ${D}${sysconfdir}/systemd/network - fi -} - -FILES_${PN} += "${sysconfdir}/e2fsck.conf " - -# SPEC-737: connmand also has a NTP client which races with systemd-timesyncd -PACKAGECONFIG_remove = "timesyncd" diff --git a/meta-agl/recipes-core/systemd/systemd_234.bbappend b/meta-agl/recipes-core/systemd/systemd_234.bbappend deleted file mode 100644 index 4df7684d0..000000000 --- a/meta-agl/recipes-core/systemd/systemd_234.bbappend +++ /dev/null @@ -1,6 +0,0 @@ -FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" - -SRC_URI += "\ - file://0001-Switch-Smack-label-earlier.patch \ -" - diff --git a/meta-agl/recipes-devtools/gdb/gdb_%.bbappend b/meta-agl/recipes-devtools/gdb/gdb_%.bbappend deleted file mode 100644 index 7cba933af..000000000 --- a/meta-agl/recipes-devtools/gdb/gdb_%.bbappend +++ /dev/null @@ -1 +0,0 @@ -PACKAGECONFIG_remove = "readline" diff --git a/meta-agl/recipes-devtools/low-level-can-generator/low-level-can-generator_git.bb b/meta-agl/recipes-devtools/low-level-can-generator/low-level-can-generator_git.bb deleted file mode 100644 index d364939b5..000000000 --- a/meta-agl/recipes-devtools/low-level-can-generator/low-level-can-generator_git.bb +++ /dev/null @@ -1,16 +0,0 @@ -SUMMARY = "Low level CAN generator" -DESCRIPTION = "Generator used to customize low level CAN service with customs signals" -SECTION = "devel" - -LICENSE = "Apache-2.0" -LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10" - -inherit cmake pkgconfig -BBCLASSEXTEND = "nativesdk" - -SRC_URI = "gitsm://gerrit.automotivelinux.org/gerrit/src/low-level-can-generator;protocol=https;branch=${AGL_BRANCH}" -SRCREV = "92f95384ce4b4a198b1fea93272201421f7b9a39" - -PV = "4.0+git${SRCPV}" -S = "${WORKDIR}/git" - diff --git a/meta-agl/recipes-devtools/packagegroups/nativesdk-packagegroup-sdk-host.bbappend b/meta-agl/recipes-devtools/packagegroups/nativesdk-packagegroup-sdk-host.bbappend deleted file mode 100644 index 504a019b4..000000000 --- a/meta-agl/recipes-devtools/packagegroups/nativesdk-packagegroup-sdk-host.bbappend +++ /dev/null @@ -1 +0,0 @@ -RDEPENDS_${PN} += "nativesdk-low-level-can-generator" diff --git a/meta-agl/recipes-devtools/packagegroups/packagegroup-agl-devel.bb b/meta-agl/recipes-devtools/packagegroups/packagegroup-agl-devel.bb deleted file mode 100644 index ade8560ab..000000000 --- a/meta-agl/recipes-devtools/packagegroups/packagegroup-agl-devel.bb +++ /dev/null @@ -1,24 +0,0 @@ -SUMMARY = "Provides a set of tools for development for AGL DISTRO" -LICENSE = "MIT" - -inherit packagegroup - -RDEPENDS_${PN} = "\ - strace \ - ldd \ - less \ - vim \ - lsof \ - gdb \ - valgrind \ - perf \ - htop \ - powertop \ - latencytop \ - systemtap \ - screen \ - usbutils \ - rsync \ - tree \ - pstree \ - " diff --git a/meta-agl/recipes-devtools/run-agl-postinsts/run-agl-postinsts/run-agl-postinsts b/meta-agl/recipes-devtools/run-agl-postinsts/run-agl-postinsts/run-agl-postinsts deleted file mode 100755 index 1d1a5a059..000000000 --- a/meta-agl/recipes-devtools/run-agl-postinsts/run-agl-postinsts/run-agl-postinsts +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/sh -# -# Copyright 2017 IoT.bzh. - -# Author: Ronan Le Martret -# - -# The following script will run all the scriptlets found in #SYSCONFDIR#/agl-postinsts. - -agl_pi_dir="#SYSCONFDIR#/agl-postinsts" - -POSTINST_LOGGING=1 -LOGFILE=/var/log/agl-postinstall.log - -[ -e $LOGFILE ] && mv ${LOGFILE} ${LOGFILE}.old.$(date +%F--%H%M.%S) - -append_log=">>$LOGFILE 2>&1" - -exec_postinst_scriptlets() { - for i in `ls $agl_pi_dir`; do - i=$agl_pi_dir/$i - echo "Running postinst $i..." - [ "$POSTINST_LOGGING" = "1" ] && eval echo "Running postinst $i..." $append_log - if [ -x $i ]; then - eval sh -c $i $append_log - if [ $? -eq 0 ]; then - rm $i - else - echo "ERROR: postinst $i failed." - [ "$POSTINST_LOGGING" = "1" ] && eval echo "ERROR: postinst $i failed." $append_log - remove_agl_pi_dir=0 - fi - else - echo "ERROR: postinst $i do not exists or do not have execute permission." - [ "$POSTINST_LOGGING" = "1" ] && eval echo "ERROR: postinst $i do not exists or do not have execute permission." $append_log - remove_agl_pi_dir=0 - fi - done -} - -remove_agl_pi_dir=1 -exec_postinst_scriptlets -systemctl daemon-reload - -# since all postinstalls executed successfully, remove the postinstalls directory -if [ $remove_agl_pi_dir = 1 ]; then - rm -rf $agl_pi_dir -fi diff --git a/meta-agl/recipes-devtools/run-agl-postinsts/run-agl-postinsts/run-agl-postinsts.service b/meta-agl/recipes-devtools/run-agl-postinsts/run-agl-postinsts/run-agl-postinsts.service deleted file mode 100644 index 8f8667db6..000000000 --- a/meta-agl/recipes-devtools/run-agl-postinsts/run-agl-postinsts/run-agl-postinsts.service +++ /dev/null @@ -1,17 +0,0 @@ -[Unit] -Description=Run pending agl postinsts -DefaultDependencies=no -After=#SYSTEMD_SERVICE_AFTER# -Before=#SYSTEMD_SERVICE_BEFORE# -ConditionPathExists=#SYSCONFDIR#/agl-postinsts - -[Service] -Type=oneshot -StandardOutput=journal+console -ExecStart=#SBINDIR#/run-agl-postinsts -ExecStartPost=#BASE_BINDIR#/systemctl disable run-agl-postinsts.service -RemainAfterExit=No -TimeoutSec=0 - -[Install] -WantedBy=multi-user.target diff --git a/meta-agl/recipes-devtools/run-agl-postinsts/run-agl-postinsts_1.0.bb b/meta-agl/recipes-devtools/run-agl-postinsts/run-agl-postinsts_1.0.bb deleted file mode 100644 index b1ecccf85..000000000 --- a/meta-agl/recipes-devtools/run-agl-postinsts/run-agl-postinsts_1.0.bb +++ /dev/null @@ -1,46 +0,0 @@ -SUMMARY = "Runs AGL postinstall scripts on first boot of the target device" -SECTION = "devel" - -LICENSE = "MIT" -LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" - -SRC_URI = "file://run-agl-postinsts \ - file://run-agl-postinsts.service" - -S = "${WORKDIR}" - -inherit allarch systemd - -SYSTEMD_SERVICE_${PN} = "run-agl-postinsts.service" - -SYSTEMD_SERVICE_AFTER ?= "dbus.service cynara.service" - -SYSTEMD_SERVICE_BEFORE ?= "systemd-user-sessions.service" - -do_configure() { - : -} - -do_compile () { - : -} - -do_install() { - install -d ${D}${sbindir} - install -m 0755 ${WORKDIR}/run-agl-postinsts ${D}${sbindir}/ - - install -d ${D}${systemd_unitdir}/system/ - install -m 0644 ${WORKDIR}/run-agl-postinsts.service ${D}${systemd_unitdir}/system/ - - sed -i -e 's:#SYSCONFDIR#:${sysconfdir}:g' \ - -e 's:#SBINDIR#:${sbindir}:g' \ - -e 's:#BASE_BINDIR#:${base_bindir}:g' \ - -e 's:#LOCALSTATEDIR#:${localstatedir}:g' \ - ${D}${sbindir}/run-agl-postinsts \ - ${D}${systemd_unitdir}/system/run-agl-postinsts.service - - sed -i -e 's:#SYSTEMD_SERVICE_AFTER#:${SYSTEMD_SERVICE_AFTER}:g' \ - -e 's:#SYSTEMD_SERVICE_BEFORE#:${SYSTEMD_SERVICE_BEFORE}:g' \ - ${D}${systemd_unitdir}/system/run-agl-postinsts.service -} - diff --git a/meta-agl/recipes-devtools/run-postinsts/run-postinsts_%.bbappend b/meta-agl/recipes-devtools/run-postinsts/run-postinsts_%.bbappend deleted file mode 100644 index fc327b6ef..000000000 --- a/meta-agl/recipes-devtools/run-postinsts/run-postinsts_%.bbappend +++ /dev/null @@ -1,5 +0,0 @@ -do_configure_append() { - if ! grep -q StandardOutput= ${WORKDIR}/run-postinsts.service; then - sed -i '/ExecStart=/iStandardOutput=journal+console' ${WORKDIR}/run-postinsts.service - fi -} diff --git a/meta-agl/recipes-graphics/agl-desktop-config/agl-desktop-config_0.1.bb b/meta-agl/recipes-graphics/agl-desktop-config/agl-desktop-config_0.1.bb deleted file mode 100644 index e0358d615..000000000 --- a/meta-agl/recipes-graphics/agl-desktop-config/agl-desktop-config_0.1.bb +++ /dev/null @@ -1,21 +0,0 @@ -SUMMARY = "AGL desktop config" - -LICENSE = "MIT" -LIC_FILES_CHKSUM = "file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420" - -SRC_URI += " \ - file://user-weston-term.service \ - file://user-weston-term.path \ -" - -do_install_append() { - install -d ${D}${systemd_user_unitdir} - install -m 0644 ${WORKDIR}/user-weston-term.service ${D}${systemd_user_unitdir} - install -m 0644 ${WORKDIR}/user-weston-term.path ${D}${systemd_user_unitdir} - - install -d ${D}${systemd_user_unitdir}/default.target.wants - ln -sf ${systemd_user_unitdir}/user-weston-term.path ${D}${libdir}/systemd/user/default.target.wants -} - -FILES_${PN} += "${systemd_user_unitdir}/*" -FILES_${PN} += "${systemd_user_unitdir}/default.target.wants/default.target.wants" diff --git a/meta-agl/recipes-graphics/agl-desktop-config/files/user-weston-term.path b/meta-agl/recipes-graphics/agl-desktop-config/files/user-weston-term.path deleted file mode 100644 index 9481840e5..000000000 --- a/meta-agl/recipes-graphics/agl-desktop-config/files/user-weston-term.path +++ /dev/null @@ -1,8 +0,0 @@ -[Unit] -Description=Terminal for weston user unit path - -[Path] -PathExists=%t/wayland-0 - -[Install] -WantedBy=default.target diff --git a/meta-agl/recipes-graphics/agl-desktop-config/files/user-weston-term.service b/meta-agl/recipes-graphics/agl-desktop-config/files/user-weston-term.service deleted file mode 100644 index ad8b9583b..000000000 --- a/meta-agl/recipes-graphics/agl-desktop-config/files/user-weston-term.service +++ /dev/null @@ -1,12 +0,0 @@ -[Unit] -Description=Terminal for weston user -After=user-config.service -Requires=user-config.service - -[Service] -Type=simple -ExecStart=/usr/bin/weston-terminal -Restart=always - -[Install] -WantedBy=multi-user.target diff --git a/meta-agl/recipes-graphics/images/agl-image-weston.bb b/meta-agl/recipes-graphics/images/agl-image-weston.bb deleted file mode 100644 index 427132ed6..000000000 --- a/meta-agl/recipes-graphics/images/agl-image-weston.bb +++ /dev/null @@ -1,12 +0,0 @@ -SUMMARY = "A very basic Wayland image with a terminal" - -require agl-image-weston.inc - -LICENSE = "MIT" - -IMAGE_INSTALL_append = "\ - packagegroup-agl-image-weston \ - " - -DISTRO_FEATURES_append = " agl-core-image-profile" -IMAGE_INSTALL_append = " agl-desktop-config" diff --git a/meta-agl/recipes-graphics/images/agl-image-weston.inc b/meta-agl/recipes-graphics/images/agl-image-weston.inc deleted file mode 100644 index 947d22b50..000000000 --- a/meta-agl/recipes-graphics/images/agl-image-weston.inc +++ /dev/null @@ -1,7 +0,0 @@ -require recipes-core/images/agl-image-minimal.inc - -IMAGE_FEATURES += "splash package-management ssh-server-dropbear" - -inherit distro_features_check - -REQUIRED_DISTRO_FEATURES = "wayland" diff --git a/meta-agl/recipes-graphics/packagegroups/packagegroup-agl-image-weston.bb b/meta-agl/recipes-graphics/packagegroups/packagegroup-agl-image-weston.bb deleted file mode 100644 index dcf21bcfb..000000000 --- a/meta-agl/recipes-graphics/packagegroups/packagegroup-agl-image-weston.bb +++ /dev/null @@ -1,17 +0,0 @@ -DESCRIPTION = "The minimal set of packages required for basic Wayland image" -LICENSE = "MIT" - -inherit packagegroup - -PACKAGES = "\ - packagegroup-agl-image-weston \ - " - -ALLOW_EMPTY_${PN} = "1" - -RDEPENDS_${PN} += "weston weston-init weston-ini-conf weston-examples" -RDEPENDS_${PN} += "agl-login-manager" - -RDEPENDS_${PN} += "\ - packagegroup-agl-image-minimal \ - " diff --git a/meta-agl/recipes-graphics/wayland/Readme.weston-ini-conf b/meta-agl/recipes-graphics/wayland/Readme.weston-ini-conf deleted file mode 100644 index bbd5a80c4..000000000 --- a/meta-agl/recipes-graphics/wayland/Readme.weston-ini-conf +++ /dev/null @@ -1,34 +0,0 @@ -##Generate a weston.ini file: - -To modify any of the default sections (core, shell, ivi-shell), add a -do_configure() function to your bbappend: - -''' -do_configure() { - echo repaint-window=34 >> ${WORKDIR}/core.cfg - - echo transition-duration=300 >> ${WORKDIR}/ivishell.cfg - echo cursor-theme=default >> ${WORKDIR}/ivishell.cfg -} -''' -or: -''' -do_configure() { - sed -i -e 's/drm-backend/fbdev-backend/' ${WORKDIR}/core.cfg -} -''' - -To change the display from the default assumption of an HDMI-1-A connected -screen that needs to be rotated 270 degrees: - -''' -SRC_URI_remove = "file://hdmi-a-1-270.cfg" -SRC_URI += "file://hdmi-a-1-90.cfg" -''' - -To add new sections just list them in SRC_URI: -''' -FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" - -SRC_URI += "file://dsi.cfg" -''' diff --git a/meta-agl/recipes-graphics/wayland/wayland/0001-Change-socket-mode-add-rw-for-group.patch b/meta-agl/recipes-graphics/wayland/wayland/0001-Change-socket-mode-add-rw-for-group.patch deleted file mode 100644 index b04127b57..000000000 --- a/meta-agl/recipes-graphics/wayland/wayland/0001-Change-socket-mode-add-rw-for-group.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 9162f7d4cfeec7103474e8703218b3679ca9ed10 Mon Sep 17 00:00:00 2001 -From: Ronan Le Martret -Date: Tue, 18 Apr 2017 13:53:26 +0200 -Subject: [PATCH] Change socket mode:add rw for group - -Signed-off-by: Ronan Le Martret ---- - src/wayland-server.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/src/wayland-server.c b/src/wayland-server.c -index 64d1bec..313c5a0 100644 ---- a/src/wayland-server.c -+++ b/src/wayland-server.c -@@ -1189,7 +1189,10 @@ _wl_display_add_socket(struct wl_display *display, struct wl_socket *s) - wl_log("bind() failed with error: %m\n"); - return -1; - } -- -+ if (chmod(s->addr.sun_path, 0660) < 0) { -+ wl_log("chmod() failed with error: %m\n"); -+ return -1; -+ } - if (listen(s->fd, 128) < 0) { - wl_log("listen() failed with error: %m\n"); - return -1; --- -2.6.6 - diff --git a/meta-agl/recipes-graphics/wayland/wayland_%.bbappend b/meta-agl/recipes-graphics/wayland/wayland_%.bbappend deleted file mode 100644 index 9d1822697..000000000 --- a/meta-agl/recipes-graphics/wayland/wayland_%.bbappend +++ /dev/null @@ -1,5 +0,0 @@ -FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" - -SRC_URI_append = "\ - file://0001-Change-socket-mode-add-rw-for-group.patch \ - " diff --git a/meta-agl/recipes-graphics/wayland/weston-ini-conf.bb b/meta-agl/recipes-graphics/wayland/weston-ini-conf.bb deleted file mode 100644 index 4628f96f8..000000000 --- a/meta-agl/recipes-graphics/wayland/weston-ini-conf.bb +++ /dev/null @@ -1,30 +0,0 @@ -SUMMARY = "Startup script and systemd unit file for the Weston Wayland compositor" -LICENSE = "MIT" -LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" - -SRC_URI = "file://core.cfg \ - file://ivishell.cfg \ - file://id-agent.cfg \ - file://shell.cfg \ - file://hdmi-a-1-270.cfg \ - " - -S = "${WORKDIR}" - -PACKAGE_ARCH = "${MACHINE_ARCH}" - -do_compile() { - # Put all of our cfg files together. - rm -f ${WORKDIR}/weston.ini - for F in ${WORKDIR}/*.cfg; do - cat $F >> ${WORKDIR}/weston.ini - echo >> ${WORKDIR}/weston.ini - done - sed -i -e '$ d' ${WORKDIR}/weston.ini -} - -do_install_append() { - WESTON_INI_CONFIG=${sysconfdir}/xdg/weston - install -d ${D}${WESTON_INI_CONFIG} - install -m 0644 ${WORKDIR}/weston.ini ${D}${WESTON_INI_CONFIG}/weston.ini -} diff --git a/meta-agl/recipes-graphics/wayland/weston-ini-conf/core.cfg b/meta-agl/recipes-graphics/wayland/weston-ini-conf/core.cfg deleted file mode 100644 index a0ec1e181..000000000 --- a/meta-agl/recipes-graphics/wayland/weston-ini-conf/core.cfg +++ /dev/null @@ -1,4 +0,0 @@ -[core] -shell=ivi-shell.so -backend=drm-backend.so -require-input=false diff --git a/meta-agl/recipes-graphics/wayland/weston-ini-conf/hdmi-a-1-270.cfg b/meta-agl/recipes-graphics/wayland/weston-ini-conf/hdmi-a-1-270.cfg deleted file mode 100644 index dffc2b6dd..000000000 --- a/meta-agl/recipes-graphics/wayland/weston-ini-conf/hdmi-a-1-270.cfg +++ /dev/null @@ -1,6 +0,0 @@ -# A display is connected to HDMI-A-1 and needs to be rotated 270 degrees -# to have a proper orientation of the homescreen. For example the various sizes -# of the GeChic display or the Dell display. -[output] -name=HDMI-A-1 -transform=270 diff --git a/meta-agl/recipes-graphics/wayland/weston-ini-conf/hdmi-a-1-90.cfg b/meta-agl/recipes-graphics/wayland/weston-ini-conf/hdmi-a-1-90.cfg deleted file mode 100644 index 88a692a1b..000000000 --- a/meta-agl/recipes-graphics/wayland/weston-ini-conf/hdmi-a-1-90.cfg +++ /dev/null @@ -1,6 +0,0 @@ -# A display is connected to HDMI-A-1 and needs to be rotated 90 degrees -# to have a proper orientation of the homescreen. For example, the 'eGalax' -# display used in some instances. -[output] -name=HDMI-A-1 -transform=90 diff --git a/meta-agl/recipes-graphics/wayland/weston-ini-conf/id-agent.cfg b/meta-agl/recipes-graphics/wayland/weston-ini-conf/id-agent.cfg deleted file mode 100644 index 726fca5f1..000000000 --- a/meta-agl/recipes-graphics/wayland/weston-ini-conf/id-agent.cfg +++ /dev/null @@ -1,2 +0,0 @@ -[id-agent] -default-id-offset=1000 diff --git a/meta-agl/recipes-graphics/wayland/weston-ini-conf/ivishell.cfg b/meta-agl/recipes-graphics/wayland/weston-ini-conf/ivishell.cfg deleted file mode 100644 index f0548f291..000000000 --- a/meta-agl/recipes-graphics/wayland/weston-ini-conf/ivishell.cfg +++ /dev/null @@ -1,4 +0,0 @@ -[ivi-shell] -ivi-input-module=ivi-input-controller.so -ivi-module=ivi-controller.so -id-agent-module=simple-id-agent.so diff --git a/meta-agl/recipes-graphics/wayland/weston-ini-conf/shell.cfg b/meta-agl/recipes-graphics/wayland/weston-ini-conf/shell.cfg deleted file mode 100644 index 056770427..000000000 --- a/meta-agl/recipes-graphics/wayland/weston-ini-conf/shell.cfg +++ /dev/null @@ -1,3 +0,0 @@ -[shell] -locking=true -panel-location=none diff --git a/meta-agl/recipes-graphics/wayland/weston-init.bbappend b/meta-agl/recipes-graphics/wayland/weston-init.bbappend deleted file mode 100644 index 1ca63b5de..000000000 --- a/meta-agl/recipes-graphics/wayland/weston-init.bbappend +++ /dev/null @@ -1,79 +0,0 @@ -FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" - -inherit agl-graphical - -WESTONSTART ??= "/usr/bin/weston ${WESTONARGS}" -WESTONSTART_append = " ${@bb.utils.contains("IMAGE_FEATURES", "debug-tweaks", " --log=${DISPLAY_XDG_RUNTIME_DIR}/weston.log", "",d)}" - -SRC_URI += " \ - file://weston_tmpfiles.conf \ - file://weston.service.add \ -" - -do_install_append() { - sed -i "/\[Unit\]/aConflicts=getty@tty${WESTONTTY}.service" \ - ${D}${systemd_system_unitdir}/weston.service - - sed -i "/\[Service\]/r ${S}/weston.service.add" \ - ${D}${systemd_system_unitdir}/weston.service - - if ! grep -q '^Group=' ${D}${systemd_system_unitdir}/weston.service; then - sed -i "/\[Service\]/aGroup=root" ${D}${systemd_system_unitdir}/weston.service - fi - if ! grep -q '^User=' ${D}${systemd_system_unitdir}/weston.service; then - sed -i "/\[Service\]/aUser=root" ${D}${systemd_system_unitdir}/weston.service - fi - - sed -e 's,User=root,User=${WESTONUSER},g' \ - -e 's,Group=root,Group=${WESTONGROUP},g' \ - -e 's,ExecStart=.*,ExecStart=${WESTONSTART},g' \ - -e 's,@WESTONTTY@,${WESTONTTY},g' \ - -e 's,@XDG_RUNTIME_DIR@,${DISPLAY_XDG_RUNTIME_DIR},g' \ - -i ${D}${systemd_system_unitdir}/weston.service - - # Add a rule to ensure the 'display' user has permissions to - # open the graphics device - install -d ${D}${sysconfdir}/init.d - install -d ${D}${sysconfdir}/udev/rules.d - cat >${D}${sysconfdir}/udev/rules.d/zz-dri.rules <<'EOF' -SUBSYSTEM=="drm", MODE="0660", GROUP="${WESTONGROUP}", SECLABEL{smack}="*", TAG+="systemd", ENV{SYSTEMD_WANTS}="weston.service" -EOF - - # user 'display' must own /dev/tty${WESTONTTY} for weston to start correctly - cat >${D}${sysconfdir}/udev/rules.d/zz-tty.rules <<'EOF' -SUBSYSTEM=="tty", KERNEL=="tty${WESTONTTY}", OWNER="${WESTONUSER}", SECLABEL{smack}="^", TAG+="systemd", ENV{SYSTEMD_WANTS}="weston.service" -EOF - - # user 'display' must also be able to access /dev/input/* - cat >${D}${sysconfdir}/udev/rules.d/zz-input.rules <<'EOF' -SUBSYSTEM=="input", MODE="0660", GROUP="input", SECLABEL{smack}="^", TAG+="systemd", ENV{SYSTEMD_WANTS}="weston.service" -EOF - - # user 'display' must also be able to access /dev/media*, etc. - cat >${D}${sysconfdir}/udev/rules.d/zz-remote-display.rules <<'EOF' -SUBSYSTEM=="media", MODE="0660", GROUP="display", SECLABEL{smack}="*", TAG+="systemd", ENV{SYSTEMD_WANTS}="weston.service" -SUBSYSTEM=="video4linux", MODE="0660", GROUP="display", SECLABEL{smack}="*", TAG+="systemd", ENV{SYSTEMD_WANTS}="weston.service" -KERNEL=="uvcs", SUBSYSTEM=="misc", MODE="0660", GROUP="display", SECLABEL{smack}="*" -KERNEL=="rgnmm", SUBSYSTEM=="misc", MODE="0660", GROUP="display", SECLABEL{smack}="*" -EOF - - install -d ${D}${sysconfdir}/tmpfiles.d - install -Dm755 ${WORKDIR}/weston_tmpfiles.conf ${D}/${libdir}/tmpfiles.d/weston.conf - - sed -e 's,@WESTONUSER@,${WESTONUSER},g' \ - -e 's,@WESTONGROUP@,${WESTONGROUP},g' \ - -i ${D}/${libdir}/tmpfiles.d/weston.conf -} - -do_install_append_imx() { - - install -d ${D}${sysconfdir}/udev/rules.d - cat >>${D}${sysconfdir}/udev/rules.d/zz-dri.rules <<'EOF' -SUBSYSTEM=="gpu_class", MODE="0660", GROUP="${WESTONGROUP}", SECLABEL{smack}="*" -EOF - -} - -FILES_${PN} += "${libdir}/tmpfiles.d/*.conf" - - diff --git a/meta-agl/recipes-graphics/wayland/weston-init/weston.service.add b/meta-agl/recipes-graphics/wayland/weston-init/weston.service.add deleted file mode 100644 index 3596e9c39..000000000 --- a/meta-agl/recipes-graphics/wayland/weston-init/weston.service.add +++ /dev/null @@ -1,7 +0,0 @@ -Environment="XDG_RUNTIME_DIR=@XDG_RUNTIME_DIR@" -TTYPath=/dev/tty@WESTONTTY@ -StandardInput=tty -TTYReset=yes -TTYVHangup=yes -TTYVTDisallocate=yes -UtmpIdentifier=tty@WESTONTTY@ diff --git a/meta-agl/recipes-graphics/wayland/weston-init/weston_tmpfiles.conf b/meta-agl/recipes-graphics/wayland/weston-init/weston_tmpfiles.conf deleted file mode 100644 index c4b302faf..000000000 --- a/meta-agl/recipes-graphics/wayland/weston-init/weston_tmpfiles.conf +++ /dev/null @@ -1,6 +0,0 @@ -# This file is distributed to create weston XDG_RUNTIME_DIR (/run/deamon/@WESTONUSER@) -# -# See tmpfiles.d(5) for details - -d /run/platform/ 0775 root root - -d /run/platform/@WESTONUSER@ 0770 @WESTONUSER@ @WESTONGROUP@ - diff --git a/meta-agl/recipes-graphics/wayland/weston/0001-Allow-regular-users-to-launch-Weston_2.0.0.patch b/meta-agl/recipes-graphics/wayland/weston/0001-Allow-regular-users-to-launch-Weston_2.0.0.patch deleted file mode 100644 index bd1a72b0f..000000000 --- a/meta-agl/recipes-graphics/wayland/weston/0001-Allow-regular-users-to-launch-Weston_2.0.0.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 6c145cea35f0b77613d6e3f48679c976b9839d7c Mon Sep 17 00:00:00 2001 -From: Ronan Le Martret -Date: Wed, 31 May 2017 22:48:18 +0000 -Subject: [PATCH] Allow regular users to launch Weston - -Signed-off-by: Ronan Le Martret ---- - configure.ac | 6 ++++++ - libweston/launcher-direct.c | 2 ++ - 2 files changed, 8 insertions(+) - -diff --git a/configure.ac b/configure.ac -index 7e84c14..8b3e17e 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -155,6 +155,12 @@ if test x$enable_xkbcommon = xyes; then - true) - fi - -+AC_ARG_ENABLE(sys-uid, [ --enable-sys-uid],, -+ enable_sys_uid=no) -+if test x$enable_sys_uid = xyes; then -+ AC_DEFINE(ENABLE_SYS_UID, [1], [Allow regular users to launch Weston]) -+fi -+ - AC_ARG_ENABLE(setuid-install, [ --enable-setuid-install],, - enable_setuid_install=yes) - AM_CONDITIONAL(ENABLE_SETUID_INSTALL, test x$enable_setuid_install = xyes) -diff --git a/libweston/launcher-direct.c b/libweston/launcher-direct.c -index 4fc1c3c..8f16a69 100644 ---- a/libweston/launcher-direct.c -+++ b/libweston/launcher-direct.c -@@ -275,8 +275,10 @@ launcher_direct_connect(struct weston_launcher **out, struct weston_compositor * - { - struct launcher_direct *launcher; - -+#ifndef ENABLE_SYS_UID - if (geteuid() != 0) - return -EINVAL; -+#endif - - launcher = zalloc(sizeof(*launcher)); - if (launcher == NULL) --- -2.7.4 - diff --git a/meta-agl/recipes-graphics/wayland/weston/0001-ivi-shell-rework-goto-labels-to-avoid-memory-leaks.patch b/meta-agl/recipes-graphics/wayland/weston/0001-ivi-shell-rework-goto-labels-to-avoid-memory-leaks.patch deleted file mode 100644 index 449b7a0fd..000000000 --- a/meta-agl/recipes-graphics/wayland/weston/0001-ivi-shell-rework-goto-labels-to-avoid-memory-leaks.patch +++ /dev/null @@ -1,66 +0,0 @@ -index 67619b8f..e9ddf9a4 100644 ---- a/ivi-shell/ivi-shell.c -+++ b/ivi-shell/ivi-shell.c -@@ -497,44 +497,53 @@ wet_shell_init(struct weston_compositor *compositor, - { - struct ivi_shell *shell; - struct ivi_shell_setting setting = { }; -- int retval = -1; - - shell = zalloc(sizeof *shell); - if (shell == NULL) - return -1; - - if (ivi_shell_setting_create(&setting, compositor, argc, argv) != 0) -- return -1; -+ goto err_shell; - - init_ivi_shell(compositor, shell, &setting); -+ /* TODO deinit_ivi_shell should be implemented, since init_ivi_shell is -+ * initializing multiple lists. */ - - shell->destroy_listener.notify = shell_destroy; - wl_signal_add(&compositor->destroy_signal, &shell->destroy_listener); - - if (input_panel_setup(shell) < 0) -- goto out_settings; -+ goto err_settings; - - shell->text_backend = text_backend_init(compositor); - if (!shell->text_backend) -- goto out_settings; -+ goto err_settings; - - if (wl_global_create(compositor->wl_display, - &ivi_application_interface, 1, - shell, bind_ivi_application) == NULL) -- goto out_settings; -+ goto err_text_backend; - - ivi_layout_init_with_compositor(compositor); -+ /* TODO ivi_layout_destroy should be implemented, since multiple lists -+ * and signals are initialized.*/ - shell_add_bindings(compositor, shell); - - /* Call module_init of ivi-modules which are defined in weston.ini */ - if (load_controller_modules(compositor, setting.ivi_module, - argc, argv) < 0) -- goto out_settings; -+ goto err_text_backend; -+ -+ return IVI_SUCCEEDED; - -- retval = 0; -+err_text_backend: -+ text_backend_destroy(shell->text_backend); - --out_settings: -+err_settings: - free(setting.ivi_module); - -- return retval; -+err_shell: -+ free(shell); -+ -+ return IVI_FAILED; - } diff --git a/meta-agl/recipes-graphics/wayland/weston/0002-ivi-shell-removed-assert.patch b/meta-agl/recipes-graphics/wayland/weston/0002-ivi-shell-removed-assert.patch deleted file mode 100644 index 4507e769c..000000000 --- a/meta-agl/recipes-graphics/wayland/weston/0002-ivi-shell-removed-assert.patch +++ /dev/null @@ -1,11 +0,0 @@ -index e9ddf9a4..f3156d35 100644 ---- a/ivi-shell/ivi-shell.c -+++ b/ivi-shell/ivi-shell.c -@@ -114,7 +114,6 @@ shell_surface_send_configure(struct weston_surface *surface, - struct ivi_shell_surface *shsurf; - - shsurf = get_ivi_shell_surface(surface); -- assert(shsurf); - if (!shsurf) - return; - diff --git a/meta-agl/recipes-graphics/wayland/weston/0003-ivi-shell-introduction-of-IVI_INVALID_ID.patch b/meta-agl/recipes-graphics/wayland/weston/0003-ivi-shell-introduction-of-IVI_INVALID_ID.patch deleted file mode 100644 index 6f683ca92..000000000 --- a/meta-agl/recipes-graphics/wayland/weston/0003-ivi-shell-introduction-of-IVI_INVALID_ID.patch +++ /dev/null @@ -1,18 +0,0 @@ -index 2317d6e9..e1e897ed 100644 ---- a/ivi-shell/ivi-layout-export.h -+++ b/ivi-shell/ivi-layout-export.h -@@ -56,12 +56,14 @@ extern "C" { - #endif /* __cplusplus */ - - #include -+#include - - #include "stdbool.h" - #include "compositor.h" - - #define IVI_SUCCEEDED (0) - #define IVI_FAILED (-1) -+#define IVI_INVALID_ID UINT_MAX - - struct ivi_layout_layer; - struct ivi_layout_screen; diff --git a/meta-agl/recipes-graphics/wayland/weston/0004-layout-interface-added-interface-to-change-surface-id.patch b/meta-agl/recipes-graphics/wayland/weston/0004-layout-interface-added-interface-to-change-surface-id.patch deleted file mode 100644 index 6401c5b81..000000000 --- a/meta-agl/recipes-graphics/wayland/weston/0004-layout-interface-added-interface-to-change-surface-id.patch +++ /dev/null @@ -1,73 +0,0 @@ -index e1e897ed..5b1f12f0 100644 ---- a/ivi-shell/ivi-layout-export.h -+++ b/ivi-shell/ivi-layout-export.h -@@ -320,6 +320,12 @@ struct ivi_layout_interface { - struct ivi_layout_surface *ivisurf, - uint32_t duration); - -+ /** -+ * \brief set id of ivi_layout_surface -+ */ -+ int32_t (*surface_set_id)(struct ivi_layout_surface *ivisurf, -+ uint32_t id_surface); -+ - /** - * layer controller interface - */ -diff --git a/ivi-shell/ivi-layout.c b/ivi-shell/ivi-layout.c -index 298e18ea..fa8e75f6 100644 ---- a/ivi-shell/ivi-layout.c -+++ b/ivi-shell/ivi-layout.c -@@ -1901,6 +1901,44 @@ ivi_layout_surface_set_transition_duration(struct ivi_layout_surface *ivisurf, - return 0; - } - -+/* -+ * This interface enables e.g. an id agent to set the id of an ivi-layout -+ * surface, that has been created by a desktop application. This can only be -+ * done once as long as the initial surface id equals IVI_INVALID_ID. Afterwards -+ * two events are emitted, namely surface_created and surface_configured. -+ */ -+static int32_t -+ivi_layout_surface_set_id(struct ivi_layout_surface *ivisurf, -+ uint32_t id_surface) -+{ -+ struct ivi_layout *layout = get_instance(); -+ struct ivi_layout_surface *search_ivisurf = NULL; -+ -+ if (!ivisurf) { -+ weston_log("%s: invalid argument\n", __func__); -+ return IVI_FAILED; -+ } -+ -+ if (ivisurf->id_surface != IVI_INVALID_ID) { -+ weston_log("surface id can only be set once\n"); -+ return IVI_FAILED; -+ } -+ -+ search_ivisurf = get_surface(&layout->surface_list, id_surface); -+ if (search_ivisurf) { -+ weston_log("id_surface(%d) is already created\n", id_surface); -+ return IVI_FAILED; -+ } -+ -+ ivisurf->id_surface = id_surface; -+ -+ wl_signal_emit(&layout->surface_notification.created, ivisurf); -+ wl_signal_emit(&layout->surface_notification.configure_changed, -+ ivisurf); -+ -+ return IVI_SUCCEEDED; -+} -+ - static int32_t - ivi_layout_surface_set_transition(struct ivi_layout_surface *ivisurf, - enum ivi_layout_transition_type type, -@@ -2058,6 +2096,7 @@ static struct ivi_layout_interface ivi_layout_interface = { - .surface_get_weston_surface = ivi_layout_surface_get_weston_surface, - .surface_set_transition = ivi_layout_surface_set_transition, - .surface_set_transition_duration = ivi_layout_surface_set_transition_duration, -+ .surface_set_id = ivi_layout_surface_set_id, - - /** - * layer controller interfaces diff --git a/meta-agl/recipes-graphics/wayland/weston/0005-ivi-layout-introcuded-configure_desktop_changed.patch b/meta-agl/recipes-graphics/wayland/weston/0005-ivi-layout-introcuded-configure_desktop_changed.patch deleted file mode 100644 index ddd949e35..000000000 --- a/meta-agl/recipes-graphics/wayland/weston/0005-ivi-layout-introcuded-configure_desktop_changed.patch +++ /dev/null @@ -1,74 +0,0 @@ -index 5b1f12f0..dd0997aa 100644 ---- a/ivi-shell/ivi-layout-export.h -+++ b/ivi-shell/ivi-layout-export.h -@@ -187,6 +187,16 @@ struct ivi_layout_interface { - */ - int32_t (*add_listener_configure_surface)(struct wl_listener *listener); - -+ /** -+ * \brief add a listener for notification when desktop_surface is configured -+ * -+ * When an desktop_surface is configured, a signal is emitted -+ * to the listening controller plugins. -+ * The pointer of the configured desktop_surface is sent as the void *data argument -+ * to the wl_listener::notify callback function of the listener. -+ */ -+ int32_t (*add_listener_configure_desktop_surface)(struct wl_listener *listener); -+ - /** - * \brief Get all ivi_surfaces which are currently registered and managed - * by the services -diff --git a/ivi-shell/ivi-layout-private.h b/ivi-shell/ivi-layout-private.h -index 2b8bd472..fe5be01a 100644 ---- a/ivi-shell/ivi-layout-private.h -+++ b/ivi-shell/ivi-layout-private.h -@@ -104,6 +104,7 @@ struct ivi_layout { - struct wl_signal created; - struct wl_signal removed; - struct wl_signal configure_changed; -+ struct wl_signal configure_desktop_changed; - } surface_notification; - - struct weston_layer layout_layer; -diff --git a/ivi-shell/ivi-layout.c b/ivi-shell/ivi-layout.c -index fa8e75f6..690af742 100644 ---- a/ivi-shell/ivi-layout.c -+++ b/ivi-shell/ivi-layout.c -@@ -1040,6 +1040,21 @@ ivi_layout_add_listener_configure_surface(struct wl_listener *listener) - return IVI_SUCCEEDED; - } - -+static int32_t -+ivi_layout_add_listener_configure_desktop_surface(struct wl_listener *listener) -+{ -+ struct ivi_layout *layout = get_instance(); -+ -+ if (!listener) { -+ weston_log("ivi_layout_add_listener_configure_desktop_surface: invalid argument\n"); -+ return IVI_FAILED; -+ } -+ -+ wl_signal_add(&layout->surface_notification.configure_desktop_changed, listener); -+ -+ return IVI_SUCCEEDED; -+} -+ - uint32_t - ivi_layout_get_id_of_surface(struct ivi_layout_surface *ivisurf) - { -@@ -2057,6 +2072,7 @@ ivi_layout_init_with_compositor(struct weston_compositor *ec) - wl_signal_init(&layout->surface_notification.created); - wl_signal_init(&layout->surface_notification.removed); - wl_signal_init(&layout->surface_notification.configure_changed); -+ wl_signal_init(&layout->surface_notification.configure_desktop_changed); - - /* Add layout_layer at the last of weston_compositor.layer_list */ - weston_layer_init(&layout->layout_layer, ec); -@@ -2081,6 +2097,7 @@ static struct ivi_layout_interface ivi_layout_interface = { - .add_listener_create_surface = ivi_layout_add_listener_create_surface, - .add_listener_remove_surface = ivi_layout_add_listener_remove_surface, - .add_listener_configure_surface = ivi_layout_add_listener_configure_surface, -+ .add_listener_configure_desktop_surface = ivi_layout_add_listener_configure_desktop_surface, - .get_surface = shell_get_ivi_layout_surface, - .get_surfaces = ivi_layout_get_surfaces, - .get_id_of_surface = ivi_layout_get_id_of_surface, diff --git a/meta-agl/recipes-graphics/wayland/weston/0006-ivi-layout-introcuded-surface_create_and_configure.patch b/meta-agl/recipes-graphics/wayland/weston/0006-ivi-layout-introcuded-surface_create_and_configure.patch deleted file mode 100644 index 04461a1d4..000000000 --- a/meta-agl/recipes-graphics/wayland/weston/0006-ivi-layout-introcuded-surface_create_and_configure.patch +++ /dev/null @@ -1,117 +0,0 @@ -index 68ca68ba..c86cbb11 100644 ---- a/ivi-shell/ivi-layout-shell.h -+++ b/ivi-shell/ivi-layout-shell.h -@@ -39,6 +39,14 @@ struct weston_view; - struct weston_surface; - struct ivi_layout_surface; - -+void -+ivi_layout_desktop_surface_configure(struct ivi_layout_surface *ivisurf, -+ int32_t width, int32_t height); -+ -+struct ivi_layout_surface* -+ivi_layout_desktop_surface_create(struct weston_surface *wl_surface, -+ uint32_t id_surface); -+ - void - ivi_layout_surface_configure(struct ivi_layout_surface *ivisurf, - int32_t width, int32_t height); -diff --git a/ivi-shell/ivi-layout.c b/ivi-shell/ivi-layout.c -index 690af742..086d0fd2 100644 ---- a/ivi-shell/ivi-layout.c -+++ b/ivi-shell/ivi-layout.c -@@ -1995,20 +1995,8 @@ ivi_layout_surface_dump(struct weston_surface *surface, - * methods of interaction between ivi-shell with ivi-layout - */ - --void --ivi_layout_surface_configure(struct ivi_layout_surface *ivisurf, -- int32_t width, int32_t height) --{ -- struct ivi_layout *layout = get_instance(); -- -- /* emit callback which is set by ivi-layout api user */ -- wl_signal_emit(&layout->surface_notification.configure_changed, -- ivisurf); --} -- --struct ivi_layout_surface* --ivi_layout_surface_create(struct weston_surface *wl_surface, -- uint32_t id_surface) -+static struct ivi_layout_surface* -+surface_create(struct weston_surface *wl_surface, uint32_t id_surface) - { - struct ivi_layout *layout = get_instance(); - struct ivi_layout_surface *ivisurf = NULL; -@@ -2018,14 +2006,6 @@ ivi_layout_surface_create(struct weston_surface *wl_surface, - return NULL; - } - -- ivisurf = get_surface(&layout->surface_list, id_surface); -- if (ivisurf != NULL) { -- if (ivisurf->surface != NULL) { -- weston_log("id_surface(%d) is already created\n", id_surface); -- return NULL; -- } -- } -- - ivisurf = calloc(1, sizeof *ivisurf); - if (ivisurf == NULL) { - weston_log("fails to allocate memory\n"); -@@ -2049,7 +2029,55 @@ ivi_layout_surface_create(struct weston_surface *wl_surface, - - wl_list_insert(&layout->surface_list, &ivisurf->link); - -- wl_signal_emit(&layout->surface_notification.created, ivisurf); -+ return ivisurf; -+} -+ -+void -+ivi_layout_desktop_surface_configure(struct ivi_layout_surface *ivisurf, -+ int32_t width, int32_t height) -+{ -+ struct ivi_layout *layout = get_instance(); -+ -+ /* emit callback which is set by ivi-layout api user */ -+ wl_signal_emit(&layout->surface_notification.configure_desktop_changed, -+ ivisurf); -+} -+ -+struct ivi_layout_surface* -+ivi_layout_desktop_surface_create(struct weston_surface *wl_surface, -+ uint32_t id_surface) -+{ -+ return surface_create(wl_surface, id_surface); -+} -+ -+void -+ivi_layout_surface_configure(struct ivi_layout_surface *ivisurf, -+ int32_t width, int32_t height) -+{ -+ struct ivi_layout *layout = get_instance(); -+ -+ /* emit callback which is set by ivi-layout api user */ -+ wl_signal_emit(&layout->surface_notification.configure_changed, -+ ivisurf); -+} -+ -+struct ivi_layout_surface* -+ivi_layout_surface_create(struct weston_surface *wl_surface, -+ uint32_t id_surface) -+{ -+ struct ivi_layout *layout = get_instance(); -+ struct ivi_layout_surface *ivisurf = NULL; -+ -+ ivisurf = get_surface(&layout->surface_list, id_surface); -+ if (ivisurf) { -+ weston_log("id_surface(%d) is already created\n", id_surface); -+ return NULL; -+ } -+ -+ ivisurf = surface_create(wl_surface, id_surface); -+ -+ if (ivisurf) -+ wl_signal_emit(&layout->surface_notification.created, ivisurf); - - return ivisurf; - } diff --git a/meta-agl/recipes-graphics/wayland/weston/0007-ivi-shell-linked-libweston-desktop-and-added-structs.patch b/meta-agl/recipes-graphics/wayland/weston/0007-ivi-shell-linked-libweston-desktop-and-added-structs.patch deleted file mode 100644 index 9286ba00b..000000000 --- a/meta-agl/recipes-graphics/wayland/weston/0007-ivi-shell-linked-libweston-desktop-and-added-structs.patch +++ /dev/null @@ -1,74 +0,0 @@ -diff --git a/Makefile.am b/Makefile.am -index cdf82ab4..d990d400 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -993,6 +993,7 @@ ivi_shell_la_LDFLAGS = -module -avoid-version - ivi_shell_la_LIBADD = \ - libshared.la \ - libweston-@LIBWESTON_MAJOR@.la \ -+ libweston-desktop-@LIBWESTON_MAJOR@.la \ - $(COMPOSITOR_LIBS) - ivi_shell_la_CFLAGS = $(AM_CFLAGS) $(COMPOSITOR_CFLAGS) - ivi_shell_la_SOURCES = \ -diff --git a/ivi-shell/ivi-layout-private.h b/ivi-shell/ivi-layout-private.h -index fe5be01a..c054130b 100644 ---- a/ivi-shell/ivi-layout-private.h -+++ b/ivi-shell/ivi-layout-private.h -@@ -30,6 +30,7 @@ - - #include "compositor.h" - #include "ivi-layout-export.h" -+#include "libweston-desktop/libweston-desktop.h" - - struct ivi_layout_view { - struct wl_list link; /* ivi_layout::view_list */ -@@ -52,6 +53,7 @@ struct ivi_layout_surface { - - struct ivi_layout *layout; - struct weston_surface *surface; -+ struct weston_desktop_surface *weston_desktop_surface; - - struct ivi_layout_surface_properties prop; - -diff --git a/ivi-shell/ivi-shell.c b/ivi-shell/ivi-shell.c -index f3156d35..84db2c97 100644 ---- a/ivi-shell/ivi-shell.c -+++ b/ivi-shell/ivi-shell.c -@@ -44,7 +44,7 @@ - - #include "ivi-shell.h" - #include "ivi-application-server-protocol.h" --#include "ivi-layout-export.h" -+#include "ivi-layout-private.h" - #include "ivi-layout-shell.h" - #include "shared/helpers.h" - #include "compositor/weston.h" -@@ -271,6 +271,8 @@ application_surface_create(struct wl_client *client, - return; - } - -+ layout_surface->weston_desktop_surface = NULL; -+ - ivisurf = zalloc(sizeof *ivisurf); - if (ivisurf == NULL) { - wl_resource_post_no_memory(resource); -diff --git a/ivi-shell/ivi-shell.h b/ivi-shell/ivi-shell.h -index e35f75f2..be430853 100644 ---- a/ivi-shell/ivi-shell.h -+++ b/ivi-shell/ivi-shell.h -@@ -30,6 +30,7 @@ - #include - - #include "compositor.h" -+#include "libweston-desktop/libweston-desktop.h" - - struct ivi_shell - { -@@ -37,6 +38,7 @@ struct ivi_shell - - struct weston_compositor *compositor; - -+ struct weston_desktop *desktop; - struct wl_list ivi_surface_list; /* struct ivi_shell_surface::link */ - - struct text_backend *text_backend; diff --git a/meta-agl/recipes-graphics/wayland/weston/0008-ivi-layout-use-libweston-desktop-api-for-views.patch b/meta-agl/recipes-graphics/wayland/weston/0008-ivi-layout-use-libweston-desktop-api-for-views.patch deleted file mode 100644 index e53a8c458..000000000 --- a/meta-agl/recipes-graphics/wayland/weston/0008-ivi-layout-use-libweston-desktop-api-for-views.patch +++ /dev/null @@ -1,30 +0,0 @@ -index 086d0fd2..6b854503 100644 ---- a/ivi-shell/ivi-layout.c -+++ b/ivi-shell/ivi-layout.c -@@ -153,7 +153,10 @@ ivi_view_destroy(struct ivi_layout_view *ivi_view) - wl_list_remove(&ivi_view->pending_link); - wl_list_remove(&ivi_view->order_link); - -- weston_view_destroy(ivi_view->view); -+ if (weston_surface_is_desktop_surface(ivi_view->ivisurf->surface)) -+ weston_desktop_surface_unlink_view(ivi_view->view); -+ else -+ weston_view_destroy(ivi_view->view); - - free(ivi_view); - } -@@ -170,7 +173,13 @@ ivi_view_create(struct ivi_layout_layer *ivilayer, - return NULL; - } - -- ivi_view->view = weston_view_create(ivisurf->surface); -+ if (weston_surface_is_desktop_surface(ivisurf->surface)) { -+ ivi_view->view = weston_desktop_surface_create_view( -+ ivisurf->weston_desktop_surface); -+ } else { -+ ivi_view->view = weston_view_create(ivisurf->surface); -+ } -+ - if (ivi_view->view == NULL) { - weston_log("fails to allocate memory\n"); - free(ivi_view); diff --git a/meta-agl/recipes-graphics/wayland/weston/0009-ivi-shell-added-libweston-desktop-api_implementation.patch b/meta-agl/recipes-graphics/wayland/weston/0009-ivi-shell-added-libweston-desktop-api_implementation.patch deleted file mode 100644 index 6a72f15d8..000000000 --- a/meta-agl/recipes-graphics/wayland/weston/0009-ivi-shell-added-libweston-desktop-api_implementation.patch +++ /dev/null @@ -1,166 +0,0 @@ -index 84db2c97..e797e4f9 100644 ---- a/ivi-shell/ivi-shell.c -+++ b/ivi-shell/ivi-shell.c -@@ -489,6 +489,162 @@ shell_add_bindings(struct weston_compositor *compositor, - shell); - } - -+/* -+ * libweston-desktop -+ */ -+ -+static void -+desktop_surface_ping_timeout(struct weston_desktop_client *client, -+ void *user_data) -+{ -+ weston_log("ivi-shell: desktop_surface_ping_timeout is not supported\n"); -+} -+ -+static void -+desktop_surface_pong(struct weston_desktop_client *client, -+ void *user_data) -+{ -+ weston_log("ivi-shell: desktop_surface_pong is not supported\n"); -+} -+ -+static void -+desktop_surface_added(struct weston_desktop_surface *surface, -+ void *user_data) -+{ -+ struct ivi_shell *shell = (struct ivi_shell *) user_data; -+ struct ivi_layout_surface *layout_surface; -+ struct ivi_shell_surface *ivisurf; -+ struct weston_surface *weston_surf = -+ weston_desktop_surface_get_surface(surface); -+ -+ layout_surface = ivi_layout_desktop_surface_create(weston_surf, -+ IVI_INVALID_ID); -+ if (!layout_surface) { -+ return; -+ } -+ -+ layout_surface->weston_desktop_surface = surface; -+ -+ ivisurf = zalloc(sizeof *ivisurf); -+ if (!ivisurf) { -+ return; -+ } -+ -+ ivisurf->shell = shell; -+ ivisurf->id_surface = IVI_INVALID_ID; -+ -+ ivisurf->width = 0; -+ ivisurf->height = 0; -+ ivisurf->layout_surface = layout_surface; -+ ivisurf->surface = weston_surf; -+ -+ weston_desktop_surface_set_user_data(surface, ivisurf); -+} -+ -+static void -+desktop_surface_removed(struct weston_desktop_surface *surface, -+ void *user_data) -+{ -+ struct ivi_shell_surface *ivisurf = (struct ivi_shell_surface *) -+ weston_desktop_surface_get_user_data(surface); -+ -+ assert(ivisurf != NULL); -+ -+ if (ivisurf->layout_surface) -+ layout_surface_cleanup(ivisurf); -+} -+ -+static void -+desktop_surface_committed(struct weston_desktop_surface *surface, -+ int32_t sx, int32_t sy, void *user_data) -+{ -+ struct ivi_shell_surface *ivisurf = (struct ivi_shell_surface *) -+ weston_desktop_surface_get_user_data(surface); -+ struct weston_surface *weston_surf = -+ weston_desktop_surface_get_surface(surface); -+ -+ if(!ivisurf) -+ return; -+ -+ if (weston_surf->width == 0 || weston_surf->height == 0) -+ return; -+ -+ if (ivisurf->width != weston_surf->width || -+ ivisurf->height != weston_surf->height) { -+ ivisurf->width = weston_surf->width; -+ ivisurf->height = weston_surf->height; -+ -+ ivi_layout_desktop_surface_configure(ivisurf->layout_surface, -+ weston_surf->width, -+ weston_surf->height); -+ } -+} -+ -+static void -+desktop_surface_move(struct weston_desktop_surface *surface, -+ struct weston_seat *seat, uint32_t serial, void *user_data) -+{ -+ weston_log("ivi-shell: desktop_surface_move is not supported\n"); -+} -+ -+static void -+desktop_surface_resize(struct weston_desktop_surface *surface, -+ struct weston_seat *seat, uint32_t serial, -+ enum weston_desktop_surface_edge edges, void *user_data) -+{ -+ weston_log("ivi-shell: desktop_surface_resize is not supported\n"); -+} -+ -+static void -+desktop_surface_fullscreen_requested(struct weston_desktop_surface *surface, -+ bool fullscreen, -+ struct weston_output *output, -+ void *user_data) -+{ -+ weston_log("ivi-shell: desktop_surface_fullscreen_requested is not supported\n"); -+} -+ -+static void -+desktop_surface_maximized_requested(struct weston_desktop_surface *surface, -+ bool maximized, void *user_data) -+{ -+ weston_log("ivi-shell: desktop_surface_maximized_requested is not supported\n"); -+} -+ -+static void -+desktop_surface_minimized_requested(struct weston_desktop_surface *surface, -+ void *user_data) -+{ -+ weston_log("ivi-shell: desktop_surface_minimized_requested is not supported\n"); -+} -+ -+static void -+desktop_surface_set_xwayland_position(struct weston_desktop_surface *surface, -+ int32_t x, int32_t y, void *user_data) -+{ -+ weston_log("ivi-shell: desktop_surface_set_xwayland_position is not supported\n"); -+} -+ -+static const struct weston_desktop_api shell_desktop_api = { -+ .struct_size = sizeof(struct weston_desktop_api), -+ .ping_timeout = desktop_surface_ping_timeout, -+ .pong = desktop_surface_pong, -+ .surface_added = desktop_surface_added, -+ .surface_removed = desktop_surface_removed, -+ .committed = desktop_surface_committed, -+ -+ .move = desktop_surface_move, -+ .resize = desktop_surface_resize, -+ .fullscreen_requested = desktop_surface_fullscreen_requested, -+ .maximized_requested = desktop_surface_maximized_requested, -+ .minimized_requested = desktop_surface_minimized_requested, -+ .set_xwayland_position = desktop_surface_set_xwayland_position, -+}; -+ -+/* -+ * end of libweston-desktop -+ */ -+ - /* - * Initialization of ivi-shell. - */ diff --git a/meta-agl/recipes-graphics/wayland/weston/0010-ivi-shell-remove-surface_destroy_listener.patch b/meta-agl/recipes-graphics/wayland/weston/0010-ivi-shell-remove-surface_destroy_listener.patch deleted file mode 100644 index b76c35d4f..000000000 --- a/meta-agl/recipes-graphics/wayland/weston/0010-ivi-shell-remove-surface_destroy_listener.patch +++ /dev/null @@ -1,24 +0,0 @@ -index e797e4f9..5f64e72d 100644 ---- a/ivi-shell/ivi-shell.c -+++ b/ivi-shell/ivi-shell.c -@@ -162,6 +162,10 @@ layout_surface_cleanup(struct ivi_shell_surface *ivisurf) - { - assert(ivisurf->layout_surface != NULL); - -+ /* destroy weston_surface destroy signal. */ -+ if (!ivisurf->layout_surface->weston_desktop_surface) -+ wl_list_remove(&ivisurf->surface_destroy_listener.link); -+ - ivi_layout_surface_destroy(ivisurf->layout_surface); - ivisurf->layout_surface = NULL; - -@@ -169,9 +173,6 @@ layout_surface_cleanup(struct ivi_shell_surface *ivisurf) - ivisurf->surface->committed_private = NULL; - weston_surface_set_label_func(ivisurf->surface, NULL); - ivisurf->surface = NULL; -- -- // destroy weston_surface destroy signal. -- wl_list_remove(&ivisurf->surface_destroy_listener.link); - } - - /* diff --git a/meta-agl/recipes-graphics/wayland/weston/0011-ivi-shell-create-weston-desktop-in_wet_shell_init.patch b/meta-agl/recipes-graphics/wayland/weston/0011-ivi-shell-create-weston-desktop-in_wet_shell_init.patch deleted file mode 100644 index 551e449ad..000000000 --- a/meta-agl/recipes-graphics/wayland/weston/0011-ivi-shell-create-weston-desktop-in_wet_shell_init.patch +++ /dev/null @@ -1,34 +0,0 @@ -index 5f64e72d..dc8e6f1d 100644 ---- a/ivi-shell/ivi-shell.c -+++ b/ivi-shell/ivi-shell.c -@@ -677,10 +677,14 @@ wet_shell_init(struct weston_compositor *compositor, - if (!shell->text_backend) - goto err_settings; - -+ shell->desktop = weston_desktop_create(compositor, &shell_desktop_api, shell); -+ if (!shell->desktop) -+ goto err_text_backend; -+ - if (wl_global_create(compositor->wl_display, - &ivi_application_interface, 1, - shell, bind_ivi_application) == NULL) -- goto err_text_backend; -+ goto err_desktop; - - ivi_layout_init_with_compositor(compositor); - /* TODO ivi_layout_destroy should be implemented, since multiple lists -@@ -690,10 +694,13 @@ wet_shell_init(struct weston_compositor *compositor, - /* Call module_init of ivi-modules which are defined in weston.ini */ - if (load_controller_modules(compositor, setting.ivi_module, - argc, argv) < 0) -- goto err_text_backend; -+ goto err_desktop; - - return IVI_SUCCEEDED; - -+err_desktop: -+ weston_desktop_destroy(shell->desktop); -+ - err_text_backend: - text_backend_destroy(shell->text_backend); - diff --git a/meta-agl/recipes-graphics/wayland/weston/0012-hmi-controller-register-for-desktop_surface_configured.patch b/meta-agl/recipes-graphics/wayland/weston/0012-hmi-controller-register-for-desktop_surface_configured.patch deleted file mode 100644 index c5d85bb17..000000000 --- a/meta-agl/recipes-graphics/wayland/weston/0012-hmi-controller-register-for-desktop_surface_configured.patch +++ /dev/null @@ -1,133 +0,0 @@ -index d5403e06..7b2f2707 100644 ---- a/ivi-shell/hmi-controller.c -+++ b/ivi-shell/hmi-controller.c -@@ -129,9 +129,9 @@ struct hmi_controller { - struct weston_compositor *compositor; - struct wl_listener destroy_listener; - -- struct wl_listener surface_created; - struct wl_listener surface_removed; - struct wl_listener surface_configured; -+ struct wl_listener desktop_surface_configured; - - struct wl_client *user_interface; - struct ui_setting ui_setting; -@@ -581,28 +581,6 @@ create_layer(struct weston_output *output, - /** - * Internal set notification - */ --static void --set_notification_create_surface(struct wl_listener *listener, void *data) --{ -- struct hmi_controller *hmi_ctrl = -- wl_container_of(listener, hmi_ctrl, -- surface_created); -- struct ivi_layout_surface *ivisurf = data; -- struct hmi_controller_layer *layer_link = -- wl_container_of(hmi_ctrl->application_layer_list.prev, -- layer_link, -- link); -- struct ivi_layout_layer *application_layer = layer_link->ivilayer; -- int32_t ret = 0; -- -- /* skip ui widgets */ -- if (is_surf_in_ui_widget(hmi_ctrl, ivisurf)) -- return; -- -- ret = ivi_layout_interface->layer_add_surface(application_layer, ivisurf); -- assert(!ret); --} -- - static void - set_notification_remove_surface(struct wl_listener *listener, void *data) - { -@@ -670,6 +648,42 @@ set_notification_configure_surface(struct wl_listener *listener, void *data) - switch_mode(hmi_ctrl, hmi_ctrl->layout_mode); - } - -+static void -+set_notification_configure_desktop_surface(struct wl_listener *listener, void *data) -+{ -+ struct hmi_controller *hmi_ctrl = -+ wl_container_of(listener, hmi_ctrl, -+ desktop_surface_configured); -+ struct ivi_layout_surface *ivisurf = data; -+ struct hmi_controller_layer *layer_link = -+ wl_container_of(hmi_ctrl->application_layer_list.prev, -+ layer_link, -+ link); -+ struct ivi_layout_layer *application_layer = layer_link->ivilayer; -+ struct weston_surface *surface; -+ int32_t ret = 0; -+ -+ /* skip ui widgets */ -+ if (is_surf_in_ui_widget(hmi_ctrl, ivisurf)) -+ return; -+ -+ ret = ivi_layout_interface->layer_add_surface(application_layer, ivisurf); -+ assert(!ret); -+ -+ /* -+ * if application changes size of wl_buffer. The source rectangle shall be -+ * fit to the size. -+ */ -+ surface = ivi_layout_interface->surface_get_weston_surface(ivisurf); -+ if (surface) { -+ ivi_layout_interface->surface_set_source_rectangle(ivisurf, 0, -+ 0, surface->width, surface->height); -+ } -+ -+ ivi_layout_interface->commit_changes(); -+ switch_mode(hmi_ctrl, hmi_ctrl->layout_mode); -+} -+ - /** - * A hmi_controller used 4 ivi_layers to manage ivi_surfaces. The IDs of - * corresponding ivi_layer are defined in weston.ini. Default scene graph -@@ -852,6 +866,9 @@ hmi_controller_create(struct weston_compositor *ec) - hmi_ctrl->surface_configured.notify = set_notification_configure_surface; - ivi_layout_interface->add_listener_configure_surface(&hmi_ctrl->surface_configured); - -+ hmi_ctrl->desktop_surface_configured.notify = set_notification_configure_desktop_surface; -+ ivi_layout_interface->add_listener_configure_desktop_surface(&hmi_ctrl->desktop_surface_configured); -+ - hmi_ctrl->destroy_listener.notify = hmi_controller_destroy; - wl_signal_add(&hmi_ctrl->compositor->destroy_signal, - &hmi_ctrl->destroy_listener); -@@ -1275,13 +1292,6 @@ ivi_hmi_controller_UI_ready(struct wl_client *client, - ivi_layout_interface->commit_changes(); - - ivi_hmi_controller_add_launchers(hmi_ctrl, 256); -- -- /* Add surface_created listener after the initialization of launchers. -- * Otherwise, surfaces of the launchers will be added to application -- * layer too.*/ -- hmi_ctrl->surface_created.notify = set_notification_create_surface; -- ivi_layout_interface->add_listener_create_surface(&hmi_ctrl->surface_created); -- - hmi_ctrl->is_initialized = 1; - } - -diff --git a/ivi-shell/ivi-layout.c b/ivi-shell/ivi-layout.c -index 6b854503..22d63708 100644 ---- a/ivi-shell/ivi-layout.c -+++ b/ivi-shell/ivi-layout.c -@@ -787,9 +787,15 @@ commit_surface_list(struct ivi_layout *layout) - ivisurf->pending.prop.transition_type = IVI_LAYOUT_TRANSITION_NONE; - - if (configured && !is_surface_transition(ivisurf)) { -- shell_surface_send_configure(ivisurf->surface, -- ivisurf->prop.dest_width, -- ivisurf->prop.dest_height); -+ if (ivisurf->weston_desktop_surface) { -+ weston_desktop_surface_set_size(ivisurf->weston_desktop_surface, -+ ivisurf->prop.dest_width, -+ ivisurf->prop.dest_height); -+ } else { -+ shell_surface_send_configure(ivisurf->surface, -+ ivisurf->prop.dest_width, -+ ivisurf->prop.dest_height); -+ } - } - } else { - configured = 0; diff --git a/meta-agl/recipes-graphics/wayland/weston/0013-simple-egl-remove-ivi-application-support.patch b/meta-agl/recipes-graphics/wayland/weston/0013-simple-egl-remove-ivi-application-support.patch deleted file mode 100644 index 8094f9b85..000000000 --- a/meta-agl/recipes-graphics/wayland/weston/0013-simple-egl-remove-ivi-application-support.patch +++ /dev/null @@ -1,164 +0,0 @@ -index 23f79dfe..f9c8010b 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -616,9 +616,7 @@ demo_clients += weston-simple-egl - weston_simple_egl_SOURCES = clients/simple-egl.c - nodist_weston_simple_egl_SOURCES = \ - protocol/xdg-shell-unstable-v6-protocol.c \ -- protocol/xdg-shell-unstable-v6-client-protocol.h \ -- protocol/ivi-application-protocol.c \ -- protocol/ivi-application-client-protocol.h -+ protocol/xdg-shell-unstable-v6-client-protocol.h - weston_simple_egl_CFLAGS = $(AM_CFLAGS) $(SIMPLE_EGL_CLIENT_CFLAGS) - weston_simple_egl_LDADD = $(SIMPLE_EGL_CLIENT_LIBS) -lm - endif -diff --git a/clients/simple-egl.c b/clients/simple-egl.c -index dad0f09b..07e7e785 100644 ---- a/clients/simple-egl.c -+++ b/clients/simple-egl.c -@@ -45,8 +45,6 @@ - #include "xdg-shell-unstable-v6-client-protocol.h" - #include - #include --#include "ivi-application-client-protocol.h" --#define IVI_SURFACE_ID 9000 - - #include "shared/helpers.h" - #include "shared/platform.h" -@@ -74,7 +72,6 @@ struct display { - EGLConfig conf; - } egl; - struct window *window; -- struct ivi_application *ivi_application; - - PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC swap_buffers_with_damage; - }; -@@ -97,7 +94,6 @@ struct window { - struct wl_surface *surface; - struct zxdg_surface_v6 *xdg_surface; - struct zxdg_toplevel_v6 *xdg_toplevel; -- struct ivi_surface *ivi_surface; - EGLSurface egl_surface; - struct wl_callback *callback; - int fullscreen, opaque, buffer_size, frame_sync, delay; -@@ -355,27 +351,22 @@ static const struct zxdg_toplevel_v6_listener xdg_toplevel_listener = { - }; - - static void --handle_ivi_surface_configure(void *data, struct ivi_surface *ivi_surface, -- int32_t width, int32_t height) -+create_surface(struct window *window) - { -- struct window *window = data; -- -- wl_egl_window_resize(window->native, width, height, 0, 0); -- -- window->geometry.width = width; -- window->geometry.height = height; -+ struct display *display = window->display; -+ EGLBoolean ret; - -- if (!window->fullscreen) -- window->window_size = window->geometry; --} -+ window->surface = wl_compositor_create_surface(display->compositor); - --static const struct ivi_surface_listener ivi_surface_listener = { -- handle_ivi_surface_configure, --}; -+ window->native = -+ wl_egl_window_create(window->surface, -+ window->geometry.width, -+ window->geometry.height); -+ window->egl_surface = -+ weston_platform_create_egl_surface(display->egl.dpy, -+ display->egl.conf, -+ window->native, NULL); - --static void --create_xdg_surface(struct window *window, struct display *display) --{ - window->xdg_surface = zxdg_shell_v6_get_xdg_surface(display->shell, - window->surface); - zxdg_surface_v6_add_listener(window->xdg_surface, -@@ -390,50 +381,6 @@ create_xdg_surface(struct window *window, struct display *display) - - window->wait_for_configure = true; - wl_surface_commit(window->surface); --} -- --static void --create_ivi_surface(struct window *window, struct display *display) --{ -- uint32_t id_ivisurf = IVI_SURFACE_ID + (uint32_t)getpid(); -- window->ivi_surface = -- ivi_application_surface_create(display->ivi_application, -- id_ivisurf, window->surface); -- -- if (window->ivi_surface == NULL) { -- fprintf(stderr, "Failed to create ivi_client_surface\n"); -- abort(); -- } -- -- ivi_surface_add_listener(window->ivi_surface, -- &ivi_surface_listener, window); --} -- --static void --create_surface(struct window *window) --{ -- struct display *display = window->display; -- EGLBoolean ret; -- -- window->surface = wl_compositor_create_surface(display->compositor); -- -- window->native = -- wl_egl_window_create(window->surface, -- window->geometry.width, -- window->geometry.height); -- window->egl_surface = -- weston_platform_create_egl_surface(display->egl.dpy, -- display->egl.conf, -- window->native, NULL); -- -- -- if (display->shell) { -- create_xdg_surface(window, display); -- } else if (display->ivi_application ) { -- create_ivi_surface(window, display); -- } else { -- assert(0); -- } - - ret = eglMakeCurrent(window->display->egl.dpy, window->egl_surface, - window->egl_surface, window->display->egl.ctx); -@@ -465,8 +412,6 @@ destroy_surface(struct window *window) - zxdg_toplevel_v6_destroy(window->xdg_toplevel); - if (window->xdg_surface) - zxdg_surface_v6_destroy(window->xdg_surface); -- if (window->display->ivi_application) -- ivi_surface_destroy(window->ivi_surface); - wl_surface_destroy(window->surface); - - if (window->callback) -@@ -821,10 +766,6 @@ registry_handle_global(void *data, struct wl_registry *registry, - fprintf(stderr, "unable to load default left pointer\n"); - // TODO: abort ? - } -- } else if (strcmp(interface, "ivi_application") == 0) { -- d->ivi_application = -- wl_registry_bind(registry, name, -- &ivi_application_interface, 1); - } - } - -@@ -939,9 +880,6 @@ main(int argc, char **argv) - if (display.shell) - zxdg_shell_v6_destroy(display.shell); - -- if (display.ivi_application) -- ivi_application_destroy(display.ivi_application); -- - if (display.compositor) - wl_compositor_destroy(display.compositor); - diff --git a/meta-agl/recipes-graphics/wayland/weston/0014-simple-shm-remove-ivi-application-support.patch b/meta-agl/recipes-graphics/wayland/weston/0014-simple-shm-remove-ivi-application-support.patch deleted file mode 100644 index 495e50ca2..000000000 --- a/meta-agl/recipes-graphics/wayland/weston/0014-simple-shm-remove-ivi-application-support.patch +++ /dev/null @@ -1,107 +0,0 @@ -index f9c8010b..c37cd00b 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -574,9 +574,7 @@ nodist_weston_simple_shm_SOURCES = \ - protocol/xdg-shell-unstable-v6-protocol.c \ - protocol/xdg-shell-unstable-v6-client-protocol.h \ - protocol/fullscreen-shell-unstable-v1-protocol.c \ -- protocol/fullscreen-shell-unstable-v1-client-protocol.h \ -- protocol/ivi-application-protocol.c \ -- protocol/ivi-application-client-protocol.h -+ protocol/fullscreen-shell-unstable-v1-client-protocol.h - weston_simple_shm_CFLAGS = $(AM_CFLAGS) $(SIMPLE_CLIENT_CFLAGS) - weston_simple_shm_LDADD = $(SIMPLE_CLIENT_LIBS) libshared.la - -diff --git a/clients/simple-shm.c b/clients/simple-shm.c -index 9fa2e214..fc2ef001 100644 ---- a/clients/simple-shm.c -+++ b/clients/simple-shm.c -@@ -40,10 +40,6 @@ - #include "xdg-shell-unstable-v6-client-protocol.h" - #include "fullscreen-shell-unstable-v1-client-protocol.h" - --#include --#include "ivi-application-client-protocol.h" --#define IVI_SURFACE_ID 9000 -- - struct display { - struct wl_display *display; - struct wl_registry *registry; -@@ -52,7 +48,6 @@ struct display { - struct zwp_fullscreen_shell_v1 *fshell; - struct wl_shm *shm; - bool has_xrgb; -- struct ivi_application *ivi_application; - }; - - struct buffer { -@@ -67,7 +62,6 @@ struct window { - struct wl_surface *surface; - struct zxdg_surface_v6 *xdg_surface; - struct zxdg_toplevel_v6 *xdg_toplevel; -- struct ivi_surface *ivi_surface; - struct buffer buffers[2]; - struct buffer *prev_buffer; - struct wl_callback *callback; -@@ -165,17 +159,6 @@ static const struct zxdg_toplevel_v6_listener xdg_toplevel_listener = { - handle_xdg_toplevel_close, - }; - --static void --handle_ivi_surface_configure(void *data, struct ivi_surface *ivi_surface, -- int32_t width, int32_t height) --{ -- /* Simple-shm is resizable */ --} -- --static const struct ivi_surface_listener ivi_surface_listener = { -- handle_ivi_surface_configure, --}; -- - static struct window * - create_window(struct display *display, int width, int height) - { -@@ -213,19 +196,6 @@ create_window(struct display *display, int width, int height) - window->surface, - ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_DEFAULT, - NULL); -- } else if (display->ivi_application ) { -- uint32_t id_ivisurf = IVI_SURFACE_ID + (uint32_t)getpid(); -- window->ivi_surface = -- ivi_application_surface_create(display->ivi_application, -- id_ivisurf, window->surface); -- if (window->ivi_surface == NULL) { -- fprintf(stderr, "Failed to create ivi_client_surface\n"); -- abort(); -- } -- -- ivi_surface_add_listener(window->ivi_surface, -- &ivi_surface_listener, window); -- - } else { - assert(0); - } -@@ -407,11 +377,6 @@ registry_handle_global(void *data, struct wl_registry *registry, - id, &wl_shm_interface, 1); - wl_shm_add_listener(d->shm, &shm_listener, d); - } -- else if (strcmp(interface, "ivi_application") == 0) { -- d->ivi_application = -- wl_registry_bind(registry, id, -- &ivi_application_interface, 1); -- } - } - - static void -@@ -555,11 +520,6 @@ main(int argc, char **argv) - - fprintf(stderr, "simple-shm exiting\n"); - -- if (window->display->ivi_application) { -- ivi_surface_destroy(window->ivi_surface); -- ivi_application_destroy(window->display->ivi_application); -- } -- - destroy_window(window); - destroy_display(display); - diff --git a/meta-agl/recipes-graphics/wayland/weston/0015-window-client-remove-ivi-application-support.patch b/meta-agl/recipes-graphics/wayland/weston/0015-window-client-remove-ivi-application-support.patch deleted file mode 100644 index f3d2fe47f..000000000 --- a/meta-agl/recipes-graphics/wayland/weston/0015-window-client-remove-ivi-application-support.patch +++ /dev/null @@ -1,130 +0,0 @@ -index c37cd00b..f30ddbe9 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -665,8 +665,6 @@ nodist_libtoytoolkit_la_SOURCES = \ - protocol/viewporter-client-protocol.h \ - protocol/xdg-shell-unstable-v6-protocol.c \ - protocol/xdg-shell-unstable-v6-client-protocol.h \ -- protocol/ivi-application-protocol.c \ -- protocol/ivi-application-client-protocol.h \ - protocol/pointer-constraints-unstable-v1-protocol.c \ - protocol/pointer-constraints-unstable-v1-client-protocol.h \ - protocol/relative-pointer-unstable-v1-protocol.c \ -diff --git a/clients/window.c b/clients/window.c -index 95796d46..aac43abd 100644 ---- a/clients/window.c -+++ b/clients/window.c -@@ -82,10 +82,6 @@ typedef void *EGLContext; - - #include "window.h" - --#include --#include "ivi-application-client-protocol.h" --#define IVI_SURFACE_ID 9000 -- - #define ZWP_RELATIVE_POINTER_MANAGER_V1_VERSION 1 - #define ZWP_POINTER_CONSTRAINTS_V1_VERSION 1 - -@@ -107,7 +103,6 @@ struct display { - struct wl_data_device_manager *data_device_manager; - struct text_cursor_position *text_cursor_position; - struct zxdg_shell_v6 *xdg_shell; -- struct ivi_application *ivi_application; /* ivi style shell */ - struct zwp_relative_pointer_manager_v1 *relative_pointer_manager; - struct zwp_pointer_constraints_v1 *pointer_constraints; - EGLDisplay dpy; -@@ -269,8 +264,6 @@ struct window { - struct window *parent; - struct window *last_parent; - -- struct ivi_surface *ivi_surface; -- - struct window_frame *frame; - - /* struct surface::link, contains also main_surface */ -@@ -1441,19 +1434,6 @@ window_get_display(struct window *window) - return window->display; - } - --static void --handle_ivi_surface_configure(void *data, struct ivi_surface *ivi_surface, -- int32_t width, int32_t height) --{ -- struct window *window = data; -- -- window_schedule_resize(window, width, height); --} -- --static const struct ivi_surface_listener ivi_surface_listener = { -- handle_ivi_surface_configure, --}; -- - static void - surface_create_surface(struct surface *surface, uint32_t flags) - { -@@ -1604,9 +1584,6 @@ window_destroy(struct window *window) - if (window->xdg_surface) - zxdg_surface_v6_destroy(window->xdg_surface); - -- if (window->ivi_surface) -- ivi_surface_destroy(window->ivi_surface); -- - surface_destroy(window->main_surface); - - wl_list_remove(&window->link); -@@ -5200,7 +5177,7 @@ window_create_internal(struct display *display, int custom) - surface = surface_create(window); - window->main_surface = surface; - -- assert(custom || display->xdg_shell || display->ivi_application); -+ assert(custom || display->xdg_shell); - - window->custom = custom; - window->preferred_format = WINDOW_PREFERRED_FORMAT_NONE; -@@ -5220,7 +5197,6 @@ struct window * - window_create(struct display *display) - { - struct window *window; -- uint32_t id_ivisurf; - - window = window_create_internal(display, 0); - -@@ -5243,16 +5219,6 @@ window_create(struct display *display) - window_inhibit_redraw(window); - - wl_surface_commit(window->main_surface->surface); -- } else if (display->ivi_application) { -- /* auto generation of ivi_id based on process id + basement of id */ -- id_ivisurf = IVI_SURFACE_ID + (uint32_t)getpid(); -- window->ivi_surface = -- ivi_application_surface_create(display->ivi_application, -- id_ivisurf, window->main_surface->surface); -- fail_on_null(window->ivi_surface, 0, __FILE__, __LINE__); -- -- ivi_surface_add_listener(window->ivi_surface, -- &ivi_surface_listener, window); - } - - return window; -@@ -6013,11 +5979,6 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t id, - wl_registry_bind(registry, id, - &wl_subcompositor_interface, 1); - } -- else if (strcmp(interface, "ivi_application") == 0) { -- d->ivi_application = -- wl_registry_bind(registry, id, -- &ivi_application_interface, 1); -- } - - if (d->global_handler) - d->global_handler(d, id, interface, version, d->user_data); -@@ -6316,9 +6277,6 @@ display_destroy(struct display *display) - if (display->xdg_shell) - zxdg_shell_v6_destroy(display->xdg_shell); - -- if (display->ivi_application) -- ivi_application_destroy(display->ivi_application); -- - if (display->shm) - wl_shm_destroy(display->shm); - diff --git a/meta-agl/recipes-graphics/wayland/weston/0016-ivi-shell_add_screen_remove_layer_api.patch b/meta-agl/recipes-graphics/wayland/weston/0016-ivi-shell_add_screen_remove_layer_api.patch deleted file mode 100644 index 3e85e93f6..000000000 --- a/meta-agl/recipes-graphics/wayland/weston/0016-ivi-shell_add_screen_remove_layer_api.patch +++ /dev/null @@ -1,82 +0,0 @@ -From deee858b0b199d8cfa8033a46d7078f30b23725e Mon Sep 17 00:00:00 2001 -From: "Ucan, Emre (ADITG/SW1)" -Date: Thu, 2 Mar 2017 08:47:33 +0000 -Subject: ivi-shell: add_screen_remove_layer API - -It is analagous to layer_remove_surface API. -The API removes a layer from the render order -of the screen. - -v3: -add the new vfunc at the end of -the ivi_layout_interface struct. - -Signed-off-by: Emre Ucan -Reviewed-by: Eugen Friedrich -Reviewed-by: Pekka Paalanen - -diff --git a/ivi-shell/ivi-layout-export.h b/ivi-shell/ivi-layout-export.h -index 2317d6e..39ffde1 100644 ---- a/ivi-shell/ivi-layout-export.h -+++ b/ivi-shell/ivi-layout-export.h -@@ -578,6 +578,16 @@ struct ivi_layout_interface { - */ - struct ivi_layout_surface * - (*get_surface)(struct weston_surface *surface); -+ -+ /** -+ * \brief Remove a ivi_layer to a weston_output which is currently managed -+ * by the service -+ * -+ * \return IVI_SUCCEEDED if the method call was successful -+ * \return IVI_FAILED if the method call was failed -+ */ -+ int32_t (*screen_remove_layer)(struct weston_output *output, -+ struct ivi_layout_layer *removelayer); - }; - - #ifdef __cplusplus -diff --git a/ivi-shell/ivi-layout.c b/ivi-shell/ivi-layout.c -index 298e18e..8e4280b 100644 ---- a/ivi-shell/ivi-layout.c -+++ b/ivi-shell/ivi-layout.c -@@ -1664,6 +1664,27 @@ ivi_layout_screen_add_layer(struct weston_output *output, - } - - static int32_t -+ivi_layout_screen_remove_layer(struct weston_output *output, -+ struct ivi_layout_layer *removelayer) -+{ -+ struct ivi_layout_screen *iviscrn; -+ -+ if (output == NULL || removelayer == NULL) { -+ weston_log("ivi_layout_screen_remove_layer: invalid argument\n"); -+ return IVI_FAILED; -+ } -+ -+ iviscrn = get_screen_from_output(output); -+ -+ wl_list_remove(&removelayer->pending.link); -+ wl_list_init(&removelayer->pending.link); -+ -+ iviscrn->order.dirty = 1; -+ -+ return IVI_SUCCEEDED; -+} -+ -+static int32_t - ivi_layout_screen_set_render_order(struct weston_output *output, - struct ivi_layout_layer **pLayer, - const int32_t number) -@@ -2088,6 +2109,7 @@ static struct ivi_layout_interface ivi_layout_interface = { - */ - .get_screens_under_layer = ivi_layout_get_screens_under_layer, - .screen_add_layer = ivi_layout_screen_add_layer, -+ .screen_remove_layer = ivi_layout_screen_remove_layer, - .screen_set_render_order = ivi_layout_screen_set_render_order, - - /** --- -cgit v0.10.2 - - diff --git a/meta-agl/recipes-graphics/wayland/weston_2.0.0.bbappend b/meta-agl/recipes-graphics/wayland/weston_2.0.0.bbappend deleted file mode 100644 index f6f88a6d6..000000000 --- a/meta-agl/recipes-graphics/wayland/weston_2.0.0.bbappend +++ /dev/null @@ -1,23 +0,0 @@ -FILESEXTRAPATHS_append := ":${THISDIR}/${PN}" - -SRC_URI_append = "\ - file://0001-Allow-regular-users-to-launch-Weston_2.0.0.patch \ - file://0001-ivi-shell-rework-goto-labels-to-avoid-memory-leaks.patch \ - file://0002-ivi-shell-removed-assert.patch \ - file://0003-ivi-shell-introduction-of-IVI_INVALID_ID.patch \ - file://0004-layout-interface-added-interface-to-change-surface-id.patch \ - file://0005-ivi-layout-introcuded-configure_desktop_changed.patch \ - file://0006-ivi-layout-introcuded-surface_create_and_configure.patch \ - file://0007-ivi-shell-linked-libweston-desktop-and-added-structs.patch \ - file://0008-ivi-layout-use-libweston-desktop-api-for-views.patch \ - file://0009-ivi-shell-added-libweston-desktop-api_implementation.patch \ - file://0010-ivi-shell-remove-surface_destroy_listener.patch \ - file://0011-ivi-shell-create-weston-desktop-in_wet_shell_init.patch \ - file://0012-hmi-controller-register-for-desktop_surface_configured.patch \ - file://0013-simple-egl-remove-ivi-application-support.patch \ - file://0014-simple-shm-remove-ivi-application-support.patch \ - file://0015-window-client-remove-ivi-application-support.patch \ - file://0016-ivi-shell_add_screen_remove_layer_api.patch \ - " - -EXTRA_OECONF_append = " --enable-sys-uid" diff --git a/meta-agl/recipes-ivi/images/agl-image-ivi-crosssdk.bb b/meta-agl/recipes-ivi/images/agl-image-ivi-crosssdk.bb deleted file mode 100644 index 0303d051d..000000000 --- a/meta-agl/recipes-ivi/images/agl-image-ivi-crosssdk.bb +++ /dev/null @@ -1,19 +0,0 @@ -SUMMARY = "Cross SDK of AGL Distribution for IVI profile" - -DESCRIPTION = "Basic image for baseline of AGL Distribution for IVI profile. \ -It includes the full meta-toolchain, plus developement headers and libraries \ -to form a standalone cross SDK." - -require agl-image-ivi.bb - -LICENSE = "MIT" - -IMAGE_FEATURES += "dev-pkgs" -IMAGE_INSTALL += "kernel-dev" - -inherit populate_sdk - -# Task do_populate_sdk and do_rootfs can't be exec simultaneously. -# Both exec "createrepo" on the same directory, and so one of them -# can failed (randomly). -addtask do_populate_sdk after do_rootfs diff --git a/meta-agl/recipes-ivi/images/agl-image-ivi-qa.bb b/meta-agl/recipes-ivi/images/agl-image-ivi-qa.bb deleted file mode 100644 index 017439454..000000000 --- a/meta-agl/recipes-ivi/images/agl-image-ivi-qa.bb +++ /dev/null @@ -1,14 +0,0 @@ -SUMMARY = "A basic system of AGL distribution of IVI profile for Quality Assurance(QA)" - -DESCRIPTION = "A basic set of AGL Distribution. This image also has additional \ -packages (e.g. commandline tools) for Quality Assurance(QA)." - -require agl-image-ivi.bb - -LICENSE = "MIT" - -IMAGE_INSTALL_append = " \ - packagegroup-agl-test \ - packagegroup-ivi-common-test \ - " - diff --git a/meta-agl/recipes-ivi/images/agl-image-ivi.bb b/meta-agl/recipes-ivi/images/agl-image-ivi.bb deleted file mode 100644 index dd4f89b15..000000000 --- a/meta-agl/recipes-ivi/images/agl-image-ivi.bb +++ /dev/null @@ -1,17 +0,0 @@ -SUMMARY = "A basic system of AGL distribution of IVI profile" - -DESCRIPTION = "Basic image for baseline of AGL Distribution for IVI profile." - -require agl-image-ivi.inc - -LICENSE = "MIT" - -IMAGE_INSTALL_append = "\ - packagegroup-agl-image-ivi \ - " - -DISTRO_FEATURES_append = " agl-core-image-profile" - -IMAGE_INSTALL += "\ - agl-desktop-config \ - " diff --git a/meta-agl/recipes-ivi/images/agl-image-ivi.inc b/meta-agl/recipes-ivi/images/agl-image-ivi.inc deleted file mode 100644 index 0b564840b..000000000 --- a/meta-agl/recipes-ivi/images/agl-image-ivi.inc +++ /dev/null @@ -1,3 +0,0 @@ -require recipes-core/images/agl-image-minimal.inc - -IMAGE_FEATURES += "splash package-management ssh-server-dropbear" diff --git a/meta-agl/recipes-ivi/packagegroups/packagegroup-agl-image-ivi.bb b/meta-agl/recipes-ivi/packagegroups/packagegroup-agl-image-ivi.bb deleted file mode 100644 index 27e90f808..000000000 --- a/meta-agl/recipes-ivi/packagegroups/packagegroup-agl-image-ivi.bb +++ /dev/null @@ -1,32 +0,0 @@ -SUMMARY = "The middlewares for AGL IVI profile" -DESCRIPTION = "The set of packages required for AGL Distribution" -LICENSE = "MIT" - -inherit packagegroup - -PACKAGES = "\ - packagegroup-agl-image-ivi \ - " - -ALLOW_EMPTY_${PN} = "1" - -RDEPENDS_${PN} += "\ - packagegroup-agl-image-minimal \ - packagegroup-ivi-common-core \ -" - -RDEPENDS_${PN} += "\ - packagegroup-agl-ivi-automotive \ - packagegroup-agl-ivi-connectivity \ - packagegroup-agl-ivi-graphics \ - packagegroup-agl-ivi-multimedia \ - packagegroup-agl-ivi-navi-lbs \ - packagegroup-agl-ivi-os-commonlibs \ - packagegroup-agl-ivi-speech-services \ - packagegroup-agl-ivi-security \ - packagegroup-agl-ivi-kernel \ - " - -RDEPENDS_${PN} += "\ - agl-login-manager \ - " diff --git a/meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-automotive.bb b/meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-automotive.bb deleted file mode 100644 index f7221517f..000000000 --- a/meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-automotive.bb +++ /dev/null @@ -1,14 +0,0 @@ -SUMMARY = "The middlewares for AGL IVI profile" -DESCRIPTION = "The set of packages required by Automotive Subsystem" -LICENSE = "MIT" - -inherit packagegroup - -PACKAGES = "\ - packagegroup-agl-ivi-automotive \ - " - -ALLOW_EMPTY_${PN} = "1" - -RDEPENDS_${PN} += "\ - " diff --git a/meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-connectivity.bb b/meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-connectivity.bb deleted file mode 100644 index 664180d55..000000000 --- a/meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-connectivity.bb +++ /dev/null @@ -1,19 +0,0 @@ -SUMMARY = "The middlewares for AGL IVI profile" -DESCRIPTION = "The set of packages required by Connectivity Subsystem" -LICENSE = "MIT" - -inherit packagegroup - -PACKAGES = "\ - packagegroup-agl-ivi-connectivity \ - " - -ALLOW_EMPTY_${PN} = "1" - -RDEPENDS_${PN} += "\ - ofono \ - rtl-sdr \ - rygel \ - rygel-plugin-media-export \ - rygel-plugin-lms \ - " diff --git a/meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-graphics.bb b/meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-graphics.bb deleted file mode 100644 index d7650564b..000000000 --- a/meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-graphics.bb +++ /dev/null @@ -1,14 +0,0 @@ -SUMMARY = "The middlewares for AGL IVI profile" -DESCRIPTION = "The set of packages required by Graphics Subsystem" -LICENSE = "MIT" - -inherit packagegroup - -PACKAGES = "\ - packagegroup-agl-ivi-graphics \ - " - -ALLOW_EMPTY_${PN} = "1" - -RDEPENDS_${PN} += "\ - " diff --git a/meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-kernel.bb b/meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-kernel.bb deleted file mode 100644 index be51817b7..000000000 --- a/meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-kernel.bb +++ /dev/null @@ -1,14 +0,0 @@ -SUMMARY = "The middlewares for AGL IVI profile" -DESCRIPTION = "The set of packages required by Kernel Subsystem" -LICENSE = "MIT" - -inherit packagegroup - -PACKAGES = "\ - packagegroup-agl-ivi-kernel \ - " - -ALLOW_EMPTY_${PN} = "1" - -RDEPENDS_${PN} += "\ - " diff --git a/meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-multimedia.bb b/meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-multimedia.bb deleted file mode 100644 index 11536405e..000000000 --- a/meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-multimedia.bb +++ /dev/null @@ -1,17 +0,0 @@ -SUMMARY = "The middlewares for AGL IVI profile" -DESCRIPTION = "The set of packages required by Multimedia Subsystem" -LICENSE = "MIT" - -inherit packagegroup - -PACKAGES = "\ - packagegroup-agl-ivi-multimedia \ - " - -ALLOW_EMPTY_${PN} = "1" - -RDEPENDS_${PN} += "\ - gstreamer1.0-plugins-base-meta \ - gstreamer1.0-plugins-good-meta \ - lightmediascanner-meta \ - " diff --git a/meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-navi-lbs.bb b/meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-navi-lbs.bb deleted file mode 100644 index b7f47eecc..000000000 --- a/meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-navi-lbs.bb +++ /dev/null @@ -1,14 +0,0 @@ -SUMMARY = "The packages of middlewares for AGL IVI profile" -DESCRIPTION = "The set of packages required by Navigation and Location Based Services Subsystem" -LICENSE = "MIT" - -inherit packagegroup - -PACKAGES = "\ - packagegroup-agl-ivi-navi-lbs \ - " - -RDEPENDS_${PN} += "\ - gpsd \ - geoclue \ - " diff --git a/meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-os-commonlibs.bb b/meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-os-commonlibs.bb deleted file mode 100644 index 0a9de8d5f..000000000 --- a/meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-os-commonlibs.bb +++ /dev/null @@ -1,14 +0,0 @@ -SUMMARY = "The packages of middlewares for AGL IVI profile" -DESCRIPTION = "The set of packages required by Operating System and Common libraries Subsystem" -LICENSE = "MIT" - -inherit packagegroup - -PACKAGES = "\ - packagegroup-agl-ivi-os-commonlibs \ - " - -ALLOW_EMPTY_${PN} = "1" - -RDEPENDS_${PN} += "\ - " diff --git a/meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-security.bb b/meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-security.bb deleted file mode 100644 index f651c50cd..000000000 --- a/meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-security.bb +++ /dev/null @@ -1,14 +0,0 @@ -SUMMARY = "The packages of middlewares for AGL IVI profile" -DESCRIPTION = "The set of packages required by Security Subsystem" -LICENSE = "MIT" - -inherit packagegroup - -PACKAGES = "\ - packagegroup-agl-ivi-security \ - " - -ALLOW_EMPTY_${PN} = "1" - -RDEPENDS_${PN} += "\ - " diff --git a/meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-speech-services.bb b/meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-speech-services.bb deleted file mode 100644 index eccebee9f..000000000 --- a/meta-agl/recipes-ivi/packagegroups/packagegroup-agl-ivi-speech-services.bb +++ /dev/null @@ -1,14 +0,0 @@ -SUMMARY = "The packages of middlewares for AGL IVI profile" -DESCRIPTION = "The set of packages required by Speech Services Subsystem" -LICENSE = "MIT" - -inherit packagegroup - -PACKAGES = "\ - packagegroup-agl-ivi-speech-services \ - " - -ALLOW_EMPTY_${PN} = "1" - -RDEPENDS_${PN} += "\ - " diff --git a/meta-agl/recipes-multimedia/gstreamer1.0-plugins-good/gstreamer1.0-plugins-good_%.bbappend b/meta-agl/recipes-multimedia/gstreamer1.0-plugins-good/gstreamer1.0-plugins-good_%.bbappend deleted file mode 100644 index 86a181fbb..000000000 --- a/meta-agl/recipes-multimedia/gstreamer1.0-plugins-good/gstreamer1.0-plugins-good_%.bbappend +++ /dev/null @@ -1,2 +0,0 @@ -# libv4l2 is useful for making more efficient use of cameras via v4l2src. -PACKAGECONFIG_append = " libv4l2" diff --git a/meta-agl/recipes-multimedia/lightmediascanner/.appends.meta-efl b/meta-agl/recipes-multimedia/lightmediascanner/.appends.meta-efl deleted file mode 100644 index e69de29bb..000000000 diff --git a/meta-agl/recipes-multimedia/lightmediascanner/files/0001-Define-comparison_fn_t-for-non-glibc-systems.patch b/meta-agl/recipes-multimedia/lightmediascanner/files/0001-Define-comparison_fn_t-for-non-glibc-systems.patch deleted file mode 100644 index 15d4b3f0e..000000000 --- a/meta-agl/recipes-multimedia/lightmediascanner/files/0001-Define-comparison_fn_t-for-non-glibc-systems.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 5bc5b8c5dad3edec6736fd7e7ce61250c4ce3725 Mon Sep 17 00:00:00 2001 -From: Khem Raj -Date: Wed, 12 Jul 2017 17:13:19 -0700 -Subject: [PATCH] Define comparison_fn_t for non-glibc systems - -lightmediascanner.c:324:12: error: 'comparison_fn_t' undeclared (first use in this function) - (comparison_fn_t)_plugin_sort); - ^~~~~~~~~~~~~~~ - -Signed-off-by: Khem Raj ---- - src/lib/lightmediascanner.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/src/lib/lightmediascanner.c b/src/lib/lightmediascanner.c -index 344b247..b866883 100644 ---- a/src/lib/lightmediascanner.c -+++ b/src/lib/lightmediascanner.c -@@ -37,6 +37,11 @@ - #define DEFAULT_SLAVE_TIMEOUT 1000 - #define DEFAULT_COMMIT_INTERVAL 100 - -+#if !defined(__GLIBC__) -+typedef int (*__compar_fn_t) (const void*, const void*); -+typedef __compar_fn_t comparison_fn_t; -+#endif -+ - #ifdef HAVE_MAGIC_H - static magic_t _magic_handle; - --- -2.13.2 - diff --git a/meta-agl/recipes-multimedia/lightmediascanner/files/dbus-lightmediascanner.conf b/meta-agl/recipes-multimedia/lightmediascanner/files/dbus-lightmediascanner.conf deleted file mode 100644 index 9cb321ba9..000000000 --- a/meta-agl/recipes-multimedia/lightmediascanner/files/dbus-lightmediascanner.conf +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/meta-agl/recipes-multimedia/lightmediascanner/files/id3-plugin-support-out-of-tree-build.patch b/meta-agl/recipes-multimedia/lightmediascanner/files/id3-plugin-support-out-of-tree-build.patch deleted file mode 100644 index 9528bec79..000000000 --- a/meta-agl/recipes-multimedia/lightmediascanner/files/id3-plugin-support-out-of-tree-build.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/src/plugins/Makefile.am 2015-10-25 16:12:29.331415823 +0000 -+++ b/src/plugins/Makefile.am 2015-10-25 16:14:37.593415808 +0000 -@@ -93,7 +93,7 @@ - id3_id3_la_SOURCES = id3/id3.c id3/id3v1_genres.c - id3_id3_la_LIBADD = $(PLUGINS_LIBADD) - --id3/id3v1_genres.c: $(srcdir)/id3/id3v1_genres.def $(srcdir)/id3/id3v1_genres_gen.awk -+$(srcdir)/id3/id3v1_genres.c: $(srcdir)/id3/id3v1_genres.def $(srcdir)/id3/id3v1_genres_gen.awk - $(AWK) -f $(srcdir)/id3/id3v1_genres_gen.awk $(srcdir)/id3/id3v1_genres.def > $@ - - EXTRA_DIST += id3/id3v1_genres.def id3/id3v1_genres_gen.awk diff --git a/meta-agl/recipes-multimedia/lightmediascanner/files/lightmediascanner.service b/meta-agl/recipes-multimedia/lightmediascanner/files/lightmediascanner.service deleted file mode 100644 index 33cf27ed0..000000000 --- a/meta-agl/recipes-multimedia/lightmediascanner/files/lightmediascanner.service +++ /dev/null @@ -1,11 +0,0 @@ -[Unit] -Description=Lightmediascanner (LMS) - -[Service] -Type=dbus -BusName=org.lightmediascanner -ExecStart=/usr/bin/lightmediascannerd --startup-scan --directory=/media --directory=${HOME}/Music --directory=${HOME}/Videos - -[Install] -WantedBy=default.target -Alias=dbus-org.lightmediascanner.service diff --git a/meta-agl/recipes-multimedia/lightmediascanner/files/plugin-ogg-fix-chucksize-issue.patch b/meta-agl/recipes-multimedia/lightmediascanner/files/plugin-ogg-fix-chucksize-issue.patch deleted file mode 100644 index 6a0b8ff93..000000000 --- a/meta-agl/recipes-multimedia/lightmediascanner/files/plugin-ogg-fix-chucksize-issue.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 3e66b97221440b17a184feb48692dce7e0561cac Mon Sep 17 00:00:00 2001 -From: Matt Ranostay -Date: Wed, 8 Mar 2017 16:30:01 -0800 -Subject: [PATCH] plugin: ogg: fix chucksize issue - -There are some OGG files that have metadata chucks that go over the -hardcoded 10 * 4096 size due to album art. This patchset just parses -each chuck and continues till it runs out of valid chunks. - -Signed-off-by: Matt Ranostay ---- - src/plugins/ogg/ogg.c | 11 ++--------- - 1 file changed, 2 insertions(+), 9 deletions(-) - -diff --git a/src/plugins/ogg/ogg.c b/src/plugins/ogg/ogg.c -index 1c0818e..c94dc38 100644 ---- a/src/plugins/ogg/ogg.c -+++ b/src/plugins/ogg/ogg.c -@@ -47,8 +47,6 @@ - int CHUNKSIZE = 4096; - #endif - --#define MAX_CHUNKS_PER_PAGE 10 -- - struct stream { - struct lms_stream base; - int serial; -@@ -122,10 +120,8 @@ _set_lms_info(struct lms_string_size *info, const char *tag) - - static bool _ogg_read_page(FILE *fp, ogg_sync_state *osync, ogg_page *page) - { -- int i; -- -- for (i = 0; i < MAX_CHUNKS_PER_PAGE && ogg_sync_pageout(osync, page) != 1; -- i++) { -+ while(ogg_sync_pageout(osync, page) != 1) -+ { - lms_ogg_buffer_t buffer = lms_get_ogg_sync_buffer(osync, CHUNKSIZE); - int bytes = fread(buffer, 1, CHUNKSIZE, fp); - -@@ -136,9 +132,6 @@ static bool _ogg_read_page(FILE *fp, ogg_sync_state *osync, ogg_page *page) - ogg_sync_wrote(osync, bytes); - } - -- if (i > MAX_CHUNKS_PER_PAGE) -- return false; -- - return true; - } - --- -2.7.4 - diff --git a/meta-agl/recipes-multimedia/lightmediascanner/lightmediascanner_%.bbappend b/meta-agl/recipes-multimedia/lightmediascanner/lightmediascanner_%.bbappend deleted file mode 100644 index cf248d3fd..000000000 --- a/meta-agl/recipes-multimedia/lightmediascanner/lightmediascanner_%.bbappend +++ /dev/null @@ -1,33 +0,0 @@ -# Disable everything but the roygalty-free formats -PACKAGECONFIG = "ogg flac wave m3u pls jpeg png" - -FILESEXTRAPATHS_prepend := "${THISDIR}/files:" - -SRC_URI += "file://lightmediascanner.service \ - file://plugin-ogg-fix-chucksize-issue.patch \ - file://dbus-lightmediascanner.conf \ - " - -CFLAGS_append = " -D_FILE_OFFSET_BITS=64" - -inherit systemd - -do_install_append() { - # Install LMS systemd service - if ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'true', 'false', d)}; then - install -m 644 -p -D ${WORKDIR}/lightmediascanner.service ${D}${systemd_user_unitdir}/lightmediascanner.service - - # Execute these manually on behalf of systemctl script (from systemd-systemctl-native.bb) - # because it does not support systemd's user mode. - mkdir -p ${D}/etc/systemd/user/default.target.wants/ - ln -sf ${systemd_user_unitdir}/lightmediascanner.service ${D}/etc/systemd/user/dbus-org.lightmediascanner.service - ln -sf ${systemd_user_unitdir}/lightmediascanner.service ${D}/etc/systemd/user/default.target.wants/lightmediascanner.service - fi - - install -d ${D}/etc/dbus-1/session.d - install -m 0644 ${WORKDIR}/dbus-lightmediascanner.conf ${D}/etc/dbus-1/session.d/lightmediascanner.conf -} - -FILES_${PN} += " \ - ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', '${systemd_user_unitdir}/lightmediascanner.service', '', d)} \ - " diff --git a/meta-agl/recipes-multimedia/lightmediascanner/lightmediascanner_0.5.1.bb b/meta-agl/recipes-multimedia/lightmediascanner/lightmediascanner_0.5.1.bb deleted file mode 100644 index f2158760f..000000000 --- a/meta-agl/recipes-multimedia/lightmediascanner/lightmediascanner_0.5.1.bb +++ /dev/null @@ -1,63 +0,0 @@ -SUMMARY = "Lightweight media scanner" -DESCRIPTION = "Lightweight media scanner meant to be used in not-so-powerful devices, like embedded systems or old machines." -SECTION = "libs/multimedia" - -LICENSE = "LGPLv2.1+" -LIC_FILES_CHKSUM = "file://COPYING;md5=a6f89e2100d9b6cdffcea4f398e37343 \ - file://src/lib/lightmediascanner.c;endline=21;md5=6d8889bccb4c6c27e8b786342a3eb267" - -DEPENDS = "file gawk glib-2.0 sqlite3" - -PV = "0.5.1+git${SRCPV}" -SRCREV = "adfddb3486276a5ed2f5008c9e43a811e1271cc9" -SRC_URI = "git://github.com/profusion/lightmediascanner.git \ - file://id3-plugin-support-out-of-tree-build.patch \ - file://0001-Define-comparison_fn_t-for-non-glibc-systems.patch \ - " - -S = "${WORKDIR}/git" - -inherit autotools pkgconfig - -EXTRA_OECONF = "--enable-static --disable-mp4" - -PACKAGECONFIG ??= "ogg flac wave id3 m3u pls asf rm jpeg png" -PACKAGECONFIG[generic] = "--enable-generic,--disable-generic,libav" -PACKAGECONFIG[ogg] = "--enable-ogg,--disable-ogg,libogg libvorbis libtheora" -PACKAGECONFIG[flac] = "--enable-flac,--disable-flac,flac" -PACKAGECONFIG[wave] = "--enable-wave,--disable-wave" -PACKAGECONFIG[id3] = "--enable-id3,--disable-id3" -PACKAGECONFIG[m3u] = "--enable-m3u,--disable-m3u" -PACKAGECONFIG[pls] = "--enable-pls,--disable-pls" -PACKAGECONFIG[asf] = "--enable-asf,--disable-asf" -PACKAGECONFIG[rm] = "--enable-rm,--disable-rm" -PACKAGECONFIG[jpeg] = "--enable-jpeg,--disable-jpeg" -PACKAGECONFIG[png] = "--enable-png,--disable-png" - -do_install_append() { - # Install "test" binary for corresponding package - install -d ${D}/${bindir} - install -m 755 ${B}/src/bin/.libs/test ${D}/${bindir}/test-lms - # Remove .la files for loadable modules - rm -f ${D}/${libdir}/${PN}/plugins/*.la -} - -FILES_${PN} += "${datadir}/dbus-1" -FILES_${PN}-dbg += "${libdir}/${PN}/plugins/.debug" - -PACKAGES_prepend = "${PN}-test " -FILES_${PN}-test_prepend = "${bindir}/test-lms " - -PACKAGES += "${PN}-meta" -ALLOW_EMPTY_${PN}-meta = "1" - -PACKAGES_DYNAMIC = "${PN}-plugin-*" - -python populate_packages_prepend () { - lms_libdir = d.expand('${libdir}/${PN}') - pkgs = [] - - pkgs += do_split_packages(d, oe.path.join(lms_libdir, "plugins"), '^(.*)\.so$', d.expand('${PN}-plugin-%s'), 'LightMediaScanner plugin for %s', prepend=True, extra_depends=d.expand('${PN}')) - metapkg = d.getVar('PN') + '-meta' - d.setVar('RDEPENDS_' + metapkg, ' '.join(pkgs)) -} diff --git a/meta-agl/recipes-multimedia/pulseaudio/agl-audio-plugin_0.1.bb b/meta-agl/recipes-multimedia/pulseaudio/agl-audio-plugin_0.1.bb deleted file mode 100644 index 633a3e248..000000000 --- a/meta-agl/recipes-multimedia/pulseaudio/agl-audio-plugin_0.1.bb +++ /dev/null @@ -1,28 +0,0 @@ -SUMMARY = "AGL Audio Policy Plugin" -DESCRIPTION = "AGL PulseAudio Routing plugin, forked from the Tizen IVI \ -PulseAudio Routing plugin, also known as module-murphy-ivi. This is a \ -stripped-down version of the former, not needing Murphy anymore and using \ -either a JSON configuration file or its own embedded configuration." -HOMEPAGE = "http://www.iot.bzh" - -LICENSE = "LGPL-2.1" -LIC_FILES_CHKSUM = "file://COPYING;md5=2d5025d4aa3495befef8f17206a5b0a1" - -DEPENDS = "json-c pulseaudio" -RDEPENDS_${PN} = "pulseaudio-server pulseaudio-module-null-sink pulseaudio-module-loopback" - -SRCREV = "952d404e87ca6001e546fe9105bdb6760c468760" -SRC_URI = "git://gerrit.automotivelinux.org/gerrit/staging/agl-audio-plugin;protocol=https;branch=${AGL_BRANCH}" - -S = "${WORKDIR}/git" - -inherit cmake pkgconfig - -FULL_OPTIMIZATION = "-O1 -pipe ${DEBUG_FLAGS}" - -PULSE_PV="9.0" - -EXTRA_OECMAKE_append = " -DPULSE_PV:STRING=${PULSE_PV}" - -FILES_${PN} += "${libdir}/pulse-${PULSE_PV}/modules/* ${sysconfdir}/pulse/*" -FILES_${PN}-dbg += "${libdir}/pulse-${PULSE_PV}/modules/.debug/*" diff --git a/meta-agl/recipes-navi-lbs/.gitkeep b/meta-agl/recipes-navi-lbs/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/meta-agl/recipes-navigation/geoclue/files/org.freedesktop.GeoClue2.Client.conf b/meta-agl/recipes-navigation/geoclue/files/org.freedesktop.GeoClue2.Client.conf deleted file mode 100644 index a7486d055..000000000 --- a/meta-agl/recipes-navigation/geoclue/files/org.freedesktop.GeoClue2.Client.conf +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/meta-agl/recipes-navigation/geoclue/geoclue_%.bbappend b/meta-agl/recipes-navigation/geoclue/geoclue_%.bbappend deleted file mode 100644 index 9d61a9f61..000000000 --- a/meta-agl/recipes-navigation/geoclue/geoclue_%.bbappend +++ /dev/null @@ -1,9 +0,0 @@ -inherit gobject-introspection - -FILESEXTRAPATHS_prepend := "${THISDIR}/files:" -SRC_URI_append = "file://org.freedesktop.GeoClue2.Client.conf" - -do_install_append() { - install -d ${D}/etc/dbus-1/system.d - install -m 0644 ${WORKDIR}/org.freedesktop.GeoClue2.Client.conf ${D}/etc/dbus-1/system.d/org.freedesktop.GeoClue2.Client.conf -} diff --git a/meta-agl/recipes-navigation/gpsd/gpsd_%.bbappend b/meta-agl/recipes-navigation/gpsd/gpsd_%.bbappend deleted file mode 100644 index af72aece9..000000000 --- a/meta-agl/recipes-navigation/gpsd/gpsd_%.bbappend +++ /dev/null @@ -1,14 +0,0 @@ -SYSTEMD_SERVICE_${PN} += " gpsdctl@.service" - -do_install_append() { - # use the systemd compatible gpsd.rules - install -d ${D}/${sysconfdir}/udev/rules.d - install -m 0644 ${S}/gpsd.rules ${D}/${sysconfdir}/udev/rules.d/60-gpsd.rules - - #support for systemd - install -d ${D}${systemd_unitdir}/system/ - install -m 0644 ${S}/systemd/gpsdctl@.service ${D}${systemd_unitdir}/system - - #autoprobe usb gps devices - echo 'USBAUTO="true"' >> ${D}${sysconfdir}/default/gpsd.default -} diff --git a/meta-agl/recipes-support/.gitkeep b/meta-agl/recipes-support/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/meta-agl/recipes-support/libsoup/libsoup-2.4_%.bbappend b/meta-agl/recipes-support/libsoup/libsoup-2.4_%.bbappend deleted file mode 100644 index 06651fc11..000000000 --- a/meta-agl/recipes-support/libsoup/libsoup-2.4_%.bbappend +++ /dev/null @@ -1 +0,0 @@ -EXTRA_OECONF_append_class-native = " --disable-tls-check" diff --git a/meta-agl/recipes-test/packagegroups/packagegroup-agl-test.bb b/meta-agl/recipes-test/packagegroups/packagegroup-agl-test.bb deleted file mode 100644 index 2a18cbc89..000000000 --- a/meta-agl/recipes-test/packagegroups/packagegroup-agl-test.bb +++ /dev/null @@ -1,15 +0,0 @@ -SUMMARY = "Utilities for testing of AGL" -DESCRIPTION = "A set of packages required by testing AGL for Quality Assurance" - -LICENSE = "MIT" - -inherit packagegroup - -PACKAGES = "\ - packagegroup-agl-test \ - " - -ALLOW_EMPTY_${PN} = "1" - -RDEPENDS_${PN} += "\ - " diff --git a/meta-ivi-common/classes/.gitkeep b/meta-ivi-common/classes/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/meta-ivi-common/conf/layer.conf b/meta-ivi-common/conf/layer.conf deleted file mode 100644 index 42517232a..000000000 --- a/meta-ivi-common/conf/layer.conf +++ /dev/null @@ -1,10 +0,0 @@ -# We have a conf and classes directory, add to BBPATH -BBPATH =. "${LAYERDIR}:" - -# We have recipes-* directories, add to BBFILES -BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \ - ${LAYERDIR}/recipes-*/*/*.bbappend" - -BBFILE_COLLECTIONS += "ivi-common" -BBFILE_PATTERN_ivi-common = "^${LAYERDIR}/" -BBFILE_PRIORITY_ivi-common = "70" diff --git a/meta-ivi-common/recipes-connectivity/.gitkeep b/meta-ivi-common/recipes-connectivity/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-automotive.bb b/meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-automotive.bb deleted file mode 100644 index e63333157..000000000 --- a/meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-automotive.bb +++ /dev/null @@ -1,14 +0,0 @@ -SUMMARY = "The middlewares for AGL IVI profile" -DESCRIPTION = "A set of common packages required by Automotive Subsystem" - -LICENSE = "MIT" - -inherit packagegroup - -PACKAGES = "\ - packagegroup-ivi-common-core-automotive \ - " - -ALLOW_EMPTY_${PN} = "1" - -RDEPENDS_${PN} += " " diff --git a/meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-connectivity.bb b/meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-connectivity.bb deleted file mode 100644 index 2453c3cb0..000000000 --- a/meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-connectivity.bb +++ /dev/null @@ -1,15 +0,0 @@ -SUMMARY = "The middlewares for AGL IVI profile" -DESCRIPTION = "A set of common packages required by Connectivity Subsystem " - -LICENSE = "MIT" - -inherit packagegroup - -PACKAGES = "\ - packagegroup-ivi-common-core-connectivity \ - " - -ALLOW_EMPTY_${PN} = "1" - -RDEPENDS_${PN} += "\ - " diff --git a/meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-graphics.bb b/meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-graphics.bb deleted file mode 100644 index c474b9fc5..000000000 --- a/meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-graphics.bb +++ /dev/null @@ -1,17 +0,0 @@ -SUMMARY = "The middlewares for AGL IVI profile" -DESCRIPTION = "A set of common packages required by Graphics Subsystem" - -LICENSE = "MIT" - -inherit packagegroup - -PACKAGES = "\ - packagegroup-ivi-common-core-graphics \ - " - -ALLOW_EMPTY_${PN} = "1" - -RDEPENDS_${PN} += "\ - weston weston-init weston-ini-conf weston-examples \ - wayland-ivi-extension \ - " diff --git a/meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-kernel.bb b/meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-kernel.bb deleted file mode 100644 index 14e5f4347..000000000 --- a/meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-kernel.bb +++ /dev/null @@ -1,15 +0,0 @@ -SUMMARY = "The middlewares for AGL IVI profile" -DESCRIPTION = "A set of common packages required by Kernel Subysystem" - -LICENSE = "MIT" - -inherit packagegroup - -PACKAGES = "\ - packagegroup-ivi-common-core-kernel \ - " - -ALLOW_EMPTY_${PN} = "1" - -RDEPENDS_${PN} += "\ - " diff --git a/meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-multimedia.bb b/meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-multimedia.bb deleted file mode 100644 index 602d247b4..000000000 --- a/meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-multimedia.bb +++ /dev/null @@ -1,28 +0,0 @@ -SUMMARY = "The middlewares for AGL IVI profile" -DESCRIPTION = "A set of common packages required by Multimedia Subsystem" - -LICENSE = "MIT" - -inherit packagegroup - -PACKAGES = "\ - packagegroup-ivi-common-core-multimedia \ - " - -ALLOW_EMPTY_${PN} = "1" - -RDEPENDS_${PN} += "\ - ${@bb.utils.contains('DISTRO_FEATURES', 'agl-audio-4a-framework', '' , 'agl-audio-plugin', d)} \ - alsa-utils \ - pulseaudio-server \ - pulseaudio-misc \ - ${@bb.utils.contains('DISTRO_FEATURES', 'bluetooth', '\ - pulseaudio-module-bluetooth-discover \ - pulseaudio-module-bluetooth-policy \ - pulseaudio-module-bluez5-discover \ - pulseaudio-module-bluez5-device \ - pulseaudio-module-switch-on-connect \ - pulseaudio-module-loopback \ - ','', d)} \ - gstreamer1.0-meta-base \ - " diff --git a/meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-navi-lbs.bb b/meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-navi-lbs.bb deleted file mode 100644 index 63c27348c..000000000 --- a/meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-navi-lbs.bb +++ /dev/null @@ -1,15 +0,0 @@ -SUMMARY = "The middlewares for AGL IVI profile" -DESCRIPTION = "A set of common packages required by Navigation and Location Based Services Subsystem" - -LICENSE = "MIT" - -inherit packagegroup - -PACKAGES = "\ - packagegroup-ivi-common-core-navi-lbs \ - " - -ALLOW_EMPTY_${PN} = "1" - -RDEPENDS_${PN} += "\ - " diff --git a/meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-os-commonlibs.bb b/meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-os-commonlibs.bb deleted file mode 100644 index 99a3abd31..000000000 --- a/meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-os-commonlibs.bb +++ /dev/null @@ -1,16 +0,0 @@ -SUMMARY = "The middlewares for AGL IVI profile" -DESCRIPTION = "A set of common packages required by Operating System and Common libraries Subsystem" - -LICENSE = "MIT" - -inherit packagegroup - -PACKAGES = "\ - packagegroup-ivi-common-core-os-commonlibs \ - " - -ALLOW_EMPTY_${PN} = "1" - -RDEPENDS_${PN} += "\ - procps \ - " diff --git a/meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-security.bb b/meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-security.bb deleted file mode 100644 index b7c15399b..000000000 --- a/meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-security.bb +++ /dev/null @@ -1,15 +0,0 @@ -SUMMARY = "The middlewares for AGL IVI profile" -DESCRIPTION = "A set of common packages required by Security Subsystem" - -LICENSE = "MIT" - -inherit packagegroup - -PACKAGES = "\ - packagegroup-ivi-common-core-security \ - " - -ALLOW_EMPTY_${PN} = "1" - -RDEPENDS_${PN} += "\ - " diff --git a/meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-speech-services.bb b/meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-speech-services.bb deleted file mode 100644 index 72105ee3a..000000000 --- a/meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core-speech-services.bb +++ /dev/null @@ -1,15 +0,0 @@ -SUMMARY = "The middlewares for AGL IVI profile" -DESCRIPTION = "A set of common packages required by Speech Services Subsystem" - -LICENSE = "MIT" - -inherit packagegroup - -PACKAGES = "\ - packagegroup-ivi-common-core-speech-services \ - " - -ALLOW_EMPTY_${PN} = "1" - -RDEPENDS_${PN} += "\ - " diff --git a/meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core.bb b/meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core.bb deleted file mode 100644 index b3cff10a6..000000000 --- a/meta-ivi-common/recipes-core/packagegroups/packagegroup-ivi-common-core.bb +++ /dev/null @@ -1,23 +0,0 @@ -SUMMARY = "The middlewares for AGL IVI profile" -DESCRIPTION = "A set of packagegroups which contain common packages required by AGL Distribution" -LICENSE = "MIT" - -inherit packagegroup - -PACKAGES = "\ - packagegroup-ivi-common-core \ - " - -ALLOW_EMPTY_${PN} = "1" - -RDEPENDS_${PN} += "\ - packagegroup-ivi-common-core-automotive \ - packagegroup-ivi-common-core-connectivity \ - packagegroup-ivi-common-core-graphics \ - packagegroup-ivi-common-core-multimedia \ - packagegroup-ivi-common-core-navi-lbs \ - packagegroup-ivi-common-core-os-commonlibs \ - packagegroup-ivi-common-core-speech-services \ - packagegroup-ivi-common-core-security \ - packagegroup-ivi-common-core-kernel \ - " diff --git a/meta-ivi-common/recipes-devtools/.gitkeep b/meta-ivi-common/recipes-devtools/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/meta-ivi-common/recipes-extended/.gitkeep b/meta-ivi-common/recipes-extended/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/meta-ivi-common/recipes-extended/dlt-daemon/dlt-daemon/0001-Fix-build-with-systemd-209.patch b/meta-ivi-common/recipes-extended/dlt-daemon/dlt-daemon/0001-Fix-build-with-systemd-209.patch deleted file mode 100644 index 5bf6bf88e..000000000 --- a/meta-ivi-common/recipes-extended/dlt-daemon/dlt-daemon/0001-Fix-build-with-systemd-209.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 8080b7395c1638baee60fb3c46667f21e00b87fb Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Erik=20Bot=C3=B6?= -Date: Fri, 4 Apr 2014 10:59:18 +0200 -Subject: [PATCH 1/4] Fix build with systemd >= 209 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Upstream-Status: Inappropriate [Configuration Specific] -Signed-off-by: Erik Botö ---- - src/system/CMakeLists.txt | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/system/CMakeLists.txt b/src/system/CMakeLists.txt -index ce87914..1d0d224 100644 ---- a/src/system/CMakeLists.txt -+++ b/src/system/CMakeLists.txt -@@ -23,7 +23,7 @@ set(dlt_system_SRCS dlt-system.c dlt-system-options.c dlt-system-process-handlin - dlt-system-syslog.c dlt-system-watchdog.c dlt-system-journal.c) - add_executable(dlt-system ${dlt_system_SRCS} ${systemd_SRCS}) - if(WITH_SYSTEMD_JOURNAL) -- target_link_libraries(dlt-system dlt ${ZLIB_LIBRARIES} systemd-journal systemd-id128) -+ target_link_libraries(dlt-system dlt ${ZLIB_LIBRARIES} systemd) - else(WITH_SYSTEMD_JOURNAL) - target_link_libraries(dlt-system dlt ${ZLIB_LIBRARIES}) - endif(WITH_SYSTEMD_JOURNAL) --- -1.9.3 - diff --git a/meta-ivi-common/recipes-extended/dlt-daemon/dlt-daemon/0002-Don-t-execute-processes-as-a-specific-user.patch b/meta-ivi-common/recipes-extended/dlt-daemon/dlt-daemon/0002-Don-t-execute-processes-as-a-specific-user.patch deleted file mode 100644 index 168847990..000000000 --- a/meta-ivi-common/recipes-extended/dlt-daemon/dlt-daemon/0002-Don-t-execute-processes-as-a-specific-user.patch +++ /dev/null @@ -1,81 +0,0 @@ -From bcca4c99394ba422d03a5e76f2a0023ef248824a Mon Sep 17 00:00:00 2001 -From: Andrei Gherzan -Date: Tue, 18 Nov 2014 15:47:22 +0100 -Subject: [PATCH 2/4] Don't execute processes as a specific user. - -Upstream-Status: Inappropriate [Configuration Specific] -Signed-off-by: Andrei Gherzan ---- - systemd/dlt-adaptor-udp.service.cmake | 1 - - systemd/dlt-example-user.service.cmake | 1 - - systemd/dlt-receive.service.cmake | 1 - - systemd/dlt-system.service.cmake | 1 - - systemd/dlt.service.cmake | 1 - - 5 files changed, 5 deletions(-) - -diff --git a/systemd/dlt-adaptor-udp.service.cmake b/systemd/dlt-adaptor-udp.service.cmake -index 8dac1f2..ecf9f9e 100644 ---- a/systemd/dlt-adaptor-udp.service.cmake -+++ b/systemd/dlt-adaptor-udp.service.cmake -@@ -21,9 +21,8 @@ Wants=dlt.service - - [Service] - Type=simple --User=@DLT_USER@ - ExecStart=@CMAKE_INSTALL_PREFIX@/bin/dlt-adaptor-udp -a @DLT_ADAPTOR_UDP_APPID@ -c @DLT_ADAPTOR_UDP_CTID@ -p @DLT_ADAPTOR_UDP_PORT@ - LimitCORE=infinity - - [Install] --WantedBy=multi-user.target -\ No newline at end of file -+WantedBy=multi-user.target -diff --git a/systemd/dlt-example-user.service.cmake b/systemd/dlt-example-user.service.cmake -index b665742..35009b0 100644 ---- a/systemd/dlt-example-user.service.cmake -+++ b/systemd/dlt-example-user.service.cmake -@@ -21,6 +21,5 @@ Wants=dlt.service - - [Service] - Type=simple --User=@DLT_USER@ - ExecStart=@CMAKE_INSTALL_PREFIX@/bin/dlt-example-user "Hallo from GENIVI DLT example user application" --LimitCORE=infinity -\ No newline at end of file -+LimitCORE=infinity -diff --git a/systemd/dlt-receive.service.cmake b/systemd/dlt-receive.service.cmake -index c07d447..8f88f00 100644 ---- a/systemd/dlt-receive.service.cmake -+++ b/systemd/dlt-receive.service.cmake -@@ -22,6 +22,5 @@ Wants=dlt.service - - [Service] - Type=simple --User=@DLT_USER@ - ExecStart=@CMAKE_INSTALL_PREFIX@/bin/dlt-receive -o /tmp/dlt_receive_log.dlt localhost --LimitCORE=infinity -\ No newline at end of file -+LimitCORE=infinity -diff --git a/systemd/dlt-system.service.cmake b/systemd/dlt-system.service.cmake -index 0e91f42..1a5b913 100755 ---- a/systemd/dlt-system.service.cmake -+++ b/systemd/dlt-system.service.cmake -@@ -22,7 +22,6 @@ Wants=dlt.service - - [Service] - Type=simple --User=@DLT_USER@ - ExecStart=@CMAKE_INSTALL_PREFIX@/bin/dlt-system - WatchdogSec=@DLT_WatchdogSec@ - NotifyAccess=main -diff --git a/systemd/dlt.service.cmake b/systemd/dlt.service.cmake -index 0b3ee2c..e4753a2 100755 ---- a/systemd/dlt.service.cmake -+++ b/systemd/dlt.service.cmake -@@ -21,7 +21,6 @@ Documentation=man:dlt-daemon(1) man:dlt.conf(5) - - [Service] - Type=simple --User=@DLT_USER@ - ExecStart=@CMAKE_INSTALL_PREFIX@/bin/dlt-daemon - WatchdogSec=@DLT_WatchdogSec@ - NotifyAccess=main diff --git a/meta-ivi-common/recipes-extended/dlt-daemon/dlt-daemon/0003-systemd-unit-type-should-be-in-lowercase-so-use-Type.patch b/meta-ivi-common/recipes-extended/dlt-daemon/dlt-daemon/0003-systemd-unit-type-should-be-in-lowercase-so-use-Type.patch deleted file mode 100644 index 691a50027..000000000 --- a/meta-ivi-common/recipes-extended/dlt-daemon/dlt-daemon/0003-systemd-unit-type-should-be-in-lowercase-so-use-Type.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 6804c68ed61f4436818c58cb0abe1c21b4d48aea Mon Sep 17 00:00:00 2001 -From: Andrei Gherzan -Date: Tue, 18 Nov 2014 15:48:50 +0100 -Subject: [PATCH 3/4] systemd/*: unit type should be in lowercase, so use - Type=simple - -Upstream-Status: Submitted [http://lists.genivi.org/pipermail/genivi-diagnostic-log-and-trace/2014-October/000546.html] -Signed-off-by: Andrei Gherzan ---- - systemd/dlt-adaptor-udp.service.cmake | 2 +- - systemd/dlt-dbus.service.cmake | 2 +- - systemd/dlt-example-user.service.cmake | 2 +- - systemd/dlt-receive.service.cmake | 2 +- - systemd/dlt-system.service.cmake | 2 +- - systemd/dlt.service.cmake | 2 +- - 6 files changed, 6 insertions(+), 6 deletions(-) - -diff --git a/systemd/dlt-adaptor-udp.service.cmake b/systemd/dlt-adaptor-udp.service.cmake -index f446757..81a7158 100644 ---- a/systemd/dlt-adaptor-udp.service.cmake -+++ b/systemd/dlt-adaptor-udp.service.cmake -@@ -19,7 +19,7 @@ Description=GENIVI DLT adaptor stdin. Adaptor for forwarding received UDP messag - Wants=dlt.service - - [Service] --Type=Simple -+Type=simple - ExecStart=@CMAKE_INSTALL_PREFIX@/bin/dlt-adaptor-udp -a @DLT_ADAPTOR_UDP_APPID@ -c @DLT_ADAPTOR_UDP_CTID@ -p @DLT_ADAPTOR_UDP_PORT@ - LimitCORE=infinity - -diff --git a/systemd/dlt-dbus.service.cmake b/systemd/dlt-dbus.service.cmake -index d1e3b12..75dcdc3 100755 ---- a/systemd/dlt-dbus.service.cmake -+++ b/systemd/dlt-dbus.service.cmake -@@ -20,7 +20,7 @@ Documentation=man:dlt-dbus(1) man:dlt-dbus.conf(5) - Wants=dlt.service - - [Service] --Type=Simple -+Type=simple - ExecStart=@CMAKE_INSTALL_PREFIX@/bin/dlt-dbus - WatchdogSec=@DLT_WatchdogSec@ - NotifyAccess=main -diff --git a/systemd/dlt-example-user.service.cmake b/systemd/dlt-example-user.service.cmake -index b67a83c..fe9c567 100644 ---- a/systemd/dlt-example-user.service.cmake -+++ b/systemd/dlt-example-user.service.cmake -@@ -19,6 +19,6 @@ Description=GENIVI DLT example user. Generate DLT messages and store them to fil - Wants=dlt.service - - [Service] --Type=Simple -+Type=simple - ExecStart=@CMAKE_INSTALL_PREFIX@/bin/dlt-example-user "Hallo from GENIVI DLT example user application" - LimitCORE=infinity -\ No newline at end of file -diff --git a/systemd/dlt-receive.service.cmake b/systemd/dlt-receive.service.cmake -index 4bbdfc2..3b47dd3 100644 ---- a/systemd/dlt-receive.service.cmake -+++ b/systemd/dlt-receive.service.cmake -@@ -20,6 +20,6 @@ Documentation=man:dlt-receive(1) - Wants=dlt.service - - [Service] --Type=Simple -+Type=simple - ExecStart=@CMAKE_INSTALL_PREFIX@/bin/dlt-receive -o /tmp/dlt_receive_log.dlt localhost - LimitCORE=infinity -\ No newline at end of file -diff --git a/systemd/dlt-system.service.cmake b/systemd/dlt-system.service.cmake -index 7ec995c..d4a4c96 100755 ---- a/systemd/dlt-system.service.cmake -+++ b/systemd/dlt-system.service.cmake -@@ -20,7 +20,7 @@ Documentation=man:dlt-system(1) man:dlt-system.conf(5) - Wants=dlt.service - - [Service] --Type=Simple -+Type=simple - ExecStart=@CMAKE_INSTALL_PREFIX@/bin/dlt-system - WatchdogSec=@DLT_WatchdogSec@ - NotifyAccess=main -diff --git a/systemd/dlt.service.cmake b/systemd/dlt.service.cmake -index 7bb05bc..5386ffd 100755 ---- a/systemd/dlt.service.cmake -+++ b/systemd/dlt.service.cmake -@@ -19,7 +19,7 @@ Description=GENIVI DLT logging daemon - Documentation=man:dlt-daemon(1) man:dlt.conf(5) - - [Service] --Type=Simple -+Type=simple - ExecStart=@CMAKE_INSTALL_PREFIX@/bin/dlt-daemon - WatchdogSec=@DLT_WatchdogSec@ - NotifyAccess=main --- -1.9.3 - diff --git a/meta-ivi-common/recipes-extended/dlt-daemon/dlt-daemon/0004-Modify-systemd-config-directory.patch b/meta-ivi-common/recipes-extended/dlt-daemon/dlt-daemon/0004-Modify-systemd-config-directory.patch deleted file mode 100644 index 685dfcddc..000000000 --- a/meta-ivi-common/recipes-extended/dlt-daemon/dlt-daemon/0004-Modify-systemd-config-directory.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 9a5e655cf57301008cd61d53c8a410a7f397e650 Mon Sep 17 00:00:00 2001 -From: Andrei Gherzan -Date: Tue, 18 Nov 2014 15:51:30 +0100 -Subject: [PATCH 4/4] Modify systemd config directory - -Upstream-Status: Inappropriate [Configuration Specific] -Signed-off-by: Andrei Gherzan ---- - systemd/CMakeLists.txt | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/CMakeLists.txt b/CMakeLists.txt -index e6b44a2..0e885bf 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -175,7 +175,7 @@ if(WITH_SYSTEMD OR WITH_SYSTEMD_WATCHDOG OR WITH_SYSTEMD_JOURNAL) - - set( systemd_SRCS ${CMAKE_SOURCE_DIR}/systemd/3rdparty/sd-daemon.c) - -- set(SYSTEMD_UNITDIR "${CMAKE_INSTALL_PREFIX}/lib/systemd/system" CACHE PATH -+ set(SYSTEMD_UNITDIR "/lib/systemd/system" CACHE PATH - "Set directory to install systemd unit files") - - add_subdirectory( systemd ) diff --git a/meta-ivi-common/recipes-extended/dlt-daemon/dlt-daemon_2.11.1.bb b/meta-ivi-common/recipes-extended/dlt-daemon/dlt-daemon_2.11.1.bb deleted file mode 100644 index b521bca91..000000000 --- a/meta-ivi-common/recipes-extended/dlt-daemon/dlt-daemon_2.11.1.bb +++ /dev/null @@ -1,54 +0,0 @@ -SUMMARY = "Diagnostic Log and Trace" -DESCRIPTION = "This component provides a standardised log and trace interface, \ -based on the standardised protocol specified in the AUTOSAR standard 4.0 DLT. \ -This component can be used by GENIVI components and other applications as \ -logging facility providing: \ -- the DLT shared library \ -- the DLT daemon, including startup scripts \ -- the DLT daemon adaptors- the DLT client console utilities \ -- the DLT test applications" -HOMEPAGE = "https://www.genivi.org/" -SECTION = "console/utils" -LICENSE = "MPLv2" -LIC_FILES_CHKSUM = "file://LICENSE.txt;md5=99ba60c3fad7eaf8c56bca6dd75cba09 \ - file://MPL.txt;md5=ccdb2761cef70c8b2612624c323f89dc" - -DEPENDS = "dbus zlib pigz-native" -do_unpack[depends] += "pigz-native:do_populate_sysroot" - -# FIX ME -# This should be TAG = "v${PV}" but yocto doesn't support lightweight tags for now -# https://bugzilla.yoctoproject.org/show_bug.cgi?id=6881 -TAG = "b8b3ea3a31f7deb681941a19878c82e7b7350ae7" -BRANCH = "v2.11.x" -SRC_URI = "git://git.projects.genivi.org/${PN}.git;branch=${BRANCH};tag=${TAG} \ - file://0001-Fix-build-with-systemd-209.patch \ - file://0002-Don-t-execute-processes-as-a-specific-user.patch \ - file://0003-systemd-unit-type-should-be-in-lowercase-so-use-Type.patch \ - file://0004-Modify-systemd-config-directory.patch" -S = "${WORKDIR}/git" - -inherit autotools gettext cmake systemd - -# -fPIC is needed to prevent relocation errors when we compile gtest with -# Yocto security flags. See this issue for more details: -# -# https://github.com/google/googletest/issues/854 -# -# If that issue is fixed, we can probably remove the manual -fPIC flags here. -OECMAKE_C_FLAGS += "-fPIC" -OECMAKE_CXX_FLAGS += "-fPIC" - -PACKAGES += "${PN}-systemd" -SYSTEMD_PACKAGES = "${PN} ${PN}-systemd" -SYSTEMD_SERVICE_${PN} = "dlt-system.service dlt.service" -SYSTEMD_AUTO_ENABLE_${PN} = "enable" -SYSTEMD_SERVICE_${PN}-systemd = "dlt-example-user.service \ - dlt-dbus.service \ - dlt-adaptor-udp.service \ - dlt-receive.service" -SYSTEMD_AUTO_ENABLE_${PN}-systemd = "disable" - -EXTRA_OECMAKE = "-DWITH_SYSTEMD=ON" - -FILES_${PN}-doc += "/usr/share/dlt-filetransfer" diff --git a/meta-ivi-common/recipes-extended/dlt-daemon/dlt-daemon_2.15.0.bb b/meta-ivi-common/recipes-extended/dlt-daemon/dlt-daemon_2.15.0.bb deleted file mode 100644 index dbc87c9ac..000000000 --- a/meta-ivi-common/recipes-extended/dlt-daemon/dlt-daemon_2.15.0.bb +++ /dev/null @@ -1,52 +0,0 @@ -SUMMARY = "Diagnostic Log and Trace" -DESCRIPTION = "This component provides a standardised log and trace interface, \ -based on the standardised protocol specified in the AUTOSAR standard 4.0 DLT. \ -This component can be used by GENIVI components and other applications as \ -logging facility providing: \ -- the DLT shared library \ -- the DLT daemon, including startup scripts \ -- the DLT daemon adaptors- the DLT client console utilities \ -- the DLT test applications" -HOMEPAGE = "https://www.genivi.org/" -SECTION = "console/utils" -LICENSE = "MPLv2" -LIC_FILES_CHKSUM = "file://LICENSE;md5=8184208060df880fe3137b93eb88aeea" - -DEPENDS = "dbus zlib pigz-native" -do_unpack[depends] += "pigz-native:do_populate_sysroot" - -SRCREV = "e9a486a08fff6d3cc7133a350cec3ee10f463207" -SRC_URI = "git://git.projects.genivi.org/${BPN}.git;protocol=http \ - file://0002-Don-t-execute-processes-as-a-specific-user.patch \ - file://0004-Modify-systemd-config-directory.patch \ - " -S = "${WORKDIR}/git" - -inherit autotools gettext cmake systemd - -# -fPIC is needed to prevent relocation errors when we compile gtest with -# Yocto security flags. See this issue for more details: -# -# https://github.com/google/googletest/issues/854 -# -# If that issue is fixed, we can probably remove the manual -fPIC flags here. -OECMAKE_C_FLAGS += "-fPIC" -OECMAKE_CXX_FLAGS += "-fPIC" - -PACKAGES += "${PN}-systemd" -SYSTEMD_PACKAGES = "${PN} ${PN}-systemd" -SYSTEMD_SERVICE_${PN} = "dlt-system.service dlt.service" -SYSTEMD_AUTO_ENABLE_${PN} = "enable" -SYSTEMD_SERVICE_${PN}-systemd = "dlt-example-user.service \ - dlt-dbus.service \ - dlt-adaptor-udp.service \ - dlt-receive.service" -SYSTEMD_AUTO_ENABLE_${PN}-systemd = "disable" - -EXTRA_OECMAKE = "-DWITH_SYSTEMD=ON" - -FILES_${PN}-doc += "/usr/share/dlt-filetransfer" - -do_install_append() { - rm -f ${D}${bindir}/dlt-test-* -} diff --git a/meta-ivi-common/recipes-graphics/.gitkeep b/meta-ivi-common/recipes-graphics/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/meta-ivi-common/recipes-graphics/wayland/wayland-ivi-extension/0001-Resolve-weston-crush-when-repeat-touching-very-quick.patch b/meta-ivi-common/recipes-graphics/wayland/wayland-ivi-extension/0001-Resolve-weston-crush-when-repeat-touching-very-quick.patch deleted file mode 100644 index 636ecf1b9..000000000 --- a/meta-ivi-common/recipes-graphics/wayland/wayland-ivi-extension/0001-Resolve-weston-crush-when-repeat-touching-very-quick.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 97af4843a4705cd7d5b6b69abb9002fd974a5b94 Mon Sep 17 00:00:00 2001 -From: Tadao Tanikawa -Date: Fri, 12 Jan 2018 01:53:01 +0900 -Subject: [PATCH] Resolve weston cursh when repeat touching very quickly - -Weston sometimes crush while the user repeat touching very -quickly icons/shortcuts on HomeScreen. - -Signed-off-by: Tadao Tanikawa ---- - ivi-input-modules/ivi-input-controller/src/ivi-input-controller.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/ivi-input-modules/ivi-input-controller/src/ivi-input-controller.c b/ivi-input-modules/ivi-input-controller/src/ivi-input-controller.c -index b0fe37d..f1a31d0 100644 ---- a/ivi-input-modules/ivi-input-controller/src/ivi-input-controller.c -+++ b/ivi-input-modules/ivi-input-controller/src/ivi-input-controller.c -@@ -557,6 +557,10 @@ touch_grab_up(struct weston_touch_grab *grab, uint32_t time, int touch_id) - const struct ivi_layout_interface *interface = - seat->input_ctx->ivi_layout_interface; - -+ /* if touch device has no focused view, there is nothing to do*/ -+ if (grab->touch->focus == NULL) -+ return; -+ - /* For each surface_ctx, check for focus and send */ - wl_list_for_each(surf_ctx, &seat->input_ctx->surface_list, link) { - struct weston_surface *surf, *send_surf; --- -2.7.4 - diff --git a/meta-ivi-common/recipes-graphics/wayland/wayland-ivi-extension/0001-simple-id-agent-initial-commit.patch b/meta-ivi-common/recipes-graphics/wayland/wayland-ivi-extension/0001-simple-id-agent-initial-commit.patch deleted file mode 100644 index 9e95167ed..000000000 --- a/meta-ivi-common/recipes-graphics/wayland/wayland-ivi-extension/0001-simple-id-agent-initial-commit.patch +++ /dev/null @@ -1,264 +0,0 @@ -From 8f67f40f7c6b6f62e094f0bdc5044793ae76b1c7 Mon Sep 17 00:00:00 2001 -From: Emre Ucan -Date: Fri, 24 Nov 2017 16:24:51 +0100 -Subject: [PATCH 1/2] simple-id-agent: initial commit - -it is a very simple id-agent plugin. -It is possible to configure default surface id -offset. Assigned ids would start -from the given id offset. - -Please check the example weston.ini for loading -and configuring the simple-id-agent - -Signed-off-by: Emre Ucan ---- - CMakeLists.txt | 1 + - id-agent-modules/simple-id-agent/CMakeLists.txt | 72 ++++++++++++ - .../simple-id-agent/src/simple-id-agent.c | 124 +++++++++++++++++++++ - id-agent-modules/simple-id-agent/weston.ini.in | 11 ++ - 4 files changed, 208 insertions(+) - create mode 100644 id-agent-modules/simple-id-agent/CMakeLists.txt - create mode 100644 id-agent-modules/simple-id-agent/src/simple-id-agent.c - create mode 100644 id-agent-modules/simple-id-agent/weston.ini.in - -diff --git a/CMakeLists.txt b/CMakeLists.txt -index bad85df..d07abf5 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -35,6 +35,7 @@ add_subdirectory(ivi-layermanagement-api/ilmClient) - add_subdirectory(ivi-layermanagement-api/ilmControl) - add_subdirectory(ivi-layermanagement-api/test) - add_subdirectory(ivi-layermanagement-examples) -+add_subdirectory(id-agent-modules/simple-id-agent) - - if(WITH_ILM_INPUT) - add_subdirectory(ivi-input-api/ilmInput) -diff --git a/id-agent-modules/simple-id-agent/CMakeLists.txt b/id-agent-modules/simple-id-agent/CMakeLists.txt -new file mode 100644 -index 0000000..8290722 ---- /dev/null -+++ b/id-agent-modules/simple-id-agent/CMakeLists.txt -@@ -0,0 +1,72 @@ -+############################################################################ -+# -+# Copyright (C) 2013 DENSO CORPORATION -+# Copyright 2014 BMW Car IT GmbH -+# -+# -+# Licensed under the Apache License, Version 2.0 (the "License"); -+# you may not use this file except in compliance with the License. -+# You may obtain a copy of the License at -+# -+# http://www.apache.org/licenses/LICENSE-2.0 -+# -+# Unless required by applicable law or agreed to in writing, software -+# distributed under the License is distributed on an "AS IS" BASIS, -+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+# See the License for the specific language governing permissions and -+# limitations under the License. -+# -+############################################################################ -+ -+cmake_minimum_required (VERSION 2.6) -+ -+project(simple-id-agent) -+ -+find_package(PkgConfig REQUIRED) -+pkg_check_modules(WAYLAND_SERVER wayland-server>=1.13.0 REQUIRED) -+pkg_check_modules(WESTON weston>=2.0.0 REQUIRED) -+pkg_check_modules(PIXMAN pixman-1 REQUIRED) -+ -+find_package(Threads REQUIRED) -+ -+GET_TARGET_PROPERTY(IVI_EXTENSION_INCLUDE_DIRS ivi-extension-protocol INCLUDE_DIRECTORIES) -+ -+include_directories( -+ src -+ ${IVI_EXTENSION_INCLUDE_DIRS} -+ ${WAYLAND_SERVER_INCLUDE_DIRS} -+ ${WESTON_INCLUDE_DIRS} -+ ${PIXMAN_INCLUDE_DIRS} -+) -+ -+link_directories( -+ ${WAYLAND_SERVER_LIBRARY_DIRS} -+ ${PIXMAN_LIBRARY_DIRS} -+) -+ -+add_library(${PROJECT_NAME} MODULE -+ src/simple-id-agent.c -+) -+ -+set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "") -+ -+add_dependencies(${PROJECT_NAME} -+ ivi-extension-protocol -+ ${WAYLAND_SERVER_LIBRARIES} -+ ${PIXMAN_LIBRARIES} -+) -+ -+set(LIBS -+ ${LIBS} -+ ivi-extension-protocol -+ ${WAYLAND_SERVER_LIBRARIES} -+) -+ -+set(CMAKE_C_LDFLAGS "-module -avoid-version") -+ -+target_link_libraries(${PROJECT_NAME} ${LIBS}) -+ -+install ( -+ TARGETS ${PROJECT_NAME} -+ LIBRARY DESTINATION lib${LIB_SUFFIX}/weston -+) -diff --git a/id-agent-modules/simple-id-agent/src/simple-id-agent.c b/id-agent-modules/simple-id-agent/src/simple-id-agent.c -new file mode 100644 -index 0000000..3c9e989 ---- /dev/null -+++ b/id-agent-modules/simple-id-agent/src/simple-id-agent.c -@@ -0,0 +1,124 @@ -+/* -+ * Copyright (C) 2017 Advanced Driver Information Technology Joint Venture GmbH -+ * -+ * Permission to use, copy, modify, distribute, and sell this software and -+ * its documentation for any purpose is hereby granted without fee, provided -+ * that the above copyright notice appear in all copies and that both that -+ * copyright notice and this permission notice appear in supporting -+ * documentation, and that the name of the copyright holders not be used in -+ * advertising or publicity pertaining to distribution of the software -+ * without specific, written prior permission. The copyright holders make -+ * no representations about the suitability of this software for any -+ * purpose. It is provided "as is" without express or implied warranty. -+ * -+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS -+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY -+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER -+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF -+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+struct ivi_id_agent -+{ -+ uint32_t default_id_offset; -+ uint32_t last_assigned_id; -+ struct weston_compositor *compositor; -+ const struct ivi_layout_interface *interface; -+ struct wl_listener desktop_surface_configured; -+}; -+ -+static void -+desktop_surface_event_configure(struct wl_listener *listener, -+ void *data) -+{ -+ struct ivi_id_agent *ida = wl_container_of(listener, ida, -+ desktop_surface_configured); -+ struct ivi_layout_surface *layout_surface = -+ (struct ivi_layout_surface *) data; -+ uint32_t tmp_id; -+ -+ tmp_id = ++ida->last_assigned_id; -+ -+ /* Find an unused id */ -+ while(ida->interface->get_surface_from_id(tmp_id)) { -+ weston_log("simple-id-agent: surface id: %d is already used\n", tmp_id); -+ tmp_id++; -+ } -+ -+ ida->last_assigned_id = tmp_id; -+ -+ if (ida->interface->surface_set_id(layout_surface, ida->last_assigned_id) != 0) -+ weston_log("simple-id-agent: failed to set surface id :%d\n", ida->last_assigned_id); -+} -+ -+static void -+deinit(struct ivi_id_agent *ida) -+{ -+ wl_list_remove(&ida->desktop_surface_configured.link); -+ free(ida); -+} -+ -+static int32_t -+read_config(struct ivi_id_agent *ida) -+{ -+ struct weston_config *config = NULL; -+ struct weston_config_section *section = NULL; -+ const char *name = NULL; -+ -+ config = wet_get_config(ida->compositor); -+ if (!config) -+ return -1; -+ -+ section = weston_config_get_section(config, "id-agent", NULL, NULL); -+ -+ if (section) { -+ -+ weston_config_section_get_uint(section, "default-id-offset", -+ &ida->default_id_offset, 0); -+ -+ } else { -+ ida->default_id_offset = 0; -+ } -+ -+ return 0; -+} -+ -+WL_EXPORT int32_t -+id_agent_module_init(struct weston_compositor *ec, -+ const struct ivi_layout_interface *interface, -+ size_t interface_version) -+{ -+ struct ivi_id_agent *ida; -+ -+ ida = calloc(1, sizeof *ida); -+ if (ida == NULL) { -+ weston_log("failed to allocate ivi_id_agent\n"); -+ return -1; -+ } -+ -+ ida->compositor = ec; -+ ida->interface = interface; -+ ida->desktop_surface_configured.notify = desktop_surface_event_configure; -+ ida->interface->add_listener_configure_desktop_surface(&ida->desktop_surface_configured); -+ -+ if(read_config(ida) != 0) { -+ deinit(ida); -+ return -1; -+ } -+ -+ ida->last_assigned_id = ida->default_id_offset; -+ -+ weston_log("id_agent_module_init: success\n"); -+ -+ return 0; -+} -diff --git a/id-agent-modules/simple-id-agent/weston.ini.in b/id-agent-modules/simple-id-agent/weston.ini.in -new file mode 100644 -index 0000000..b5e5fa1 ---- /dev/null -+++ b/id-agent-modules/simple-id-agent/weston.ini.in -@@ -0,0 +1,11 @@ -+[core] -+shell=ivi-shell.so -+require-input=false -+ -+[ivi-shell] -+ivi-module=ivi-controller.so -+ivi-input-module=ivi-input-controller.so -+id-agent-module=simple-id-agent.so -+ -+[id-agent] -+default-id-offset=10 --- -2.13.6 - diff --git a/meta-ivi-common/recipes-graphics/wayland/wayland-ivi-extension/0002-ivi-controller-load-id-agent-module.patch b/meta-ivi-common/recipes-graphics/wayland/wayland-ivi-extension/0002-ivi-controller-load-id-agent-module.patch deleted file mode 100644 index f44786a36..000000000 --- a/meta-ivi-common/recipes-graphics/wayland/wayland-ivi-extension/0002-ivi-controller-load-id-agent-module.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 26f2f7ce78ba2002809048b227ad9c35921a9cd8 Mon Sep 17 00:00:00 2001 -From: Emre Ucan -Date: Fri, 24 Nov 2017 16:27:01 +0100 -Subject: [PATCH 2/2] ivi-controller: load id-agent module - -Signed-off-by: Emre Ucan ---- - weston-ivi-shell/src/ivi-controller.c | 39 +++++++++++++++++++++++++++++++++++ - 1 file changed, 39 insertions(+) - -diff --git a/weston-ivi-shell/src/ivi-controller.c b/weston-ivi-shell/src/ivi-controller.c -index 312a978..47b6de2 100644 ---- a/weston-ivi-shell/src/ivi-controller.c -+++ b/weston-ivi-shell/src/ivi-controller.c -@@ -1518,6 +1518,40 @@ load_input_module(struct weston_compositor *ec, - return 0; - } - -+static int load_id_agent_module(struct weston_compositor *ec, -+ const struct ivi_layout_interface *interface, -+ size_t interface_version) -+{ -+ struct weston_config *config = wet_get_config(ec); -+ struct weston_config_section *section; -+ char *id_agent_module = NULL; -+ -+ int (*id_agent_module_init)(struct weston_compositor *ec, -+ const struct ivi_layout_interface *interface, -+ size_t interface_version); -+ -+ section = weston_config_get_section(config, "ivi-shell", NULL, NULL); -+ -+ if (weston_config_section_get_string(section, "id-agent-module", -+ &id_agent_module, NULL) < 0) { -+ weston_log("ivi-controller: No id-agent-module set\n"); -+ return 0; -+ } -+ -+ id_agent_module_init = wet_load_module_entrypoint(id_agent_module, "id_agent_module_init"); -+ if (!id_agent_module_init) -+ return -1; -+ -+ if (id_agent_module_init(ec, interface, -+ sizeof(struct ivi_layout_interface)) != 0) { -+ weston_log("ivi-controller: Initialization of id agent module fails\n"); -+ return -1; -+ } -+ -+ free(id_agent_module); -+ return 0; -+} -+ - WL_EXPORT int - controller_module_init(struct weston_compositor *compositor, - int *argc, char *argv[], -@@ -1555,5 +1589,10 @@ controller_module_init(struct weston_compositor *compositor, - return -1; - } - -+ if (load_id_agent_module(compositor, interface, interface_version) < 0) { -+ free(shell); -+ return -1; -+ } -+ - return 0; - } --- -2.13.6 - diff --git a/meta-ivi-common/recipes-graphics/wayland/wayland-ivi-extension/0003-ivi-controller-add-resize-setting-suit-to-surface-si.patch b/meta-ivi-common/recipes-graphics/wayland/wayland-ivi-extension/0003-ivi-controller-add-resize-setting-suit-to-surface-si.patch deleted file mode 100644 index d2d027256..000000000 --- a/meta-ivi-common/recipes-graphics/wayland/wayland-ivi-extension/0003-ivi-controller-add-resize-setting-suit-to-surface-si.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 525b5bf65303d661f44c01b11bafd5ba90976850 Mon Sep 17 00:00:00 2001 -From: Wataru Mizuno -Date: Wed, 6 Dec 2017 19:35:51 +0900 -Subject: [PATCH] ivi-controller: add resize setting suit to surface size - -The ivi-controller resizes surface size like desktop usecase. - -When window manager swicths the half size window to full size, -resize was not working correctly. -This patch fixs this issue by changing surface source region at -the same timing of destination region is changed. - -This patch is not necessary later version of wayland-ivi-extension -2.0 since this resize function has already been implemented by -appropriate manner. - -Signed-off-by: Wataru Mizuno ---- - weston-ivi-shell/src/ivi-controller.c | 17 ++++++++++++++--- - 1 file changed, 14 insertions(+), 3 deletions(-) - -diff --git a/weston-ivi-shell/src/ivi-controller.c b/weston-ivi-shell/src/ivi-controller.c -index 312a978..9450cf2 100644 ---- a/weston-ivi-shell/src/ivi-controller.c -+++ b/weston-ivi-shell/src/ivi-controller.c -@@ -1334,7 +1334,7 @@ surface_event_configure(struct wl_listener *listener, void *data) - struct ivisurface *ivisurf = NULL; - struct ivi_layout_surface *layout_surface = - (struct ivi_layout_surface *) data; -- const struct ivi_layout_surface_properties *prop; -+ struct weston_surface *w_surface; - - ivisurf = get_surface(&shell->list_surface, layout_surface); - if (ivisurf == NULL) { -@@ -1342,11 +1342,22 @@ surface_event_configure(struct wl_listener *listener, void *data) - return; - } - -- prop = lyt->get_properties_of_surface(layout_surface); -+ w_surface = lyt->surface_get_weston_surface(layout_surface); -+ lyt->surface_set_destination_rectangle(layout_surface, -+ ivisurf->prop->dest_x, -+ ivisurf->prop->dest_y, -+ w_surface->width, -+ w_surface->height); -+ lyt->surface_set_source_rectangle(layout_surface, -+ 0, -+ 0, -+ w_surface->width, -+ w_surface->height); -+ lyt->commit_changes(); - - wl_resource_for_each(resource, &ivisurf->resource_list) { - send_surface_event(resource, ivisurf, -- prop, IVI_NOTIFICATION_CONFIGURE); -+ ivisurf->prop, IVI_NOTIFICATION_CONFIGURE); - } - } - --- -2.7.4 - diff --git a/meta-ivi-common/recipes-graphics/wayland/wayland-ivi-extension/disable-sanitizer-tests.patch b/meta-ivi-common/recipes-graphics/wayland/wayland-ivi-extension/disable-sanitizer-tests.patch deleted file mode 100644 index df5d616fd..000000000 --- a/meta-ivi-common/recipes-graphics/wayland/wayland-ivi-extension/disable-sanitizer-tests.patch +++ /dev/null @@ -1,13 +0,0 @@ -Index: git/ivi-layermanagement-api/test/CMakeLists.txt -=================================================================== ---- git.orig/ivi-layermanagement-api/test/CMakeLists.txt -+++ git/ivi-layermanagement-api/test/CMakeLists.txt -@@ -58,7 +58,7 @@ IF(BUILD_ILM_API_TESTS) - ) - - SET(GCC_SANITIZER_COMPILE_FLAGS "-fsanitize=address -fsanitize=undefined -fno-sanitize-recover -fstack-protector-all") -- SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_SANITIZER_COMPILE_FLAGS}" ) -+ SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" ) - SET( CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -static-libasan -static-libubsan" ) - - ADD_EXECUTABLE(${PROJECT_NAME} ${SRC_FILES}) diff --git a/meta-ivi-common/recipes-graphics/wayland/wayland-ivi-extension/wandboard_fix_build.patch b/meta-ivi-common/recipes-graphics/wayland/wayland-ivi-extension/wandboard_fix_build.patch deleted file mode 100644 index 86b448be1..000000000 --- a/meta-ivi-common/recipes-graphics/wayland/wayland-ivi-extension/wandboard_fix_build.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/CMakeLists.txt b/CMakeLists.txt -index 3610fa9..8b4614d 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -34,7 +34,7 @@ add_subdirectory(ivi-layermanagement-api/ilmCommon) - add_subdirectory(ivi-layermanagement-api/ilmClient) - add_subdirectory(ivi-layermanagement-api/ilmControl) - add_subdirectory(ivi-layermanagement-api/test) --add_subdirectory(ivi-layermanagement-examples) -+#add_subdirectory(ivi-layermanagement-examples) - - if(WITH_ILM_INPUT) - add_subdirectory(ivi-input-api/ilmInput) diff --git a/meta-ivi-common/recipes-graphics/wayland/wayland-ivi-extension_1.13.0.bb b/meta-ivi-common/recipes-graphics/wayland/wayland-ivi-extension_1.13.0.bb deleted file mode 100644 index 68e92adb5..000000000 --- a/meta-ivi-common/recipes-graphics/wayland/wayland-ivi-extension_1.13.0.bb +++ /dev/null @@ -1,33 +0,0 @@ -SUMMARY = "Wayland IVI Extension" -DESCRIPTION = "GENIVI Layer Management API based on Wayland IVI Extension" -HOMEPAGE = "http://projects.genivi.org/wayland-ivi-extension" -BUGTRACKER = "http://bugs.genivi.org/enter_bug.cgi?product=Wayland%20IVI%20Extension" -LICENSE = "Apache-2.0" -LIC_FILES_CHKSUM = "file://LICENSE;md5=1f1a56bb2dadf5f2be8eb342acf4ed79" - -SRCREV = "ede33c1c898eeaf673dd2c275e92763a5aabd066" -SRC_URI = "git://github.com/GENIVI/${BPN}.git;protocol=http \ - file://0001-simple-id-agent-initial-commit.patch;patch=1 \ - file://0002-ivi-controller-load-id-agent-module.patch;patch=1 \ - file://0003-ivi-controller-add-resize-setting-suit-to-surface-si.patch \ - file://0001-Resolve-weston-crush-when-repeat-touching-very-quick.patch \ -" -S = "${WORKDIR}/git" - -DEPENDS = "weston virtual/libgles2 pixman wayland-native" - -inherit cmake - -EXTRA_OECMAKE := "-DWITH_ILM_INPUT=1" - -FILES_${PN} += "${libdir}/weston/*" -FILES_${PN}-dbg += "${libdir}/weston/.debug/*" - -EXTRA_OECMAKE += "-DLIB_SUFFIX=${@d.getVar('baselib', True).replace('lib', '')}" - -FILESEXTRAPATHS_prepend := ":${THISDIR}/wayland-ivi-extension:" - -SRC_URI_append_wandboard = " file://wandboard_fix_build.patch" - -# workaround paralellism issue: -PARALLEL_MAKE = "" diff --git a/meta-ivi-common/recipes-graphics/wayland/wayland-ivi-extension_2.0.2.bb b/meta-ivi-common/recipes-graphics/wayland/wayland-ivi-extension_2.0.2.bb deleted file mode 100644 index ea74e384c..000000000 --- a/meta-ivi-common/recipes-graphics/wayland/wayland-ivi-extension_2.0.2.bb +++ /dev/null @@ -1,31 +0,0 @@ -SUMMARY = "Wayland IVI Extension" -DESCRIPTION = "GENIVI Layer Management API based on Wayland IVI Extension" -HOMEPAGE = "http://projects.genivi.org/wayland-ivi-extension" -BUGTRACKER = "http://bugs.genivi.org/enter_bug.cgi?product=Wayland%20IVI%20Extension" -LICENSE = "Apache-2.0" -LIC_FILES_CHKSUM = "file://LICENSE;md5=1f1a56bb2dadf5f2be8eb342acf4ed79" - -SRCREV = "ff067a640451de46836200624ece7ac777977c30" -SRC_URI = "git://github.com/GENIVI/${BPN}.git;branch=2.0;protocol=http \ - " -SRC_URI_append_wandboard = " file://wandboard_fix_build.patch" - -S = "${WORKDIR}/git" - -DEPENDS = "weston virtual/libgles2 pixman wayland-native" - -FILESEXTRAPATHS_prepend := ":${THISDIR}/wayland-ivi-extension:" - -# workaround paralellism issue: -PARALLEL_MAKE = "" - -inherit cmake - -EXTRA_OECMAKE := "-DWITH_ILM_INPUT=1" - -FILES_${PN} += "${libdir}/weston/*" -FILES_${PN} += "${datadir}/wayland-protocols/stable/ivi-application/*" - -FILES_${PN}-dbg += "${libdir}/weston/.debug/*" - -EXTRA_OECMAKE += "-DLIB_SUFFIX=${@d.getVar('baselib', True).replace('lib', '')}" diff --git a/meta-ivi-common/recipes-graphics/wayland/weston_%.bbappend b/meta-ivi-common/recipes-graphics/wayland/weston_%.bbappend deleted file mode 100644 index 226126378..000000000 --- a/meta-ivi-common/recipes-graphics/wayland/weston_%.bbappend +++ /dev/null @@ -1 +0,0 @@ -EXTRA_OECONF_append = " --enable-ivi-shell" diff --git a/meta-ivi-common/recipes-multimedia/audiomanager/audiomanager/0001-Fix-duplicated-command-line-arg-t.patch b/meta-ivi-common/recipes-multimedia/audiomanager/audiomanager/0001-Fix-duplicated-command-line-arg-t.patch deleted file mode 100644 index fcdf9c540..000000000 --- a/meta-ivi-common/recipes-multimedia/audiomanager/audiomanager/0001-Fix-duplicated-command-line-arg-t.patch +++ /dev/null @@ -1,25 +0,0 @@ -From c4b6030f575e38dfc9cca7dfd029d207f3af6a13 Mon Sep 17 00:00:00 2001 -From: "Andre Moreira Magalhaes (andrunko)" -Date: Thu, 5 May 2016 00:01:19 -0300 -Subject: [PATCH] Fix duplicated command line arg -t. - ---- - AudioManagerDaemon/src/main.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/AudioManagerDaemon/src/main.cpp b/AudioManagerDaemon/src/main.cpp -index 795795d..67c0977 100755 ---- a/AudioManagerDaemon/src/main.cpp -+++ b/AudioManagerDaemon/src/main.cpp -@@ -87,7 +87,7 @@ TCLAP::ValueArg commandPluginDir("l","CommandPluginDir","path for l - TCLAP::ValueArg databasePath ("p","databasePath","path for sqlite database (default is in memory)",false,":memory:","string"); - TCLAP::ValueArg telnetPort ("t","telnetport","The port that is used for telnet",false,DEFAULT_TELNETPORT,"int"); - TCLAP::ValueArg maxConnections ("m","maxConnections","Maximal number of connections for telnet",false,MAX_TELNETCONNECTIONS,"int"); --TCLAP::SwitchArg dbusWrapperTypeBool ("t","dbusType","DbusType to be used by CAmDbusWrapper: if option is selected, DBUS_SYSTEM is used otherwise DBUS_SESSION",false); -+TCLAP::SwitchArg dbusWrapperTypeBool ("T","dbusType","DbusType to be used by CAmDbusWrapper: if option is selected, DBUS_SYSTEM is used otherwise DBUS_SESSION",false); - TCLAP::SwitchArg enableNoDLTDebug ("V","logDlt","print DLT logs to stdout",false); - TCLAP::SwitchArg currentSettings("i","currentSettings","print current settings and exit",false); - TCLAP::SwitchArg daemonizeAM("d","daemonize","daemonize Audiomanager. Better use systemd...",false); --- -2.5.0 - diff --git a/meta-ivi-common/recipes-multimedia/audiomanager/audiomanager/audiomanager.service b/meta-ivi-common/recipes-multimedia/audiomanager/audiomanager/audiomanager.service deleted file mode 100644 index 2210a377b..000000000 --- a/meta-ivi-common/recipes-multimedia/audiomanager/audiomanager/audiomanager.service +++ /dev/null @@ -1,17 +0,0 @@ -# AudioManager systemd service file - -[Unit] -Description=GENIVI AudioManager -Requires=dbus.service -After=dbus.service -Before=pulseaudio.service - -[Service] -Type=notify -ExecStart=/usr/bin/AudioManager -T -Restart=always -TimeoutSec=2 -WatchdogSec=2 - -[Install] -WantedBy=multi-user.target diff --git a/meta-ivi-common/recipes-multimedia/audiomanager/audiomanager_7.4.bb b/meta-ivi-common/recipes-multimedia/audiomanager/audiomanager_7.4.bb deleted file mode 100644 index 15eb36252..000000000 --- a/meta-ivi-common/recipes-multimedia/audiomanager/audiomanager_7.4.bb +++ /dev/null @@ -1,56 +0,0 @@ -DESCRIPTION = "GENIVI Audio Manager" -HOMEPAGE = "http://projects.genivi.org/audio-manager/home" -LICENSE = "MPLv2" -SECTION = "multimedia" -DEPENDS = "dbus dlt-daemon systemd" -LIC_FILES_CHKSUM = "file://LICENCE;md5=f164349b56ed530a6642e9b9f244eec5" - -SRC_URI = " \ - git://github.com/GENIVI/AudioManager.git;protocol=https;branch=master \ - file://audiomanager.service \ -" -RDEPENDS_${PN} = "audiomanager-plugins module-router" -SRCREV = "daf851ee7a41d1b0572c0c95e15f61e427ce97f1" - -S = "${WORKDIR}/git" -inherit cmake systemd -SYSTEMD_PACKAGES = "${PN}" -SYSTEMD_SERVICE_${PN} = "audiomanager.service" -SYSTEMD_AUTO_ENABLE = "enable" - -EXTRA_OECMAKE = " \ - -DWITH_TESTS=OFF \ - -DWITH_DOCUMENTATION=OFF \ - -DWITH_DLT=ON \ - -DWITH_TELNET=OFF \ - -DWITH_SYSTEMD_WATCHDOG=ON \ - -DGLIB_DBUS_TYPES_TOLERANT=ON \ - -DWITH_CAPI_WRAPPER=OFF \ - -DWITH_DBUS_WRAPPER=ON \ - -DWITH_SHARED_UTILITIES=ON \ - -DWITH_SHARED_CORE=ON \ -" - -FILES_${PN} = " \ - ${bindir}/AudioManager \ - ${libdir}/libAudioManagerCore.so.7 \ - ${libdir}/libAudioManagerCore.so.7.4 \ - ${libdir}/libAudioManagerCore.so.7.4.12 \ - ${libdir}/libAudioManagerUtilities.so.7 \ - ${libdir}/libAudioManagerUtilities.so.7.4 \ - ${libdir}/libAudioManagerUtilities.so.7.4.12 \ - ${systemd_unitdir}/audiomanager.service \ -" - -FILES_${PN}-dev = " \ - ${includedir}/audiomanager/* \ - ${libdir}/cmake/* \ - ${libdir}/pkgconfig/* \ - ${libdir}/libAudioManagerCore.so \ - ${libdir}/libAudioManagerUtilities.so \ -" - -do_install_append() { - install -d ${D}${systemd_unitdir}/system/ - install -m 0644 ${WORKDIR}/audiomanager.service ${D}${systemd_unitdir}/system/ -} diff --git a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio-10.0/0001-install-files-for-a-module-development.patch b/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio-10.0/0001-install-files-for-a-module-development.patch deleted file mode 100644 index 8c5f9efd4..000000000 --- a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio-10.0/0001-install-files-for-a-module-development.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 53281e2d11f84e2dae0704e0167369710ee2cb30 Mon Sep 17 00:00:00 2001 -From: Yannick Gicquel -Date: Fri, 23 Sep 2016 14:26:03 +0200 -Subject: [PATCH 1/6] install files for a module development - -Signed-off-by: Yannick Gicquel ---- - Makefile.am | 14 +++++++++++++- - configure.ac | 1 + - pulseaudio-module-devel.pc.in | 12 ++++++++++++ - 3 files changed, 26 insertions(+), 1 deletion(-) - create mode 100644 pulseaudio-module-devel.pc.in - -diff --git a/Makefile.am b/Makefile.am -index 13bc469..f0d68a2 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -53,7 +53,16 @@ dist_vapi_DATA = \ - vala/libpulse-simple.deps vala/libpulse-simple.vapi - - pkgconfigdir = $(libdir)/pkgconfig --pkgconfig_DATA = libpulse.pc libpulse-simple.pc -+pkgconfig_DATA = libpulse.pc libpulse-simple.pc pulseaudio-module-devel.pc -+ -+moduledev_DATA = pulsecore-config.h $(top_srcdir)/src/pulsecore/*.h -+moduledevdir = $(includedir)/pulsemodule/pulsecore -+ -+moduledevfilter_DATA = $(top_srcdir)/src/pulsecore/filter/*.h -+moduledevfilterdir = $(includedir)/pulsemodule/pulsecore/filter -+ -+moduledevinternal_DATA = src/pulse/internal.h src/pulse/client-conf.h src/pulse/fork-detect.h -+moduledevinternaldir = $(includedir)/pulsemodule/pulse - - if HAVE_GLIB20 - pkgconfig_DATA += \ -@@ -107,6 +116,9 @@ dist-hook: - check-daemon: - $(MAKE) -C src check-daemon - -+pulsecore-config.h: config.h -+ cp $< $@ -+ - .PHONY: homepage distcleancheck doxygen - - # see git-version-gen -diff --git a/configure.ac b/configure.ac -index 9250c05..f9201ee 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -1502,6 +1502,7 @@ man/pulse-client.conf.5.xml - man/default.pa.5.xml - man/pulse-cli-syntax.5.xml - man/start-pulseaudio-x11.1.xml -+pulseaudio-module-devel.pc - ]) - - AC_CONFIG_FILES([src/esdcompat:src/daemon/esdcompat.in], [chmod +x src/esdcompat]) -diff --git a/pulseaudio-module-devel.pc.in b/pulseaudio-module-devel.pc.in -new file mode 100644 -index 0000000..85aadbc ---- /dev/null -+++ b/pulseaudio-module-devel.pc.in -@@ -0,0 +1,12 @@ -+prefix=@prefix@ -+exec_prefix=@exec_prefix@ -+libdir=@libdir@ -+includedir=@includedir@ -+modlibexecdir=@modlibexecdir@ -+ -+Name: pulseaudio-module-devel -+Description: PulseAudio Module Development Interface -+Version: @PACKAGE_VERSION@ -+Libs: -L${libdir} -L${libdir}/pulseaudio -L${modlibexecdir} -lpulsecommon-@PA_MAJORMINOR@ -lpulsecore-@PA_MAJORMINOR@ -lprotocol-native -+Libs.private: -+Cflags: -I${includedir}/pulsemodule -D_REENTRANT --- -1.9.1 - diff --git a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio-10.0/0002-volume-ramp-additions-to-the-low-level-infra.patch b/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio-10.0/0002-volume-ramp-additions-to-the-low-level-infra.patch deleted file mode 100644 index 9cee6f5de..000000000 --- a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio-10.0/0002-volume-ramp-additions-to-the-low-level-infra.patch +++ /dev/null @@ -1,566 +0,0 @@ -From 7757059ffc6e63ea20ba9013682d72d619e7aefc Mon Sep 17 00:00:00 2001 -From: Sangchul Lee -Date: Sat, 27 Aug 2016 21:33:16 +0900 -Subject: [PATCH 2/6] volume ramp: additions to the low level infra - -The original patch is - - https://review.tizen.org/git/?p=platform/upstream/pulseaudio.git;a=commit;h=df1c4275ed79e0b708c75b92f9d247e0492bc1f0 - - by Jaska Uimonen helsinki.fi> - -Signed-off-by: Sangchul Lee ---- - src/map-file | 4 + - src/pulse/def.h | 13 ++- - src/pulse/volume.c | 74 ++++++++++++- - src/pulse/volume.h | 33 ++++++ - src/pulsecore/mix.c | 310 ++++++++++++++++++++++++++++++++++++++++++++++++++++ - src/pulsecore/mix.h | 27 +++++ - 6 files changed, 459 insertions(+), 2 deletions(-) - -diff --git a/src/map-file b/src/map-file -index 93a62b8..ef9b57d 100644 ---- a/src/map-file -+++ b/src/map-file -@@ -138,6 +138,10 @@ pa_cvolume_max_mask; - pa_cvolume_merge; - pa_cvolume_min; - pa_cvolume_min_mask; -+pa_cvolume_ramp_equal; -+pa_cvolume_ramp_init; -+pa_cvolume_ramp_set; -+pa_cvolume_ramp_channel_ramp_set; - pa_cvolume_remap; - pa_cvolume_scale; - pa_cvolume_scale_mask; -diff --git a/src/pulse/def.h b/src/pulse/def.h -index 680bdc9..bc3cedd 100644 ---- a/src/pulse/def.h -+++ b/src/pulse/def.h -@@ -347,11 +347,15 @@ typedef enum pa_stream_flags { - * consider absolute when the sink is in flat volume mode, - * relative otherwise. \since 0.9.20 */ - -- PA_STREAM_PASSTHROUGH = 0x80000U -+ PA_STREAM_PASSTHROUGH = 0x80000U, - /**< Used to tag content that will be rendered by passthrough sinks. - * The data will be left as is and not reformatted, resampled. - * \since 1.0 */ - -+ PA_STREAM_START_RAMP_MUTED = 0x100000U -+ /**< Used to tag content that the stream will be started ramp volume -+ * muted so that you can nicely fade it in */ -+ - } pa_stream_flags_t; - - /** \cond fulldocs */ -@@ -380,6 +384,7 @@ typedef enum pa_stream_flags { - #define PA_STREAM_FAIL_ON_SUSPEND PA_STREAM_FAIL_ON_SUSPEND - #define PA_STREAM_RELATIVE_VOLUME PA_STREAM_RELATIVE_VOLUME - #define PA_STREAM_PASSTHROUGH PA_STREAM_PASSTHROUGH -+#define PA_STREAM_START_RAMP_MUTED PA_STREAM_START_RAMP_MUTED - - /** \endcond */ - -@@ -1047,6 +1052,12 @@ typedef enum pa_port_available { - /** \endcond */ - #endif - -+/** \cond fulldocs */ -+#define PA_VOLUMER_RAMP_TYPE_LINEAR PA_VOLUMER_RAMP_TYPE_LINEAR -+#define PA_VOLUMER_RAMP_TYPE_LOGARITHMIC PA_VOLUMER_RAMP_TYPE_LOGARITHMIC -+#define PA_VOLUMER_RAMP_TYPE_CUBIC PA_VOLUMER_RAMP_TYPE_CUBIC -+/** \endcond */ -+ - PA_C_DECL_END - - #endif -diff --git a/src/pulse/volume.c b/src/pulse/volume.c -index 1667b94..85072c1 100644 ---- a/src/pulse/volume.c -+++ b/src/pulse/volume.c -@@ -445,7 +445,10 @@ int pa_cvolume_channels_equal_to(const pa_cvolume *a, pa_volume_t v) { - unsigned c; - pa_assert(a); - -- pa_return_val_if_fail(pa_cvolume_valid(a), 0); -+ if (pa_cvolume_valid(a) == 0) -+ abort(); -+ -+ /* pa_return_val_if_fail(pa_cvolume_valid(a), 0); */ - pa_return_val_if_fail(PA_VOLUME_IS_VALID(v), 0); - - for (c = 0; c < a->channels; c++) -@@ -977,3 +980,72 @@ pa_cvolume* pa_cvolume_dec(pa_cvolume *v, pa_volume_t dec) { - - return pa_cvolume_scale(v, m); - } -+ -+int pa_cvolume_ramp_equal(const pa_cvolume_ramp *a, const pa_cvolume_ramp *b) { -+ int i; -+ pa_assert(a); -+ pa_assert(b); -+ -+ if (PA_UNLIKELY(a == b)) -+ return 1; -+ -+ if (a->channels != b->channels) -+ return 0; -+ -+ for (i = 0; i < a->channels; i++) { -+ if (a->ramps[i].type != b->ramps[i].type || -+ a->ramps[i].length != b->ramps[i].length || -+ a->ramps[i].target != b->ramps[i].target) -+ return 0; -+ } -+ -+ return 1; -+} -+ -+pa_cvolume_ramp* pa_cvolume_ramp_init(pa_cvolume_ramp *ramp) { -+ unsigned c; -+ -+ pa_assert(ramp); -+ -+ ramp->channels = 0; -+ -+ for (c = 0; c < PA_CHANNELS_MAX; c++) { -+ ramp->ramps[c].type = PA_VOLUME_RAMP_TYPE_LINEAR; -+ ramp->ramps[c].length = 0; -+ ramp->ramps[c].target = PA_VOLUME_INVALID; -+ } -+ -+ return ramp; -+} -+ -+pa_cvolume_ramp* pa_cvolume_ramp_set(pa_cvolume_ramp *ramp, unsigned channels, pa_volume_ramp_type_t type, long time, pa_volume_t vol) { -+ int i; -+ -+ pa_assert(ramp); -+ pa_assert(channels > 0); -+ pa_assert(time >= 0); -+ pa_assert(channels <= PA_CHANNELS_MAX); -+ -+ ramp->channels = (uint8_t) channels; -+ -+ for (i = 0; i < ramp->channels; i++) { -+ ramp->ramps[i].type = type; -+ ramp->ramps[i].length = time; -+ ramp->ramps[i].target = PA_CLAMP_VOLUME(vol); -+ } -+ -+ return ramp; -+} -+ -+pa_cvolume_ramp* pa_cvolume_ramp_channel_ramp_set(pa_cvolume_ramp *ramp, unsigned channel, pa_volume_ramp_type_t type, long time, pa_volume_t vol) { -+ -+ pa_assert(ramp); -+ pa_assert(channel <= ramp->channels); -+ pa_assert(time >= 0); -+ -+ ramp->ramps[channel].type = type; -+ ramp->ramps[channel].length = time; -+ ramp->ramps[channel].target = PA_CLAMP_VOLUME(vol); -+ -+ return ramp; -+} -diff --git a/src/pulse/volume.h b/src/pulse/volume.h -index 8cf4fa4..2ae3451 100644 ---- a/src/pulse/volume.h -+++ b/src/pulse/volume.h -@@ -431,6 +431,39 @@ pa_cvolume* pa_cvolume_inc(pa_cvolume *v, pa_volume_t inc); - * the channels are kept. \since 0.9.16 */ - pa_cvolume* pa_cvolume_dec(pa_cvolume *v, pa_volume_t dec); - -+/** Volume ramp type -+*/ -+typedef enum pa_volume_ramp_type { -+ PA_VOLUME_RAMP_TYPE_LINEAR = 0, /**< linear */ -+ PA_VOLUME_RAMP_TYPE_LOGARITHMIC = 1, /**< logarithmic */ -+ PA_VOLUME_RAMP_TYPE_CUBIC = 2, -+} pa_volume_ramp_type_t; -+ -+/** A structure encapsulating a volume ramp */ -+typedef struct pa_volume_ramp_t { -+ pa_volume_ramp_type_t type; -+ long length; -+ pa_volume_t target; -+} pa_volume_ramp_t; -+ -+/** A structure encapsulating a multichannel volume ramp */ -+typedef struct pa_cvolume_ramp { -+ uint8_t channels; -+ pa_volume_ramp_t ramps[PA_CHANNELS_MAX]; -+} pa_cvolume_ramp; -+ -+/** Return non-zero when *a == *b */ -+int pa_cvolume_ramp_equal(const pa_cvolume_ramp *a, const pa_cvolume_ramp *b); -+ -+/** Init volume ramp struct */ -+pa_cvolume_ramp* pa_cvolume_ramp_init(pa_cvolume_ramp *ramp); -+ -+/** Set first n channels of ramp struct to certain value */ -+pa_cvolume_ramp* pa_cvolume_ramp_set(pa_cvolume_ramp *ramp, unsigned channel, pa_volume_ramp_type_t type, long time, pa_volume_t vol); -+ -+/** Set individual channel in the channel struct */ -+pa_cvolume_ramp* pa_cvolume_ramp_channel_ramp_set(pa_cvolume_ramp *ramp, unsigned channel, pa_volume_ramp_type_t type, long time, pa_volume_t vol); -+ - PA_C_DECL_END - - #endif -diff --git a/src/pulsecore/mix.c b/src/pulsecore/mix.c -index 59622d7..1e4cc1e 100644 ---- a/src/pulsecore/mix.c -+++ b/src/pulsecore/mix.c -@@ -724,3 +724,313 @@ void pa_volume_memchunk( - - pa_memblock_release(c->memblock); - } -+ -+static void calc_linear_integer_volume_no_mapping(int32_t linear[], float volume[], unsigned nchannels) { -+ unsigned channel, padding; -+ -+ pa_assert(linear); -+ pa_assert(volume); -+ -+ for (channel = 0; channel < nchannels; channel++) -+ linear[channel] = (int32_t) lrint(volume[channel] * 0x10000U); -+ -+ for (padding = 0; padding < VOLUME_PADDING; padding++, channel++) -+ linear[channel] = linear[padding]; -+} -+ -+static void calc_linear_float_volume_no_mapping(float linear[], float volume[], unsigned nchannels) { -+ unsigned channel, padding; -+ -+ pa_assert(linear); -+ pa_assert(volume); -+ -+ for (channel = 0; channel < nchannels; channel++) -+ linear[channel] = volume[channel]; -+ -+ for (padding = 0; padding < VOLUME_PADDING; padding++, channel++) -+ linear[channel] = linear[padding]; -+} -+ -+typedef void (*pa_calc_volume_no_mapping_func_t) (void *volumes, float *volume, int channels); -+ -+static const pa_calc_volume_no_mapping_func_t calc_volume_table_no_mapping[] = { -+ [PA_SAMPLE_U8] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, -+ [PA_SAMPLE_ALAW] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, -+ [PA_SAMPLE_ULAW] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, -+ [PA_SAMPLE_S16LE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, -+ [PA_SAMPLE_S16BE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, -+ [PA_SAMPLE_FLOAT32LE] = (pa_calc_volume_no_mapping_func_t) calc_linear_float_volume_no_mapping, -+ [PA_SAMPLE_FLOAT32BE] = (pa_calc_volume_no_mapping_func_t) calc_linear_float_volume_no_mapping, -+ [PA_SAMPLE_S32LE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, -+ [PA_SAMPLE_S32BE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, -+ [PA_SAMPLE_S24LE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, -+ [PA_SAMPLE_S24BE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, -+ [PA_SAMPLE_S24_32LE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, -+ [PA_SAMPLE_S24_32BE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping -+}; -+ -+static const unsigned format_sample_size_table[] = { -+ [PA_SAMPLE_U8] = 1, -+ [PA_SAMPLE_ALAW] = 1, -+ [PA_SAMPLE_ULAW] = 1, -+ [PA_SAMPLE_S16LE] = 2, -+ [PA_SAMPLE_S16BE] = 2, -+ [PA_SAMPLE_FLOAT32LE] = 4, -+ [PA_SAMPLE_FLOAT32BE] = 4, -+ [PA_SAMPLE_S32LE] = 4, -+ [PA_SAMPLE_S32BE] = 4, -+ [PA_SAMPLE_S24LE] = 3, -+ [PA_SAMPLE_S24BE] = 3, -+ [PA_SAMPLE_S24_32LE] = 4, -+ [PA_SAMPLE_S24_32BE] = 4 -+}; -+ -+static float calc_volume_ramp_linear(pa_volume_ramp_int_t *ramp) { -+ pa_assert(ramp); -+ pa_assert(ramp->length > 0); -+ -+ /* basic linear interpolation */ -+ return ramp->start + (ramp->length - ramp->left) * (ramp->end - ramp->start) / (float) ramp->length; -+} -+ -+static float calc_volume_ramp_logarithmic(pa_volume_ramp_int_t *ramp) { -+ float x_val, s, e; -+ long temp; -+ -+ pa_assert(ramp); -+ pa_assert(ramp->length > 0); -+ -+ if (ramp->end > ramp->start) { -+ temp = ramp->left; -+ s = ramp->end; -+ e = ramp->start; -+ } else { -+ temp = ramp->length - ramp->left; -+ s = ramp->start; -+ e = ramp->end; -+ } -+ -+ x_val = temp == 0 ? 0.0 : powf(temp, 10); -+ -+ /* base 10 logarithmic interpolation */ -+ return s + x_val * (e - s) / powf(ramp->length, 10); -+} -+ -+static float calc_volume_ramp_cubic(pa_volume_ramp_int_t *ramp) { -+ float x_val, s, e; -+ long temp; -+ -+ pa_assert(ramp); -+ pa_assert(ramp->length > 0); -+ -+ if (ramp->end > ramp->start) { -+ temp = ramp->left; -+ s = ramp->end; -+ e = ramp->start; -+ } else { -+ temp = ramp->length - ramp->left; -+ s = ramp->start; -+ e = ramp->end; -+ } -+ -+ x_val = temp == 0 ? 0.0 : cbrtf(temp); -+ -+ /* cubic interpolation */ -+ return s + x_val * (e - s) / cbrtf(ramp->length); -+} -+ -+typedef float (*pa_calc_volume_ramp_func_t) (pa_volume_ramp_int_t *); -+ -+static const pa_calc_volume_ramp_func_t calc_volume_ramp_table[] = { -+ [PA_VOLUME_RAMP_TYPE_LINEAR] = (pa_calc_volume_ramp_func_t) calc_volume_ramp_linear, -+ [PA_VOLUME_RAMP_TYPE_LOGARITHMIC] = (pa_calc_volume_ramp_func_t) calc_volume_ramp_logarithmic, -+ [PA_VOLUME_RAMP_TYPE_CUBIC] = (pa_calc_volume_ramp_func_t) calc_volume_ramp_cubic -+}; -+ -+static void calc_volume_ramps(pa_cvolume_ramp_int *ram, float *vol) -+{ -+ int i; -+ -+ for (i = 0; i < ram->channels; i++) { -+ if (ram->ramps[i].left <= 0) { -+ if (ram->ramps[i].target == PA_VOLUME_NORM) { -+ vol[i] = 1.0; -+ } -+ } else { -+ vol[i] = ram->ramps[i].curr = calc_volume_ramp_table[ram->ramps[i].type] (&ram->ramps[i]); -+ ram->ramps[i].left--; -+ } -+ } -+} -+ -+void pa_volume_ramp_memchunk( -+ pa_memchunk *c, -+ const pa_sample_spec *spec, -+ pa_cvolume_ramp_int *ramp) { -+ -+ void *ptr; -+ volume_val linear[PA_CHANNELS_MAX + VOLUME_PADDING]; -+ float vol[PA_CHANNELS_MAX + VOLUME_PADDING]; -+ pa_do_volume_func_t do_volume; -+ long length_in_frames; -+ int i; -+ -+ pa_assert(c); -+ pa_assert(spec); -+ pa_assert(pa_frame_aligned(c->length, spec)); -+ pa_assert(ramp); -+ -+ length_in_frames = c->length / format_sample_size_table[spec->format] / spec->channels; -+ -+ if (pa_memblock_is_silence(c->memblock)) { -+ for (i = 0; i < ramp->channels; i++) { -+ if (ramp->ramps[i].length > 0) -+ ramp->ramps[i].length -= length_in_frames; -+ } -+ return; -+ } -+ -+ if (spec->format < 0 || spec->format >= PA_SAMPLE_MAX) { -+ pa_log_warn("Unable to change volume of format"); -+ return; -+ } -+ -+ do_volume = pa_get_volume_func(spec->format); -+ pa_assert(do_volume); -+ -+ ptr = (uint8_t*) pa_memblock_acquire(c->memblock) + c->index; -+ -+ for (i = 0; i < length_in_frames; i++) { -+ calc_volume_ramps(ramp, vol); -+ calc_volume_table_no_mapping[spec->format] ((void *)linear, vol, spec->channels); -+ -+ /* we only process one frame per iteration */ -+ do_volume (ptr, (void *)linear, spec->channels, format_sample_size_table[spec->format] * spec->channels); -+ -+ /* pa_log_debug("1: %d 2: %d", linear[0], linear[1]); */ -+ -+ ptr = (uint8_t*)ptr + format_sample_size_table[spec->format] * spec->channels; -+ } -+ -+ pa_memblock_release(c->memblock); -+} -+ -+pa_cvolume_ramp_int* pa_cvolume_ramp_convert(const pa_cvolume_ramp *src, pa_cvolume_ramp_int *dst, int sample_rate) { -+ -+ int i, j, channels, remaining_channels; -+ float temp; -+ -+ if (dst->channels < src->channels) { -+ channels = dst->channels; -+ remaining_channels = 0; -+ } -+ else { -+ channels = src->channels; -+ remaining_channels = dst->channels; -+ } -+ -+ for (i = 0; i < channels; i++) { -+ dst->ramps[i].type = src->ramps[i].type; -+ /* ms to samples */ -+ dst->ramps[i].length = src->ramps[i].length * sample_rate / 1000; -+ dst->ramps[i].left = dst->ramps[i].length; -+ dst->ramps[i].start = dst->ramps[i].end; -+ dst->ramps[i].target = src->ramps[i].target; -+ /* scale to pulse internal mapping so that when ramp is over there's no glitch in volume */ -+ temp = src->ramps[i].target / (float)0x10000U; -+ dst->ramps[i].end = temp * temp * temp; -+ } -+ -+ j = i; -+ -+ for (i--; j < remaining_channels; j++) { -+ dst->ramps[j].type = dst->ramps[i].type; -+ dst->ramps[j].length = dst->ramps[i].length; -+ dst->ramps[j].left = dst->ramps[i].left; -+ dst->ramps[j].start = dst->ramps[i].start; -+ dst->ramps[j].target = dst->ramps[i].target; -+ dst->ramps[j].end = dst->ramps[i].end; -+ } -+ -+ return dst; -+} -+ -+bool pa_cvolume_ramp_active(pa_cvolume_ramp_int *ramp) { -+ int i; -+ -+ for (i = 0; i < ramp->channels; i++) { -+ if (ramp->ramps[i].left > 0) -+ return true; -+ } -+ -+ return false; -+} -+ -+bool pa_cvolume_ramp_target_active(pa_cvolume_ramp_int *ramp) { -+ int i; -+ -+ for (i = 0; i < ramp->channels; i++) { -+ if (ramp->ramps[i].target != PA_VOLUME_NORM) -+ return true; -+ } -+ -+ return false; -+} -+ -+pa_cvolume * pa_cvolume_ramp_get_targets(pa_cvolume_ramp_int *ramp, pa_cvolume *volume) { -+ int i = 0; -+ -+ volume->channels = ramp->channels; -+ -+ for (i = 0; i < ramp->channels; i++) -+ volume->values[i] = ramp->ramps[i].target; -+ -+ return volume; -+} -+ -+pa_cvolume_ramp_int* pa_cvolume_ramp_start_from(pa_cvolume_ramp_int *src, pa_cvolume_ramp_int *dst) { -+ int i; -+ -+ for (i = 0; i < src->channels; i++) { -+ /* if new vols are invalid, copy old ramp i.e. no effect */ -+ if (dst->ramps[i].target == PA_VOLUME_INVALID) -+ dst->ramps[i] = src->ramps[i]; -+ /* if there's some old ramp still left */ -+ else if (src->ramps[i].left > 0) -+ dst->ramps[i].start = src->ramps[i].curr; -+ } -+ -+ return dst; -+} -+ -+pa_cvolume_ramp_int* pa_cvolume_ramp_int_init(pa_cvolume_ramp_int *src, pa_volume_t vol, int channels) { -+ int i; -+ float temp; -+ -+ src->channels = channels; -+ -+ for (i = 0; i < channels; i++) { -+ src->ramps[i].type = PA_VOLUME_RAMP_TYPE_LINEAR; -+ src->ramps[i].length = 0; -+ src->ramps[i].left = 0; -+ if (vol == PA_VOLUME_NORM) { -+ src->ramps[i].start = 1.0; -+ src->ramps[i].end = 1.0; -+ src->ramps[i].curr = 1.0; -+ } -+ else if (vol == PA_VOLUME_MUTED) { -+ src->ramps[i].start = 0.0; -+ src->ramps[i].end = 0.0; -+ src->ramps[i].curr = 0.0; -+ } -+ else { -+ temp = vol / (float)0x10000U; -+ src->ramps[i].start = temp * temp * temp; -+ src->ramps[i].end = src->ramps[i].start; -+ src->ramps[i].curr = src->ramps[i].start; -+ } -+ src->ramps[i].target = vol; -+ } -+ -+ return src; -+} -diff --git a/src/pulsecore/mix.h b/src/pulsecore/mix.h -index 8102bcd..0f86b6f 100644 ---- a/src/pulsecore/mix.h -+++ b/src/pulsecore/mix.h -@@ -59,4 +59,31 @@ void pa_volume_memchunk( - const pa_sample_spec *spec, - const pa_cvolume *volume); - -+typedef struct pa_volume_ramp_int_t { -+ pa_volume_ramp_type_t type; -+ long length; -+ long left; -+ float start; -+ float end; -+ float curr; -+ pa_volume_t target; -+} pa_volume_ramp_int_t; -+ -+typedef struct pa_cvolume_ramp_int { -+ uint8_t channels; -+ pa_volume_ramp_int_t ramps[PA_CHANNELS_MAX]; -+} pa_cvolume_ramp_int; -+ -+pa_cvolume_ramp_int* pa_cvolume_ramp_convert(const pa_cvolume_ramp *src, pa_cvolume_ramp_int *dst, int sample_rate); -+bool pa_cvolume_ramp_active(pa_cvolume_ramp_int *ramp); -+bool pa_cvolume_ramp_target_active(pa_cvolume_ramp_int *ramp); -+pa_cvolume_ramp_int* pa_cvolume_ramp_start_from(pa_cvolume_ramp_int *src, pa_cvolume_ramp_int *dst); -+pa_cvolume_ramp_int* pa_cvolume_ramp_int_init(pa_cvolume_ramp_int *src, pa_volume_t vol, int channels); -+pa_cvolume * pa_cvolume_ramp_get_targets(pa_cvolume_ramp_int *ramp, pa_cvolume *volume); -+ -+void pa_volume_ramp_memchunk( -+ pa_memchunk *c, -+ const pa_sample_spec *spec, -+ pa_cvolume_ramp_int *ramp); -+ - #endif --- -1.9.1 - diff --git a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio-10.0/0003-volume-ramp-adding-volume-ramping-to-sink-input.patch b/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio-10.0/0003-volume-ramp-adding-volume-ramping-to-sink-input.patch deleted file mode 100644 index eb485ca7c..000000000 --- a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio-10.0/0003-volume-ramp-adding-volume-ramping-to-sink-input.patch +++ /dev/null @@ -1,189 +0,0 @@ -From e4469df7c69316b49cad93dd288badc98fa1cad5 Mon Sep 17 00:00:00 2001 -From: Sangchul Lee -Date: Sat, 27 Aug 2016 21:33:17 +0900 -Subject: [PATCH 3/6] volume ramp: adding volume ramping to sink-input - -The original patch is - - https://review.tizen.org/git/?p=platform/upstream/pulseaudio.git;a=commit;h=98042248fd67ce0ab3807c5c472c0d5d8b0f99d3 - - by Jaska Uimonen helsinki.fi> - -Signed-off-by: Sangchul Lee ---- - src/pulsecore/sink-input.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++ - src/pulsecore/sink-input.h | 11 ++++++++- - 2 files changed, 71 insertions(+), 1 deletion(-) - -diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c -index 8ec63b5..cc8953f 100644 ---- a/src/pulsecore/sink-input.c -+++ b/src/pulsecore/sink-input.c -@@ -526,6 +526,11 @@ int pa_sink_input_new( - reset_callbacks(i); - i->userdata = NULL; - -+ if (data->flags & PA_SINK_INPUT_START_RAMP_MUTED) -+ pa_cvolume_ramp_int_init(&i->ramp, PA_VOLUME_MUTED, data->sample_spec.channels); -+ else -+ pa_cvolume_ramp_int_init(&i->ramp, PA_VOLUME_NORM, data->sample_spec.channels); -+ - i->thread_info.state = i->state; - i->thread_info.attached = false; - pa_atomic_store(&i->thread_info.drained, 1); -@@ -542,6 +547,8 @@ int pa_sink_input_new( - i->thread_info.playing_for = 0; - i->thread_info.direct_outputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); - -+ i->thread_info.ramp = i->ramp; -+ - pa_assert_se(pa_idxset_put(core->sink_inputs, i, &i->index) == 0); - pa_assert_se(pa_idxset_put(i->sink->inputs, pa_sink_input_ref(i), NULL) == 0); - -@@ -923,6 +930,8 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink bytes */, pa - while (tchunk.length > 0) { - pa_memchunk wchunk; - bool nvfs = need_volume_factor_sink; -+ pa_cvolume target; -+ pa_bool_t tmp; - - wchunk = tchunk; - pa_memblock_ref(wchunk.memblock); -@@ -959,6 +968,16 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink bytes */, pa - pa_volume_memchunk(&wchunk, &i->sink->sample_spec, &i->volume_factor_sink); - } - -+ /* check for possible volume ramp */ -+ if (pa_cvolume_ramp_active(&i->thread_info.ramp)) { -+ pa_memchunk_make_writable(&wchunk, 0); -+ pa_volume_ramp_memchunk(&wchunk, &i->sink->sample_spec, &(i->thread_info.ramp)); -+ } else if ((tmp = pa_cvolume_ramp_target_active(&(i->thread_info.ramp)))) { -+ pa_memchunk_make_writable(&wchunk, 0); -+ pa_cvolume_ramp_get_targets(&i->thread_info.ramp, &target); -+ pa_volume_memchunk(&wchunk, &i->sink->sample_spec, &target); -+ } -+ - pa_memblockq_push_align(i->thread_info.render_memblockq, &wchunk); - } else { - pa_memchunk rchunk; -@@ -975,6 +994,16 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink bytes */, pa - pa_volume_memchunk(&rchunk, &i->sink->sample_spec, &i->volume_factor_sink); - } - -+ /* check for possible volume ramp */ -+ if (pa_cvolume_ramp_active(&(i->thread_info.ramp))) { -+ pa_memchunk_make_writable(&rchunk, 0); -+ pa_volume_ramp_memchunk(&rchunk, &i->sink->sample_spec, &(i->thread_info.ramp)); -+ } else if (pa_cvolume_ramp_target_active(&(i->thread_info.ramp))) { -+ pa_memchunk_make_writable(&rchunk, 0); -+ pa_cvolume_ramp_get_targets(&i->thread_info.ramp, &target); -+ pa_volume_memchunk(&rchunk, &i->sink->sample_spec, &target); -+ } -+ - pa_memblockq_push_align(i->thread_info.render_memblockq, &rchunk); - pa_memblock_unref(rchunk.memblock); - } -@@ -1339,6 +1368,31 @@ int pa_sink_input_remove_volume_factor(pa_sink_input *i, const char *key) { - return 0; - } - -+/* Called from main thread */ -+void pa_sink_input_set_volume_ramp( -+ pa_sink_input *i, -+ const pa_cvolume_ramp *ramp, -+ pa_bool_t send_msg, -+ pa_bool_t save) { -+ -+ pa_sink_input_assert_ref(i); -+ pa_assert_ctl_context(); -+ pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); -+ pa_assert(ramp); -+ -+ pa_cvolume_ramp_convert(ramp, &i->ramp, i->sample_spec.rate); -+ -+ pa_log_debug("setting volume ramp with target vol:%d and length:%ld", -+ i->ramp.ramps[0].target, -+ i->ramp.ramps[0].length); -+ -+ -+ /* This tells the sink that volume ramp changed */ -+ if (send_msg) -+ pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP, -+ NULL, 0, NULL) == 0); -+} -+ - /* Called from main context */ - static void set_real_ratio(pa_sink_input *i, const pa_cvolume *v) { - pa_sink_input_assert_ref(i); -@@ -1932,6 +1986,13 @@ int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t - } - return 0; - -+ case PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP: -+ /* we have ongoing ramp where we take current start values */ -+ pa_cvolume_ramp_start_from(&i->thread_info.ramp, &i->ramp); -+ i->thread_info.ramp = i->ramp; -+ pa_sink_input_request_rewind(i, 0, true, false, false); -+ return 0; -+ - case PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE: - if (i->thread_info.muted != i->muted) { - i->thread_info.muted = i->muted; -diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h -index 86deab2..6e1b211 100644 ---- a/src/pulsecore/sink-input.h -+++ b/src/pulsecore/sink-input.h -@@ -32,6 +32,7 @@ - #include - #include - #include -+#include - - typedef enum pa_sink_input_state { - PA_SINK_INPUT_INIT, /*< The stream is not active yet, because pa_sink_input_put() has not been called yet */ -@@ -58,7 +59,8 @@ typedef enum pa_sink_input_flags { - PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND = 256, - PA_SINK_INPUT_NO_CREATE_ON_SUSPEND = 512, - PA_SINK_INPUT_KILL_ON_SUSPEND = 1024, -- PA_SINK_INPUT_PASSTHROUGH = 2048 -+ PA_SINK_INPUT_PASSTHROUGH = 2048, -+ PA_SINK_INPUT_START_RAMP_MUTED = 4096, - } pa_sink_input_flags_t; - - struct pa_sink_input { -@@ -121,6 +123,9 @@ struct pa_sink_input { - * this.*/ - bool save_sink:1, save_volume:1, save_muted:1; - -+ /* for volume ramps */ -+ pa_cvolume_ramp_int ramp; -+ - pa_resample_method_t requested_resample_method, actual_resample_method; - - /* Returns the chunk of audio data and drops it from the -@@ -249,6 +254,8 @@ struct pa_sink_input { - pa_usec_t requested_sink_latency; - - pa_hashmap *direct_outputs; -+ -+ pa_cvolume_ramp_int ramp; - } thread_info; - - void *userdata; -@@ -265,6 +272,7 @@ enum { - PA_SINK_INPUT_MESSAGE_SET_STATE, - PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY, - PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY, -+ PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP, - PA_SINK_INPUT_MESSAGE_MAX - }; - -@@ -370,6 +378,7 @@ void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, bool s - void pa_sink_input_add_volume_factor(pa_sink_input *i, const char *key, const pa_cvolume *volume_factor); - int pa_sink_input_remove_volume_factor(pa_sink_input *i, const char *key); - pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i, pa_cvolume *volume, bool absolute); -+void pa_sink_input_set_volume_ramp(pa_sink_input *i, const pa_cvolume_ramp *ramp, pa_bool_t send_msg, pa_bool_t save); - - void pa_sink_input_set_mute(pa_sink_input *i, bool mute, bool save); - --- -1.9.1 - diff --git a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio-10.0/0004-sink-input-Code-cleanup-regarding-volume-ramping.patch b/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio-10.0/0004-sink-input-Code-cleanup-regarding-volume-ramping.patch deleted file mode 100644 index 64d7b141d..000000000 --- a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio-10.0/0004-sink-input-Code-cleanup-regarding-volume-ramping.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 49d8943b151a73be3dd726561a720c0f4bfdccac Mon Sep 17 00:00:00 2001 -From: Sangchul Lee -Date: Sat, 27 Aug 2016 21:33:18 +0900 -Subject: [PATCH 4/6] sink-input: Code cleanup regarding volume ramping - -Remove unused parameter of pa_sink_input_set_volume_ramp(). -Use bool instead of pa_bool_t. - -Signed-off-by: Sangchul Lee ---- - src/pulsecore/sink-input.c | 7 ++----- - src/pulsecore/sink-input.h | 2 +- - 2 files changed, 3 insertions(+), 6 deletions(-) - -diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c -index cc8953f..e1968e0 100644 ---- a/src/pulsecore/sink-input.c -+++ b/src/pulsecore/sink-input.c -@@ -931,7 +931,6 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink bytes */, pa - pa_memchunk wchunk; - bool nvfs = need_volume_factor_sink; - pa_cvolume target; -- pa_bool_t tmp; - - wchunk = tchunk; - pa_memblock_ref(wchunk.memblock); -@@ -972,7 +971,7 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink bytes */, pa - if (pa_cvolume_ramp_active(&i->thread_info.ramp)) { - pa_memchunk_make_writable(&wchunk, 0); - pa_volume_ramp_memchunk(&wchunk, &i->sink->sample_spec, &(i->thread_info.ramp)); -- } else if ((tmp = pa_cvolume_ramp_target_active(&(i->thread_info.ramp)))) { -+ } else if ((pa_cvolume_ramp_target_active(&(i->thread_info.ramp)))) { - pa_memchunk_make_writable(&wchunk, 0); - pa_cvolume_ramp_get_targets(&i->thread_info.ramp, &target); - pa_volume_memchunk(&wchunk, &i->sink->sample_spec, &target); -@@ -1372,9 +1371,7 @@ int pa_sink_input_remove_volume_factor(pa_sink_input *i, const char *key) { - void pa_sink_input_set_volume_ramp( - pa_sink_input *i, - const pa_cvolume_ramp *ramp, -- pa_bool_t send_msg, -- pa_bool_t save) { -- -+ bool send_msg) { - pa_sink_input_assert_ref(i); - pa_assert_ctl_context(); - pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); -diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h -index 6e1b211..92f61c3 100644 ---- a/src/pulsecore/sink-input.h -+++ b/src/pulsecore/sink-input.h -@@ -378,7 +378,7 @@ void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, bool s - void pa_sink_input_add_volume_factor(pa_sink_input *i, const char *key, const pa_cvolume *volume_factor); - int pa_sink_input_remove_volume_factor(pa_sink_input *i, const char *key); - pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i, pa_cvolume *volume, bool absolute); --void pa_sink_input_set_volume_ramp(pa_sink_input *i, const pa_cvolume_ramp *ramp, pa_bool_t send_msg, pa_bool_t save); -+void pa_sink_input_set_volume_ramp(pa_sink_input *i, const pa_cvolume_ramp *ramp, bool send_msg); - - void pa_sink_input_set_mute(pa_sink_input *i, bool mute, bool save); - --- -1.9.1 - diff --git a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio-10.0/0005-sink-input-volume-Add-support-for-volume-ramp-factor.patch b/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio-10.0/0005-sink-input-volume-Add-support-for-volume-ramp-factor.patch deleted file mode 100644 index e371b7ec5..000000000 --- a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio-10.0/0005-sink-input-volume-Add-support-for-volume-ramp-factor.patch +++ /dev/null @@ -1,299 +0,0 @@ -From a98e78ccc4f12d6efad2832a09202651e2a8b6cd Mon Sep 17 00:00:00 2001 -From: Sangchul Lee -Date: Sat, 27 Aug 2016 21:33:19 +0900 -Subject: [PATCH 5/6] sink-input, volume: Add support for volume ramp factor - -Previously, using pa_sink_input_set_volume_ramp() is hard to manage -if there are several callers. These new volume ramp factor APIs make it -easy for caller to use and to set more than one volume ramp factor. -New volume ramp factor will be applied by the multiplication of the other -ramp factors that have been already set. - -APIs are added as below. - - pa_sink_input_add_volume_ramp_factor() - - pa_sink_input_remove_volume_ramp_factor() - - pa_cvolume_ramp_compatible() - - pa_sw_cvolume_ramp_multiply() - - pa_cvolume_ramp_valid() - -Signed-off-by: Sangchul Lee ---- - src/map-file | 3 ++ - src/pulse/volume.c | 44 ++++++++++++++++++ - src/pulse/volume.h | 9 ++++ - src/pulsecore/sink-input.c | 108 +++++++++++++++++++++++++++++++++++++++++++++ - src/pulsecore/sink-input.h | 5 +++ - 5 files changed, 169 insertions(+) - -diff --git a/src/map-file b/src/map-file -index ef9b57d..7577c14 100644 ---- a/src/map-file -+++ b/src/map-file -@@ -142,6 +142,8 @@ pa_cvolume_ramp_equal; - pa_cvolume_ramp_init; - pa_cvolume_ramp_set; - pa_cvolume_ramp_channel_ramp_set; -+pa_cvolume_ramp_compatible; -+pa_cvolume_ramp_valid; - pa_cvolume_remap; - pa_cvolume_scale; - pa_cvolume_scale_mask; -@@ -344,6 +346,7 @@ pa_sw_cvolume_divide_scalar; - pa_sw_cvolume_multiply; - pa_sw_cvolume_multiply_scalar; - pa_sw_cvolume_snprint_dB; -+pa_sw_cvolume_ramp_multiply; - pa_sw_volume_divide; - pa_sw_volume_from_dB; - pa_sw_volume_from_linear; -diff --git a/src/pulse/volume.c b/src/pulse/volume.c -index 85072c1..8d99150 100644 ---- a/src/pulse/volume.c -+++ b/src/pulse/volume.c -@@ -1049,3 +1049,47 @@ pa_cvolume_ramp* pa_cvolume_ramp_channel_ramp_set(pa_cvolume_ramp *ramp, unsigne - - return ramp; - } -+ -+int pa_cvolume_ramp_compatible(const pa_cvolume_ramp *ramp, const pa_sample_spec *ss) { -+ -+ pa_assert(ramp); -+ pa_assert(ss); -+ -+ pa_return_val_if_fail(pa_cvolume_ramp_valid(ramp), 0); -+ pa_return_val_if_fail(pa_sample_spec_valid(ss), 0); -+ -+ return ramp->channels == ss->channels; -+} -+ -+pa_cvolume_ramp *pa_sw_cvolume_ramp_multiply(pa_cvolume_ramp *dest, const pa_cvolume_ramp *a, const pa_cvolume_ramp *b) { -+ unsigned i; -+ -+ pa_assert(dest); -+ pa_assert(a); -+ pa_assert(b); -+ -+ pa_return_val_if_fail(pa_cvolume_ramp_valid(a), NULL); -+ pa_return_val_if_fail(pa_cvolume_ramp_valid(b), NULL); -+ -+ for (i = 0; i < a->channels && i < b->channels; i++) -+ dest->ramps[i].target = pa_sw_volume_multiply(a->ramps[i].target, b->ramps[i].target); -+ -+ dest->channels = (uint8_t) i; -+ -+ return dest; -+} -+ -+int pa_cvolume_ramp_valid(const pa_cvolume_ramp *ramp) { -+ unsigned c; -+ -+ pa_assert(ramp); -+ -+ if (!pa_channels_valid(ramp->channels)) -+ return 0; -+ -+ for (c = 0; c < ramp->channels; c++) -+ if (!PA_VOLUME_IS_VALID(ramp->ramps[c].target)) -+ return 0; -+ -+ return 1; -+} -diff --git a/src/pulse/volume.h b/src/pulse/volume.h -index 2ae3451..65fcb08 100644 ---- a/src/pulse/volume.h -+++ b/src/pulse/volume.h -@@ -458,12 +458,21 @@ int pa_cvolume_ramp_equal(const pa_cvolume_ramp *a, const pa_cvolume_ramp *b); - /** Init volume ramp struct */ - pa_cvolume_ramp* pa_cvolume_ramp_init(pa_cvolume_ramp *ramp); - -+/** Set the volume ramp of the first n channels to PA_VOLUME_NORM */ -+#define pa_cvolume_ramp_reset(a, n, t, l) pa_cvolume_ramp_set((a), (n), (t), (l), PA_VOLUME_NORM) -+ - /** Set first n channels of ramp struct to certain value */ - pa_cvolume_ramp* pa_cvolume_ramp_set(pa_cvolume_ramp *ramp, unsigned channel, pa_volume_ramp_type_t type, long time, pa_volume_t vol); - - /** Set individual channel in the channel struct */ - pa_cvolume_ramp* pa_cvolume_ramp_channel_ramp_set(pa_cvolume_ramp *ramp, unsigned channel, pa_volume_ramp_type_t type, long time, pa_volume_t vol); - -+int pa_cvolume_ramp_compatible(const pa_cvolume_ramp *ramp, const pa_sample_spec *ss); -+ -+int pa_cvolume_ramp_valid(const pa_cvolume_ramp *ramp); -+ -+pa_cvolume_ramp *pa_sw_cvolume_ramp_multiply(pa_cvolume_ramp *dest, const pa_cvolume_ramp *a, const pa_cvolume_ramp *b); -+ - PA_C_DECL_END - - #endif -diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c -index e1968e0..6f89aa1 100644 ---- a/src/pulsecore/sink-input.c -+++ b/src/pulsecore/sink-input.c -@@ -53,6 +53,11 @@ struct volume_factor_entry { - pa_cvolume volume; - }; - -+struct volume_ramp_factor_entry { -+ char *key; -+ pa_cvolume_ramp ramp; -+}; -+ - static struct volume_factor_entry *volume_factor_entry_new(const char *key, const pa_cvolume *volume) { - struct volume_factor_entry *entry; - -@@ -83,6 +88,37 @@ static void volume_factor_from_hashmap(pa_cvolume *v, pa_hashmap *items, uint8_t - pa_sw_cvolume_multiply(v, v, &entry->volume); - } - -+static struct volume_ramp_factor_entry *volume_ramp_factor_entry_new(const char *key, const pa_cvolume_ramp *ramp) { -+ struct volume_ramp_factor_entry *entry; -+ -+ pa_assert(key); -+ pa_assert(ramp); -+ -+ entry = pa_xnew(struct volume_ramp_factor_entry, 1); -+ entry->key = pa_xstrdup(key); -+ -+ entry->ramp = *ramp; -+ -+ return entry; -+} -+ -+static void volume_ramp_factor_entry_free(struct volume_ramp_factor_entry *ramp_entry) { -+ pa_assert(ramp_entry); -+ -+ pa_xfree(ramp_entry->key); -+ pa_xfree(ramp_entry); -+} -+ -+static void volume_ramp_factor_from_hashmap(pa_cvolume_ramp *r, pa_hashmap *items, uint8_t channels, pa_volume_ramp_type_t type, long length) { -+ struct volume_ramp_factor_entry *entry; -+ void *state = NULL; -+ -+ pa_cvolume_ramp_reset(r, channels, type, length); -+ PA_HASHMAP_FOREACH(entry, items, state) -+ pa_sw_cvolume_ramp_multiply(r, r, &entry->ramp); -+ -+} -+ - static void sink_input_free(pa_object *o); - static void set_real_ratio(pa_sink_input *i, const pa_cvolume *v); - -@@ -500,6 +536,8 @@ int pa_sink_input_new( - i->volume_factor_sink_items = data->volume_factor_sink_items; - data->volume_factor_sink_items = NULL; - volume_factor_from_hashmap(&i->volume_factor_sink, i->volume_factor_sink_items, i->sink->sample_spec.channels); -+ i->ramp_factor_items = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, -+ (pa_free_cb_t) volume_ramp_factor_entry_free); - - i->real_ratio = i->reference_ratio = data->volume; - pa_cvolume_reset(&i->soft_volume, i->sample_spec.channels); -@@ -764,6 +802,9 @@ static void sink_input_free(pa_object *o) { - if (i->volume_factor_sink_items) - pa_hashmap_free(i->volume_factor_sink_items); - -+ if (i->ramp_factor_items) -+ pa_hashmap_free(i->ramp_factor_items); -+ - pa_xfree(i->driver); - pa_xfree(i); - } -@@ -1367,6 +1408,73 @@ int pa_sink_input_remove_volume_factor(pa_sink_input *i, const char *key) { - return 0; - } - -+void pa_sink_input_add_volume_ramp_factor(pa_sink_input *i, const char *key, const pa_cvolume_ramp *ramp_factor, bool send_msg) { -+ struct volume_ramp_factor_entry *r; -+ -+ pa_sink_input_assert_ref(i); -+ pa_assert_ctl_context(); -+ pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); -+ pa_assert(ramp_factor); -+ pa_assert(key); -+ pa_assert(pa_cvolume_ramp_valid(ramp_factor)); -+ pa_assert(ramp_factor->channels == 1 || pa_cvolume_ramp_compatible(ramp_factor, &i->sample_spec)); -+ -+ r = volume_ramp_factor_entry_new(key, ramp_factor); -+ if (!pa_cvolume_ramp_compatible(ramp_factor, &i->sample_spec)) -+ pa_cvolume_ramp_set(&r->ramp, i->sample_spec.channels, ramp_factor->ramps[0].type, ramp_factor->ramps[0].length, ramp_factor->ramps[0].target); -+ -+ pa_assert_se(pa_hashmap_put(i->ramp_factor_items, r->key, r) >= 0); -+ if (pa_hashmap_size(i->ramp_factor_items) == 1) -+ pa_cvolume_ramp_set(&i->ramp_factor, i->sample_spec.channels, r->ramp.ramps[0].type, r->ramp.ramps[0].length, r->ramp.ramps[0].target); -+ else -+ pa_sw_cvolume_ramp_multiply(&i->ramp_factor, &i->ramp_factor, &r->ramp); -+ -+ pa_cvolume_ramp_convert(&i->ramp_factor, &i->ramp, i->sample_spec.rate); -+ -+ if (send_msg) -+ pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP, NULL, 0, NULL) == 0); -+ -+ return 0; -+} -+ -+/* Returns 0 if an entry was removed and -1 if no entry for the given key was -+ * found. */ -+int pa_sink_input_remove_volume_ramp_factor(pa_sink_input *i, const char *key, bool send_msg) { -+ struct volume_ramp_factor_entry *r; -+ -+ pa_sink_input_assert_ref(i); -+ pa_assert(key); -+ pa_assert_ctl_context(); -+ pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); -+ -+ r = pa_hashmap_remove(i->ramp_factor_items, key); -+ if (!r) -+ return -1; -+ -+ switch (pa_hashmap_size(i->ramp_factor_items)) { -+ case 0: -+ pa_cvolume_ramp_reset(&i->ramp_factor, i->sample_spec.channels, r->ramp.ramps[0].type, r->ramp.ramps[0].length); -+ break; -+ case 1: { -+ struct volume_ramp_factor_entry *rf; -+ rf = pa_hashmap_first(i->ramp_factor_items); -+ pa_cvolume_ramp_set(&i->ramp_factor, i->sample_spec.channels, r->ramp.ramps[0].type, r->ramp.ramps[0].length, rf->ramp.ramps[0].target); -+ break; -+ } -+ default: -+ volume_ramp_factor_from_hashmap(&i->ramp_factor, i->ramp_factor_items, i->ramp_factor.channels, i->ramp_factor.ramps[0].type, i->ramp_factor.ramps[0].length); -+ } -+ -+ volume_ramp_factor_entry_free(r); -+ -+ pa_cvolume_ramp_convert(&i->ramp_factor, &i->ramp, i->sample_spec.rate); -+ -+ if (send_msg) -+ pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP, NULL, 0, NULL) == 0); -+ -+ return 0; -+} -+ - /* Called from main thread */ - void pa_sink_input_set_volume_ramp( - pa_sink_input *i, -diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h -index 92f61c3..5430d53 100644 ---- a/src/pulsecore/sink-input.h -+++ b/src/pulsecore/sink-input.h -@@ -113,6 +113,9 @@ struct pa_sink_input { - pa_cvolume volume_factor_sink; /* A second volume factor in format of the sink this stream is connected to. */ - pa_hashmap *volume_factor_sink_items; - -+ pa_cvolume_ramp ramp_factor; -+ pa_hashmap *ramp_factor_items; -+ - bool volume_writable:1; - - bool muted:1; -@@ -379,6 +382,8 @@ void pa_sink_input_add_volume_factor(pa_sink_input *i, const char *key, const pa - int pa_sink_input_remove_volume_factor(pa_sink_input *i, const char *key); - pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i, pa_cvolume *volume, bool absolute); - void pa_sink_input_set_volume_ramp(pa_sink_input *i, const pa_cvolume_ramp *ramp, bool send_msg); -+void pa_sink_input_add_volume_ramp_factor(pa_sink_input *i, const char *key, const pa_cvolume_ramp *ramp_factor, bool send_msg); -+int pa_sink_input_remove_volume_ramp_factor(pa_sink_input *i, const char *key, bool send_msg); - - void pa_sink_input_set_mute(pa_sink_input *i, bool mute, bool save); - --- -1.9.1 - diff --git a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio-10.0/0006-sink-input-Remove-pa_sink_input_set_volume_ramp.patch b/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio-10.0/0006-sink-input-Remove-pa_sink_input_set_volume_ramp.patch deleted file mode 100644 index 50110bd14..000000000 --- a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio-10.0/0006-sink-input-Remove-pa_sink_input_set_volume_ramp.patch +++ /dev/null @@ -1,63 +0,0 @@ -From ac9a99505fd768b66dd92e9091e80b576cabc00d Mon Sep 17 00:00:00 2001 -From: Sangchul Lee -Date: Sat, 27 Aug 2016 21:33:20 +0900 -Subject: [PATCH 6/6] sink-input: Remove pa_sink_input_set_volume_ramp() - -Please use pa_sink_input_add_volume_ramp_factor() or -pa_sink_input_remove_volume_ramp_factor() instead of it. - -Signed-off-by: Sangchul Lee ---- - src/pulsecore/sink-input.c | 23 ----------------------- - src/pulsecore/sink-input.h | 1 - - 2 files changed, 24 deletions(-) - -diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c -index 6f89aa1..4c7c568 100644 ---- a/src/pulsecore/sink-input.c -+++ b/src/pulsecore/sink-input.c -@@ -1475,29 +1475,6 @@ int pa_sink_input_remove_volume_ramp_factor(pa_sink_input *i, const char *key, b - return 0; - } - --/* Called from main thread */ --void pa_sink_input_set_volume_ramp( -- pa_sink_input *i, -- const pa_cvolume_ramp *ramp, -- bool send_msg) { -- pa_sink_input_assert_ref(i); -- pa_assert_ctl_context(); -- pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); -- pa_assert(ramp); -- -- pa_cvolume_ramp_convert(ramp, &i->ramp, i->sample_spec.rate); -- -- pa_log_debug("setting volume ramp with target vol:%d and length:%ld", -- i->ramp.ramps[0].target, -- i->ramp.ramps[0].length); -- -- -- /* This tells the sink that volume ramp changed */ -- if (send_msg) -- pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP, -- NULL, 0, NULL) == 0); --} -- - /* Called from main context */ - static void set_real_ratio(pa_sink_input *i, const pa_cvolume *v) { - pa_sink_input_assert_ref(i); -diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h -index 5430d53..5fef3d5 100644 ---- a/src/pulsecore/sink-input.h -+++ b/src/pulsecore/sink-input.h -@@ -381,7 +381,6 @@ void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, bool s - void pa_sink_input_add_volume_factor(pa_sink_input *i, const char *key, const pa_cvolume *volume_factor); - int pa_sink_input_remove_volume_factor(pa_sink_input *i, const char *key); - pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i, pa_cvolume *volume, bool absolute); --void pa_sink_input_set_volume_ramp(pa_sink_input *i, const pa_cvolume_ramp *ramp, bool send_msg); - void pa_sink_input_add_volume_ramp_factor(pa_sink_input *i, const char *key, const pa_cvolume_ramp *ramp_factor, bool send_msg); - int pa_sink_input_remove_volume_ramp_factor(pa_sink_input *i, const char *key, bool send_msg); - --- -1.9.1 - diff --git a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio-10.0/enable-ofono-hfp-backend.patch b/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio-10.0/enable-ofono-hfp-backend.patch deleted file mode 100644 index 85b1ae03d..000000000 --- a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio-10.0/enable-ofono-hfp-backend.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- pulseaudio-9.0/src/daemon/default.pa.in.orig 2017-05-17 17:26:20.415369638 +0000 -+++ pulseaudio-9.0/src/daemon/default.pa.in 2017-05-17 17:26:49.995316383 +0000 -@@ -82,7 +82,7 @@ - .endif - - .ifexists module-bluetooth-discover@PA_SOEXT@ --load-module module-bluetooth-discover -+load-module module-bluetooth-discover headset=ofono - .endif - ])dnl - diff --git a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0008-install-files-for-a-module-development.patch b/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0008-install-files-for-a-module-development.patch deleted file mode 100644 index ac164d643..000000000 --- a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0008-install-files-for-a-module-development.patch +++ /dev/null @@ -1,53 +0,0 @@ ---- a/Makefile.am 2016-04-12 11:28:10.832997230 +0200 -+++ b/Makefile.am 2016-04-12 11:32:41.868996777 +0200 -@@ -49,7 +49,13 @@ - vala/libpulse-simple.deps vala/libpulse-simple.vapi - - pkgconfigdir = $(libdir)/pkgconfig --pkgconfig_DATA = libpulse.pc libpulse-simple.pc -+pkgconfig_DATA = libpulse.pc libpulse-simple.pc pulseaudio-module-devel.pc -+ -+moduledev_DATA = pulsecore-config.h $(top_srcdir)/src/pulsecore/*.h -+moduledevdir = $(includedir)/pulsemodule/pulsecore -+ -+moduledevinternal_DATA = src/pulse/internal.h src/pulse/client-conf.h src/pulse/fork-detect.h -+moduledevinternaldir = $(includedir)/pulsemodule/pulse - - if HAVE_GLIB20 - pkgconfig_DATA += \ -@@ -103,6 +109,9 @@ - check-daemon: - $(MAKE) -C src check-daemon - -+pulsecore-config.h: config.h -+ cp $< $@ -+ - .PHONY: homepage distcleancheck doxygen - - # see git-version-gen ---- a/configure.ac 2016-04-12 11:34:10.605996629 +0200 -+++ b/configure.ac 2016-04-12 11:37:43.502996274 +0200 -@@ -1464,6 +1464,7 @@ - man/default.pa.5.xml - man/pulse-cli-syntax.5.xml - man/start-pulseaudio-x11.1.xml -+pulseaudio-module-devel.pc - ]) - - AC_CONFIG_FILES([src/esdcompat:src/daemon/esdcompat.in], [chmod +x src/esdcompat]) ---- /dev/null 2016-03-15 16:08:23.302999643 +0100 -+++ b/pulseaudio-module-devel.pc.in 2016-03-17 16:16:58.427977484 +0100 -@@ -0,0 +1,12 @@ -+prefix=@prefix@ -+exec_prefix=@exec_prefix@ -+libdir=@libdir@ -+includedir=@includedir@ -+modlibexecdir=@modlibexecdir@ -+ -+Name: pulseaudio-module-devel -+Description: PulseAudio Module Development Interface -+Version: @PACKAGE_VERSION@ -+Libs: -L${libdir} -L${libdir}/pulseaudio -L${modlibexecdir} -lpulsecommon-@PA_MAJORMINOR@ -lpulsecore-@PA_MAJORMINOR@ -lprotocol-native -+Libs.private: -+Cflags: -I${includedir}/pulsemodule -D_REENTRANT - diff --git a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0010-volume-ramp-additions-to-the-low-level-infra.patch b/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0010-volume-ramp-additions-to-the-low-level-infra.patch deleted file mode 100644 index e249bc438..000000000 --- a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0010-volume-ramp-additions-to-the-low-level-infra.patch +++ /dev/null @@ -1,503 +0,0 @@ ---- a/src/map-file 2016-04-12 15:03:17.009975690 +0200 -+++ b/src/map-file 2016-04-12 15:03:52.389975631 +0200 -@@ -136,6 +136,9 @@ - pa_cvolume_merge; - pa_cvolume_min; - pa_cvolume_min_mask; -+pa_cvolume_ramp_init; -+pa_cvolume_ramp_set; -+pa_cvolume_ramp_channel_ramp_set; - pa_cvolume_remap; - pa_cvolume_scale; - pa_cvolume_scale_mask; ---- a/src/pulse/def.h 2016-04-12 15:05:58.245975421 +0200 -+++ b/src/pulse/def.h 2016-04-12 15:13:19.424974685 +0200 -@@ -347,11 +347,15 @@ - * consider absolute when the sink is in flat volume mode, - * relative otherwise. \since 0.9.20 */ - -- PA_STREAM_PASSTHROUGH = 0x80000U -+ PA_STREAM_PASSTHROUGH = 0x80000U, - /**< Used to tag content that will be rendered by passthrough sinks. - * The data will be left as is and not reformatted, resampled. - * \since 1.0 */ - -+ PA_STREAM_START_RAMP_MUTED = 0x100000U -+ /**< Used to tag content that the stream will be started ramp volume -+ * muted so that you can nicely fade it in */ -+ - } pa_stream_flags_t; - - /** \cond fulldocs */ -@@ -380,6 +384,7 @@ - #define PA_STREAM_FAIL_ON_SUSPEND PA_STREAM_FAIL_ON_SUSPEND - #define PA_STREAM_RELATIVE_VOLUME PA_STREAM_RELATIVE_VOLUME - #define PA_STREAM_PASSTHROUGH PA_STREAM_PASSTHROUGH -+#define PA_STREAM_START_RAMP_MUTED PA_STREAM_START_RAMP_MUTED - - /** \endcond */ - -@@ -1047,6 +1052,13 @@ - /** \endcond */ - #endif - -+/** \cond fulldocs */ -+#define PA_VOLUMER_RAMP_TYPE_LINEAR PA_VOLUMER_RAMP_TYPE_LINEAR -+#define PA_VOLUMER_RAMP_TYPE_LOGARITHMIC PA_VOLUMER_RAMP_TYPE_LOGARITHMIC -+#define PA_VOLUMER_RAMP_TYPE_CUBIC PA_VOLUMER_RAMP_TYPE_CUBIC -+ -+/** \endcond */ -+ - PA_C_DECL_END - - #endif ---- a/src/pulse/volume.c 2016-04-12 15:13:38.598974653 +0200 -+++ b/src/pulse/volume.c 2016-04-12 15:27:57.729973219 +0200 -@@ -445,7 +445,10 @@ - unsigned c; - pa_assert(a); - -- pa_return_val_if_fail(pa_cvolume_valid(a), 0); -+ if (pa_cvolume_valid(a) == 0) -+ abort(); -+ -+ /* pa_return_val_if_fail(pa_cvolume_valid(a), 0); */ - pa_return_val_if_fail(PA_VOLUME_IS_VALID(v), 0); - - for (c = 0; c < a->channels; c++) -@@ -986,3 +989,51 @@ - - return pa_cvolume_scale(v, m); - } -+ -+pa_cvolume_ramp* pa_cvolume_ramp_init(pa_cvolume_ramp *ramp) { -+ unsigned c; -+ -+ pa_assert(ramp); -+ -+ ramp->channels = 0; -+ -+ for (c = 0; c < PA_CHANNELS_MAX; c++) { -+ ramp->ramps[c].type = PA_VOLUME_RAMP_TYPE_LINEAR; -+ ramp->ramps[c].length = 0; -+ ramp->ramps[c].target = PA_VOLUME_INVALID; -+ } -+ -+ return ramp; -+} -+ -+pa_cvolume_ramp* pa_cvolume_ramp_set(pa_cvolume_ramp *ramp, unsigned channels, pa_volume_ramp_type_t type, long time, pa_volume_t vol) { -+ int i; -+ -+ pa_assert(ramp); -+ pa_assert(channels > 0); -+ pa_assert(time >= 0); -+ pa_assert(channels <= PA_CHANNELS_MAX); -+ -+ ramp->channels = (uint8_t) channels; -+ -+ for (i = 0; i < ramp->channels; i++) { -+ ramp->ramps[i].type = type; -+ ramp->ramps[i].length = time; -+ ramp->ramps[i].target = PA_CLAMP_VOLUME(vol); -+ } -+ -+ return ramp; -+} -+ -+pa_cvolume_ramp* pa_cvolume_ramp_channel_ramp_set(pa_cvolume_ramp *ramp, unsigned channel, pa_volume_ramp_type_t type, long time, pa_volume_t vol) { -+ -+ pa_assert(ramp); -+ pa_assert(channel <= ramp->channels); -+ pa_assert(time >= 0); -+ -+ ramp->ramps[channel].type = type; -+ ramp->ramps[channel].length = time; -+ ramp->ramps[channel].target = PA_CLAMP_VOLUME(vol); -+ -+ return ramp; -+} ---- a/src/pulse/volume.h 2016-04-12 15:40:34.989971955 +0200 -+++ b/src/pulse/volume.h 2016-04-12 15:38:50.708972129 +0200 -@@ -413,6 +413,36 @@ - * the channels are kept. \since 0.9.16 */ - pa_cvolume* pa_cvolume_dec(pa_cvolume *v, pa_volume_t dec); - -+/** Volume ramp type -+*/ -+typedef enum pa_volume_ramp_type { -+ PA_VOLUME_RAMP_TYPE_LINEAR = 0, /**< linear */ -+ PA_VOLUME_RAMP_TYPE_LOGARITHMIC = 1, /**< logarithmic */ -+ PA_VOLUME_RAMP_TYPE_CUBIC = 2, -+} pa_volume_ramp_type_t; -+ -+/** A structure encapsulating a volume ramp */ -+typedef struct pa_volume_ramp_t { -+ pa_volume_ramp_type_t type; -+ long length; -+ pa_volume_t target; -+} pa_volume_ramp_t; -+ -+/** A structure encapsulating a multichannel volume ramp */ -+typedef struct pam_cvolume_ramp { -+ uint8_t channels; -+ pa_volume_ramp_t ramps[PA_CHANNELS_MAX]; -+} pa_cvolume_ramp; -+ -+/** Init volume ramp struct */ -+pa_cvolume_ramp* pa_cvolume_ramp_init(pa_cvolume_ramp *ramp); -+ -+/** Set first n channels of ramp struct to certain value */ -+pa_cvolume_ramp* pa_cvolume_ramp_set(pa_cvolume_ramp *ramp, unsigned channel, pa_volume_ramp_type_t type, long time, pa_volume_t vol); -+ -+/** Set individual channel in the channel struct */ -+pa_cvolume_ramp* pa_cvolume_ramp_channel_ramp_set(pa_cvolume_ramp *ramp, unsigned channel, pa_volume_ramp_type_t type, long time, pa_volume_t vol); -+ - PA_C_DECL_END - - #endif ---- a/src/pulsecore/sample-util.c 2016-04-12 15:41:51.812971827 +0200 -+++ b/src/pulsecore/sample-util.c 2016-04-12 16:31:56.795966812 +0200 -@@ -41,6 +41,13 @@ - - #define PA_SILENCE_MAX (PA_PAGE_SIZE*16) - -+#define VOLUME_PADDING 32 -+ -+typedef union { -+ float f; -+ uint32_t i; -+} volume_val; -+ - pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec) { - void *data; - -@@ -403,3 +410,292 @@ - usec = pa_bytes_to_usec_round_up(size, from); - return pa_usec_to_bytes_round_up(usec, to); - } -+ -+static void calc_linear_integer_volume_no_mapping(int32_t linear[], float volume[], unsigned nchannels) { -+ unsigned channel, padding; -+ -+ pa_assert(linear); -+ pa_assert(volume); -+ -+ for (channel = 0; channel < nchannels; channel++) -+ linear[channel] = (int32_t) lrint(volume[channel] * 0x10000U); -+ -+ for (padding = 0; padding < VOLUME_PADDING; padding++, channel++) -+ linear[channel] = linear[padding]; -+} -+ -+static void calc_linear_float_volume_no_mapping(float linear[], float volume[], unsigned nchannels) { -+ unsigned channel, padding; -+ -+ pa_assert(linear); -+ pa_assert(volume); -+ -+ for (channel = 0; channel < nchannels; channel++) -+ linear[channel] = volume[channel]; -+ -+ for (padding = 0; padding < VOLUME_PADDING; padding++, channel++) -+ linear[channel] = linear[padding]; -+} -+ -+typedef void (*pa_calc_volume_no_mapping_func_t) (void *volumes, float *volume, int channels); -+ -+static const pa_calc_volume_no_mapping_func_t calc_volume_table_no_mapping[] = { -+ [PA_SAMPLE_U8] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, -+ [PA_SAMPLE_ALAW] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, -+ [PA_SAMPLE_ULAW] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, -+ [PA_SAMPLE_S16LE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, -+ [PA_SAMPLE_S16BE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, -+ [PA_SAMPLE_FLOAT32LE] = (pa_calc_volume_no_mapping_func_t) calc_linear_float_volume_no_mapping, -+ [PA_SAMPLE_FLOAT32BE] = (pa_calc_volume_no_mapping_func_t) calc_linear_float_volume_no_mapping, -+ [PA_SAMPLE_S32LE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, -+ [PA_SAMPLE_S32BE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, -+ [PA_SAMPLE_S24LE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, -+ [PA_SAMPLE_S24BE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, -+ [PA_SAMPLE_S24_32LE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping, -+ [PA_SAMPLE_S24_32BE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping -+}; -+ -+static const unsigned format_sample_size_table[] = { -+ [PA_SAMPLE_U8] = 1, -+ [PA_SAMPLE_ALAW] = 1, -+ [PA_SAMPLE_ULAW] = 1, -+ [PA_SAMPLE_S16LE] = 2, -+ [PA_SAMPLE_S16BE] = 2, -+ [PA_SAMPLE_FLOAT32LE] = 4, -+ [PA_SAMPLE_FLOAT32BE] = 4, -+ [PA_SAMPLE_S32LE] = 4, -+ [PA_SAMPLE_S32BE] = 4, -+ [PA_SAMPLE_S24LE] = 3, -+ [PA_SAMPLE_S24BE] = 3, -+ [PA_SAMPLE_S24_32LE] = 4, -+ [PA_SAMPLE_S24_32BE] = 4 -+}; -+ -+static float calc_volume_ramp_linear(pa_volume_ramp_int_t *ramp) { -+ pa_assert(ramp); -+ pa_assert(ramp->length > 0); -+ -+ /* basic linear interpolation */ -+ return ramp->start + (ramp->length - ramp->left) * (ramp->end - ramp->start) / (float) ramp->length; -+} -+ -+static float calc_volume_ramp_logarithmic(pa_volume_ramp_int_t *ramp) { -+ float x_val, s, e; -+ long temp; -+ -+ pa_assert(ramp); -+ pa_assert(ramp->length > 0); -+ -+ if (ramp->end > ramp->start) { -+ temp = ramp->left; -+ s = ramp->end; -+ e = ramp->start; -+ } else { -+ temp = ramp->length - ramp->left; -+ s = ramp->start; -+ e = ramp->end; -+ } -+ -+ x_val = temp == 0 ? 0.0 : powf(temp, 10); -+ -+ /* base 10 logarithmic interpolation */ -+ return s + x_val * (e - s) / powf(ramp->length, 10); -+} -+ -+static float calc_volume_ramp_cubic(pa_volume_ramp_int_t *ramp) { -+ float x_val, s, e; -+ long temp; -+ -+ pa_assert(ramp); -+ pa_assert(ramp->length > 0); -+ -+ if (ramp->end > ramp->start) { -+ temp = ramp->left; -+ s = ramp->end; -+ e = ramp->start; -+ } else { -+ temp = ramp->length - ramp->left; -+ s = ramp->start; -+ e = ramp->end; -+ } -+ -+ x_val = temp == 0 ? 0.0 : cbrtf(temp); -+ -+ /* cubic interpolation */ -+ return s + x_val * (e - s) / cbrtf(ramp->length); -+} -+ -+typedef float (*pa_calc_volume_ramp_func_t) (pa_volume_ramp_int_t *); -+ -+static const pa_calc_volume_ramp_func_t calc_volume_ramp_table[] = { -+ [PA_VOLUME_RAMP_TYPE_LINEAR] = (pa_calc_volume_ramp_func_t) calc_volume_ramp_linear, -+ [PA_VOLUME_RAMP_TYPE_LOGARITHMIC] = (pa_calc_volume_ramp_func_t) calc_volume_ramp_logarithmic, -+ [PA_VOLUME_RAMP_TYPE_CUBIC] = (pa_calc_volume_ramp_func_t) calc_volume_ramp_cubic -+}; -+ -+static void calc_volume_ramps(pa_cvolume_ramp_int *ram, float *vol) -+{ -+ int i; -+ -+ for (i = 0; i < ram->channels; i++) { -+ if (ram->ramps[i].left <= 0) { -+ if (ram->ramps[i].target == PA_VOLUME_NORM) { -+ vol[i] = 1.0; -+ } -+ } else { -+ vol[i] = ram->ramps[i].curr = calc_volume_ramp_table[ram->ramps[i].type] (&ram->ramps[i]); -+ ram->ramps[i].left--; -+ } -+ } -+} -+ -+void pa_volume_ramp_memchunk( -+ pa_memchunk *c, -+ const pa_sample_spec *spec, -+ pa_cvolume_ramp_int *ramp) { -+ -+ void *ptr; -+ volume_val linear[PA_CHANNELS_MAX + VOLUME_PADDING]; -+ float vol[PA_CHANNELS_MAX + VOLUME_PADDING]; -+ pa_do_volume_func_t do_volume; -+ long length_in_frames; -+ int i; -+ -+ pa_assert(c); -+ pa_assert(spec); -+ pa_assert(pa_frame_aligned(c->length, spec)); -+ pa_assert(ramp); -+ -+ length_in_frames = c->length / format_sample_size_table[spec->format] / spec->channels; -+ -+ if (pa_memblock_is_silence(c->memblock)) { -+ for (i = 0; i < ramp->channels; i++) { -+ if (ramp->ramps[i].length > 0) -+ ramp->ramps[i].length -= length_in_frames; -+ } -+ return; -+ } -+ -+ if (spec->format < 0 || spec->format >= PA_SAMPLE_MAX) { -+ pa_log_warn("Unable to change volume of format"); -+ return; -+ } -+ -+ do_volume = pa_get_volume_func(spec->format); -+ pa_assert(do_volume); -+ -+ ptr = (uint8_t*) pa_memblock_acquire(c->memblock) + c->index; -+ -+ for (i = 0; i < length_in_frames; i++) { -+ calc_volume_ramps(ramp, vol); -+ calc_volume_table_no_mapping[spec->format] ((void *)linear, vol, spec->channels); -+ -+ /* we only process one frame per iteration */ -+ do_volume (ptr, (void *)linear, spec->channels, format_sample_size_table[spec->format] * spec->channels); -+ -+ /* pa_log_debug("1: %d 2: %d", linear[0], linear[1]); */ -+ -+ ptr = (uint8_t*)ptr + format_sample_size_table[spec->format] * spec->channels; -+ } -+ -+ pa_memblock_release(c->memblock); -+} -+ -+pa_cvolume_ramp_int* pa_cvolume_ramp_convert(const pa_cvolume_ramp *src, pa_cvolume_ramp_int *dst, int sample_rate) { -+ int i; -+ float temp; -+ -+ for (i = 0; i < dst->channels; i++) { -+ dst->ramps[i].type = src->ramps[i].type; -+ /* ms to samples */ -+ dst->ramps[i].length = src->ramps[i].length * sample_rate / 1000; -+ dst->ramps[i].left = dst->ramps[i].length; -+ dst->ramps[i].start = dst->ramps[i].end; -+ dst->ramps[i].target = src->ramps[i].target; -+ /* scale to pulse internal mapping so that when ramp is over there's no glitch in volume */ -+ temp = src->ramps[i].target / (float)0x10000U; -+ dst->ramps[i].end = temp * temp * temp; -+ } -+ -+ return dst; -+} -+ -+bool pa_cvolume_ramp_active(pa_cvolume_ramp_int *ramp) { -+ int i; -+ -+ for (i = 0; i < ramp->channels; i++) { -+ if (ramp->ramps[i].left > 0) -+ return true; -+ } -+ -+ return false; -+} -+ -+bool pa_cvolume_ramp_target_active(pa_cvolume_ramp_int *ramp) { -+ int i; -+ -+ for (i = 0; i < ramp->channels; i++) { -+ if (ramp->ramps[i].target != PA_VOLUME_NORM) -+ return true; -+ } -+ -+ return false; -+} -+ -+pa_cvolume * pa_cvolume_ramp_get_targets(pa_cvolume_ramp_int *ramp, pa_cvolume *volume) { -+ int i = 0; -+ -+ volume->channels = ramp->channels; -+ -+ for (i = 0; i < ramp->channels; i++) -+ volume->values[i] = ramp->ramps[i].target; -+ -+ return volume; -+} -+ -+pa_cvolume_ramp_int* pa_cvolume_ramp_start_from(pa_cvolume_ramp_int *src, pa_cvolume_ramp_int *dst) { -+ int i; -+ -+ for (i = 0; i < src->channels; i++) { -+ /* if new vols are invalid, copy old ramp i.e. no effect */ -+ if (dst->ramps[i].target == PA_VOLUME_INVALID) -+ dst->ramps[i] = src->ramps[i]; -+ /* if there's some old ramp still left */ -+ else if (src->ramps[i].left > 0) -+ dst->ramps[i].start = src->ramps[i].curr; -+ } -+ -+ return dst; -+} -+ -+pa_cvolume_ramp_int* pa_cvolume_ramp_int_init(pa_cvolume_ramp_int *src, pa_volume_t vol, int channels) { -+ int i; -+ float temp; -+ -+ src->channels = channels; -+ -+ for (i = 0; i < channels; i++) { -+ src->ramps[i].type = PA_VOLUME_RAMP_TYPE_LINEAR; -+ src->ramps[i].length = 0; -+ src->ramps[i].left = 0; -+ if (vol == PA_VOLUME_NORM) { -+ src->ramps[i].start = 1.0; -+ src->ramps[i].end = 1.0; -+ src->ramps[i].curr = 1.0; -+ } -+ else if (vol == PA_VOLUME_MUTED) { -+ src->ramps[i].start = 0.0; -+ src->ramps[i].end = 0.0; -+ src->ramps[i].curr = 0.0; -+ } -+ else { -+ temp = vol / (float)0x10000U; -+ src->ramps[i].start = temp * temp * temp; -+ src->ramps[i].end = src->ramps[i].start; -+ src->ramps[i].curr = src->ramps[i].start; -+ } -+ src->ramps[i].target = vol; -+ } -+ -+ return src; -+} ---- a/src/pulsecore/sample-util.h 2016-04-12 15:53:06.327970701 +0200 -+++ b/src/pulsecore/sample-util.h 2016-04-12 16:24:16.356967580 +0200 -@@ -45,6 +45,33 @@ - - pa_memchunk* pa_silence_memchunk_get(pa_silence_cache *cache, pa_mempool *pool, pa_memchunk* ret, const pa_sample_spec *spec, size_t length); - -+typedef struct pa_volume_ramp_int_t { -+ pa_volume_ramp_type_t type; -+ long length; -+ long left; -+ float start; -+ float end; -+ float curr; -+ pa_volume_t target; -+} pa_volume_ramp_int_t; -+ -+typedef struct pa_cvolume_ramp_int { -+ uint8_t channels; -+ pa_volume_ramp_int_t ramps[PA_CHANNELS_MAX]; -+} pa_cvolume_ramp_int; -+ -+pa_cvolume_ramp_int* pa_cvolume_ramp_convert(const pa_cvolume_ramp *src, pa_cvolume_ramp_int *dst, int sample_rate); -+bool pa_cvolume_ramp_active(pa_cvolume_ramp_int *ramp); -+bool pa_cvolume_ramp_target_active(pa_cvolume_ramp_int *ramp); -+pa_cvolume_ramp_int* pa_cvolume_ramp_start_from(pa_cvolume_ramp_int *src, pa_cvolume_ramp_int *dst); -+pa_cvolume_ramp_int* pa_cvolume_ramp_int_init(pa_cvolume_ramp_int *src, pa_volume_t vol, int channels); -+pa_cvolume * pa_cvolume_ramp_get_targets(pa_cvolume_ramp_int *ramp, pa_cvolume *volume); -+ -+void pa_volume_ramp_memchunk( -+ pa_memchunk *c, -+ const pa_sample_spec *spec, -+ pa_cvolume_ramp_int *ramp); -+ - size_t pa_frame_align(size_t l, const pa_sample_spec *ss) PA_GCC_PURE; - - bool pa_frame_aligned(size_t l, const pa_sample_spec *ss) PA_GCC_PURE; diff --git a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0011-volume-ramp-adding-volume-ramping-to-sink-input.patch b/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0011-volume-ramp-adding-volume-ramping-to-sink-input.patch deleted file mode 100644 index 08fb79248..000000000 --- a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0011-volume-ramp-adding-volume-ramping-to-sink-input.patch +++ /dev/null @@ -1,159 +0,0 @@ ---- a/src/pulsecore/sink-input.c 2016-04-12 16:50:41.311964935 +0200 -+++ b/src/pulsecore/sink-input.c 2016-04-12 17:22:40.420961732 +0200 -@@ -525,6 +525,11 @@ - reset_callbacks(i); - i->userdata = NULL; - -+ if (data->flags & PA_SINK_INPUT_START_RAMP_MUTED) -+ pa_cvolume_ramp_int_init(&i->ramp, PA_VOLUME_MUTED, data->sample_spec.channels); -+ else -+ pa_cvolume_ramp_int_init(&i->ramp, PA_VOLUME_NORM, data->sample_spec.channels); -+ - i->thread_info.state = i->state; - i->thread_info.attached = false; - pa_atomic_store(&i->thread_info.drained, 1); -@@ -541,6 +546,8 @@ - i->thread_info.playing_for = 0; - i->thread_info.direct_outputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); - -+ i->thread_info.ramp = i->ramp; -+ - pa_assert_se(pa_idxset_put(core->sink_inputs, i, &i->index) == 0); - pa_assert_se(pa_idxset_put(i->sink->inputs, pa_sink_input_ref(i), NULL) == 0); - -@@ -922,6 +929,8 @@ - while (tchunk.length > 0) { - pa_memchunk wchunk; - bool nvfs = need_volume_factor_sink; -+ pa_cvolume target; -+ bool tmp; - - wchunk = tchunk; - pa_memblock_ref(wchunk.memblock); -@@ -958,6 +967,16 @@ - pa_volume_memchunk(&wchunk, &i->sink->sample_spec, &i->volume_factor_sink); - } - -+ /* check for possible volume ramp */ -+ if (pa_cvolume_ramp_active(&i->thread_info.ramp)) { -+ pa_memchunk_make_writable(&wchunk, 0); -+ pa_volume_ramp_memchunk(&wchunk, &i->sink->sample_spec, &(i->thread_info.ramp)); -+ } else if ((tmp = pa_cvolume_ramp_target_active(&(i->thread_info.ramp)))) { -+ pa_memchunk_make_writable(&wchunk, 0); -+ pa_cvolume_ramp_get_targets(&i->thread_info.ramp, &target); -+ pa_volume_memchunk(&wchunk, &i->sink->sample_spec, &target); -+ } -+ - pa_memblockq_push_align(i->thread_info.render_memblockq, &wchunk); - } else { - pa_memchunk rchunk; -@@ -974,6 +993,16 @@ - pa_volume_memchunk(&rchunk, &i->sink->sample_spec, &i->volume_factor_sink); - } - -+ /* check for possible volume ramp */ -+ if (pa_cvolume_ramp_active(&i->thread_info.ramp)) { -+ pa_memchunk_make_writable(&wchunk, 0); -+ pa_volume_ramp_memchunk(&wchunk, &i->sink->sample_spec, &(i->thread_info.ramp)); -+ } else if ((tmp = pa_cvolume_ramp_target_active(&(i->thread_info.ramp)))) { -+ pa_memchunk_make_writable(&wchunk, 0); -+ pa_cvolume_ramp_get_targets(&i->thread_info.ramp, &target); -+ pa_volume_memchunk(&wchunk, &i->sink->sample_spec, &target); -+ } -+ - pa_memblockq_push_align(i->thread_info.render_memblockq, &rchunk); - pa_memblock_unref(rchunk.memblock); - } -@@ -1338,6 +1367,31 @@ - return 0; - } - -+/* Called from main thread */ -+void pa_sink_input_set_volume_ramp( -+ pa_sink_input *i, -+ const pa_cvolume_ramp *ramp, -+ bool send_msg, -+ bool save) { -+ -+ pa_sink_input_assert_ref(i); -+ pa_assert_ctl_context(); -+ pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); -+ pa_assert(ramp); -+ -+ pa_cvolume_ramp_convert(ramp, &i->ramp, i->sample_spec.rate); -+ -+ pa_log_debug("setting volume ramp with target vol:%d and length:%ld", -+ i->ramp.ramps[0].target, -+ i->ramp.ramps[0].length); -+ -+ -+ /* This tells the sink that volume ramp changed */ -+ if (send_msg) -+ pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP, -+ NULL, 0, NULL) == 0); -+} -+ - /* Called from main context */ - static void set_real_ratio(pa_sink_input *i, const pa_cvolume *v) { - pa_sink_input_assert_ref(i); -@@ -1929,6 +1983,12 @@ - } - return 0; - -+ case PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP: -+ /* we have ongoing ramp where we take current start values */ -+ pa_cvolume_ramp_start_from(&i->thread_info.ramp, &i->ramp); -+ i->thread_info.ramp = i->ramp; -+ return 0; -+ - case PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE: - if (i->thread_info.muted != i->muted) { - i->thread_info.muted = i->muted; ---- a/src/pulsecore/sink-input.h 2016-04-12 16:50:46.712964926 +0200 -+++ b/src/pulsecore/sink-input.h 2016-04-12 17:30:24.289960958 +0200 -@@ -59,7 +59,8 @@ - PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND = 256, - PA_SINK_INPUT_NO_CREATE_ON_SUSPEND = 512, - PA_SINK_INPUT_KILL_ON_SUSPEND = 1024, -- PA_SINK_INPUT_PASSTHROUGH = 2048 -+ PA_SINK_INPUT_PASSTHROUGH = 2048, -+ PA_SINK_INPUT_START_RAMP_MUTED = 4096, - } pa_sink_input_flags_t; - - struct pa_sink_input { -@@ -122,6 +123,9 @@ - * this.*/ - bool save_sink:1, save_volume:1, save_muted:1; - -+ /* for volume ramps */ -+ pa_cvolume_ramp_int ramp; -+ - pa_resample_method_t requested_resample_method, actual_resample_method; - - /* Returns the chunk of audio data and drops it from the -@@ -250,6 +254,8 @@ - pa_usec_t requested_sink_latency; - - pa_hashmap *direct_outputs; -+ -+ pa_cvolume_ramp_int ramp; - } thread_info; - - void *userdata; -@@ -266,6 +272,7 @@ - PA_SINK_INPUT_MESSAGE_SET_STATE, - PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY, - PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY, -+ PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP, - PA_SINK_INPUT_MESSAGE_MAX - }; - -@@ -374,6 +381,8 @@ - - void pa_sink_input_set_mute(pa_sink_input *i, bool mute, bool save); - -+void pa_sink_input_set_volume_ramp(pa_sink_input *i, const pa_cvolume_ramp *ramp, bool send_msg, bool save); -+ - void pa_sink_input_update_proplist(pa_sink_input *i, pa_update_mode_t mode, pa_proplist *p); - - pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i); diff --git a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0012-volume-ramp-add-volume-ramping-to-sink.patch b/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0012-volume-ramp-add-volume-ramping-to-sink.patch deleted file mode 100644 index 43e8283ef..000000000 --- a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0012-volume-ramp-add-volume-ramping-to-sink.patch +++ /dev/null @@ -1,159 +0,0 @@ ---- a/src/pulsecore/sink.c 2016-04-12 18:01:23.403957855 +0200 -+++ b/src/pulsecore/sink.c 2016-04-12 18:44:49.677953506 +0200 -@@ -324,6 +324,8 @@ - &s->sample_spec, - 0); - -+ pa_cvolume_ramp_int_init(&s->ramp, PA_VOLUME_NORM, data->sample_spec.channels); -+ - s->thread_info.rtpoll = NULL; - s->thread_info.inputs = pa_hashmap_new_full(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func, NULL, - (pa_free_cb_t) pa_sink_input_unref); -@@ -347,6 +349,8 @@ - s->thread_info.volume_change_extra_delay = core->deferred_volume_extra_delay_usec; - s->thread_info.latency_offset = s->latency_offset; - -+ s->thread_info.ramp = s->ramp; -+ - /* FIXME: This should probably be moved to pa_sink_put() */ - pa_assert_se(pa_idxset_put(core->sinks, s, &s->index) >= 0); - -@@ -1182,6 +1186,7 @@ - - } else if (n == 1) { - pa_cvolume volume; -+ pa_cvolume target; - - *result = info[0].chunk; - pa_memblock_ref(result->memblock); -@@ -1198,9 +1203,20 @@ - result, - &s->sample_spec, - result->length); -- } else if (!pa_cvolume_is_norm(&volume)) { -+ } else if (!pa_cvolume_is_norm(&volume) || pa_cvolume_ramp_target_active(&s->thread_info.ramp) || pa_cvolume_ramp_active(&s->thread_info.ramp)) { - pa_memchunk_make_writable(result, 0); -- pa_volume_memchunk(result, &s->sample_spec, &volume); -+ if (!pa_cvolume_ramp_active(&s->thread_info.ramp)) { -+ if (!pa_cvolume_is_norm(&volume)) -+ pa_volume_memchunk(result, &s->sample_spec, &volume); -+ pa_volume_ramp_memchunk(result, &s->sample_spec, &(s->thread_info.ramp)); -+ } -+ else { -+ if (pa_cvolume_ramp_target_active(&s->thread_info.ramp)) { -+ pa_cvolume_ramp_get_targets(&s->thread_info.ramp, &target); -+ pa_sw_cvolume_multiply(&volume, &volume, &target); -+ } -+ pa_volume_memchunk(result, &s->sample_spec, &volume); -+ } - } - } else { - void *ptr; -@@ -1290,6 +1306,7 @@ - - } else { - void *ptr; -+ pa_cvolume target_vol; - - ptr = pa_memblock_acquire(target->memblock); - -@@ -1299,6 +1316,15 @@ - &s->thread_info.soft_volume, - s->thread_info.soft_muted); - -+ if (pa_cvolume_ramp_target_active(&s->thread_info.ramp) || pa_cvolume_ramp_active(&s->thread_info.ramp)) { -+ if (pa_cvolume_ramp_active(&s->thread_info.ramp)) -+ pa_volume_ramp_memchunk(target, &s->sample_spec, &(s->thread_info.ramp)); -+ else { -+ pa_cvolume_ramp_get_targets(&s->thread_info.ramp, &target_vol); -+ pa_volume_memchunk(target, &s->sample_spec, &target_vol); -+ } -+ } -+ - pa_memblock_release(target->memblock); - } - -@@ -2058,6 +2084,32 @@ - pa_assert_se(pa_asyncmsgq_send(root_sink->asyncmsgq, PA_MSGOBJECT(root_sink), PA_SINK_MESSAGE_SET_SHARED_VOLUME, NULL, 0, NULL) == 0); - } - -+/* Called from main thread */ -+void pa_sink_set_volume_ramp( -+ pa_sink *s, -+ const pa_cvolume_ramp *ramp, -+ bool send_msg, -+ bool save) { -+ -+ pa_sink_assert_ref(s); -+ pa_assert_ctl_context(); -+ pa_assert(PA_SINK_IS_LINKED(s->state)); -+ pa_assert(ramp); -+ -+ /* make sure we don't change the volume when a PASSTHROUGH input is connected ... -+ * ... *except* if we're being invoked to reset the volume to ensure 0 dB gain */ -+ if (pa_sink_is_passthrough(s)) { -+ pa_log_warn("Cannot do volume ramp, Sink is connected to PASSTHROUGH input"); -+ return; -+ } -+ -+ pa_cvolume_ramp_convert(ramp, &s->ramp, s->sample_spec.rate); -+ -+ /* This tells the sink that volume ramp changed */ -+ if (send_msg) -+ pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_VOLUME_RAMP, NULL, 0, NULL) == 0); -+} -+ - /* Called from the io thread if sync volume is used, otherwise from the main thread. - * Only to be called by sink implementor */ - void pa_sink_set_soft_volume(pa_sink *s, const pa_cvolume *volume) { -@@ -2713,6 +2765,12 @@ - sync_input_volumes_within_thread(s); - return 0; - -+ case PA_SINK_MESSAGE_SET_VOLUME_RAMP: -+ /* if we have ongoing ramp where we take current start values */ -+ pa_cvolume_ramp_start_from(&s->thread_info.ramp, &s->ramp); -+ s->thread_info.ramp = s->ramp; -+ return 0; -+ - case PA_SINK_MESSAGE_GET_VOLUME: - - if ((s->flags & PA_SINK_DEFERRED_VOLUME) && s->get_volume) { ---- a/src/pulsecore/sink.h 2016-04-12 18:01:42.117957824 +0200 -+++ b/src/pulsecore/sink.h 2016-04-12 18:23:29.394955642 +0200 -@@ -105,6 +105,9 @@ - pa_cvolume saved_volume; - bool saved_save_volume:1; - -+ /* for volume ramps */ -+ pa_cvolume_ramp_int ramp; -+ - pa_asyncmsgq *asyncmsgq; - - pa_memchunk silence; -@@ -300,6 +303,8 @@ - uint32_t volume_change_safety_margin; - /* Usec delay added to all volume change events, may be negative. */ - int32_t volume_change_extra_delay; -+ -+ pa_cvolume_ramp_int ramp; - } thread_info; - - void *userdata; -@@ -333,6 +338,7 @@ - PA_SINK_MESSAGE_SET_MAX_REQUEST, - PA_SINK_MESSAGE_SET_PORT, - PA_SINK_MESSAGE_UPDATE_VOLUME_AND_MUTE, -+ PA_SINK_MESSAGE_SET_VOLUME_RAMP, - PA_SINK_MESSAGE_SET_LATENCY_OFFSET, - PA_SINK_MESSAGE_MAX - } pa_sink_message_t; -@@ -453,6 +459,8 @@ - void pa_sink_set_mute(pa_sink *sink, bool mute, bool save); - bool pa_sink_get_mute(pa_sink *sink, bool force_refresh); - -+void pa_sink_set_volume_ramp(pa_sink *s, const pa_cvolume_ramp *ramp, bool send_msg, bool save); -+ - bool pa_sink_update_proplist(pa_sink *s, pa_update_mode_t mode, pa_proplist *p); - - int pa_sink_set_port(pa_sink *s, const char *name, bool save); diff --git a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0013-add-internal-corking-state-for-sink-input.patch b/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0013-add-internal-corking-state-for-sink-input.patch deleted file mode 100644 index cb68e26af..000000000 --- a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0013-add-internal-corking-state-for-sink-input.patch +++ /dev/null @@ -1,72 +0,0 @@ ---- a/src/pulsecore/sink-input.c 2016-04-13 11:44:04.389999429 +0200 -+++ b/src/pulsecore/sink-input.c 2016-04-13 11:52:45.167998560 +0200 -@@ -786,6 +786,9 @@ - update_n_corked(i, state); - i->state = state; - -+ i->corked = false; -+ i->corked_internal = false; -+ - /* We might need to update the sink's volume if we are in flat volume mode. */ - if (pa_sink_flat_volume_enabled(i->sink)) - pa_sink_set_volume(i->sink, NULL, false, i->save_volume); -@@ -1493,13 +1496,38 @@ - } - } - -+static void pa_sink_input_cork_really(pa_sink_input *i, bool b) { -+ pa_sink_input_assert_ref(i); -+ pa_assert_ctl_context(); -+ pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); -+ -+ if (i->corked_internal == false && i->corked == false) -+ b = false; -+ else -+ b = true; -+ -+ sink_input_set_state(i, b ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING); -+} -+ - /* Called from main context */ - void pa_sink_input_cork(pa_sink_input *i, bool b) { - pa_sink_input_assert_ref(i); - pa_assert_ctl_context(); - pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); - -- sink_input_set_state(i, b ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING); -+ i->corked = b; -+ -+ pa_sink_input_cork_really(i, b); -+} -+ -+void pa_sink_input_cork_internal(pa_sink_input *i, bool b) { -+ pa_sink_input_assert_ref(i); -+ pa_assert_ctl_context(); -+ pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); -+ -+ i->corked_internal = b; -+ -+ pa_sink_input_cork_really(i, b); - } - - /* Called from main context */ ---- a/src/pulsecore/sink-input.h 2016-04-13 11:44:28.035999390 +0200 -+++ b/src/pulsecore/sink-input.h 2016-04-13 11:53:56.325998441 +0200 -@@ -126,6 +126,9 @@ - /* for volume ramps */ - pa_cvolume_ramp_int ramp; - -+ bool corked; -+ bool corked_internal; -+ - pa_resample_method_t requested_resample_method, actual_resample_method; - - /* Returns the chunk of audio data and drops it from the -@@ -357,6 +360,7 @@ - void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes, bool rewrite, bool flush, bool dont_rewind_render); - - void pa_sink_input_cork(pa_sink_input *i, bool b); -+void pa_sink_input_cork_internal(pa_sink_input *i, bool b); - - int pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate); - int pa_sink_input_update_rate(pa_sink_input *i); diff --git a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0020-core-util-Add-pa_join.patch b/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0020-core-util-Add-pa_join.patch deleted file mode 100644 index 891a5b83a..000000000 --- a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0020-core-util-Add-pa_join.patch +++ /dev/null @@ -1,37 +0,0 @@ ---- a/src/pulsecore/core-util.c 2016-04-13 16:17:33.314016929 +0200 -+++ b/src/pulsecore/core-util.c 2016-04-13 16:18:31.186016833 +0200 -@@ -1104,6 +1104,24 @@ - return pa_xstrndup(current, l); - } - -+char *pa_join(const char * const *strings, unsigned n_strings, const char *delimiter) { -+ pa_strbuf *buf; -+ unsigned i; -+ -+ pa_assert(strings || n_strings == 0); -+ -+ buf = pa_strbuf_new(); -+ -+ for (i = 0; i < n_strings; i++) { -+ if (i > 0 && delimiter) -+ pa_strbuf_puts(buf, delimiter); -+ -+ pa_strbuf_puts(buf, strings[i]); -+ } -+ -+ return pa_strbuf_tostring_free(buf); -+} -+ - PA_STATIC_TLS_DECLARE(signame, pa_xfree); - - /* Return the name of an UNIX signal. Similar to Solaris sig2str() */ ---- a/src/pulsecore/core-util.h 2016-04-13 16:17:39.177016919 +0200 -+++ b/src/pulsecore/core-util.h 2016-04-13 16:19:09.141016769 +0200 -@@ -108,6 +108,7 @@ - char *pa_split(const char *c, const char*delimiters, const char **state); - const char *pa_split_in_place(const char *c, const char*delimiters, int *n, const char **state); - char *pa_split_spaces(const char *c, const char **state); -+char *pa_join(const char * const *strings, unsigned n_strings, const char *delimiter); - - char *pa_strip_nl(char *s); - char *pa_strip(char *s); diff --git a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0021-dynarray-Add-pa_dynarray_get_raw_array.patch b/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0021-dynarray-Add-pa_dynarray_get_raw_array.patch deleted file mode 100644 index 040913c8f..000000000 --- a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0021-dynarray-Add-pa_dynarray_get_raw_array.patch +++ /dev/null @@ -1,21 +0,0 @@ ---- a/src/pulsecore/dynarray.c 2016-04-13 16:25:38.628016119 +0200 -+++ b/src/pulsecore/dynarray.c 2016-04-13 16:26:54.694015992 +0200 -@@ -91,3 +91,9 @@ - - return array->n_entries; - } -+ -+void * const *pa_dynarray_get_raw_array(pa_dynarray *array) { -+ pa_assert(array); -+ -+ return array->data; -+} ---- a/src/pulsecore/dynarray.h 2016-04-13 16:25:43.225016112 +0200 -+++ b/src/pulsecore/dynarray.h 2016-04-13 16:27:47.414015904 +0200 -@@ -52,5 +52,5 @@ - void *pa_dynarray_steal_last(pa_dynarray *array); - - unsigned pa_dynarray_size(pa_dynarray *array); -- -+void * const *pa_dynarray_get_raw_array(pa_dynarray *array); - #endif diff --git a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0022-device-port-Add-pa_device_port.active.patch b/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0022-device-port-Add-pa_device_port.active.patch deleted file mode 100644 index 4a8143f61..000000000 --- a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0022-device-port-Add-pa_device_port.active.patch +++ /dev/null @@ -1,198 +0,0 @@ ---- a/src/pulsecore/core.h 2016-04-13 16:38:56.392014788 +0200 -+++ b/src/pulsecore/core.h 2016-04-13 16:41:50.331014498 +0200 -@@ -125,6 +125,7 @@ - PA_CORE_HOOK_CARD_PROFILE_ADDED, - PA_CORE_HOOK_CARD_PROFILE_AVAILABLE_CHANGED, - PA_CORE_HOOK_PORT_AVAILABLE_CHANGED, -+ PA_CORE_HOOK_PORT_ACTIVE_CHANGED, - PA_CORE_HOOK_PORT_LATENCY_OFFSET_CHANGED, - PA_CORE_HOOK_MAX - } pa_core_hook_t; ---- a/src/pulsecore/device-port.c 2016-04-13 16:39:37.411014719 +0200 -+++ b/src/pulsecore/device-port.c 2016-04-13 17:06:47.393011999 +0200 -@@ -175,6 +175,21 @@ - pa_hook_fire(&core->hooks[PA_CORE_HOOK_PORT_LATENCY_OFFSET_CHANGED], p); - } - -+void pa_device_port_active_changed(pa_device_port *port, bool new_active) { -+ bool old_active; -+ -+ pa_assert(port); -+ -+ old_active = port->active; -+ -+ if (new_active == old_active) -+ return; -+ -+ port->active = new_active; -+ pa_log_debug("Port %s %s.", port->name, new_active ? "activated" : "deactivated"); -+ pa_hook_fire(&port->core->hooks[PA_CORE_HOOK_PORT_ACTIVE_CHANGED], port); -+} -+ - pa_device_port *pa_device_port_find_best(pa_hashmap *ports) - { - void *state; ---- a/src/pulsecore/device-port.h 2016-04-13 16:39:51.603014696 +0200 -+++ b/src/pulsecore/device-port.h 2016-04-13 17:07:12.649011957 +0200 -@@ -46,6 +46,7 @@ - - unsigned priority; - pa_available_t available; /* PA_AVAILABLE_UNKNOWN, PA_AVAILABLE_NO or PA_AVAILABLE_YES */ -+ bool active; - - pa_proplist *proplist; - pa_hashmap *profiles; /* Does not own the profiles */ ---- a/src/pulsecore/sink.c 2016-04-13 16:40:11.131014663 +0200 -+++ b/src/pulsecore/sink.c 2016-04-13 17:14:30.963011225 +0200 -@@ -658,6 +658,9 @@ - else - pa_assert_se(sink_set_state(s, PA_SINK_IDLE) == 0); - -+ if (s->active_port) -+ pa_device_port_active_changed(s->active_port, true); -+ - pa_source_put(s->monitor_source); - - pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_NEW, s->index); -@@ -685,6 +688,9 @@ - if (linked) - pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK], s); - -+ if (s->active_port) -+ pa_device_port_active_changed(s->active_port, false); -+ - if (s->state != PA_SINK_UNLINKED) - pa_namereg_unregister(s->core, s->name); - pa_idxset_remove_by_data(s->core->sinks, s, NULL); -@@ -3297,6 +3303,7 @@ - /* Called from main context */ - int pa_sink_set_port(pa_sink *s, const char *name, bool save) { - pa_device_port *port; -+ pa_device_port *old_port; - int ret; - - pa_sink_assert_ref(s); -@@ -3313,11 +3320,15 @@ - if (!(port = pa_hashmap_get(s->ports, name))) - return -PA_ERR_NOENTITY; - -- if (s->active_port == port) { -+ old_port = s->active_port; -+ -+ if (port == old_port) { - s->save_port = s->save_port || save; - return 0; - } - -+ pa_device_port_active_changed(old_port, false); -+ - if (s->flags & PA_SINK_DEFERRED_VOLUME) { - struct sink_message_set_port msg = { .port = port, .ret = 0 }; - pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_PORT, &msg, 0, NULL) == 0); -@@ -3326,17 +3337,26 @@ - else - ret = s->set_port(s, port); - -- if (ret < 0) -- return -PA_ERR_NOENTITY; -+ if (ret < 0) { -+ pa_log("Failed to set the port of sink %s from %s to %s.", s->name, old_port->name, port->name); -+ -+ /* We don't know the real state of the device, but let's assume that -+ * the old port is still active, because s->active_port is left to -+ * point to the old port anyway. */ -+ pa_device_port_active_changed(old_port, true); -+ -+ return ret; -+ } - - pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); - -- pa_log_info("Changed port of sink %u \"%s\" to %s", s->index, s->name, port->name); -+ pa_log_info("Changed port of sink %u \"%s\" from %s to %s", s->index, s->name, old_port->name, port->name); - - s->active_port = port; - s->save_port = save; - - pa_sink_set_latency_offset(s, s->active_port->latency_offset); -+ pa_device_port_active_changed(port, true); - - pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PORT_CHANGED], s); - ---- a/src/pulsecore/source.c 2016-04-13 16:40:25.290014640 +0200 -+++ b/src/pulsecore/source.c 2016-04-13 17:21:26.051010533 +0200 -@@ -603,6 +603,9 @@ - else - pa_assert_se(source_set_state(s, PA_SOURCE_IDLE) == 0); - -+ if (s->active_port) -+ pa_device_port_active_changed(s->active_port, true); -+ - pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_NEW, s->index); - pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PUT], s); - } -@@ -623,6 +626,9 @@ - if (linked) - pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], s); - -+ if (s->active_port) -+ pa_device_port_active_changed(s->active_port, false); -+ - if (s->state != PA_SOURCE_UNLINKED) - pa_namereg_unregister(s->core, s->name); - pa_idxset_remove_by_data(s->core->sources, s, NULL); -@@ -2576,6 +2582,7 @@ - /* Called from main context */ - int pa_source_set_port(pa_source *s, const char *name, bool save) { - pa_device_port *port; -+ pa_device_port *old_port; - int ret; - - pa_source_assert_ref(s); -@@ -2592,11 +2599,15 @@ - if (!(port = pa_hashmap_get(s->ports, name))) - return -PA_ERR_NOENTITY; - -- if (s->active_port == port) { -+ old_port = s->active_port; -+ -+ if (port == old_port) { - s->save_port = s->save_port || save; - return 0; - } - -+ pa_device_port_active_changed(old_port, false); -+ - if (s->flags & PA_SOURCE_DEFERRED_VOLUME) { - struct source_message_set_port msg = { .port = port, .ret = 0 }; - pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_PORT, &msg, 0, NULL) == 0); -@@ -2605,16 +2616,26 @@ - else - ret = s->set_port(s, port); - -- if (ret < 0) -- return -PA_ERR_NOENTITY; -+ if (ret < 0) { -+ pa_log("Failed to set the port of sink %s from %s to %s.", s->name, old_port->name, port->name); -+ -+ /* We don't know the real state of the device, but let's assume that -+ * the old port is still active, because s->active_port is left to -+ * point to the old port anyway. */ -+ pa_device_port_active_changed(old_port, true); -+ -+ return ret; -+ } - - pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); - -- pa_log_info("Changed port of source %u \"%s\" to %s", s->index, s->name, port->name); -+ pa_log_info("Changed port of source %u \"%s\" from %s to %s", s->index, s->name, old_port->name, port->name); - - s->active_port = port; - s->save_port = save; - -+ pa_device_port_active_changed(port, true); -+ - pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PORT_CHANGED], s); - - return 0; diff --git a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0030-volume-api-Add-libvolume-api.patch b/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0030-volume-api-Add-libvolume-api.patch deleted file mode 100644 index b904ac315..000000000 --- a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0030-volume-api-Add-libvolume-api.patch +++ /dev/null @@ -1,6118 +0,0 @@ -From 0223ac3e092249c792bedcab2bf5dbaec443f960 Mon Sep 17 00:00:00 2001 -From: Tanu Kaskinen -Date: Wed, 21 May 2014 11:51:27 +0300 -Subject: [PATCH 1/1] volume-api: Add libvolume-api.so - -This library implements the "core" of the new volume system, which -will be used by several modules. - -Change-Id: Ib25ada1392e83237a3908e6064ee0ad6dff7afaf -Signed-off-by: Jaska Uimonen ---- - Makefile.am | 3 + - src/Makefile.am | 19 +- - src/map-file | 15 + - src/modules/volume-api/audio-group.c | 448 +++++++++++++ - src/modules/volume-api/audio-group.h | 85 +++ - src/modules/volume-api/binding.c | 386 +++++++++++ - src/modules/volume-api/binding.h | 128 ++++ - src/modules/volume-api/bvolume.h | 43 ++ - src/modules/volume-api/device-creator.c | 1108 +++++++++++++++++++++++++++++++ - src/modules/volume-api/device-creator.h | 32 + - src/modules/volume-api/device.c | 293 ++++++++ - src/modules/volume-api/device.h | 76 +++ - src/modules/volume-api/mute-control.c | 306 +++++++++ - src/modules/volume-api/mute-control.h | 102 +++ - src/modules/volume-api/sstream.c | 366 ++++++++++ - src/modules/volume-api/sstream.h | 108 +++ - src/modules/volume-api/stream-creator.c | 691 +++++++++++++++++++ - src/modules/volume-api/stream-creator.h | 32 + - src/modules/volume-api/volume-api.c | 647 ++++++++++++++++++ - src/modules/volume-api/volume-api.h | 163 +++++ - src/modules/volume-api/volume-control.c | 363 ++++++++++ - src/modules/volume-api/volume-control.h | 112 ++++ - src/pulse/ext-volume-api.c | 275 ++++++++ - src/pulse/ext-volume-api.h | 68 ++ - 24 files changed, 5868 insertions(+), 1 deletion(-) - create mode 100644 src/modules/volume-api/audio-group.c - create mode 100644 src/modules/volume-api/audio-group.h - create mode 100644 src/modules/volume-api/binding.c - create mode 100644 src/modules/volume-api/binding.h - create mode 100644 src/modules/volume-api/bvolume.h - create mode 100644 src/modules/volume-api/device-creator.c - create mode 100644 src/modules/volume-api/device-creator.h - create mode 100644 src/modules/volume-api/device.c - create mode 100644 src/modules/volume-api/device.h - create mode 100644 src/modules/volume-api/mute-control.c - create mode 100644 src/modules/volume-api/mute-control.h - create mode 100644 src/modules/volume-api/sstream.c - create mode 100644 src/modules/volume-api/sstream.h - create mode 100644 src/modules/volume-api/stream-creator.c - create mode 100644 src/modules/volume-api/stream-creator.h - create mode 100644 src/modules/volume-api/volume-api.c - create mode 100644 src/modules/volume-api/volume-api.h - create mode 100644 src/modules/volume-api/volume-control.c - create mode 100644 src/modules/volume-api/volume-control.h - create mode 100644 src/pulse/ext-volume-api.c - create mode 100644 src/pulse/ext-volume-api.h - -diff --git a/Makefile.am b/Makefile.am -index 9431d4a..cf4a648 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -57,6 +57,9 @@ - moduledevinternal_DATA = src/pulse/internal.h src/pulse/client-conf.h src/pulse/fork-detect.h - moduledevinternaldir = $(includedir)/pulsemodule/pulse - -+moduledevvolumeapi_DATA = $(top_srcdir)/src/modules/volume-api/*.h -+moduledevvolumeapidir = $(includedir)/pulsemodule/modules/volume-api -+ - if HAVE_GLIB20 - pkgconfig_DATA += \ - libpulse-mainloop-glib.pc -diff --git a/src/Makefile.am b/src/Makefile.am -index 22b9b81..bc41dca 100644 ---- a/src/Makefile.am 2016-04-13 15:51:34.439019531 +0200 -+++ b/src/Makefile.am 2016-04-13 15:53:03.721019382 +0200 -@@ -792,6 +792,7 @@ - pulse/ext-device-manager.h \ - pulse/ext-device-restore.h \ - pulse/ext-stream-restore.h \ -+ pulse/ext-volume-api.h \ - pulse/format.h \ - pulse/gccmacro.h \ - pulse/introspect.h \ -@@ -838,6 +839,7 @@ - pulse/ext-device-manager.c pulse/ext-device-manager.h \ - pulse/ext-device-restore.c pulse/ext-device-restore.h \ - pulse/ext-stream-restore.c pulse/ext-stream-restore.h \ -+ pulse/ext-volume-api.c pulse/ext-volume-api.h \ - pulse/format.c pulse/format.h \ - pulse/gccmacro.h \ - pulse/internal.h \ -@@ -1018,7 +1020,8 @@ modlibexec_LTLIBRARIES = \ - libprotocol-cli.la \ - libprotocol-simple.la \ - libprotocol-http.la \ -- libprotocol-native.la -+ libprotocol-native.la \ -+ libvolume-api.la - - if HAVE_WEBRTC - modlibexec_LTLIBRARIES += libwebrtc-util.la -@@ -1065,6 +1068,20 @@ libprotocol_native_la_CFLAGS += $(DBUS_CFLAGS) - libprotocol_native_la_LIBADD += $(DBUS_LIBS) - endif - -+libvolume_api_la_SOURCES = \ -+ modules/volume-api/audio-group.c modules/volume-api/audio-group.h \ -+ modules/volume-api/binding.c modules/volume-api/binding.h \ -+ modules/volume-api/bvolume.h \ -+ modules/volume-api/device.c modules/volume-api/device.h \ -+ modules/volume-api/device-creator.c modules/volume-api/device-creator.h \ -+ modules/volume-api/mute-control.c modules/volume-api/mute-control.h \ -+ modules/volume-api/sstream.c modules/volume-api/sstream.h \ -+ modules/volume-api/stream-creator.c modules/volume-api/stream-creator.h \ -+ modules/volume-api/volume-api.c modules/volume-api/volume-api.h \ -+ modules/volume-api/volume-control.c modules/volume-api/volume-control.h -+libvolume_api_la_LDFLAGS = $(AM_LDFLAGS) -avoid-version -+libvolume_api_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINOR@.la libpulsecommon-@PA_MAJORMINOR@.la libpulse.la -+ - if HAVE_ESOUND - libprotocol_esound_la_SOURCES = pulsecore/protocol-esound.c pulsecore/protocol-esound.h pulsecore/esound.h - libprotocol_esound_la_LDFLAGS = $(AM_LDFLAGS) -avoid-version -diff --git a/src/map-file b/src/map-file -index fbf3f22..1f64a2f 100644 ---- a/src/map-file -+++ b/src/map-file -@@ -172,6 +172,21 @@ - pa_ext_stream_restore_subscribe; - pa_ext_stream_restore_test; - pa_ext_stream_restore_write; -+pa_ext_volume_api_balance_valid; -+pa_ext_volume_api_bvolume_copy_balance; -+pa_ext_volume_api_bvolume_get_left_right_balance; -+pa_ext_volume_api_bvolume_get_rear_front_balance; -+pa_ext_volume_api_bvolume_equal; -+pa_ext_volume_api_bvolume_from_cvolume; -+pa_ext_volume_api_bvolume_init_invalid; -+pa_ext_volume_api_bvolume_init_mono; -+pa_ext_volume_api_bvolume_remap; -+pa_ext_volume_api_bvolume_reset_balance; -+pa_ext_volume_api_bvolume_set_left_right_balance; -+pa_ext_volume_api_bvolume_set_rear_front_balance; -+pa_ext_volume_api_bvolume_snprint_balance; -+pa_ext_volume_api_bvolume_to_cvolume; -+pa_ext_volume_api_bvolume_valid; - pa_format_info_copy; - pa_format_info_free; - pa_format_info_from_string; -diff --git a/src/modules/volume-api/audio-group.c b/src/modules/volume-api/audio-group.c -new file mode 100644 -index 0000000..76bfa69 ---- /dev/null -+++ b/src/modules/volume-api/audio-group.c -@@ -0,0 +1,448 @@ -+/*** -+ This file is part of PulseAudio. -+ -+ Copyright 2014 Intel Corporation -+ -+ PulseAudio is free software; you can redistribute it and/or modify -+ it under the terms of the GNU Lesser General Public License as published -+ by the Free Software Foundation; either version 2.1 of the License, -+ or (at your option) any later version. -+ -+ PulseAudio 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 Lesser General Public License -+ along with PulseAudio; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ USA. -+***/ -+ -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ -+#include "audio-group.h" -+ -+#include -+ -+#include -+ -+int pa_audio_group_new(pa_volume_api *api, const char *name, const char *description, pa_audio_group **group) { -+ pa_audio_group *group_local; -+ int r; -+ -+ pa_assert(api); -+ pa_assert(name); -+ pa_assert(description); -+ pa_assert(group); -+ -+ group_local = pa_xnew0(pa_audio_group, 1); -+ group_local->volume_api = api; -+ group_local->index = pa_volume_api_allocate_audio_group_index(api); -+ -+ r = pa_volume_api_register_name(api, name, true, &group_local->name); -+ if (r < 0) -+ goto fail; -+ -+ group_local->description = pa_xstrdup(description); -+ group_local->proplist = pa_proplist_new(); -+ group_local->volume_streams = pa_hashmap_new(NULL, NULL); -+ group_local->mute_streams = pa_hashmap_new(NULL, NULL); -+ -+ *group = group_local; -+ -+ return 0; -+ -+fail: -+ pa_audio_group_free(group_local); -+ -+ return r; -+} -+ -+void pa_audio_group_put(pa_audio_group *group) { -+ const char *prop_key; -+ void *state = NULL; -+ -+ pa_assert(group); -+ -+ pa_volume_api_add_audio_group(group->volume_api, group); -+ -+ group->linked = true; -+ -+ pa_log_debug("Created audio group #%u.", group->index); -+ pa_log_debug(" Name: %s", group->name); -+ pa_log_debug(" Description: %s", group->description); -+ pa_log_debug(" Volume control: %s", group->volume_control ? group->volume_control->name : "(unset)"); -+ pa_log_debug(" Mute control: %s", group->mute_control ? group->mute_control->name : "(unset)"); -+ pa_log_debug(" Properties:"); -+ -+ while ((prop_key = pa_proplist_iterate(group->proplist, &state))) -+ pa_log_debug(" %s = %s", prop_key, pa_strnull(pa_proplist_gets(group->proplist, prop_key))); -+ -+ pa_hook_fire(&group->volume_api->hooks[PA_VOLUME_API_HOOK_AUDIO_GROUP_PUT], group); -+} -+ -+void pa_audio_group_unlink(pa_audio_group *group) { -+ pas_stream *stream; -+ -+ pa_assert(group); -+ -+ if (group->unlinked) { -+ pa_log_debug("Unlinking audio group %s (already unlinked, this is a no-op).", group->name); -+ return; -+ } -+ -+ group->unlinked = true; -+ -+ pa_log_debug("Unlinking audio group %s.", group->name); -+ -+ if (group->linked) -+ pa_hook_fire(&group->volume_api->hooks[PA_VOLUME_API_HOOK_AUDIO_GROUP_UNLINK], group); -+ -+ pa_volume_api_remove_audio_group(group->volume_api, group); -+ -+ while ((stream = pa_hashmap_first(group->mute_streams))) -+ pas_stream_set_audio_group_for_mute(stream, NULL); -+ -+ while ((stream = pa_hashmap_first(group->volume_streams))) -+ pas_stream_set_audio_group_for_volume(stream, NULL); -+ -+ if (group->mute_control_binding) { -+ pa_binding_free(group->mute_control_binding); -+ group->mute_control_binding = NULL; -+ } -+ -+ if (group->volume_control_binding) { -+ pa_binding_free(group->volume_control_binding); -+ group->volume_control_binding = NULL; -+ } -+ -+ pa_audio_group_set_have_own_mute_control(group, false); -+ pa_audio_group_set_have_own_volume_control(group, false); -+ -+ if (group->mute_control) { -+ pa_mute_control_remove_audio_group(group->mute_control, group); -+ group->mute_control = NULL; -+ } -+ -+ if (group->volume_control) { -+ pa_volume_control_remove_audio_group(group->volume_control, group); -+ group->volume_control = NULL; -+ } -+} -+ -+void pa_audio_group_free(pa_audio_group *group) { -+ pa_assert(group); -+ -+ if (!group->unlinked) -+ pa_audio_group_unlink(group); -+ -+ if (group->mute_streams) -+ pa_hashmap_free(group->mute_streams); -+ -+ if (group->volume_streams) -+ pa_hashmap_free(group->volume_streams); -+ -+ if (group->proplist) -+ pa_proplist_free(group->proplist); -+ -+ pa_xfree(group->description); -+ -+ if (group->name) -+ pa_volume_api_unregister_name(group->volume_api, group->name); -+ -+ pa_xfree(group); -+} -+ -+const char *pa_audio_group_get_name(pa_audio_group *group) { -+ pa_assert(group); -+ -+ return group->name; -+} -+ -+static int volume_control_set_volume_cb(pa_volume_control *control, const pa_bvolume *volume, bool set_volume, -+ bool set_balance) { -+ pa_audio_group *group; -+ pas_stream *stream; -+ void *state; -+ -+ pa_assert(control); -+ pa_assert(volume); -+ -+ group = control->userdata; -+ -+ PA_HASHMAP_FOREACH(stream, group->volume_streams, state) { -+ if (stream->own_volume_control) -+ pa_volume_control_set_volume(stream->own_volume_control, volume, set_volume, set_balance); -+ } -+ -+ return 0; -+} -+ -+static void volume_control_set_initial_volume_cb(pa_volume_control *control) { -+ pa_audio_group *group; -+ pas_stream *stream; -+ void *state; -+ -+ pa_assert(control); -+ -+ group = control->userdata; -+ -+ PA_HASHMAP_FOREACH(stream, group->volume_streams, state) { -+ if (stream->own_volume_control) -+ pa_volume_control_set_volume(stream->own_volume_control, &control->volume, true, true); -+ } -+} -+ -+void pa_audio_group_set_have_own_volume_control(pa_audio_group *group, bool have) { -+ pa_assert(group); -+ -+ if (have == group->have_own_volume_control) -+ return; -+ -+ if (have) { -+ pa_bvolume initial_volume; -+ -+ if (group->volume_api->core->flat_volumes) -+ /* Usually the initial volume should get overridden by some module -+ * that manages audio group volume levels, but if there's no such -+ * module, let's try to avoid too high volume in flat volume -+ * mode. */ -+ pa_bvolume_init_mono(&initial_volume, 0.3 * PA_VOLUME_NORM); -+ else -+ pa_bvolume_init_mono(&initial_volume, PA_VOLUME_NORM); -+ -+ pa_assert(!group->own_volume_control); -+ group->own_volume_control = pa_volume_control_new(group->volume_api, "audio-group-volume-control", -+ group->description, false, false); -+ pa_volume_control_set_owner_audio_group(group->own_volume_control, group); -+ group->own_volume_control->set_volume = volume_control_set_volume_cb; -+ group->own_volume_control->userdata = group; -+ pa_volume_control_put(group->own_volume_control, &initial_volume, volume_control_set_initial_volume_cb); -+ } else { -+ pa_volume_control_free(group->own_volume_control); -+ group->own_volume_control = NULL; -+ } -+ -+ group->have_own_volume_control = have; -+} -+ -+static int mute_control_set_mute_cb(pa_mute_control *control, bool mute) { -+ pa_audio_group *group; -+ pas_stream *stream; -+ void *state; -+ -+ pa_assert(control); -+ -+ group = control->userdata; -+ -+ PA_HASHMAP_FOREACH(stream, group->mute_streams, state) { -+ if (stream->own_mute_control) -+ pa_mute_control_set_mute(stream->own_mute_control, mute); -+ } -+ -+ return 0; -+} -+ -+static void mute_control_set_initial_mute_cb(pa_mute_control *control) { -+ pa_audio_group *group; -+ pas_stream *stream; -+ void *state; -+ -+ pa_assert(control); -+ -+ group = control->userdata; -+ -+ PA_HASHMAP_FOREACH(stream, group->mute_streams, state) { -+ if (stream->own_mute_control) -+ pa_mute_control_set_mute(stream->own_mute_control, control->mute); -+ } -+} -+ -+void pa_audio_group_set_have_own_mute_control(pa_audio_group *group, bool have) { -+ pa_assert(group); -+ -+ if (have == group->have_own_mute_control) -+ return; -+ -+ group->have_own_mute_control = have; -+ -+ if (have) { -+ pa_assert(!group->own_mute_control); -+ group->own_mute_control = pa_mute_control_new(group->volume_api, "audio-group-mute-control", group->description); -+ pa_mute_control_set_owner_audio_group(group->own_mute_control, group); -+ group->own_mute_control->set_mute = mute_control_set_mute_cb; -+ group->own_mute_control->userdata = group; -+ pa_mute_control_put(group->own_mute_control, false, true, mute_control_set_initial_mute_cb); -+ } else { -+ pa_mute_control_free(group->own_mute_control); -+ group->own_mute_control = NULL; -+ } -+} -+ -+static void set_volume_control_internal(pa_audio_group *group, pa_volume_control *control) { -+ pa_volume_control *old_control; -+ -+ pa_assert(group); -+ -+ old_control = group->volume_control; -+ -+ if (control == old_control) -+ return; -+ -+ if (old_control) -+ pa_volume_control_remove_audio_group(old_control, group); -+ -+ group->volume_control = control; -+ -+ if (control) -+ pa_volume_control_add_audio_group(control, group); -+ -+ if (!group->linked || group->unlinked) -+ return; -+ -+ pa_log_debug("The volume control of audio group %s changed from %s to %s.", group->name, -+ old_control ? old_control->name : "(unset)", control ? control->name : "(unset)"); -+ -+ pa_hook_fire(&group->volume_api->hooks[PA_VOLUME_API_HOOK_AUDIO_GROUP_VOLUME_CONTROL_CHANGED], group); -+} -+ -+void pa_audio_group_set_volume_control(pa_audio_group *group, pa_volume_control *control) { -+ pa_assert(group); -+ -+ if (group->volume_control_binding) { -+ pa_binding_free(group->volume_control_binding); -+ group->volume_control_binding = NULL; -+ } -+ -+ set_volume_control_internal(group, control); -+} -+ -+static void set_mute_control_internal(pa_audio_group *group, pa_mute_control *control) { -+ pa_mute_control *old_control; -+ -+ pa_assert(group); -+ -+ old_control = group->mute_control; -+ -+ if (control == old_control) -+ return; -+ -+ if (old_control) -+ pa_mute_control_remove_audio_group(old_control, group); -+ -+ group->mute_control = control; -+ -+ if (control) -+ pa_mute_control_add_audio_group(control, group); -+ -+ if (!group->linked || group->unlinked) -+ return; -+ -+ pa_log_debug("The mute control of audio group %s changed from %s to %s.", group->name, -+ old_control ? old_control->name : "(unset)", control ? control->name : "(unset)"); -+ -+ pa_hook_fire(&group->volume_api->hooks[PA_VOLUME_API_HOOK_AUDIO_GROUP_MUTE_CONTROL_CHANGED], group); -+} -+ -+void pa_audio_group_set_mute_control(pa_audio_group *group, pa_mute_control *control) { -+ pa_assert(group); -+ -+ if (group->mute_control_binding) { -+ pa_binding_free(group->mute_control_binding); -+ group->mute_control_binding = NULL; -+ } -+ -+ set_mute_control_internal(group, control); -+} -+ -+void pa_audio_group_bind_volume_control(pa_audio_group *group, pa_binding_target_info *target_info) { -+ pa_binding_owner_info owner_info = { -+ .userdata = group, -+ .set_value = (pa_binding_set_value_cb_t) set_volume_control_internal, -+ }; -+ -+ pa_assert(group); -+ pa_assert(target_info); -+ -+ if (group->volume_control_binding) -+ pa_binding_free(group->volume_control_binding); -+ -+ group->volume_control_binding = pa_binding_new(group->volume_api, &owner_info, target_info); -+} -+ -+void pa_audio_group_bind_mute_control(pa_audio_group *group, pa_binding_target_info *target_info) { -+ pa_binding_owner_info owner_info = { -+ .userdata = group, -+ .set_value = (pa_binding_set_value_cb_t) set_mute_control_internal, -+ }; -+ -+ pa_assert(group); -+ pa_assert(target_info); -+ -+ if (group->mute_control_binding) -+ pa_binding_free(group->mute_control_binding); -+ -+ group->mute_control_binding = pa_binding_new(group->volume_api, &owner_info, target_info); -+} -+ -+void pa_audio_group_add_volume_stream(pa_audio_group *group, pas_stream *stream) { -+ pa_assert(group); -+ pa_assert(stream); -+ -+ pa_assert_se(pa_hashmap_put(group->volume_streams, stream, stream) >= 0); -+ -+ if (stream->own_volume_control && group->own_volume_control) -+ pa_volume_control_set_volume(stream->own_volume_control, &group->own_volume_control->volume, true, true); -+ -+ pa_log_debug("Stream %s added to audio group %s (volume).", stream->name, group->name); -+} -+ -+void pa_audio_group_remove_volume_stream(pa_audio_group *group, pas_stream *stream) { -+ pa_assert(group); -+ pa_assert(stream); -+ -+ pa_assert_se(pa_hashmap_remove(group->volume_streams, stream)); -+ -+ pa_log_debug("Stream %s removed from audio group %s (volume).", stream->name, group->name); -+} -+ -+void pa_audio_group_add_mute_stream(pa_audio_group *group, pas_stream *stream) { -+ pa_assert(group); -+ pa_assert(stream); -+ -+ pa_assert_se(pa_hashmap_put(group->mute_streams, stream, stream) >= 0); -+ -+ if (stream->own_mute_control && group->own_mute_control) -+ pa_mute_control_set_mute(stream->own_mute_control, group->own_mute_control->mute); -+ -+ pa_log_debug("Stream %s added to audio group %s (mute).", stream->name, group->name); -+} -+ -+void pa_audio_group_remove_mute_stream(pa_audio_group *group, pas_stream *stream) { -+ pa_assert(group); -+ pa_assert(stream); -+ -+ pa_assert_se(pa_hashmap_remove(group->mute_streams, stream)); -+ -+ pa_log_debug("Stream %s removed from audio group %s (mute).", stream->name, group->name); -+} -+ -+pa_binding_target_type *pa_audio_group_create_binding_target_type(pa_volume_api *api) { -+ pa_binding_target_type *type; -+ -+ pa_assert(api); -+ -+ type = pa_binding_target_type_new(PA_AUDIO_GROUP_BINDING_TARGET_TYPE, api->audio_groups, -+ &api->hooks[PA_VOLUME_API_HOOK_AUDIO_GROUP_PUT], -+ &api->hooks[PA_VOLUME_API_HOOK_AUDIO_GROUP_UNLINK], -+ (pa_binding_target_type_get_name_cb_t) pa_audio_group_get_name); -+ pa_binding_target_type_add_field(type, PA_AUDIO_GROUP_BINDING_TARGET_FIELD_VOLUME_CONTROL, -+ PA_BINDING_CALCULATE_FIELD_OFFSET(pa_audio_group, volume_control)); -+ pa_binding_target_type_add_field(type, PA_AUDIO_GROUP_BINDING_TARGET_FIELD_MUTE_CONTROL, -+ PA_BINDING_CALCULATE_FIELD_OFFSET(pa_audio_group, mute_control)); -+ -+ return type; -+} -diff --git a/src/modules/volume-api/audio-group.h b/src/modules/volume-api/audio-group.h -new file mode 100644 -index 0000000..41591ba ---- /dev/null -+++ b/src/modules/volume-api/audio-group.h -@@ -0,0 +1,85 @@ -+#ifndef fooaudiogrouphfoo -+#define fooaudiogrouphfoo -+ -+/*** -+ This file is part of PulseAudio. -+ -+ Copyright 2014 Intel Corporation -+ -+ PulseAudio is free software; you can redistribute it and/or modify -+ it under the terms of the GNU Lesser General Public License as published -+ by the Free Software Foundation; either version 2.1 of the License, -+ or (at your option) any later version. -+ -+ PulseAudio 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 Lesser General Public License -+ along with PulseAudio; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ USA. -+***/ -+ -+#include -+#include -+#include -+ -+#include -+ -+#include -+ -+typedef struct pa_audio_group pa_audio_group; -+ -+#define PA_AUDIO_GROUP_BINDING_TARGET_TYPE "AudioGroup" -+#define PA_AUDIO_GROUP_BINDING_TARGET_FIELD_VOLUME_CONTROL "volume_control" -+#define PA_AUDIO_GROUP_BINDING_TARGET_FIELD_MUTE_CONTROL "mute_control" -+ -+struct pa_audio_group { -+ pa_volume_api *volume_api; -+ uint32_t index; -+ const char *name; -+ char *description; -+ pa_proplist *proplist; -+ pa_volume_control *volume_control; -+ pa_mute_control *mute_control; -+ bool have_own_volume_control; -+ bool have_own_mute_control; -+ pa_volume_control *own_volume_control; -+ pa_mute_control *own_mute_control; -+ -+ pa_binding *volume_control_binding; -+ pa_binding *mute_control_binding; -+ pa_hashmap *volume_streams; /* pas_stream -> pas_stream (hashmap-as-a-set) */ -+ pa_hashmap *mute_streams; /* pas_stream -> pas_stream (hashmap-as-a-set) */ -+ -+ bool linked; -+ bool unlinked; -+}; -+ -+int pa_audio_group_new(pa_volume_api *api, const char *name, const char *description, pa_audio_group **group); -+void pa_audio_group_put(pa_audio_group *group); -+void pa_audio_group_unlink(pa_audio_group *group); -+void pa_audio_group_free(pa_audio_group *group); -+ -+const char *pa_audio_group_get_name(pa_audio_group *group); -+ -+/* Called by policy modules. */ -+void pa_audio_group_set_have_own_volume_control(pa_audio_group *group, bool have); -+void pa_audio_group_set_have_own_mute_control(pa_audio_group *group, bool have); -+void pa_audio_group_set_volume_control(pa_audio_group *group, pa_volume_control *control); -+void pa_audio_group_set_mute_control(pa_audio_group *group, pa_mute_control *control); -+void pa_audio_group_bind_volume_control(pa_audio_group *group, pa_binding_target_info *target_info); -+void pa_audio_group_bind_mute_control(pa_audio_group *group, pa_binding_target_info *target_info); -+ -+/* Called from sstream.c only. */ -+void pa_audio_group_add_volume_stream(pa_audio_group *group, pas_stream *stream); -+void pa_audio_group_remove_volume_stream(pa_audio_group *group, pas_stream *stream); -+void pa_audio_group_add_mute_stream(pa_audio_group *group, pas_stream *stream); -+void pa_audio_group_remove_mute_stream(pa_audio_group *group, pas_stream *stream); -+ -+/* Called from volume-api.c only. */ -+pa_binding_target_type *pa_audio_group_create_binding_target_type(pa_volume_api *api); -+ -+#endif -diff --git a/src/modules/volume-api/binding.c b/src/modules/volume-api/binding.c -new file mode 100644 -index 0000000..6e73119 ---- /dev/null -+++ b/src/modules/volume-api/binding.c -@@ -0,0 +1,386 @@ -+/*** -+ This file is part of PulseAudio. -+ -+ Copyright 2014 Intel Corporation -+ -+ PulseAudio is free software; you can redistribute it and/or modify -+ it under the terms of the GNU Lesser General Public License as published -+ by the Free Software Foundation; either version 2.1 of the License, -+ or (at your option) any later version. -+ -+ PulseAudio 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 Lesser General Public License -+ along with PulseAudio; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ USA. -+***/ -+ -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ -+#include "binding.h" -+ -+#include -+#include -+ -+#include -+#include -+ -+struct field_entry { -+ char *name; -+ size_t offset; -+}; -+ -+static void set_target_type(pa_binding *binding, pa_binding_target_type *type); -+static void set_target_object(pa_binding *binding, void *object); -+ -+pa_binding_owner_info *pa_binding_owner_info_new(pa_binding_set_value_cb_t set_value, void *userdata) { -+ pa_binding_owner_info *info; -+ -+ pa_assert(set_value); -+ -+ info = pa_xnew0(pa_binding_owner_info, 1); -+ info->set_value = set_value; -+ info->userdata = userdata; -+ -+ return info; -+} -+ -+pa_binding_owner_info *pa_binding_owner_info_copy(const pa_binding_owner_info *info) { -+ pa_assert(info); -+ -+ return pa_binding_owner_info_new(info->set_value, info->userdata); -+} -+ -+void pa_binding_owner_info_free(pa_binding_owner_info *info) { -+ pa_assert(info); -+ -+ pa_xfree(info); -+} -+ -+pa_binding_target_info *pa_binding_target_info_new(const char *type, const char *name, const char *field) { -+ pa_binding_target_info *info; -+ -+ pa_assert(type); -+ pa_assert(name); -+ pa_assert(field); -+ -+ info = pa_xnew0(pa_binding_target_info, 1); -+ info->type = pa_xstrdup(type); -+ info->name = pa_xstrdup(name); -+ info->field = pa_xstrdup(field); -+ -+ return info; -+} -+ -+int pa_binding_target_info_new_from_string(const char *str, const char *field, pa_binding_target_info **info) { -+ const char *colon; -+ char *type = NULL; -+ char *name = NULL; -+ -+ pa_assert(str); -+ pa_assert(field); -+ pa_assert(info); -+ -+ if (!pa_startswith(str, "bind:")) -+ goto fail; -+ -+ colon = strchr(str + 5, ':'); -+ if (!colon) -+ goto fail; -+ -+ type = pa_xstrndup(str + 5, colon - (str + 5)); -+ -+ if (!*type) -+ goto fail; -+ -+ name = pa_xstrdup(colon + 1); -+ -+ if (!*name) -+ goto fail; -+ -+ *info = pa_binding_target_info_new(type, name, field); -+ pa_xfree(name); -+ pa_xfree(type); -+ -+ return 0; -+ -+fail: -+ pa_log("Invalid binding target: %s", str); -+ pa_xfree(name); -+ pa_xfree(type); -+ -+ return -PA_ERR_INVALID; -+} -+ -+pa_binding_target_info *pa_binding_target_info_copy(const pa_binding_target_info *info) { -+ pa_assert(info); -+ -+ return pa_binding_target_info_new(info->type, info->name, info->field); -+} -+ -+void pa_binding_target_info_free(pa_binding_target_info *info) { -+ pa_assert(info); -+ -+ pa_xfree(info->field); -+ pa_xfree(info->name); -+ pa_xfree(info->type); -+ pa_xfree(info); -+} -+ -+static void field_entry_free(struct field_entry *entry) { -+ pa_assert(entry); -+ -+ pa_xfree(entry->name); -+ pa_xfree(entry); -+} -+ -+pa_binding_target_type *pa_binding_target_type_new(const char *name, pa_hashmap *objects, pa_hook *put_hook, -+ pa_hook *unlink_hook, pa_binding_target_type_get_name_cb_t get_name) { -+ pa_binding_target_type *type; -+ -+ pa_assert(name); -+ pa_assert(objects); -+ pa_assert(put_hook); -+ pa_assert(unlink_hook); -+ pa_assert(get_name); -+ -+ type = pa_xnew0(pa_binding_target_type, 1); -+ type->name = pa_xstrdup(name); -+ type->objects = objects; -+ type->put_hook = put_hook; -+ type->unlink_hook = unlink_hook; -+ type->get_name = get_name; -+ type->fields = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, (pa_free_cb_t) field_entry_free); -+ -+ return type; -+} -+ -+void pa_binding_target_type_free(pa_binding_target_type *type) { -+ pa_assert(type); -+ -+ if (type->fields) -+ pa_hashmap_free(type->fields); -+ -+ pa_xfree(type->name); -+ pa_xfree(type); -+} -+ -+void pa_binding_target_type_add_field(pa_binding_target_type *type, const char *name, size_t offset) { -+ struct field_entry *entry; -+ -+ pa_assert(type); -+ pa_assert(name); -+ -+ entry = pa_xnew0(struct field_entry, 1); -+ entry->name = pa_xstrdup(name); -+ entry->offset = offset; -+ -+ pa_assert_se(pa_hashmap_put(type->fields, entry->name, entry) >= 0); -+} -+ -+int pa_binding_target_type_get_field_offset(pa_binding_target_type *type, const char *field, size_t *offset) { -+ struct field_entry *entry; -+ -+ pa_assert(type); -+ pa_assert(field); -+ pa_assert(offset); -+ -+ entry = pa_hashmap_get(type->fields, field); -+ if (!entry) -+ return -PA_ERR_NOENTITY; -+ -+ *offset = entry->offset; -+ -+ return 0; -+} -+ -+static pa_hook_result_t target_type_added_cb(void *hook_data, void *call_data, void *userdata) { -+ pa_binding_target_type *type = call_data; -+ pa_binding *binding = userdata; -+ -+ pa_assert(type); -+ pa_assert(binding); -+ -+ if (!pa_streq(type->name, binding->target_info->type)) -+ return PA_HOOK_OK; -+ -+ set_target_type(binding, type); -+ -+ return PA_HOOK_OK; -+} -+ -+static pa_hook_result_t target_type_removed_cb(void *hook_data, void *call_data, void *userdata) { -+ pa_binding_target_type *type = call_data; -+ pa_binding *binding = userdata; -+ -+ pa_assert(type); -+ pa_assert(binding); -+ -+ if (type != binding->target_type) -+ return PA_HOOK_OK; -+ -+ set_target_type(binding, NULL); -+ -+ return PA_HOOK_OK; -+} -+ -+static pa_hook_result_t target_put_cb(void *hook_data, void *call_data, void *userdata) { -+ pa_binding *binding = userdata; -+ -+ pa_assert(call_data); -+ pa_assert(binding); -+ -+ if (!pa_streq(binding->target_type->get_name(call_data), binding->target_info->name)) -+ return PA_HOOK_OK; -+ -+ set_target_object(binding, call_data); -+ -+ return PA_HOOK_OK; -+} -+ -+static pa_hook_result_t target_unlink_cb(void *hook_data, void *call_data, void *userdata) { -+ pa_binding *binding = userdata; -+ -+ pa_assert(call_data); -+ pa_assert(binding); -+ -+ if (call_data != binding->target_object) -+ return PA_HOOK_OK; -+ -+ set_target_object(binding, NULL); -+ -+ return PA_HOOK_OK; -+} -+ -+static void set_target_object(pa_binding *binding, void *object) { -+ pa_assert(binding); -+ -+ binding->target_object = object; -+ -+ if (object) { -+ if (binding->target_put_slot) { -+ pa_hook_slot_free(binding->target_put_slot); -+ binding->target_put_slot = NULL; -+ } -+ -+ if (!binding->target_unlink_slot) -+ binding->target_unlink_slot = pa_hook_connect(binding->target_type->unlink_hook, PA_HOOK_NORMAL, target_unlink_cb, -+ binding); -+ -+ if (binding->target_field_offset_valid) -+ binding->owner_info->set_value(binding->owner_info->userdata, -+ *((void **) (((uint8_t *) object) + binding->target_field_offset))); -+ else -+ binding->owner_info->set_value(binding->owner_info->userdata, NULL); -+ } else { -+ if (binding->target_unlink_slot) { -+ pa_hook_slot_free(binding->target_unlink_slot); -+ binding->target_unlink_slot = NULL; -+ } -+ -+ if (binding->target_type) { -+ if (!binding->target_put_slot) -+ binding->target_put_slot = pa_hook_connect(binding->target_type->put_hook, PA_HOOK_NORMAL, target_put_cb, binding); -+ } else { -+ if (binding->target_put_slot) { -+ pa_hook_slot_free(binding->target_put_slot); -+ binding->target_put_slot = NULL; -+ } -+ } -+ -+ binding->owner_info->set_value(binding->owner_info->userdata, NULL); -+ } -+} -+ -+static void set_target_type(pa_binding *binding, pa_binding_target_type *type) { -+ pa_assert(binding); -+ -+ binding->target_type = type; -+ -+ if (type) { -+ int r; -+ -+ if (binding->target_type_added_slot) { -+ pa_hook_slot_free(binding->target_type_added_slot); -+ binding->target_type_added_slot = NULL; -+ } -+ -+ if (!binding->target_type_removed_slot) -+ binding->target_type_removed_slot = -+ pa_hook_connect(&binding->volume_api->hooks[PA_VOLUME_API_HOOK_BINDING_TARGET_TYPE_REMOVED], -+ PA_HOOK_NORMAL, target_type_removed_cb, binding); -+ -+ r = pa_binding_target_type_get_field_offset(type, binding->target_info->field, &binding->target_field_offset); -+ if (r >= 0) -+ binding->target_field_offset_valid = true; -+ else { -+ pa_log_warn("Reference to non-existing field \"%s\" in binding target type \"%s\".", binding->target_info->field, -+ type->name); -+ binding->target_field_offset_valid = false; -+ } -+ -+ set_target_object(binding, pa_hashmap_get(type->objects, binding->target_info->name)); -+ } else { -+ if (binding->target_type_removed_slot) { -+ pa_hook_slot_free(binding->target_type_removed_slot); -+ binding->target_type_removed_slot = NULL; -+ } -+ -+ if (!binding->target_type_added_slot) -+ binding->target_type_added_slot = -+ pa_hook_connect(&binding->volume_api->hooks[PA_VOLUME_API_HOOK_BINDING_TARGET_TYPE_ADDED], -+ PA_HOOK_NORMAL, target_type_added_cb, binding); -+ -+ binding->target_field_offset_valid = false; -+ -+ set_target_object(binding, NULL); -+ } -+} -+ -+pa_binding *pa_binding_new(pa_volume_api *api, const pa_binding_owner_info *owner_info, -+ const pa_binding_target_info *target_info) { -+ pa_binding *binding; -+ -+ pa_assert(api); -+ pa_assert(owner_info); -+ pa_assert(target_info); -+ -+ binding = pa_xnew0(pa_binding, 1); -+ binding->volume_api = api; -+ binding->owner_info = pa_binding_owner_info_copy(owner_info); -+ binding->target_info = pa_binding_target_info_copy(target_info); -+ -+ set_target_type(binding, pa_hashmap_get(api->binding_target_types, target_info->type)); -+ -+ return binding; -+} -+ -+void pa_binding_free(pa_binding *binding) { -+ pa_assert(binding); -+ -+ if (binding->target_unlink_slot) -+ pa_hook_slot_free(binding->target_unlink_slot); -+ -+ if (binding->target_put_slot) -+ pa_hook_slot_free(binding->target_put_slot); -+ -+ if (binding->target_type_removed_slot) -+ pa_hook_slot_free(binding->target_type_removed_slot); -+ -+ if (binding->target_type_added_slot) -+ pa_hook_slot_free(binding->target_type_added_slot); -+ -+ if (binding->target_info) -+ pa_binding_target_info_free(binding->target_info); -+ -+ if (binding->owner_info) -+ pa_binding_owner_info_free(binding->owner_info); -+ -+ pa_xfree(binding); -+} -diff --git a/src/modules/volume-api/binding.h b/src/modules/volume-api/binding.h -new file mode 100644 -index 0000000..ba4dea8 ---- /dev/null -+++ b/src/modules/volume-api/binding.h -@@ -0,0 +1,128 @@ -+#ifndef foobindinghfoo -+#define foobindinghfoo -+ -+/*** -+ This file is part of PulseAudio. -+ -+ Copyright 2014 Intel Corporation -+ -+ PulseAudio is free software; you can redistribute it and/or modify -+ it under the terms of the GNU Lesser General Public License as published -+ by the Free Software Foundation; either version 2.1 of the License, -+ or (at your option) any later version. -+ -+ PulseAudio 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 Lesser General Public License -+ along with PulseAudio; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ USA. -+***/ -+ -+#include -+ -+typedef struct pa_binding pa_binding; -+typedef struct pa_binding_owner_info pa_binding_owner_info; -+typedef struct pa_binding_target_info pa_binding_target_info; -+typedef struct pa_binding_target_type pa_binding_target_type; -+ -+typedef void (*pa_binding_set_value_cb_t)(void *userdata, void *value); -+ -+struct pa_binding_owner_info { -+ /* This is the object that has the variable that the binding is created -+ * for. */ -+ void *userdata; -+ -+ /* Called when the owner object's value needs to be updated. The userdata -+ * parameter of the callback is the same as the userdata field in this -+ * struct, and the value parameter is the new value for whatever variable -+ * the binding was created for. */ -+ pa_binding_set_value_cb_t set_value; -+}; -+ -+pa_binding_owner_info *pa_binding_owner_info_new(pa_binding_set_value_cb_t set_value, void *userdata); -+pa_binding_owner_info *pa_binding_owner_info_copy(const pa_binding_owner_info *info); -+void pa_binding_owner_info_free(pa_binding_owner_info *info); -+ -+struct pa_binding_target_info { -+ /* The target type name as registered with -+ * pa_binding_target_type_register(). */ -+ char *type; -+ -+ /* The target object name as returned by the get_name callback of -+ * pa_binding_target_type. */ -+ char *name; -+ -+ /* The target field of the target object. */ -+ char *field; -+}; -+ -+pa_binding_target_info *pa_binding_target_info_new(const char *type, const char *name, const char *field); -+ -+/* The string format is "bind:TYPE:NAME". */ -+int pa_binding_target_info_new_from_string(const char *str, const char *field, pa_binding_target_info **info); -+ -+pa_binding_target_info *pa_binding_target_info_copy(const pa_binding_target_info *info); -+void pa_binding_target_info_free(pa_binding_target_info *info); -+ -+typedef const char *(*pa_binding_target_type_get_name_cb_t)(void *object); -+ -+struct pa_binding_target_type { -+ /* Identifier for this target type. */ -+ char *name; -+ -+ /* name -> object. Points directly to some "master" object hashmap, so the -+ * hashmap is not owned by pa_binding_target_type. */ -+ pa_hashmap *objects; -+ -+ /* The hook that notifies of new objects if this target type. The call data -+ * of the hook must be a pointer to the new object (this should be true for -+ * all PUT hooks, so don't worry too much). */ -+ pa_hook *put_hook; -+ -+ /* The hook that notifies of unlinked objects of this target type. The call -+ * data of the hook must be a pointer to the removed object (this should be -+ * true for all UNLINK hooks, so don't worry too much). */ -+ pa_hook *unlink_hook; -+ -+ /* Function for getting the name of an object of this target type. */ -+ pa_binding_target_type_get_name_cb_t get_name; -+ -+ pa_hashmap *fields; -+}; -+ -+pa_binding_target_type *pa_binding_target_type_new(const char *name, pa_hashmap *objects, pa_hook *put_hook, -+ pa_hook *unlink_hook, pa_binding_target_type_get_name_cb_t get_name); -+void pa_binding_target_type_free(pa_binding_target_type *type); -+ -+/* Useful when calling pa_binding_target_type_add_field(). */ -+#define PA_BINDING_CALCULATE_FIELD_OFFSET(type, field) ((size_t) &(((type *) 0)->field)) -+ -+/* Called during the type initialization (right after -+ * pa_binding_target_type_new()). */ -+void pa_binding_target_type_add_field(pa_binding_target_type *type, const char *name, size_t offset); -+ -+int pa_binding_target_type_get_field_offset(pa_binding_target_type *type, const char *field, size_t *offset); -+ -+struct pa_binding { -+ pa_volume_api *volume_api; -+ pa_binding_owner_info *owner_info; -+ pa_binding_target_info *target_info; -+ pa_binding_target_type *target_type; -+ void *target_object; -+ size_t target_field_offset; -+ bool target_field_offset_valid; -+ pa_hook_slot *target_type_added_slot; -+ pa_hook_slot *target_type_removed_slot; -+ pa_hook_slot *target_put_slot; -+ pa_hook_slot *target_unlink_slot; -+}; -+ -+pa_binding *pa_binding_new(pa_volume_api *api, const pa_binding_owner_info *owner_info, -+ const pa_binding_target_info *target_info); -+void pa_binding_free(pa_binding *binding); -+ -+#endif -diff --git a/src/modules/volume-api/bvolume.h b/src/modules/volume-api/bvolume.h -new file mode 100644 -index 0000000..0317fb6 ---- /dev/null -+++ b/src/modules/volume-api/bvolume.h -@@ -0,0 +1,43 @@ -+#ifndef foobvolumehfoo -+#define foobvolumehfoo -+ -+/*** -+ This file is part of PulseAudio. -+ -+ Copyright 2014 Intel Corporation -+ -+ PulseAudio is free software; you can redistribute it and/or modify -+ it under the terms of the GNU Lesser General Public License as published -+ by the Free Software Foundation; either version 2.1 of the License, -+ or (at your option) any later version. -+ -+ PulseAudio 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 Lesser General Public License -+ along with PulseAudio; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ USA. -+***/ -+ -+#include -+ -+typedef pa_ext_volume_api_bvolume pa_bvolume; -+ -+#define pa_balance_valid pa_ext_volume_api_balance_valid -+#define pa_bvolume_valid pa_ext_volume_api_bvolume_valid -+#define pa_bvolume_init_invalid pa_ext_volume_api_bvolume_init_invalid -+#define pa_bvolume_init_mono pa_ext_volume_api_bvolume_init_mono -+#define pa_bvolume_equal pa_ext_volume_api_bvolume_equal -+#define pa_bvolume_from_cvolume pa_ext_volume_api_bvolume_from_cvolume -+#define pa_bvolume_to_cvolume pa_ext_volume_api_bvolume_to_cvolume -+#define pa_bvolume_copy_balance pa_ext_volume_api_bvolume_copy_balance -+#define pa_bvolume_reset_balance pa_ext_volume_api_bvolume_reset_balance -+#define pa_bvolume_remap pa_ext_volume_api_bvolume_remap -+ -+#define PA_BVOLUME_SNPRINT_BALANCE_MAX PA_EXT_VOLUME_API_BVOLUME_SNPRINT_BALANCE_MAX -+#define pa_bvolume_snprint_balance pa_ext_volume_api_bvolume_snprint_balance -+ -+#endif -diff --git a/src/modules/volume-api/device-creator.c b/src/modules/volume-api/device-creator.c -new file mode 100644 -index 0000000..1d912ba ---- /dev/null -+++ b/src/modules/volume-api/device-creator.c -@@ -0,0 +1,1108 @@ -+/*** -+ This file is part of PulseAudio. -+ -+ Copyright 2014 Intel Corporation -+ -+ PulseAudio is free software; you can redistribute it and/or modify -+ it under the terms of the GNU Lesser General Public License as published -+ by the Free Software Foundation; either version 2.1 of the License, -+ or (at your option) any later version. -+ -+ PulseAudio 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 Lesser General Public License -+ along with PulseAudio; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ USA. -+***/ -+ -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ -+#include "device-creator.h" -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+struct pa_device_creator { -+ pa_volume_api *volume_api; -+ pa_hashmap *devices; /* pa_device_port/pa_sink/pa_source -> struct device */ -+ pa_hook_slot *card_put_slot; -+ pa_hook_slot *card_unlink_slot; -+ pa_hook_slot *sink_put_slot; -+ pa_hook_slot *sink_unlink_slot; -+ pa_hook_slot *source_put_slot; -+ pa_hook_slot *source_unlink_slot; -+}; -+ -+enum device_type { -+ DEVICE_TYPE_PORT, -+ DEVICE_TYPE_PORT_MONITOR, -+ DEVICE_TYPE_SINK, -+ DEVICE_TYPE_SOURCE, -+}; -+ -+struct device_volume_control { -+ struct device *device; -+ pa_volume_control *volume_control; -+ -+ bool unlinked; -+ -+ pa_hook_slot *volume_changed_slot; -+}; -+ -+struct device_mute_control { -+ struct device *device; -+ pa_mute_control *mute_control; -+ -+ bool unlinked; -+ -+ pa_hook_slot *mute_changed_slot; -+}; -+ -+struct device { -+ pa_device_creator *creator; -+ enum device_type type; -+ pa_device_port *port; -+ pa_sink *sink; -+ pa_source *source; -+ pa_device *device; -+ struct device_volume_control *volume_control; -+ struct device_mute_control *mute_control; -+ -+ bool unlinked; -+ -+ pa_hook_slot *proplist_changed_slot; -+ pa_hook_slot *port_active_changed_slot; -+ struct device *monitor; -+}; -+ -+static const char *device_type_from_icon_name(const char *icon_name) { -+ if (!icon_name) -+ return NULL; -+ -+ if (pa_streq(icon_name, "audio-input-microphone")) -+ return "microphone"; -+ -+ if (pa_streq(icon_name, "audio-speakers")) -+ return "speakers"; -+ -+ if (pa_streq(icon_name, "audio-headphones")) -+ return "headphones"; -+ -+ return NULL; -+} -+ -+static const char *device_type_from_port_name(pa_device_port *port) { -+ pa_assert(port); -+ -+ if (strstr(port->name, "analog")) { -+ if (port->direction == PA_DIRECTION_INPUT) -+ return "analog-input"; -+ else -+ return "analog-output"; -+ } -+ -+ if (strstr(port->name, "hdmi")) { -+ if (port->direction == PA_DIRECTION_INPUT) -+ return "hdmi-input"; -+ else -+ return "hdmi-output"; -+ } -+ -+ if (strstr(port->name, "iec958")) { -+ if (port->direction == PA_DIRECTION_INPUT) -+ return "spdif-input"; -+ else -+ return "spdif-output"; -+ } -+ -+ return NULL; -+} -+ -+static const char *device_type_from_port(pa_device_port *port) { -+ const char *device_type; -+ -+ pa_assert(port); -+ -+ device_type = device_type_from_icon_name(pa_proplist_gets(port->proplist, PA_PROP_DEVICE_ICON_NAME)); -+ if (device_type) -+ return device_type; -+ -+ device_type = device_type_from_port_name(port); -+ if (device_type) -+ return device_type; -+ -+ return NULL; -+} -+ -+static const char *get_sink_description(pa_sink *sink) { -+ const char *description; -+ -+ pa_assert(sink); -+ -+ description = pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_DESCRIPTION); -+ if (description) -+ return description; -+ -+ return sink->name; -+} -+ -+static const char *get_source_description(pa_source *source) { -+ const char *description; -+ -+ pa_assert(source); -+ -+ description = pa_proplist_gets(source->proplist, PA_PROP_DEVICE_DESCRIPTION); -+ if (description) -+ return description; -+ -+ return source->name; -+} -+ -+static int volume_control_set_volume_cb(pa_volume_control *c, const pa_bvolume *volume, bool set_volume, bool set_balance) { -+ struct device_volume_control *control; -+ struct device *device; -+ pa_bvolume bvolume; -+ pa_cvolume cvolume; -+ -+ pa_assert(c); -+ pa_assert(volume); -+ -+ control = c->userdata; -+ device = control->device; -+ -+ switch (device->type) { -+ case DEVICE_TYPE_PORT: -+ if (device->port->direction == PA_DIRECTION_OUTPUT) -+ pa_bvolume_from_cvolume(&bvolume, &device->sink->reference_volume, &device->sink->channel_map); -+ else -+ pa_bvolume_from_cvolume(&bvolume, &device->source->reference_volume, &device->source->channel_map); -+ break; -+ -+ case DEVICE_TYPE_SINK: -+ pa_bvolume_from_cvolume(&bvolume, &device->sink->reference_volume, &device->sink->channel_map); -+ break; -+ -+ case DEVICE_TYPE_PORT_MONITOR: -+ case DEVICE_TYPE_SOURCE: -+ pa_bvolume_from_cvolume(&bvolume, &device->source->reference_volume, &device->source->channel_map); -+ break; -+ } -+ -+ if (set_volume) -+ bvolume.volume = volume->volume; -+ -+ if (set_balance) -+ pa_bvolume_copy_balance(&bvolume, volume); -+ -+ pa_bvolume_to_cvolume(&bvolume, &cvolume); -+ -+ switch (device->type) { -+ case DEVICE_TYPE_PORT: -+ if (device->port->direction == PA_DIRECTION_OUTPUT) -+ pa_sink_set_volume(device->sink, &cvolume, true, true); -+ else -+ pa_source_set_volume(device->source, &cvolume, true, true); -+ break; -+ -+ case DEVICE_TYPE_PORT_MONITOR: -+ case DEVICE_TYPE_SOURCE: -+ pa_source_set_volume(device->source, &cvolume, true, true); -+ break; -+ -+ case DEVICE_TYPE_SINK: -+ pa_sink_set_volume(device->sink, &cvolume, true, true); -+ break; -+ } -+ -+ return 0; -+} -+ -+static struct device_volume_control *device_volume_control_new(struct device *device) { -+ struct device_volume_control *control; -+ const char *name = NULL; -+ bool convertible_to_dB = false; -+ bool channel_map_is_writable; -+ -+ pa_assert(device); -+ -+ control = pa_xnew0(struct device_volume_control, 1); -+ control->device = device; -+ -+ switch (device->type) { -+ case DEVICE_TYPE_PORT: -+ name = "port-volume-control"; -+ -+ if (device->port->direction == PA_DIRECTION_OUTPUT) -+ convertible_to_dB = device->sink->flags & PA_SINK_DECIBEL_VOLUME; -+ else -+ convertible_to_dB = device->source->flags & PA_SOURCE_DECIBEL_VOLUME; -+ -+ break; -+ -+ case DEVICE_TYPE_PORT_MONITOR: -+ name = "port-monitor-volume-control"; -+ convertible_to_dB = device->source->flags & PA_SOURCE_DECIBEL_VOLUME; -+ break; -+ -+ case DEVICE_TYPE_SINK: -+ name = "sink-volume-control"; -+ convertible_to_dB = device->sink->flags & PA_SINK_DECIBEL_VOLUME; -+ break; -+ -+ case DEVICE_TYPE_SOURCE: -+ name = "source-volume-control"; -+ convertible_to_dB = device->source->flags & PA_SOURCE_DECIBEL_VOLUME; -+ break; -+ } -+ -+ channel_map_is_writable = false; -+ control->volume_control = pa_volume_control_new(device->creator->volume_api, name, device->device->description, -+ convertible_to_dB, channel_map_is_writable); -+ control->volume_control->set_volume = volume_control_set_volume_cb; -+ control->volume_control->userdata = control; -+ -+ return control; -+} -+ -+static pa_hook_result_t sink_or_source_volume_changed_cb(void *hook_data, void *call_data, void *userdata) { -+ struct device_volume_control *control = userdata; -+ struct device *device; -+ pa_sink *sink = NULL; -+ pa_source *source = NULL; -+ pa_bvolume bvolume; -+ -+ pa_assert(control); -+ pa_assert(call_data); -+ -+ device = control->device; -+ -+ switch (device->type) { -+ case DEVICE_TYPE_PORT: -+ if (device->port->direction == PA_DIRECTION_OUTPUT) -+ sink = call_data; -+ else -+ source = call_data; -+ break; -+ -+ case DEVICE_TYPE_PORT_MONITOR: -+ case DEVICE_TYPE_SOURCE: -+ source = call_data; -+ break; -+ -+ case DEVICE_TYPE_SINK: -+ sink = call_data; -+ break; -+ } -+ -+ if ((sink && sink != device->sink) || (source && source != device->source)) -+ return PA_HOOK_OK; -+ -+ if (sink) -+ pa_bvolume_from_cvolume(&bvolume, &sink->reference_volume, &sink->channel_map); -+ else -+ pa_bvolume_from_cvolume(&bvolume, &source->reference_volume, &source->channel_map); -+ -+ pa_volume_control_volume_changed(control->volume_control, &bvolume, true, true); -+ -+ return PA_HOOK_OK; -+} -+ -+static void volume_control_set_initial_volume_cb(pa_volume_control *c) { -+ struct device_volume_control *control; -+ struct device *device; -+ pa_cvolume cvolume; -+ -+ pa_assert(c); -+ -+ control = c->userdata; -+ device = control->device; -+ pa_bvolume_to_cvolume(&control->volume_control->volume, &cvolume); -+ -+ switch (device->type) { -+ case DEVICE_TYPE_PORT: -+ if (device->port->direction == PA_DIRECTION_OUTPUT) -+ pa_sink_set_volume(device->sink, &cvolume, true, true); -+ else -+ pa_source_set_volume(device->source, &cvolume, true, true); -+ break; -+ -+ case DEVICE_TYPE_PORT_MONITOR: -+ case DEVICE_TYPE_SOURCE: -+ pa_source_set_volume(device->source, &cvolume, true, true); -+ break; -+ -+ case DEVICE_TYPE_SINK: -+ pa_sink_set_volume(device->sink, &cvolume, true, true); -+ break; -+ } -+} -+ -+static void device_volume_control_put(struct device_volume_control *control) { -+ struct device *device; -+ pa_bvolume volume; -+ -+ pa_assert(control); -+ -+ device = control->device; -+ -+ switch (device->type) { -+ case DEVICE_TYPE_PORT: -+ if (device->port->direction == PA_DIRECTION_OUTPUT) { -+ control->volume_changed_slot = pa_hook_connect(&device->port->core->hooks[PA_CORE_HOOK_SINK_VOLUME_CHANGED], -+ PA_HOOK_NORMAL, sink_or_source_volume_changed_cb, control); -+ pa_bvolume_from_cvolume(&volume, &device->sink->reference_volume, &device->sink->channel_map); -+ } else { -+ control->volume_changed_slot = pa_hook_connect(&device->port->core->hooks[PA_CORE_HOOK_SOURCE_VOLUME_CHANGED], -+ PA_HOOK_NORMAL, sink_or_source_volume_changed_cb, control); -+ pa_bvolume_from_cvolume(&volume, &device->source->reference_volume, &device->source->channel_map); -+ } -+ break; -+ -+ case DEVICE_TYPE_PORT_MONITOR: -+ case DEVICE_TYPE_SOURCE: -+ control->volume_changed_slot = pa_hook_connect(&device->source->core->hooks[PA_CORE_HOOK_SOURCE_VOLUME_CHANGED], -+ PA_HOOK_NORMAL, sink_or_source_volume_changed_cb, control); -+ pa_bvolume_from_cvolume(&volume, &device->source->reference_volume, &device->source->channel_map); -+ break; -+ -+ case DEVICE_TYPE_SINK: -+ control->volume_changed_slot = pa_hook_connect(&device->sink->core->hooks[PA_CORE_HOOK_SINK_VOLUME_CHANGED], -+ PA_HOOK_NORMAL, sink_or_source_volume_changed_cb, control); -+ pa_bvolume_from_cvolume(&volume, &device->sink->reference_volume, &device->sink->channel_map); -+ break; -+ } -+ -+ pa_volume_control_put(control->volume_control, &volume, volume_control_set_initial_volume_cb); -+} -+ -+static void device_volume_control_unlink(struct device_volume_control *control) { -+ pa_assert(control); -+ -+ if (control->unlinked) -+ return; -+ -+ control->unlinked = true; -+ -+ if (control->volume_control) -+ pa_volume_control_unlink(control->volume_control); -+ -+ if (control->volume_changed_slot) { -+ pa_hook_slot_free(control->volume_changed_slot); -+ control->volume_changed_slot = NULL; -+ } -+} -+ -+static void device_volume_control_free(struct device_volume_control *control) { -+ pa_assert(control); -+ -+ if (!control->unlinked) -+ device_volume_control_unlink(control); -+ -+ if (control->volume_control) -+ pa_volume_control_free(control->volume_control); -+ -+ pa_xfree(control); -+} -+ -+static int mute_control_set_mute_cb(pa_mute_control *c, bool mute) { -+ struct device_mute_control *control; -+ struct device *device; -+ -+ pa_assert(c); -+ -+ control = c->userdata; -+ device = control->device; -+ -+ switch (device->type) { -+ case DEVICE_TYPE_PORT: -+ if (device->port->direction == PA_DIRECTION_OUTPUT) -+ pa_sink_set_mute(device->sink, mute, true); -+ else -+ pa_source_set_mute(device->source, mute, true); -+ break; -+ -+ case DEVICE_TYPE_PORT_MONITOR: -+ case DEVICE_TYPE_SOURCE: -+ pa_source_set_mute(device->source, mute, true); -+ break; -+ -+ case DEVICE_TYPE_SINK: -+ pa_sink_set_mute(device->sink, mute, true); -+ break; -+ } -+ -+ return 0; -+} -+ -+static struct device_mute_control *device_mute_control_new(struct device *device) { -+ struct device_mute_control *control; -+ const char *name = NULL; -+ -+ pa_assert(device); -+ -+ control = pa_xnew0(struct device_mute_control, 1); -+ control->device = device; -+ -+ switch (device->type) { -+ case DEVICE_TYPE_PORT: -+ name = "port-mute-control"; -+ break; -+ -+ case DEVICE_TYPE_PORT_MONITOR: -+ name = "port-monitor-mute-control"; -+ break; -+ -+ case DEVICE_TYPE_SINK: -+ name = "sink-mute-control"; -+ break; -+ -+ case DEVICE_TYPE_SOURCE: -+ name = "source-mute-control"; -+ break; -+ } -+ -+ control->mute_control = pa_mute_control_new(device->creator->volume_api, name, device->device->description); -+ control->mute_control->set_mute = mute_control_set_mute_cb; -+ control->mute_control->userdata = control; -+ -+ return control; -+} -+ -+static pa_hook_result_t sink_or_source_mute_changed_cb(void *hook_data, void *call_data, void *userdata) { -+ struct device_mute_control *control = userdata; -+ struct device *device; -+ pa_sink *sink = NULL; -+ pa_source *source = NULL; -+ bool mute; -+ -+ pa_assert(control); -+ pa_assert(call_data); -+ -+ device = control->device; -+ -+ switch (device->type) { -+ case DEVICE_TYPE_PORT: -+ if (device->port->direction == PA_DIRECTION_OUTPUT) -+ sink = call_data; -+ else -+ source = call_data; -+ break; -+ -+ case DEVICE_TYPE_PORT_MONITOR: -+ case DEVICE_TYPE_SOURCE: -+ source = call_data; -+ break; -+ -+ case DEVICE_TYPE_SINK: -+ sink = call_data; -+ break; -+ } -+ -+ if ((sink && sink != device->sink) || (source && source != device->source)) -+ return PA_HOOK_OK; -+ -+ if (sink) -+ mute = sink->muted; -+ else -+ mute = source->muted; -+ -+ pa_mute_control_mute_changed(control->mute_control, mute); -+ -+ return PA_HOOK_OK; -+} -+ -+static void mute_control_set_initial_mute_cb(pa_mute_control *c) { -+ struct device_volume_control *control; -+ struct device *device; -+ -+ pa_assert(c); -+ -+ control = c->userdata; -+ device = control->device; -+ -+ switch (device->type) { -+ case DEVICE_TYPE_PORT: -+ if (device->port->direction == PA_DIRECTION_OUTPUT) -+ pa_sink_set_mute(device->sink, c->mute, true); -+ else -+ pa_source_set_mute(device->source, c->mute, true); -+ break; -+ -+ case DEVICE_TYPE_PORT_MONITOR: -+ case DEVICE_TYPE_SOURCE: -+ pa_source_set_mute(device->source, c->mute, true); -+ break; -+ -+ case DEVICE_TYPE_SINK: -+ pa_sink_set_mute(device->sink, c->mute, true); -+ break; -+ } -+} -+ -+static void device_mute_control_put(struct device_mute_control *control) { -+ struct device *device; -+ bool mute = false; -+ -+ pa_assert(control); -+ -+ device = control->device; -+ -+ switch (device->type) { -+ case DEVICE_TYPE_PORT: -+ if (device->port->direction == PA_DIRECTION_OUTPUT) { -+ control->mute_changed_slot = pa_hook_connect(&device->port->core->hooks[PA_CORE_HOOK_SINK_MUTE_CHANGED], -+ PA_HOOK_NORMAL, sink_or_source_mute_changed_cb, control); -+ mute = device->sink->muted; -+ } else { -+ control->mute_changed_slot = pa_hook_connect(&device->port->core->hooks[PA_CORE_HOOK_SOURCE_MUTE_CHANGED], -+ PA_HOOK_NORMAL, sink_or_source_mute_changed_cb, control); -+ mute = device->source->muted; -+ } -+ break; -+ -+ case DEVICE_TYPE_PORT_MONITOR: -+ case DEVICE_TYPE_SOURCE: -+ control->mute_changed_slot = pa_hook_connect(&device->source->core->hooks[PA_CORE_HOOK_SOURCE_MUTE_CHANGED], -+ PA_HOOK_NORMAL, sink_or_source_mute_changed_cb, control); -+ mute = device->source->muted; -+ break; -+ -+ case DEVICE_TYPE_SINK: -+ control->mute_changed_slot = pa_hook_connect(&device->sink->core->hooks[PA_CORE_HOOK_SINK_MUTE_CHANGED], -+ PA_HOOK_NORMAL, sink_or_source_mute_changed_cb, control); -+ mute = device->sink->muted; -+ break; -+ } -+ -+ pa_mute_control_put(control->mute_control, mute, true, mute_control_set_initial_mute_cb); -+} -+ -+static void device_mute_control_unlink(struct device_mute_control *control) { -+ pa_assert(control); -+ -+ if (control->unlinked) -+ return; -+ -+ control->unlinked = true; -+ -+ if (control->mute_control) -+ pa_mute_control_unlink(control->mute_control); -+ -+ if (control->mute_changed_slot) { -+ pa_hook_slot_free(control->mute_changed_slot); -+ control->mute_changed_slot = NULL; -+ } -+} -+ -+static void device_mute_control_free(struct device_mute_control *control) { -+ pa_assert(control); -+ -+ if (!control->unlinked) -+ device_mute_control_unlink(control); -+ -+ if (control->mute_control) -+ pa_mute_control_free(control->mute_control); -+ -+ pa_xfree(control); -+} -+ -+static void device_set_sink_and_source_from_port(struct device *device) { -+ pa_sink *sink; -+ pa_source *source; -+ uint32_t idx; -+ -+ pa_assert(device); -+ -+ device->sink = NULL; -+ device->source = NULL; -+ -+ if (!device->port->active) -+ return; -+ -+ switch (device->type) { -+ case DEVICE_TYPE_PORT: -+ if (device->port->direction == PA_DIRECTION_OUTPUT) { -+ PA_IDXSET_FOREACH(sink, device->port->card->sinks, idx) { -+ if (sink->active_port == device->port) { -+ device->sink = sink; -+ break; -+ } -+ } -+ -+ pa_assert(device->sink); -+ } else { -+ PA_IDXSET_FOREACH(source, device->port->card->sources, idx) { -+ if (source->active_port == device->port) { -+ device->source = source; -+ break; -+ } -+ } -+ -+ pa_assert(device->source); -+ } -+ break; -+ -+ case DEVICE_TYPE_PORT_MONITOR: { -+ PA_IDXSET_FOREACH(sink, device->port->card->sinks, idx) { -+ if (sink->active_port == device->port) { -+ device->sink = sink; -+ device->source = sink->monitor_source; -+ break; -+ } -+ } -+ -+ pa_assert(device->sink); -+ break; -+ } -+ -+ case DEVICE_TYPE_SINK: -+ case DEVICE_TYPE_SOURCE: -+ pa_assert_not_reached(); -+ } -+} -+ -+static pa_hook_result_t sink_or_source_proplist_changed_cb(void *hook_data, void *call_data, void *userdata) { -+ struct device *device = userdata; -+ pa_sink *sink = NULL; -+ pa_source *source = NULL; -+ const char *description = NULL; -+ -+ pa_assert(device); -+ pa_assert(call_data); -+ -+ switch (device->type) { -+ case DEVICE_TYPE_PORT: -+ case DEVICE_TYPE_PORT_MONITOR: -+ pa_assert_not_reached(); -+ -+ case DEVICE_TYPE_SINK: -+ sink = call_data; -+ -+ if (sink != device->sink) -+ return PA_HOOK_OK; -+ -+ description = get_sink_description(sink); -+ break; -+ -+ case DEVICE_TYPE_SOURCE: -+ source = call_data; -+ -+ if (source != device->source) -+ return PA_HOOK_OK; -+ -+ description = get_source_description(source); -+ break; -+ } -+ -+ pa_device_description_changed(device->device, description); -+ pa_volume_control_description_changed(device->volume_control->volume_control, description); -+ pa_mute_control_description_changed(device->mute_control->mute_control, description); -+ -+ return PA_HOOK_OK; -+} -+ -+static struct device *device_new(pa_device_creator *creator, enum device_type type, void *core_device) { -+ struct device *device = NULL; -+ const char *name = NULL; -+ char *description = NULL; -+ pa_direction_t direction = PA_DIRECTION_OUTPUT; -+ const char *device_type = NULL; -+ bool create_volume_and_mute_controls = true; -+ -+ pa_assert(creator); -+ pa_assert(core_device); -+ -+ device = pa_xnew0(struct device, 1); -+ device->creator = creator; -+ device->type = type; -+ -+ switch (type) { -+ case DEVICE_TYPE_PORT: -+ device->port = core_device; -+ device_set_sink_and_source_from_port(device); -+ name = "port-device"; -+ description = pa_xstrdup(device->port->description); -+ direction = device->port->direction; -+ device_type = device_type_from_port(device->port); -+ -+ if (!device->sink && !device->source) -+ create_volume_and_mute_controls = false; -+ break; -+ -+ case DEVICE_TYPE_PORT_MONITOR: -+ device->port = core_device; -+ device_set_sink_and_source_from_port(device); -+ name = "port-monitor-device"; -+ description = pa_sprintf_malloc(_("Monitor of %s"), device->port->description); -+ direction = PA_DIRECTION_INPUT; -+ -+ if (!device->source) -+ create_volume_and_mute_controls = false; -+ break; -+ -+ case DEVICE_TYPE_SINK: -+ device->sink = core_device; -+ name = "sink-device"; -+ description = pa_xstrdup(get_sink_description(device->sink)); -+ direction = PA_DIRECTION_OUTPUT; -+ break; -+ -+ case DEVICE_TYPE_SOURCE: -+ device->source = core_device; -+ name = "source-device"; -+ description = pa_xstrdup(get_source_description(device->source)); -+ direction = PA_DIRECTION_INPUT; -+ break; -+ } -+ -+ device->device = pa_device_new(creator->volume_api, name, description, direction, &device_type, device_type ? 1 : 0); -+ pa_xfree(description); -+ -+ if (create_volume_and_mute_controls) { -+ device->volume_control = device_volume_control_new(device); -+ device->mute_control = device_mute_control_new(device); -+ } -+ -+ switch (type) { -+ case DEVICE_TYPE_PORT: -+ if (device->port->direction == PA_DIRECTION_OUTPUT) -+ device->monitor = device_new(creator, DEVICE_TYPE_PORT_MONITOR, device->port); -+ break; -+ -+ case DEVICE_TYPE_PORT_MONITOR: -+ break; -+ -+ case DEVICE_TYPE_SINK: -+ device->proplist_changed_slot = pa_hook_connect(&device->sink->core->hooks[PA_CORE_HOOK_SINK_PROPLIST_CHANGED], -+ PA_HOOK_NORMAL, sink_or_source_proplist_changed_cb, device); -+ break; -+ -+ case DEVICE_TYPE_SOURCE: -+ device->proplist_changed_slot = pa_hook_connect(&device->source->core->hooks[PA_CORE_HOOK_SOURCE_PROPLIST_CHANGED], -+ PA_HOOK_NORMAL, sink_or_source_proplist_changed_cb, device); -+ break; -+ } -+ -+ return device; -+} -+ -+static pa_hook_result_t port_active_changed_cb(void *hook_data, void *call_data, void *userdata) { -+ struct device *device = userdata; -+ pa_device_port *port = call_data; -+ bool should_have_volume_and_mute_controls = false; -+ -+ pa_assert(device); -+ pa_assert(port); -+ -+ if (port != device->port) -+ return PA_HOOK_OK; -+ -+ device_set_sink_and_source_from_port(device); -+ -+ switch (device->type) { -+ case DEVICE_TYPE_PORT: -+ should_have_volume_and_mute_controls = device->sink || device->source; -+ break; -+ -+ case DEVICE_TYPE_PORT_MONITOR: -+ should_have_volume_and_mute_controls = !!device->source; -+ break; -+ -+ case DEVICE_TYPE_SINK: -+ case DEVICE_TYPE_SOURCE: -+ pa_assert_not_reached(); -+ } -+ -+ if (should_have_volume_and_mute_controls && !device->volume_control) { -+ pa_assert(!device->mute_control); -+ -+ device->volume_control = device_volume_control_new(device); -+ device_volume_control_put(device->volume_control); -+ pa_device_set_default_volume_control(device->device, device->volume_control->volume_control); -+ -+ device->mute_control = device_mute_control_new(device); -+ device_mute_control_put(device->mute_control); -+ pa_device_set_default_mute_control(device->device, device->mute_control->mute_control); -+ } -+ -+ if (!should_have_volume_and_mute_controls && device->volume_control) { -+ pa_assert(device->mute_control); -+ -+ device_mute_control_free(device->mute_control); -+ device->mute_control = NULL; -+ device_volume_control_free(device->volume_control); -+ device->volume_control = NULL; -+ } -+ -+ return PA_HOOK_OK; -+} -+ -+static void device_put(struct device *device) { -+ pa_assert(device); -+ -+ switch (device->type) { -+ case DEVICE_TYPE_PORT: -+ case DEVICE_TYPE_PORT_MONITOR: -+ device->port_active_changed_slot = pa_hook_connect(&device->port->core->hooks[PA_CORE_HOOK_PORT_ACTIVE_CHANGED], -+ PA_HOOK_NORMAL, port_active_changed_cb, device); -+ -+ case DEVICE_TYPE_SINK: -+ case DEVICE_TYPE_SOURCE: -+ break; -+ } -+ -+ if (device->volume_control) -+ device_volume_control_put(device->volume_control); -+ -+ if (device->mute_control) -+ device_mute_control_put(device->mute_control); -+ -+ pa_device_put(device->device, device->volume_control ? device->volume_control->volume_control : NULL, -+ device->mute_control ? device->mute_control->mute_control : NULL); -+ -+ if (device->monitor) -+ device_put(device->monitor); -+} -+ -+static void device_unlink(struct device *device) { -+ pa_assert(device); -+ -+ if (device->unlinked) -+ return; -+ -+ device->unlinked = true; -+ -+ if (device->monitor) -+ device_unlink(device->monitor); -+ -+ if (device->device) -+ pa_device_unlink(device->device); -+ -+ if (device->mute_control) -+ device_mute_control_unlink(device->mute_control); -+ -+ if (device->volume_control) -+ device_volume_control_unlink(device->volume_control); -+ -+ if (device->port_active_changed_slot) { -+ pa_hook_slot_free(device->port_active_changed_slot); -+ device->port_active_changed_slot = NULL; -+ } -+} -+ -+static void device_free(struct device *device) { -+ pa_assert(device); -+ -+ if (!device->unlinked) -+ device_unlink(device); -+ -+ if (device->monitor) -+ device_free(device->monitor); -+ -+ if (device->proplist_changed_slot) -+ pa_hook_slot_free(device->proplist_changed_slot); -+ -+ if (device->mute_control) -+ device_mute_control_free(device->mute_control); -+ -+ if (device->volume_control) -+ device_volume_control_free(device->volume_control); -+ -+ if (device->device) -+ pa_device_free(device->device); -+ -+ pa_xfree(device); -+} -+ -+static void create_device(pa_device_creator *creator, enum device_type type, void *core_device) { -+ struct device *device; -+ -+ pa_assert(creator); -+ pa_assert(core_device); -+ -+ switch (type) { -+ case DEVICE_TYPE_PORT: -+ break; -+ -+ case DEVICE_TYPE_PORT_MONITOR: -+ pa_assert_not_reached(); -+ -+ case DEVICE_TYPE_SINK: -+ if (!pa_hashmap_isempty(((pa_sink *) core_device)->ports)) -+ return; -+ break; -+ -+ case DEVICE_TYPE_SOURCE: { -+ pa_source *source = core_device; -+ -+ if (source->monitor_of && !pa_hashmap_isempty(source->monitor_of->ports)) -+ return; -+ -+ if (!pa_hashmap_isempty(((pa_source *) core_device)->ports)) -+ return; -+ break; -+ } -+ } -+ -+ device = device_new(creator, type, core_device); -+ pa_hashmap_put(creator->devices, core_device, device); -+ device_put(device); -+} -+ -+static pa_hook_result_t card_put_cb(void *hook_data, void *call_data, void *userdata) { -+ pa_device_creator *creator = userdata; -+ pa_card *card = call_data; -+ pa_device_port *port; -+ void *state; -+ -+ pa_assert(creator); -+ pa_assert(card); -+ -+ PA_HASHMAP_FOREACH(port, card->ports, state) -+ create_device(creator, DEVICE_TYPE_PORT, port); -+ -+ return PA_HOOK_OK; -+} -+ -+static pa_hook_result_t card_unlink_cb(void *hook_data, void *call_data, void *userdata) { -+ pa_device_creator *creator = userdata; -+ pa_card *card = call_data; -+ pa_device_port *port; -+ void *state; -+ -+ pa_assert(creator); -+ pa_assert(card); -+ -+ PA_HASHMAP_FOREACH(port, card->ports, state) -+ pa_hashmap_remove_and_free(creator->devices, port); -+ -+ return PA_HOOK_OK; -+} -+ -+static pa_hook_result_t sink_put_cb(void *hook_data, void *call_data, void *userdata) { -+ pa_device_creator *creator = userdata; -+ pa_sink *sink = call_data; -+ -+ pa_assert(creator); -+ pa_assert(sink); -+ -+ create_device(creator, DEVICE_TYPE_SINK, sink); -+ -+ return PA_HOOK_OK; -+} -+ -+static pa_hook_result_t sink_unlink_cb(void *hook_data, void *call_data, void *userdata) { -+ pa_device_creator *creator = userdata; -+ pa_sink *sink = call_data; -+ -+ pa_assert(creator); -+ pa_assert(sink); -+ -+ pa_hashmap_remove_and_free(creator->devices, sink); -+ -+ return PA_HOOK_OK; -+} -+ -+static pa_hook_result_t source_put_cb(void *hook_data, void *call_data, void *userdata) { -+ pa_device_creator *creator = userdata; -+ pa_source *source = call_data; -+ -+ pa_assert(creator); -+ pa_assert(source); -+ -+ create_device(creator, DEVICE_TYPE_SOURCE, source); -+ -+ return PA_HOOK_OK; -+} -+ -+static pa_hook_result_t source_unlink_cb(void *hook_data, void *call_data, void *userdata) { -+ pa_device_creator *creator = userdata; -+ pa_source *source = call_data; -+ -+ pa_assert(creator); -+ pa_assert(source); -+ -+ pa_hashmap_remove_and_free(creator->devices, source); -+ -+ return PA_HOOK_OK; -+} -+ -+pa_device_creator *pa_device_creator_new(pa_volume_api *api) { -+ pa_device_creator *creator; -+ pa_card *card; -+ uint32_t idx; -+ pa_sink *sink; -+ pa_source *source; -+ -+ pa_assert(api); -+ -+ creator = pa_xnew0(pa_device_creator, 1); -+ creator->volume_api = api; -+ creator->devices = pa_hashmap_new_full(NULL, NULL, NULL, (pa_free_cb_t) device_free); -+ creator->card_put_slot = pa_hook_connect(&api->core->hooks[PA_CORE_HOOK_CARD_PUT], PA_HOOK_NORMAL, card_put_cb, creator); -+ creator->card_unlink_slot = pa_hook_connect(&api->core->hooks[PA_CORE_HOOK_CARD_UNLINK], PA_HOOK_NORMAL, card_unlink_cb, -+ creator); -+ creator->sink_put_slot = pa_hook_connect(&api->core->hooks[PA_CORE_HOOK_SINK_PUT], PA_HOOK_NORMAL, sink_put_cb, creator); -+ creator->sink_unlink_slot = pa_hook_connect(&api->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_NORMAL, sink_unlink_cb, -+ creator); -+ creator->source_put_slot = pa_hook_connect(&api->core->hooks[PA_CORE_HOOK_SOURCE_PUT], PA_HOOK_NORMAL, source_put_cb, -+ creator); -+ creator->source_unlink_slot = pa_hook_connect(&api->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_NORMAL, -+ source_unlink_cb, creator); -+ -+ PA_IDXSET_FOREACH(card, api->core->cards, idx) { -+ pa_device_port *port; -+ void *state; -+ -+ PA_HASHMAP_FOREACH(port, card->ports, state) -+ create_device(creator, DEVICE_TYPE_PORT, port); -+ } -+ -+ PA_IDXSET_FOREACH(sink, api->core->sinks, idx) -+ create_device(creator, DEVICE_TYPE_SINK, sink); -+ -+ PA_IDXSET_FOREACH(source, api->core->sources, idx) -+ create_device(creator, DEVICE_TYPE_SOURCE, source); -+ -+ return creator; -+} -+ -+void pa_device_creator_free(pa_device_creator *creator) { -+ pa_assert(creator); -+ -+ if (creator->devices) -+ pa_hashmap_remove_all(creator->devices); -+ -+ if (creator->source_unlink_slot) -+ pa_hook_slot_free(creator->source_unlink_slot); -+ -+ if (creator->source_put_slot) -+ pa_hook_slot_free(creator->source_put_slot); -+ -+ if (creator->sink_unlink_slot) -+ pa_hook_slot_free(creator->sink_unlink_slot); -+ -+ if (creator->sink_put_slot) -+ pa_hook_slot_free(creator->sink_put_slot); -+ -+ if (creator->card_unlink_slot) -+ pa_hook_slot_free(creator->card_unlink_slot); -+ -+ if (creator->card_put_slot) -+ pa_hook_slot_free(creator->card_put_slot); -+ -+ if (creator->devices) -+ pa_hashmap_free(creator->devices); -+ -+ pa_xfree(creator); -+} -diff --git a/src/modules/volume-api/device-creator.h b/src/modules/volume-api/device-creator.h -new file mode 100644 -index 0000000..bcec8d9 ---- /dev/null -+++ b/src/modules/volume-api/device-creator.h -@@ -0,0 +1,32 @@ -+#ifndef foodevicecreatorhfoo -+#define foodevicecreatorhfoo -+ -+/*** -+ This file is part of PulseAudio. -+ -+ Copyright 2014 Intel Corporation -+ -+ PulseAudio is free software; you can redistribute it and/or modify -+ it under the terms of the GNU Lesser General Public License as published -+ by the Free Software Foundation; either version 2.1 of the License, -+ or (at your option) any later version. -+ -+ PulseAudio 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 Lesser General Public License -+ along with PulseAudio; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ USA. -+***/ -+ -+#include -+ -+typedef struct pa_device_creator pa_device_creator; -+ -+pa_device_creator *pa_device_creator_new(pa_volume_api *api); -+void pa_device_creator_free(pa_device_creator *creator); -+ -+#endif -diff --git a/src/modules/volume-api/device.c b/src/modules/volume-api/device.c -new file mode 100644 -index 0000000..ea496ba ---- /dev/null -+++ b/src/modules/volume-api/device.c -@@ -0,0 +1,293 @@ -+/*** -+ This file is part of PulseAudio. -+ -+ Copyright 2014 Intel Corporation -+ -+ PulseAudio is free software; you can redistribute it and/or modify -+ it under the terms of the GNU Lesser General Public License as published -+ by the Free Software Foundation; either version 2.1 of the License, -+ or (at your option) any later version. -+ -+ PulseAudio 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 Lesser General Public License -+ along with PulseAudio; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ USA. -+***/ -+ -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ -+#include "device.h" -+ -+#include -+#include -+ -+#include -+ -+#include -+ -+pa_device *pa_device_new(pa_volume_api *api, const char *name, const char *description, pa_direction_t direction, -+ const char * const *device_types, unsigned n_device_types) { -+ pa_device *device; -+ unsigned i; -+ -+ pa_assert(api); -+ pa_assert(name); -+ pa_assert(description); -+ pa_assert(device_types || n_device_types == 0); -+ -+ device = pa_xnew0(pa_device, 1); -+ device->volume_api = api; -+ device->index = pa_volume_api_allocate_device_index(api); -+ pa_assert_se(pa_volume_api_register_name(api, name, false, &device->name) >= 0); -+ device->description = pa_xstrdup(description); -+ device->direction = direction; -+ device->device_types = pa_dynarray_new(pa_xfree); -+ -+ for (i = 0; i < n_device_types; i++) -+ pa_dynarray_append(device->device_types, pa_xstrdup(device_types[i])); -+ -+ device->proplist = pa_proplist_new(); -+ device->use_default_volume_control = true; -+ device->use_default_mute_control = true; -+ -+ return device; -+} -+ -+void pa_device_put(pa_device *device, pa_volume_control *default_volume_control, pa_mute_control *default_mute_control) { -+ char *device_types_str; -+ const char *prop_key; -+ void *state = NULL; -+ -+ pa_assert(device); -+ -+ if (default_volume_control) { -+ device->default_volume_control = default_volume_control; -+ pa_volume_control_add_default_for_device(default_volume_control, device); -+ -+ device->volume_control = default_volume_control; -+ pa_volume_control_add_device(default_volume_control, device); -+ } -+ -+ if (default_mute_control) { -+ device->default_mute_control = default_mute_control; -+ pa_mute_control_add_default_for_device(default_mute_control, device); -+ -+ device->mute_control = default_mute_control; -+ pa_mute_control_add_device(default_mute_control, device); -+ } -+ -+ pa_volume_api_add_device(device->volume_api, device); -+ -+ device->linked = true; -+ -+ device_types_str = pa_join((const char * const *) pa_dynarray_get_raw_array(device->device_types), -+ pa_dynarray_size(device->device_types), ", "); -+ -+ pa_log_debug("Created device #%u.", device->index); -+ pa_log_debug(" Name: %s", device->name); -+ pa_log_debug(" Description: %s", device->description); -+ pa_log_debug(" Direction: %s", pa_direction_to_string(device->direction)); -+ pa_log_debug(" Device Types: %s", *device_types_str ? device_types_str : "(none)"); -+ pa_log_debug(" Volume control: %s", device->volume_control ? device->volume_control->name : "(unset)"); -+ pa_log_debug(" Mute control: %s", device->mute_control ? device->mute_control->name : "(unset)"); -+ pa_log_debug(" Properties:"); -+ -+ while ((prop_key = pa_proplist_iterate(device->proplist, &state))) -+ pa_log_debug(" %s = %s", prop_key, pa_strnull(pa_proplist_gets(device->proplist, prop_key))); -+ -+ pa_xfree(device_types_str); -+ -+ pa_hook_fire(&device->volume_api->hooks[PA_VOLUME_API_HOOK_DEVICE_PUT], device); -+} -+ -+void pa_device_unlink(pa_device *device) { -+ pa_assert(device); -+ -+ if (device->unlinked) { -+ pa_log_debug("Unlinking device %s (already unlinked, this is a no-op).", device->name); -+ return; -+ } -+ -+ device->unlinked = true; -+ -+ pa_log_debug("Unlinking device %s.", device->name); -+ -+ if (device->linked) -+ pa_hook_fire(&device->volume_api->hooks[PA_VOLUME_API_HOOK_DEVICE_UNLINK], device); -+ -+ pa_volume_api_remove_device(device->volume_api, device); -+ -+ if (device->mute_control) { -+ pa_mute_control_remove_device(device->mute_control, device); -+ device->mute_control = NULL; -+ } -+ -+ if (device->default_mute_control) { -+ pa_mute_control_remove_default_for_device(device->default_mute_control, device); -+ device->default_mute_control = NULL; -+ } -+ -+ if (device->volume_control) { -+ pa_volume_control_remove_device(device->volume_control, device); -+ device->volume_control = NULL; -+ } -+ -+ if (device->default_volume_control) { -+ pa_volume_control_remove_default_for_device(device->default_volume_control, device); -+ device->default_volume_control = NULL; -+ } -+} -+ -+void pa_device_free(pa_device *device) { -+ pa_assert(device); -+ -+ if (!device->unlinked) -+ pa_device_unlink(device); -+ -+ if (device->proplist) -+ pa_proplist_free(device->proplist); -+ -+ if (device->device_types) -+ pa_dynarray_free(device->device_types); -+ -+ pa_xfree(device->description); -+ -+ if (device->name) -+ pa_volume_api_unregister_name(device->volume_api, device->name); -+ -+ pa_xfree(device); -+} -+ -+static void set_volume_control_internal(pa_device *device, pa_volume_control *control) { -+ pa_volume_control *old_control; -+ -+ pa_assert(device); -+ -+ old_control = device->volume_control; -+ -+ if (control == old_control) -+ return; -+ -+ if (old_control) -+ pa_volume_control_remove_device(old_control, device); -+ -+ device->volume_control = control; -+ -+ if (control) -+ pa_volume_control_add_device(control, device); -+ -+ if (!device->linked || device->unlinked) -+ return; -+ -+ pa_log_debug("The volume control of device %s changed from %s to %s.", device->name, -+ old_control ? old_control->name : "(unset)", control ? control->name : "(unset)"); -+ -+ pa_hook_fire(&device->volume_api->hooks[PA_VOLUME_API_HOOK_DEVICE_VOLUME_CONTROL_CHANGED], device); -+} -+ -+void pa_device_set_volume_control(pa_device *device, pa_volume_control *control) { -+ pa_assert(device); -+ -+ device->use_default_volume_control = false; -+ set_volume_control_internal(device, control); -+} -+ -+static void set_mute_control_internal(pa_device *device, pa_mute_control *control) { -+ pa_mute_control *old_control; -+ -+ pa_assert(device); -+ -+ old_control = device->mute_control; -+ -+ if (control == old_control) -+ return; -+ -+ if (old_control) -+ pa_mute_control_remove_device(old_control, device); -+ -+ device->mute_control = control; -+ -+ if (control) -+ pa_mute_control_add_device(control, device); -+ -+ pa_log_debug("The mute control of device %s changed from %s to %s.", device->name, -+ old_control ? old_control->name : "(unset)", control ? control->name : "(unset)"); -+ -+ pa_hook_fire(&device->volume_api->hooks[PA_VOLUME_API_HOOK_DEVICE_MUTE_CONTROL_CHANGED], device); -+} -+ -+void pa_device_set_mute_control(pa_device *device, pa_mute_control *control) { -+ pa_assert(device); -+ -+ device->use_default_mute_control = false; -+ set_mute_control_internal(device, control); -+} -+ -+void pa_device_description_changed(pa_device *device, const char *new_description) { -+ char *old_description; -+ -+ pa_assert(device); -+ pa_assert(new_description); -+ -+ old_description = device->description; -+ -+ if (pa_streq(new_description, old_description)) -+ return; -+ -+ device->description = pa_xstrdup(new_description); -+ pa_log_debug("The description of device %s changed from \"%s\" to \"%s\".", device->name, old_description, -+ new_description); -+ pa_xfree(old_description); -+ pa_hook_fire(&device->volume_api->hooks[PA_VOLUME_API_HOOK_DEVICE_DESCRIPTION_CHANGED], device); -+} -+ -+void pa_device_set_default_volume_control(pa_device *device, pa_volume_control *control) { -+ pa_volume_control *old_control; -+ -+ pa_assert(device); -+ -+ old_control = device->default_volume_control; -+ -+ if (control == old_control) -+ return; -+ -+ if (old_control) -+ pa_volume_control_remove_default_for_device(old_control, device); -+ -+ device->default_volume_control = control; -+ -+ if (control) -+ pa_volume_control_add_default_for_device(control, device); -+ -+ if (device->use_default_volume_control) -+ set_volume_control_internal(device, control); -+} -+ -+void pa_device_set_default_mute_control(pa_device *device, pa_mute_control *control) { -+ pa_mute_control *old_control; -+ -+ pa_assert(device); -+ -+ old_control = device->default_mute_control; -+ -+ if (control == old_control) -+ return; -+ -+ if (old_control) -+ pa_mute_control_remove_default_for_device(old_control, device); -+ -+ device->default_mute_control = control; -+ -+ if (control) -+ pa_mute_control_add_default_for_device(control, device); -+ -+ if (device->use_default_mute_control) -+ set_mute_control_internal(device, control); -+} -diff --git a/src/modules/volume-api/device.h b/src/modules/volume-api/device.h -new file mode 100644 -index 0000000..9eac7e9 ---- /dev/null -+++ b/src/modules/volume-api/device.h -@@ -0,0 +1,76 @@ -+#ifndef foodevicehfoo -+#define foodevicehfoo -+ -+/*** -+ This file is part of PulseAudio. -+ -+ Copyright 2014 Intel Corporation -+ -+ PulseAudio is free software; you can redistribute it and/or modify -+ it under the terms of the GNU Lesser General Public License as published -+ by the Free Software Foundation; either version 2.1 of the License, -+ or (at your option) any later version. -+ -+ PulseAudio 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 Lesser General Public License -+ along with PulseAudio; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ USA. -+***/ -+ -+#include -+ -+#include -+ -+typedef struct pa_device pa_device; -+ -+struct pa_device { -+ pa_volume_api *volume_api; -+ uint32_t index; -+ const char *name; -+ char *description; -+ pa_direction_t direction; -+ pa_dynarray *device_types; -+ pa_proplist *proplist; -+ pa_volume_control *volume_control; -+ pa_mute_control *mute_control; -+ -+ /* The device implementation can provide default volume and mute controls, -+ * which are used in case there's no policy module that wants to override -+ * the defaults. */ -+ pa_volume_control *default_volume_control; -+ bool use_default_volume_control; -+ pa_mute_control *default_mute_control; -+ bool use_default_mute_control; -+ -+ bool linked; -+ bool unlinked; -+}; -+ -+pa_device *pa_device_new(pa_volume_api *api, const char *name, const char *description, pa_direction_t direction, -+ const char * const *device_types, unsigned n_device_types); -+void pa_device_put(pa_device *device, pa_volume_control *default_volume_control, pa_mute_control *default_mute_control); -+void pa_device_unlink(pa_device *device); -+void pa_device_free(pa_device *device); -+ -+/* Called by policy modules. */ -+void pa_device_set_volume_control(pa_device *device, pa_volume_control *control); -+void pa_device_set_mute_control(pa_device *device, pa_mute_control *control); -+ -+/* Called by policy modules. Note that pa_device_set_volume_control() and -+ * pa_device_set_mute_control() automatically disable the corresponding -+ * use_default flags, so these functions are mainly useful for re-enabling the -+ * flags. */ -+void pa_device_set_use_default_volume_control(pa_device *device, bool use); -+void pa_device_set_use_default_mute_control(pa_device *device, bool use); -+ -+/* Called by the device implementation. */ -+void pa_device_description_changed(pa_device *device, const char *new_description); -+void pa_device_set_default_volume_control(pa_device *device, pa_volume_control *control); -+void pa_device_set_default_mute_control(pa_device *device, pa_mute_control *control); -+ -+#endif -diff --git a/src/modules/volume-api/mute-control.c b/src/modules/volume-api/mute-control.c -new file mode 100644 -index 0000000..adc008e ---- /dev/null -+++ b/src/modules/volume-api/mute-control.c -@@ -0,0 +1,306 @@ -+/*** -+ This file is part of PulseAudio. -+ -+ Copyright 2014 Intel Corporation -+ -+ PulseAudio is free software; you can redistribute it and/or modify -+ it under the terms of the GNU Lesser General Public License as published -+ by the Free Software Foundation; either version 2.1 of the License, -+ or (at your option) any later version. -+ -+ PulseAudio 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 Lesser General Public License -+ along with PulseAudio; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ USA. -+***/ -+ -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ -+#include "mute-control.h" -+ -+#include -+#include -+#include -+ -+#include -+ -+pa_mute_control *pa_mute_control_new(pa_volume_api *api, const char *name, const char *description) { -+ pa_mute_control *control; -+ -+ pa_assert(api); -+ pa_assert(name); -+ pa_assert(description); -+ -+ control = pa_xnew0(pa_mute_control, 1); -+ control->volume_api = api; -+ control->index = pa_volume_api_allocate_mute_control_index(api); -+ pa_assert_se(pa_volume_api_register_name(api, name, false, &control->name) >= 0); -+ control->description = pa_xstrdup(description); -+ control->proplist = pa_proplist_new(); -+ control->devices = pa_hashmap_new(NULL, NULL); -+ control->default_for_devices = pa_hashmap_new(NULL, NULL); -+ control->streams = pa_hashmap_new(NULL, NULL); -+ control->audio_groups = pa_hashmap_new(NULL, NULL); -+ -+ return control; -+} -+ -+void pa_mute_control_put(pa_mute_control *control, bool initial_mute, bool initial_mute_is_set, -+ pa_mute_control_set_initial_mute_cb_t set_initial_mute_cb) { -+ const char *prop_key; -+ void *state = NULL; -+ -+ pa_assert(control); -+ pa_assert(initial_mute_is_set || control->set_mute); -+ pa_assert(set_initial_mute_cb || !control->set_mute); -+ -+ if (initial_mute_is_set) -+ control->mute = initial_mute; -+ else -+ control->mute = false; -+ -+ if (set_initial_mute_cb) -+ set_initial_mute_cb(control); -+ -+ pa_volume_api_add_mute_control(control->volume_api, control); -+ -+ control->linked = true; -+ -+ pa_log_debug("Created mute control #%u.", control->index); -+ pa_log_debug(" Name: %s", control->name); -+ pa_log_debug(" Description: %s", control->description); -+ pa_log_debug(" Mute: %s", pa_yes_no(control->mute)); -+ pa_log_debug(" Properties:"); -+ -+ while ((prop_key = pa_proplist_iterate(control->proplist, &state))) -+ pa_log_debug(" %s = %s", prop_key, pa_strnull(pa_proplist_gets(control->proplist, prop_key))); -+ -+ pa_hook_fire(&control->volume_api->hooks[PA_VOLUME_API_HOOK_MUTE_CONTROL_PUT], control); -+} -+ -+void pa_mute_control_unlink(pa_mute_control *control) { -+ pa_audio_group *group; -+ pa_device *device; -+ pas_stream *stream; -+ -+ pa_assert(control); -+ -+ if (control->unlinked) { -+ pa_log_debug("Unlinking mute control %s (already unlinked, this is a no-op).", control->name); -+ return; -+ } -+ -+ control->unlinked = true; -+ -+ pa_log_debug("Unlinking mute control %s.", control->name); -+ -+ if (control->linked) -+ pa_hook_fire(&control->volume_api->hooks[PA_VOLUME_API_HOOK_MUTE_CONTROL_UNLINK], control); -+ -+ pa_volume_api_remove_mute_control(control->volume_api, control); -+ -+ while ((group = pa_hashmap_first(control->audio_groups))) -+ pa_audio_group_set_mute_control(group, NULL); -+ -+ while ((stream = pa_hashmap_first(control->streams))) -+ pas_stream_set_mute_control(stream, NULL); -+ -+ while ((device = pa_hashmap_first(control->default_for_devices))) -+ pa_device_set_default_mute_control(device, NULL); -+ -+ while ((device = pa_hashmap_first(control->devices))) { -+ /* Why do we have this assertion here? The concern is that if we call -+ * pa_device_set_mute_control() for some device that has the -+ * use_default_mute_control flag set, then that flag will be unset as -+ * a side effect, and we don't want that side effect. This assertion -+ * should be safe, because we just called -+ * pa_device_set_default_mute_control(NULL) for each device that this -+ * control was the default for, and that should ensure that we don't -+ * any more hold any references to devices that used to use this -+ * control as the default. */ -+ pa_assert(!device->use_default_mute_control); -+ pa_device_set_mute_control(device, NULL); -+ } -+} -+ -+void pa_mute_control_free(pa_mute_control *control) { -+ pa_assert(control); -+ -+ if (!control->unlinked) -+ pa_mute_control_unlink(control); -+ -+ if (control->audio_groups) { -+ pa_assert(pa_hashmap_isempty(control->audio_groups)); -+ pa_hashmap_free(control->audio_groups); -+ } -+ -+ if (control->streams) { -+ pa_assert(pa_hashmap_isempty(control->streams)); -+ pa_hashmap_free(control->streams); -+ } -+ -+ if (control->default_for_devices) { -+ pa_assert(pa_hashmap_isempty(control->default_for_devices)); -+ pa_hashmap_free(control->default_for_devices); -+ } -+ -+ if (control->devices) { -+ pa_assert(pa_hashmap_isempty(control->devices)); -+ pa_hashmap_free(control->devices); -+ } -+ -+ if (control->proplist) -+ pa_proplist_free(control->proplist); -+ -+ pa_xfree(control->description); -+ -+ if (control->name) -+ pa_volume_api_unregister_name(control->volume_api, control->name); -+ -+ pa_xfree(control); -+} -+ -+void pa_mute_control_set_owner_audio_group(pa_mute_control *control, pa_audio_group *group) { -+ pa_assert(control); -+ pa_assert(group); -+ -+ control->owner_audio_group = group; -+} -+ -+static void set_mute_internal(pa_mute_control *control, bool mute) { -+ bool old_mute; -+ -+ pa_assert(control); -+ -+ old_mute = control->mute; -+ -+ if (mute == old_mute) -+ return; -+ -+ control->mute = mute; -+ -+ if (!control->linked || control->unlinked) -+ return; -+ -+ pa_log_debug("The mute of mute control %s changed from %s to %s.", control->name, pa_yes_no(old_mute), -+ pa_yes_no(control->mute)); -+ -+ pa_hook_fire(&control->volume_api->hooks[PA_VOLUME_API_HOOK_MUTE_CONTROL_MUTE_CHANGED], control); -+} -+ -+int pa_mute_control_set_mute(pa_mute_control *control, bool mute) { -+ int r; -+ -+ pa_assert(control); -+ -+ if (!control->set_mute) { -+ pa_log_info("Tried to set the mute of mute control %s, but the mute control doesn't support the operation.", -+ control->name); -+ return -PA_ERR_NOTSUPPORTED; -+ } -+ -+ if (mute == control->mute) -+ return 0; -+ -+ control->set_mute_in_progress = true; -+ r = control->set_mute(control, mute); -+ control->set_mute_in_progress = false; -+ -+ if (r >= 0) -+ set_mute_internal(control, mute); -+ -+ return r; -+} -+ -+void pa_mute_control_description_changed(pa_mute_control *control, const char *new_description) { -+ char *old_description; -+ -+ pa_assert(control); -+ pa_assert(new_description); -+ -+ old_description = control->description; -+ -+ if (pa_streq(new_description, old_description)) -+ return; -+ -+ control->description = pa_xstrdup(new_description); -+ pa_log_debug("The description of mute control %s changed from \"%s\" to \"%s\".", control->name, old_description, -+ new_description); -+ pa_xfree(old_description); -+ pa_hook_fire(&control->volume_api->hooks[PA_VOLUME_API_HOOK_MUTE_CONTROL_DESCRIPTION_CHANGED], control); -+} -+ -+void pa_mute_control_mute_changed(pa_mute_control *control, bool new_mute) { -+ pa_assert(control); -+ -+ if (!control->linked) -+ return; -+ -+ if (control->set_mute_in_progress) -+ return; -+ -+ set_mute_internal(control, new_mute); -+} -+ -+void pa_mute_control_add_device(pa_mute_control *control, pa_device *device) { -+ pa_assert(control); -+ pa_assert(device); -+ -+ pa_assert_se(pa_hashmap_put(control->devices, device, device) >= 0); -+} -+ -+void pa_mute_control_remove_device(pa_mute_control *control, pa_device *device) { -+ pa_assert(control); -+ pa_assert(device); -+ -+ pa_assert_se(pa_hashmap_remove(control->devices, device)); -+} -+ -+void pa_mute_control_add_default_for_device(pa_mute_control *control, pa_device *device) { -+ pa_assert(control); -+ pa_assert(device); -+ -+ pa_assert_se(pa_hashmap_put(control->default_for_devices, device, device) >= 0); -+} -+ -+void pa_mute_control_remove_default_for_device(pa_mute_control *control, pa_device *device) { -+ pa_assert(control); -+ pa_assert(device); -+ -+ pa_assert_se(pa_hashmap_remove(control->default_for_devices, device)); -+} -+ -+void pa_mute_control_add_stream(pa_mute_control *control, pas_stream *stream) { -+ pa_assert(control); -+ pa_assert(stream); -+ -+ pa_assert_se(pa_hashmap_put(control->streams, stream, stream) >= 0); -+} -+ -+void pa_mute_control_remove_stream(pa_mute_control *control, pas_stream *stream) { -+ pa_assert(control); -+ pa_assert(stream); -+ -+ pa_assert_se(pa_hashmap_remove(control->streams, stream)); -+} -+ -+void pa_mute_control_add_audio_group(pa_mute_control *control, pa_audio_group *group) { -+ pa_assert(control); -+ pa_assert(group); -+ -+ pa_assert_se(pa_hashmap_put(control->audio_groups, group, group) >= 0); -+} -+ -+void pa_mute_control_remove_audio_group(pa_mute_control *control, pa_audio_group *group) { -+ pa_assert(control); -+ pa_assert(group); -+ -+ pa_assert_se(pa_hashmap_remove(control->audio_groups, group)); -+} -diff --git a/src/modules/volume-api/mute-control.h b/src/modules/volume-api/mute-control.h -new file mode 100644 -index 0000000..1f70a43 ---- /dev/null -+++ b/src/modules/volume-api/mute-control.h -@@ -0,0 +1,102 @@ -+#ifndef foomutecontrolhfoo -+#define foomutecontrolhfoo -+ -+/*** -+ This file is part of PulseAudio. -+ -+ Copyright 2014 Intel Corporation -+ -+ PulseAudio is free software; you can redistribute it and/or modify -+ it under the terms of the GNU Lesser General Public License as published -+ by the Free Software Foundation; either version 2.1 of the License, -+ or (at your option) any later version. -+ -+ PulseAudio 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 Lesser General Public License -+ along with PulseAudio; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ USA. -+***/ -+ -+#include -+ -+typedef struct pa_mute_control pa_mute_control; -+ -+struct pa_mute_control { -+ pa_volume_api *volume_api; -+ uint32_t index; -+ const char *name; -+ char *description; -+ pa_proplist *proplist; -+ bool mute; -+ -+ /* If this mute control is the "own mute control" of an audio group, this -+ * is set to point to that group, otherwise this is NULL. */ -+ pa_audio_group *owner_audio_group; -+ -+ pa_hashmap *devices; /* pa_device -> pa_device (hashmap-as-a-set) */ -+ pa_hashmap *default_for_devices; /* pa_device -> pa_device (hashmap-as-a-set) */ -+ pa_hashmap *streams; /* pas_stream -> pas_stream (hashmap-as-a-set) */ -+ pa_hashmap *audio_groups; /* pa_audio_group -> pa_audio_group (hashmap-as-a-set) */ -+ -+ bool linked; -+ bool unlinked; -+ bool set_mute_in_progress; -+ -+ /* Called from pa_mute_control_set_mute(). The implementation is expected -+ * to return a negative error code on failure. May be NULL, if the mute -+ * control is read-only. */ -+ int (*set_mute)(pa_mute_control *control, bool mute); -+ -+ void *userdata; -+}; -+ -+pa_mute_control *pa_mute_control_new(pa_volume_api *api, const char *name, const char *description); -+ -+typedef void (*pa_mute_control_set_initial_mute_cb_t)(pa_mute_control *control); -+ -+/* initial_mute is the preferred initial mute of the mute control -+ * implementation. It may be unset, if the implementation doesn't care about -+ * the initial state of the mute control. Read-only mute controls, however, -+ * must always set initial_mute. -+ * -+ * The implementation's initial mute preference may be overridden by policy, if -+ * the mute control isn't read-only. When the final initial mute is known, the -+ * the implementation is notified via set_initial_mute_cb (the mute can be read -+ * from control->mute). set_initial_mute_cb may be NULL, if the mute control is -+ * read-only. */ -+void pa_mute_control_put(pa_mute_control *control, bool initial_mute, bool initial_mute_is_set, -+ pa_mute_control_set_initial_mute_cb_t set_initial_mute_cb); -+ -+void pa_mute_control_unlink(pa_mute_control *control); -+void pa_mute_control_free(pa_mute_control *control); -+ -+/* Called by audio-group.c only. */ -+void pa_mute_control_set_owner_audio_group(pa_mute_control *control, pa_audio_group *group); -+ -+/* Called by clients and policy modules. */ -+int pa_mute_control_set_mute(pa_mute_control *control, bool mute); -+ -+/* Called by the mute control implementation. */ -+void pa_mute_control_description_changed(pa_mute_control *control, const char *new_description); -+void pa_mute_control_mute_changed(pa_mute_control *control, bool new_mute); -+ -+/* Called from device.c only. */ -+void pa_mute_control_add_device(pa_mute_control *control, pa_device *device); -+void pa_mute_control_remove_device(pa_mute_control *control, pa_device *device); -+void pa_mute_control_add_default_for_device(pa_mute_control *control, pa_device *device); -+void pa_mute_control_remove_default_for_device(pa_mute_control *control, pa_device *device); -+ -+/* Called from sstream.c only. */ -+void pa_mute_control_add_stream(pa_mute_control *control, pas_stream *stream); -+void pa_mute_control_remove_stream(pa_mute_control *control, pas_stream *stream); -+ -+/* Called from audio-group.c only. */ -+void pa_mute_control_add_audio_group(pa_mute_control *control, pa_audio_group *group); -+void pa_mute_control_remove_audio_group(pa_mute_control *control, pa_audio_group *group); -+ -+#endif -diff --git a/src/modules/volume-api/sstream.c b/src/modules/volume-api/sstream.c -new file mode 100644 -index 0000000..e3531a8 ---- /dev/null -+++ b/src/modules/volume-api/sstream.c -@@ -0,0 +1,366 @@ -+/*** -+ This file is part of PulseAudio. -+ -+ Copyright 2014 Intel Corporation -+ -+ PulseAudio is free software; you can redistribute it and/or modify -+ it under the terms of the GNU Lesser General Public License as published -+ by the Free Software Foundation; either version 2.1 of the License, -+ or (at your option) any later version. -+ -+ PulseAudio 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 Lesser General Public License -+ along with PulseAudio; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ USA. -+***/ -+ -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ -+#include "sstream.h" -+ -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+ -+pas_stream *pas_stream_new(pa_volume_api *api, const char *name, const char *description, pa_direction_t direction) { -+ pas_stream *stream; -+ -+ pa_assert(api); -+ pa_assert(name); -+ pa_assert(description); -+ -+ stream = pa_xnew0(pas_stream, 1); -+ stream->volume_api = api; -+ stream->index = pa_volume_api_allocate_stream_index(api); -+ pa_assert_se(pa_volume_api_register_name(api, name, false, &stream->name) >= 0); -+ stream->description = pa_xstrdup(description); -+ stream->direction = direction; -+ stream->proplist = pa_proplist_new(); -+ stream->use_default_volume_control = true; -+ stream->use_default_mute_control = true; -+ -+ return stream; -+} -+ -+static void set_volume_control_internal(pas_stream *stream, pa_volume_control *control) { -+ pa_volume_control *old_control; -+ -+ pa_assert(stream); -+ -+ old_control = stream->volume_control; -+ -+ if (control == old_control) -+ return; -+ -+ if (old_control) { -+ /* If the old control pointed to the own volume control of an audio -+ * group, then the stream's audio group for volume needs to be -+ * updated. We set it to NULL here, and if it should be non-NULL, that -+ * will be fixed very soon (a few lines down). */ -+ pas_stream_set_audio_group_for_volume(stream, NULL); -+ -+ pa_volume_control_remove_stream(old_control, stream); -+ } -+ -+ stream->volume_control = control; -+ -+ if (control) { -+ pa_volume_control_add_stream(control, stream); -+ pas_stream_set_audio_group_for_volume(stream, control->owner_audio_group); -+ } -+ -+ if (!stream->linked || stream->unlinked) -+ return; -+ -+ pa_log_debug("The volume control of stream %s changed from %s to %s.", stream->name, -+ old_control ? old_control->name : "(unset)", control ? control->name : "(unset)"); -+ -+ pa_hook_fire(&stream->volume_api->hooks[PA_VOLUME_API_HOOK_STREAM_VOLUME_CONTROL_CHANGED], stream); -+} -+ -+static void set_mute_control_internal(pas_stream *stream, pa_mute_control *control) { -+ pa_mute_control *old_control; -+ -+ pa_assert(stream); -+ -+ old_control = stream->mute_control; -+ -+ if (control == old_control) -+ return; -+ -+ if (old_control) { -+ /* If the old control pointed to the own mute control of an audio -+ * group, then the stream's audio group for mute needs to be updated. -+ * We set it to NULL here, and if it should be non-NULL, that will be -+ * fixed very soon (a few lines down). */ -+ pas_stream_set_audio_group_for_mute(stream, NULL); -+ -+ pa_mute_control_remove_stream(old_control, stream); -+ } -+ -+ stream->mute_control = control; -+ -+ if (control) { -+ pa_mute_control_add_stream(control, stream); -+ pas_stream_set_audio_group_for_mute(stream, control->owner_audio_group); -+ } -+ -+ if (!stream->linked || stream->unlinked) -+ return; -+ -+ pa_log_debug("The mute control of stream %s changed from %s to %s.", stream->name, -+ old_control ? old_control->name : "(unset)", control ? control->name : "(unset)"); -+ -+ pa_hook_fire(&stream->volume_api->hooks[PA_VOLUME_API_HOOK_STREAM_MUTE_CONTROL_CHANGED], stream); -+} -+ -+void pas_stream_put(pas_stream *stream, pa_proplist *initial_properties) { -+ const char *prop_key; -+ void *state = NULL; -+ -+ pa_assert(stream); -+ pa_assert(!stream->create_own_volume_control || stream->delete_own_volume_control); -+ pa_assert(!stream->create_own_mute_control || stream->delete_own_mute_control); -+ -+ if (initial_properties) -+ pa_proplist_update(stream->proplist, PA_UPDATE_REPLACE, initial_properties); -+ -+ pa_hook_fire(&stream->volume_api->hooks[PA_VOLUME_API_HOOK_STREAM_SET_INITIAL_VOLUME_CONTROL], stream); -+ -+ if (stream->use_default_volume_control) -+ set_volume_control_internal(stream, stream->own_volume_control); -+ -+ pa_hook_fire(&stream->volume_api->hooks[PA_VOLUME_API_HOOK_STREAM_SET_INITIAL_MUTE_CONTROL], stream); -+ -+ if (stream->use_default_mute_control) -+ set_mute_control_internal(stream, stream->own_mute_control); -+ -+ pa_volume_api_add_stream(stream->volume_api, stream); -+ -+ stream->linked = true; -+ -+ pa_log_debug("Created stream #%u.", stream->index); -+ pa_log_debug(" Name: %s", stream->name); -+ pa_log_debug(" Description: %s", stream->description); -+ pa_log_debug(" Direction: %s", pa_direction_to_string(stream->direction)); -+ pa_log_debug(" Volume control: %s", stream->volume_control ? stream->volume_control->name : "(unset)"); -+ pa_log_debug(" Mute control: %s", stream->mute_control ? stream->mute_control->name : "(unset)"); -+ pa_log_debug(" Properties:"); -+ -+ while ((prop_key = pa_proplist_iterate(stream->proplist, &state))) -+ pa_log_debug(" %s = %s", prop_key, pa_strnull(pa_proplist_gets(stream->proplist, prop_key))); -+ -+ pa_hook_fire(&stream->volume_api->hooks[PA_VOLUME_API_HOOK_STREAM_PUT], stream); -+} -+ -+void pas_stream_unlink(pas_stream *stream) { -+ pa_assert(stream); -+ -+ if (stream->unlinked) { -+ pa_log_debug("Unlinking stream %s (already unlinked, this is a no-op).", stream->name); -+ return; -+ } -+ -+ stream->unlinked = true; -+ -+ pa_log_debug("Unlinking stream %s.", stream->name); -+ -+ if (stream->linked) -+ pa_hook_fire(&stream->volume_api->hooks[PA_VOLUME_API_HOOK_STREAM_UNLINK], stream); -+ -+ pa_volume_api_remove_stream(stream->volume_api, stream); -+ -+ pas_stream_set_audio_group_for_mute(stream, NULL); -+ pas_stream_set_audio_group_for_volume(stream, NULL); -+ pas_stream_set_mute_control(stream, NULL); -+ pas_stream_set_volume_control(stream, NULL); -+ pas_stream_set_have_own_mute_control(stream, false); -+ pas_stream_set_have_own_volume_control(stream, false); -+} -+ -+void pas_stream_free(pas_stream *stream) { -+ pa_assert(stream); -+ -+ if (!stream->unlinked) -+ pas_stream_unlink(stream); -+ -+ if (stream->proplist) -+ pa_proplist_free(stream->proplist); -+ -+ pa_xfree(stream->description); -+ -+ if (stream->name) -+ pa_volume_api_unregister_name(stream->volume_api, stream->name); -+ -+ pa_xfree(stream); -+} -+ -+int pas_stream_set_have_own_volume_control(pas_stream *stream, bool have) { -+ pa_assert(stream); -+ -+ if (have == stream->have_own_volume_control) -+ return 0; -+ -+ if (have) { -+ pa_assert(!stream->own_volume_control); -+ -+ if (!stream->create_own_volume_control) { -+ pa_log_debug("Stream %s doesn't support own volume control.", stream->name); -+ return -PA_ERR_NOTSUPPORTED; -+ } -+ -+ stream->own_volume_control = stream->create_own_volume_control(stream); -+ } else { -+ stream->delete_own_volume_control(stream); -+ stream->own_volume_control = NULL; -+ } -+ -+ stream->have_own_volume_control = have; -+ -+ return 0; -+} -+ -+int pas_stream_set_have_own_mute_control(pas_stream *stream, bool have) { -+ pa_assert(stream); -+ -+ if (have == stream->have_own_mute_control) -+ return 0; -+ -+ if (have) { -+ pa_assert(!stream->own_mute_control); -+ -+ if (!stream->create_own_mute_control) { -+ pa_log_debug("Stream %s doesn't support own mute control.", stream->name); -+ return -PA_ERR_NOTSUPPORTED; -+ } -+ -+ stream->own_mute_control = stream->create_own_mute_control(stream); -+ } else { -+ stream->delete_own_mute_control(stream); -+ stream->own_mute_control = NULL; -+ } -+ -+ stream->have_own_mute_control = have; -+ -+ return 0; -+} -+ -+void pas_stream_set_volume_control(pas_stream *stream, pa_volume_control *control) { -+ pa_assert(stream); -+ -+ stream->use_default_volume_control = false; -+ -+ if (stream->volume_control_binding) { -+ pa_binding_free(stream->volume_control_binding); -+ stream->volume_control_binding = NULL; -+ } -+ -+ set_volume_control_internal(stream, control); -+} -+ -+void pas_stream_set_mute_control(pas_stream *stream, pa_mute_control *control) { -+ pa_assert(stream); -+ -+ stream->use_default_mute_control = false; -+ -+ if (stream->mute_control_binding) { -+ pa_binding_free(stream->mute_control_binding); -+ stream->mute_control_binding = NULL; -+ } -+ -+ set_mute_control_internal(stream, control); -+} -+ -+void pas_stream_bind_volume_control(pas_stream *stream, pa_binding_target_info *target_info) { -+ pa_binding_owner_info owner_info = { -+ .userdata = stream, -+ .set_value = (pa_binding_set_value_cb_t) set_volume_control_internal, -+ }; -+ -+ pa_assert(stream); -+ pa_assert(target_info); -+ -+ stream->use_default_volume_control = false; -+ -+ if (stream->volume_control_binding) -+ pa_binding_free(stream->volume_control_binding); -+ -+ stream->volume_control_binding = pa_binding_new(stream->volume_api, &owner_info, target_info); -+} -+ -+void pas_stream_bind_mute_control(pas_stream *stream, pa_binding_target_info *target_info) { -+ pa_binding_owner_info owner_info = { -+ .userdata = stream, -+ .set_value = (pa_binding_set_value_cb_t) set_mute_control_internal, -+ }; -+ -+ pa_assert(stream); -+ pa_assert(target_info); -+ -+ stream->use_default_mute_control = false; -+ -+ if (stream->mute_control_binding) -+ pa_binding_free(stream->mute_control_binding); -+ -+ stream->mute_control_binding = pa_binding_new(stream->volume_api, &owner_info, target_info); -+} -+ -+void pas_stream_description_changed(pas_stream *stream, const char *new_description) { -+ char *old_description; -+ -+ pa_assert(stream); -+ pa_assert(new_description); -+ -+ old_description = stream->description; -+ -+ if (pa_streq(new_description, old_description)) -+ return; -+ -+ stream->description = pa_xstrdup(new_description); -+ pa_log_debug("The description of stream %s changed from \"%s\" to \"%s\".", stream->name, old_description, -+ new_description); -+ pa_xfree(old_description); -+ pa_hook_fire(&stream->volume_api->hooks[PA_VOLUME_API_HOOK_STREAM_DESCRIPTION_CHANGED], stream); -+} -+ -+void pas_stream_set_audio_group_for_volume(pas_stream *stream, pa_audio_group *group) { -+ pa_assert(stream); -+ -+ if (group == stream->audio_group_for_volume) -+ return; -+ -+ if (stream->audio_group_for_volume) -+ pa_audio_group_remove_volume_stream(stream->audio_group_for_volume, stream); -+ -+ stream->audio_group_for_volume = group; -+ -+ if (group) -+ pa_audio_group_add_volume_stream(group, stream); -+} -+ -+void pas_stream_set_audio_group_for_mute(pas_stream *stream, pa_audio_group *group) { -+ pa_assert(stream); -+ -+ if (group == stream->audio_group_for_mute) -+ return; -+ -+ if (stream->audio_group_for_mute) -+ pa_audio_group_remove_mute_stream(stream->audio_group_for_mute, stream); -+ -+ stream->audio_group_for_mute = group; -+ -+ if (group) -+ pa_audio_group_add_mute_stream(group, stream); -+} -diff --git a/src/modules/volume-api/sstream.h b/src/modules/volume-api/sstream.h -new file mode 100644 -index 0000000..a65b34c ---- /dev/null -+++ b/src/modules/volume-api/sstream.h -@@ -0,0 +1,108 @@ -+#ifndef foosstreamhfoo -+#define foosstreamhfoo -+ -+/*** -+ This file is part of PulseAudio. -+ -+ Copyright 2014 Intel Corporation -+ -+ PulseAudio is free software; you can redistribute it and/or modify -+ it under the terms of the GNU Lesser General Public License as published -+ by the Free Software Foundation; either version 2.1 of the License, -+ or (at your option) any later version. -+ -+ PulseAudio 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 Lesser General Public License -+ along with PulseAudio; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ USA. -+***/ -+ -+#include -+ -+/* We use the "pas_" prefix in pas_stream, because there's already pa_stream in -+ * the client API, and there's no good alternative term for streams. The 's' in -+ * "pas" means "server", i.e. the point is that this stuff is for servers, -+ * while pa_stream is for clients. */ -+ -+typedef struct pas_stream pas_stream; -+ -+struct pas_stream { -+ pa_volume_api *volume_api; -+ uint32_t index; -+ const char *name; -+ char *description; -+ pa_direction_t direction; -+ pa_proplist *proplist; -+ pa_volume_control *volume_control; -+ pa_mute_control *mute_control; -+ bool use_default_volume_control; -+ bool use_default_mute_control; -+ bool have_own_volume_control; -+ bool have_own_mute_control; -+ pa_volume_control *own_volume_control; -+ pa_mute_control *own_mute_control; -+ -+ pa_binding *volume_control_binding; -+ pa_binding *mute_control_binding; -+ pa_audio_group *audio_group_for_volume; -+ pa_audio_group *audio_group_for_mute; -+ -+ bool linked; -+ bool unlinked; -+ -+ /* Called when the own volume control is enabled. The callback -+ * implementation should return a new linked volume control object. The -+ * callback may be NULL, in which case the own volume control can't be -+ * enabled. */ -+ pa_volume_control *(*create_own_volume_control)(pas_stream *stream); -+ -+ /* Called when the own volume control is disabled. The implementation -+ * should free stream->own_volume_control. The callback may be NULL only if -+ * create_own_volume_control is NULL also. */ -+ void (*delete_own_volume_control)(pas_stream *stream); -+ -+ /* Called when the own mute control is enabled. The callback implementation -+ * should return a new linked mute control object. The callback may be -+ * NULL, in which case the own mute control can't be enabled. */ -+ pa_mute_control *(*create_own_mute_control)(pas_stream *stream); -+ -+ /* Called when the own mute control is disabled. The implementation should -+ * free stream->own_mute_control. The callback may be NULL only if -+ * create_own_mute_control is NULL also. */ -+ void (*delete_own_mute_control)(pas_stream *stream); -+ -+ void *userdata; -+}; -+ -+pas_stream *pas_stream_new(pa_volume_api *api, const char *name, const char *description, pa_direction_t direction); -+void pas_stream_put(pas_stream *stream, pa_proplist *initial_properties); -+void pas_stream_unlink(pas_stream *stream); -+void pas_stream_free(pas_stream *stream); -+ -+/* Called by the stream implementation and possibly by policy modules. -+ * Enabling own controls may fail (the stream may not support own controls), -+ * disabling will never fail. */ -+int pas_stream_set_have_own_volume_control(pas_stream *stream, bool have); -+int pas_stream_set_have_own_mute_control(pas_stream *stream, bool have); -+ -+/* Called by policy modules. */ -+void pas_stream_set_volume_control(pas_stream *stream, pa_volume_control *control); -+void pas_stream_set_mute_control(pas_stream *stream, pa_mute_control *control); -+void pas_stream_bind_volume_control(pas_stream *stream, pa_binding_target_info *target_info); -+void pas_stream_bind_mute_control(pas_stream *stream, pa_binding_target_info *target_info); -+ -+/* Called by the stream implementation. */ -+void pas_stream_description_changed(pas_stream *stream, const char *new_description); -+ -+/* Called by audio-group.c only. Adding a stream to an audio group happens -+ * implicitly when the volume or mute control of a stream is set to point to -+ * the own control of an audio group. */ -+void pas_stream_set_audio_group_for_volume(pas_stream *stream, pa_audio_group *group); -+void pas_stream_set_audio_group_for_mute(pas_stream *stream, pa_audio_group *group); -+ -+#endif -diff --git a/src/modules/volume-api/stream-creator.c b/src/modules/volume-api/stream-creator.c -new file mode 100644 -index 0000000..2bd0053 ---- /dev/null -+++ b/src/modules/volume-api/stream-creator.c -@@ -0,0 +1,691 @@ -+/*** -+ This file is part of PulseAudio. -+ -+ Copyright 2014 Intel Corporation -+ -+ PulseAudio is free software; you can redistribute it and/or modify -+ it under the terms of the GNU Lesser General Public License as published -+ by the Free Software Foundation; either version 2.1 of the License, -+ or (at your option) any later version. -+ -+ PulseAudio 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 Lesser General Public License -+ along with PulseAudio; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ USA. -+***/ -+ -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ -+#include "stream-creator.h" -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+struct pa_stream_creator { -+ pa_volume_api *volume_api; -+ pa_hashmap *streams; /* pa_sink_input/pa_source_output -> struct stream */ -+ pa_hook_slot *sink_input_put_slot; -+ pa_hook_slot *sink_input_unlink_slot; -+ pa_hook_slot *source_output_put_slot; -+ pa_hook_slot *source_output_unlink_slot; -+}; -+ -+enum stream_type { -+ STREAM_TYPE_SINK_INPUT, -+ STREAM_TYPE_SOURCE_OUTPUT, -+}; -+ -+struct stream { -+ pa_stream_creator *creator; -+ enum stream_type type; -+ pa_sink_input *sink_input; -+ pa_source_output *source_output; -+ pa_client *client; -+ pas_stream *stream; -+ -+ bool unlinked; -+ -+ pa_hook_slot *proplist_changed_slot; -+ pa_hook_slot *client_proplist_changed_slot; -+ pa_hook_slot *volume_changed_slot; -+ pa_hook_slot *mute_changed_slot; -+}; -+ -+static char *get_stream_volume_and_mute_control_description_malloc(struct stream *stream) { -+ const char *application_name = NULL; -+ char *description; -+ -+ pa_assert(stream); -+ -+ if (stream->client) -+ application_name = pa_proplist_gets(stream->client->proplist, PA_PROP_APPLICATION_NAME); -+ -+ if (application_name) -+ description = pa_sprintf_malloc("%s: %s", application_name, stream->stream->description); -+ else -+ description = pa_xstrdup(stream->stream->description); -+ -+ return description; -+} -+ -+static int volume_control_set_volume_cb(pa_volume_control *control, const pa_bvolume *volume, bool set_volume, bool set_balance) { -+ struct stream *stream; -+ pa_bvolume bvolume; -+ pa_cvolume cvolume; -+ -+ pa_assert(control); -+ pa_assert(volume); -+ -+ stream = control->userdata; -+ -+ switch (stream->type) { -+ case STREAM_TYPE_SINK_INPUT: -+ pa_bvolume_from_cvolume(&bvolume, &stream->sink_input->volume, &stream->sink_input->channel_map); -+ break; -+ -+ case STREAM_TYPE_SOURCE_OUTPUT: -+ pa_bvolume_from_cvolume(&bvolume, &stream->source_output->volume, &stream->source_output->channel_map); -+ break; -+ } -+ -+ if (set_volume) -+ bvolume.volume = volume->volume; -+ -+ if (set_balance) -+ pa_bvolume_copy_balance(&bvolume, volume); -+ -+ pa_bvolume_to_cvolume(&bvolume, &cvolume); -+ -+ switch (stream->type) { -+ case STREAM_TYPE_SINK_INPUT: -+ pa_sink_input_set_volume(stream->sink_input, &cvolume, true, true); -+ break; -+ -+ case STREAM_TYPE_SOURCE_OUTPUT: -+ pa_source_output_set_volume(stream->source_output, &cvolume, true, true); -+ break; -+ } -+ -+ return 0; -+} -+ -+static pa_hook_result_t sink_input_or_source_output_volume_changed_cb(void *hook_data, void *call_data, void *userdata) { -+ struct stream *stream = userdata; -+ pa_sink_input *input = NULL; -+ pa_source_output *output = NULL; -+ pa_bvolume bvolume; -+ -+ pa_assert(stream); -+ pa_assert(call_data); -+ -+ switch (stream->type) { -+ case STREAM_TYPE_SINK_INPUT: -+ input = call_data; -+ break; -+ -+ case STREAM_TYPE_SOURCE_OUTPUT: -+ output = call_data; -+ break; -+ } -+ -+ if ((input && input != stream->sink_input) || (output && output != stream->source_output)) -+ return PA_HOOK_OK; -+ -+ if (input) -+ pa_bvolume_from_cvolume(&bvolume, &input->volume, &input->channel_map); -+ else -+ pa_bvolume_from_cvolume(&bvolume, &output->volume, &output->channel_map); -+ -+ pa_volume_control_volume_changed(stream->stream->own_volume_control, &bvolume, true, true); -+ -+ return PA_HOOK_OK; -+} -+ -+static void volume_control_set_initial_volume_cb(pa_volume_control *control) { -+ struct stream *stream; -+ pa_cvolume cvolume; -+ -+ pa_assert(control); -+ -+ stream = control->userdata; -+ pa_bvolume_to_cvolume(&control->volume, &cvolume); -+ -+ switch (stream->type) { -+ case STREAM_TYPE_SINK_INPUT: -+ pa_sink_input_set_volume(stream->sink_input, &cvolume, true, true); -+ break; -+ -+ case STREAM_TYPE_SOURCE_OUTPUT: -+ pa_source_output_set_volume(stream->source_output, &cvolume, true, true); -+ break; -+ } -+} -+ -+static int mute_control_set_mute_cb(pa_mute_control *control, bool mute) { -+ struct stream *stream; -+ -+ pa_assert(control); -+ -+ stream = control->userdata; -+ -+ switch (stream->type) { -+ case STREAM_TYPE_SINK_INPUT: -+ pa_sink_input_set_mute(stream->sink_input, mute, true); -+ break; -+ -+ case STREAM_TYPE_SOURCE_OUTPUT: -+ pa_source_output_set_mute(stream->source_output, mute, true); -+ break; -+ } -+ -+ return 0; -+} -+ -+static pa_hook_result_t sink_input_or_source_output_mute_changed_cb(void *hook_data, void *call_data, void *userdata) { -+ struct stream *stream = userdata; -+ pa_sink_input *input = NULL; -+ pa_source_output *output = NULL; -+ bool mute; -+ -+ pa_assert(stream); -+ pa_assert(call_data); -+ -+ switch (stream->type) { -+ case STREAM_TYPE_SINK_INPUT: -+ input = call_data; -+ break; -+ -+ case STREAM_TYPE_SOURCE_OUTPUT: -+ output = call_data; -+ break; -+ } -+ -+ if ((input && input != stream->sink_input) || (output && output != stream->source_output)) -+ return PA_HOOK_OK; -+ -+ if (input) -+ mute = input->muted; -+ else -+ mute = output->muted; -+ -+ pa_mute_control_mute_changed(stream->stream->own_mute_control, mute); -+ -+ return PA_HOOK_OK; -+} -+ -+static void mute_control_set_initial_mute_cb(pa_mute_control *control) { -+ struct stream *stream; -+ -+ pa_assert(control); -+ -+ stream = control->userdata; -+ -+ switch (stream->type) { -+ case STREAM_TYPE_SINK_INPUT: -+ pa_sink_input_set_mute(stream->sink_input, control->mute, true); -+ break; -+ -+ case STREAM_TYPE_SOURCE_OUTPUT: -+ pa_source_output_set_mute(stream->source_output, control->mute, true); -+ break; -+ } -+} -+ -+static const char *get_sink_input_description(pa_sink_input *input) { -+ const char *description; -+ -+ pa_assert(input); -+ -+ description = pa_proplist_gets(input->proplist, PA_PROP_MEDIA_NAME); -+ if (description) -+ return description; -+ -+ return NULL; -+} -+ -+static const char *get_source_output_description(pa_source_output *output) { -+ const char *description; -+ -+ pa_assert(output); -+ -+ description = pa_proplist_gets(output->proplist, PA_PROP_MEDIA_NAME); -+ if (description) -+ return description; -+ -+ return NULL; -+} -+ -+static pa_volume_control *stream_create_own_volume_control_cb(pas_stream *s) { -+ struct stream *stream; -+ const char *name = NULL; -+ char *description; -+ pa_volume_control *control; -+ pa_bvolume volume; -+ -+ pa_assert(s); -+ -+ stream = s->userdata; -+ -+ switch (stream->type) { -+ case STREAM_TYPE_SINK_INPUT: -+ name = "sink-input-volume-control"; -+ break; -+ -+ case STREAM_TYPE_SOURCE_OUTPUT: -+ name = "source-output-volume-control"; -+ break; -+ } -+ -+ description = get_stream_volume_and_mute_control_description_malloc(stream); -+ control = pa_volume_control_new(stream->creator->volume_api, name, description, true, false); -+ pa_xfree(description); -+ control->set_volume = volume_control_set_volume_cb; -+ control->userdata = stream; -+ -+ pa_assert(!stream->volume_changed_slot); -+ -+ switch (stream->type) { -+ case STREAM_TYPE_SINK_INPUT: -+ stream->volume_changed_slot = -+ pa_hook_connect(&stream->sink_input->core->hooks[PA_CORE_HOOK_SINK_INPUT_VOLUME_CHANGED], PA_HOOK_NORMAL, -+ sink_input_or_source_output_volume_changed_cb, stream); -+ pa_bvolume_from_cvolume(&volume, &stream->sink_input->volume, &stream->sink_input->channel_map); -+ break; -+ -+ case STREAM_TYPE_SOURCE_OUTPUT: -+ stream->volume_changed_slot = -+ pa_hook_connect(&stream->source_output->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_VOLUME_CHANGED], -+ PA_HOOK_NORMAL, sink_input_or_source_output_volume_changed_cb, stream); -+ pa_bvolume_from_cvolume(&volume, &stream->source_output->volume, &stream->source_output->channel_map); -+ break; -+ } -+ -+ pa_volume_control_put(control, &volume, volume_control_set_initial_volume_cb); -+ -+ return control; -+} -+ -+static void stream_delete_own_volume_control_cb(pas_stream *s) { -+ struct stream *stream; -+ -+ pa_assert(s); -+ -+ stream = s->userdata; -+ pa_hook_slot_free(stream->volume_changed_slot); -+ stream->volume_changed_slot = NULL; -+ pa_volume_control_free(s->own_volume_control); -+} -+ -+static pa_mute_control *stream_create_own_mute_control_cb(pas_stream *s) { -+ struct stream *stream; -+ const char *name = NULL; -+ char *description; -+ pa_mute_control *control; -+ bool mute = false; -+ -+ pa_assert(s); -+ -+ stream = s->userdata; -+ -+ switch (stream->type) { -+ case STREAM_TYPE_SINK_INPUT: -+ name = "sink-input-mute-control"; -+ break; -+ -+ case STREAM_TYPE_SOURCE_OUTPUT: -+ name = "source-output-mute-control"; -+ break; -+ } -+ -+ description = get_stream_volume_and_mute_control_description_malloc(stream); -+ control = pa_mute_control_new(stream->creator->volume_api, name, description); -+ pa_xfree(description); -+ control->set_mute = mute_control_set_mute_cb; -+ control->userdata = stream; -+ -+ pa_assert(!stream->mute_changed_slot); -+ -+ switch (stream->type) { -+ case STREAM_TYPE_SINK_INPUT: -+ stream->mute_changed_slot = -+ pa_hook_connect(&stream->sink_input->core->hooks[PA_CORE_HOOK_SINK_INPUT_MUTE_CHANGED], PA_HOOK_NORMAL, -+ sink_input_or_source_output_mute_changed_cb, stream); -+ mute = stream->sink_input->muted; -+ break; -+ -+ case STREAM_TYPE_SOURCE_OUTPUT: -+ stream->mute_changed_slot = -+ pa_hook_connect(&stream->source_output->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MUTE_CHANGED], -+ PA_HOOK_NORMAL, sink_input_or_source_output_mute_changed_cb, stream); -+ mute = stream->source_output->muted; -+ break; -+ } -+ -+ pa_mute_control_put(control, mute, true, mute_control_set_initial_mute_cb); -+ -+ return control; -+} -+ -+static void stream_delete_own_mute_control_cb(pas_stream *s) { -+ struct stream *stream; -+ -+ pa_assert(s); -+ -+ stream = s->userdata; -+ pa_hook_slot_free(stream->mute_changed_slot); -+ stream->mute_changed_slot = NULL; -+ pa_mute_control_free(s->own_mute_control); -+} -+ -+static pa_hook_result_t sink_input_or_source_output_proplist_changed_cb(void *hook_data, void *call_data, void *userdata) { -+ struct stream *stream = userdata; -+ pa_sink_input *input = NULL; -+ pa_source_output *output = NULL; -+ const char *new_stream_description = NULL; -+ char *new_control_description; -+ -+ pa_assert(stream); -+ pa_assert(call_data); -+ -+ switch (stream->type) { -+ case STREAM_TYPE_SINK_INPUT: -+ input = call_data; -+ -+ if (input != stream->sink_input) -+ return PA_HOOK_OK; -+ -+ new_stream_description = get_sink_input_description(input); -+ if (!new_stream_description) -+ new_stream_description = stream->stream->name; -+ break; -+ -+ case STREAM_TYPE_SOURCE_OUTPUT: -+ output = call_data; -+ -+ if (output != stream->source_output) -+ return PA_HOOK_OK; -+ -+ new_stream_description = get_source_output_description(output); -+ if (!new_stream_description) -+ new_stream_description = stream->stream->name; -+ break; -+ } -+ -+ pas_stream_description_changed(stream->stream, new_stream_description); -+ -+ new_control_description = get_stream_volume_and_mute_control_description_malloc(stream); -+ -+ if (stream->stream->own_volume_control) -+ pa_volume_control_description_changed(stream->stream->own_volume_control, new_control_description); -+ -+ if (stream->stream->own_mute_control) -+ pa_mute_control_description_changed(stream->stream->own_mute_control, new_control_description); -+ -+ pa_xfree(new_control_description); -+ -+ return PA_HOOK_OK; -+} -+ -+static pa_hook_result_t client_proplist_changed_cb(void *hook_data, void *call_data, void *userdata) { -+ struct stream *stream = userdata; -+ pa_client *client = call_data; -+ char *description; -+ -+ pa_assert(stream); -+ pa_assert(client); -+ -+ if (client != stream->client) -+ return PA_HOOK_OK; -+ -+ description = get_stream_volume_and_mute_control_description_malloc(stream); -+ -+ if (stream->stream->own_volume_control) -+ pa_volume_control_description_changed(stream->stream->own_volume_control, description); -+ -+ if (stream->stream->own_mute_control) -+ pa_mute_control_description_changed(stream->stream->own_mute_control, description); -+ -+ pa_xfree(description); -+ -+ return PA_HOOK_OK; -+} -+ -+static struct stream *stream_new(pa_stream_creator *creator, enum stream_type type, void *core_stream) { -+ struct stream *stream; -+ const char *name = NULL; -+ const char *description = NULL; -+ pa_direction_t direction = PA_DIRECTION_OUTPUT; -+ -+ pa_assert(creator); -+ pa_assert(core_stream); -+ -+ stream = pa_xnew0(struct stream, 1); -+ stream->creator = creator; -+ stream->type = type; -+ -+ switch (type) { -+ case STREAM_TYPE_SINK_INPUT: -+ stream->sink_input = core_stream; -+ stream->client = stream->sink_input->client; -+ name = "sink-input-stream"; -+ -+ description = get_sink_input_description(stream->sink_input); -+ if (!description) -+ description = name; -+ -+ direction = PA_DIRECTION_OUTPUT; -+ break; -+ -+ case STREAM_TYPE_SOURCE_OUTPUT: -+ stream->source_output = core_stream; -+ stream->client = stream->source_output->client; -+ name = "source-output-stream"; -+ -+ description = get_source_output_description(stream->source_output); -+ if (!description) -+ description = name; -+ -+ direction = PA_DIRECTION_INPUT; -+ break; -+ } -+ -+ stream->stream = pas_stream_new(creator->volume_api, name, description, direction); -+ stream->stream->create_own_volume_control = stream_create_own_volume_control_cb; -+ stream->stream->delete_own_volume_control = stream_delete_own_volume_control_cb; -+ stream->stream->create_own_mute_control = stream_create_own_mute_control_cb; -+ stream->stream->delete_own_mute_control = stream_delete_own_mute_control_cb; -+ stream->stream->userdata = stream; -+ pas_stream_set_have_own_volume_control(stream->stream, true); -+ pas_stream_set_have_own_mute_control(stream->stream, true); -+ -+ switch (type) { -+ case STREAM_TYPE_SINK_INPUT: -+ stream->proplist_changed_slot = -+ pa_hook_connect(&stream->sink_input->core->hooks[PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED], PA_HOOK_NORMAL, -+ sink_input_or_source_output_proplist_changed_cb, stream); -+ break; -+ -+ case STREAM_TYPE_SOURCE_OUTPUT: -+ stream->proplist_changed_slot = -+ pa_hook_connect(&stream->source_output->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PROPLIST_CHANGED], -+ PA_HOOK_NORMAL, sink_input_or_source_output_proplist_changed_cb, stream); -+ break; -+ } -+ -+ stream->client_proplist_changed_slot = -+ pa_hook_connect(&stream->creator->volume_api->core->hooks[PA_CORE_HOOK_CLIENT_PROPLIST_CHANGED], -+ PA_HOOK_NORMAL, client_proplist_changed_cb, stream); -+ -+ return stream; -+} -+ -+static void stream_put(struct stream *stream) { -+ pa_proplist *proplist = NULL; -+ -+ pa_assert(stream); -+ -+ switch (stream->type) { -+ case STREAM_TYPE_SINK_INPUT: -+ proplist = stream->sink_input->proplist; -+ break; -+ -+ case STREAM_TYPE_SOURCE_OUTPUT: -+ proplist = stream->source_output->proplist; -+ break; -+ } -+ -+ pas_stream_put(stream->stream, proplist); -+} -+ -+static void stream_unlink(struct stream *stream) { -+ pa_assert(stream); -+ -+ if (stream->unlinked) -+ return; -+ -+ stream->unlinked = true; -+ -+ if (stream->stream) -+ pas_stream_unlink(stream->stream); -+} -+ -+static void stream_free(struct stream *stream) { -+ pa_assert(stream); -+ -+ if (!stream->unlinked) -+ stream_unlink(stream); -+ -+ if (stream->client_proplist_changed_slot) -+ pa_hook_slot_free(stream->client_proplist_changed_slot); -+ -+ if (stream->proplist_changed_slot) -+ pa_hook_slot_free(stream->proplist_changed_slot); -+ -+ if (stream->stream) -+ pas_stream_free(stream->stream); -+ -+ pa_xfree(stream); -+} -+ -+static void create_stream(pa_stream_creator *creator, enum stream_type type, void *core_stream) { -+ struct stream *stream; -+ -+ pa_assert(creator); -+ pa_assert(core_stream); -+ -+ stream = stream_new(creator, type, core_stream); -+ pa_hashmap_put(creator->streams, core_stream, stream); -+ stream_put(stream); -+} -+ -+static pa_hook_result_t sink_input_put_cb(void *hook_data, void *call_data, void *userdata) { -+ pa_stream_creator *creator = userdata; -+ pa_sink_input *input = call_data; -+ -+ pa_assert(creator); -+ pa_assert(input); -+ -+ create_stream(creator, STREAM_TYPE_SINK_INPUT, input); -+ -+ return PA_HOOK_OK; -+} -+ -+static pa_hook_result_t sink_input_unlink_cb(void *hook_data, void *call_data, void *userdata) { -+ pa_stream_creator *creator = userdata; -+ pa_sink_input *input = call_data; -+ -+ pa_assert(creator); -+ pa_assert(input); -+ -+ pa_hashmap_remove_and_free(creator->streams, input); -+ -+ return PA_HOOK_OK; -+} -+ -+static pa_hook_result_t source_output_put_cb(void *hook_data, void *call_data, void *userdata) { -+ pa_stream_creator *creator = userdata; -+ pa_source_output *output = call_data; -+ -+ pa_assert(creator); -+ pa_assert(output); -+ -+ create_stream(creator, STREAM_TYPE_SOURCE_OUTPUT, output); -+ -+ return PA_HOOK_OK; -+} -+ -+static pa_hook_result_t source_output_unlink_cb(void *hook_data, void *call_data, void *userdata) { -+ pa_stream_creator *creator = userdata; -+ pa_source_output *output = call_data; -+ -+ pa_assert(creator); -+ pa_assert(output); -+ -+ pa_hashmap_remove_and_free(creator->streams, output); -+ -+ return PA_HOOK_OK; -+} -+ -+pa_stream_creator *pa_stream_creator_new(pa_volume_api *api) { -+ pa_stream_creator *creator; -+ uint32_t idx; -+ pa_sink_input *input; -+ pa_source_output *output; -+ -+ pa_assert(api); -+ -+ creator = pa_xnew0(pa_stream_creator, 1); -+ creator->volume_api = api; -+ creator->streams = pa_hashmap_new_full(NULL, NULL, NULL, (pa_free_cb_t) stream_free); -+ creator->sink_input_put_slot = pa_hook_connect(&api->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT], PA_HOOK_NORMAL, -+ sink_input_put_cb, creator); -+ creator->sink_input_unlink_slot = pa_hook_connect(&api->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK], PA_HOOK_NORMAL, -+ sink_input_unlink_cb, creator); -+ creator->source_output_put_slot = pa_hook_connect(&api->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PUT], PA_HOOK_NORMAL, -+ source_output_put_cb, creator); -+ creator->source_output_unlink_slot = pa_hook_connect(&api->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK], PA_HOOK_NORMAL, -+ source_output_unlink_cb, creator); -+ -+ PA_IDXSET_FOREACH(input, api->core->sink_inputs, idx) -+ create_stream(creator, STREAM_TYPE_SINK_INPUT, input); -+ -+ PA_IDXSET_FOREACH(output, api->core->source_outputs, idx) -+ create_stream(creator, STREAM_TYPE_SOURCE_OUTPUT, output); -+ -+ return creator; -+} -+ -+void pa_stream_creator_free(pa_stream_creator *creator) { -+ pa_assert(creator); -+ -+ if (creator->streams) -+ pa_hashmap_remove_all(creator->streams); -+ -+ if (creator->source_output_unlink_slot) -+ pa_hook_slot_free(creator->source_output_unlink_slot); -+ -+ if (creator->source_output_put_slot) -+ pa_hook_slot_free(creator->source_output_put_slot); -+ -+ if (creator->sink_input_unlink_slot) -+ pa_hook_slot_free(creator->sink_input_unlink_slot); -+ -+ if (creator->sink_input_put_slot) -+ pa_hook_slot_free(creator->sink_input_put_slot); -+ -+ if (creator->streams) -+ pa_hashmap_free(creator->streams); -+ -+ pa_xfree(creator); -+} -diff --git a/src/modules/volume-api/stream-creator.h b/src/modules/volume-api/stream-creator.h -new file mode 100644 -index 0000000..97a03a4 ---- /dev/null -+++ b/src/modules/volume-api/stream-creator.h -@@ -0,0 +1,32 @@ -+#ifndef foostreamcreatorhfoo -+#define foostreamcreatorhfoo -+ -+/*** -+ This file is part of PulseAudio. -+ -+ Copyright 2014 Intel Corporation -+ -+ PulseAudio is free software; you can redistribute it and/or modify -+ it under the terms of the GNU Lesser General Public License as published -+ by the Free Software Foundation; either version 2.1 of the License, -+ or (at your option) any later version. -+ -+ PulseAudio 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 Lesser General Public License -+ along with PulseAudio; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ USA. -+***/ -+ -+#include -+ -+typedef struct pa_stream_creator pa_stream_creator; -+ -+pa_stream_creator *pa_stream_creator_new(pa_volume_api *api); -+void pa_stream_creator_free(pa_stream_creator *creator); -+ -+#endif -diff --git a/src/modules/volume-api/volume-api.c b/src/modules/volume-api/volume-api.c -new file mode 100644 -index 0000000..9abea7e ---- /dev/null -+++ b/src/modules/volume-api/volume-api.c -@@ -0,0 +1,647 @@ -+/*** -+ This file is part of PulseAudio. -+ -+ Copyright 2014 Intel Corporation -+ -+ PulseAudio is free software; you can redistribute it and/or modify -+ it under the terms of the GNU Lesser General Public License as published -+ by the Free Software Foundation; either version 2.1 of the License, -+ or (at your option) any later version. -+ -+ PulseAudio 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 Lesser General Public License -+ along with PulseAudio; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ USA. -+***/ -+ -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ -+#include "volume-api.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+static pa_volume_api *volume_api_new(pa_core *core); -+static void volume_api_free(pa_volume_api *api); -+ -+pa_volume_api *pa_volume_api_get(pa_core *core) { -+ pa_volume_api *api; -+ -+ pa_assert(core); -+ -+ api = pa_shared_get(core, "volume-api"); -+ -+ if (api) -+ pa_volume_api_ref(api); -+ else { -+ api = volume_api_new(core); -+ pa_assert_se(pa_shared_set(core, "volume-api", api) >= 0); -+ } -+ -+ return api; -+} -+ -+pa_volume_api *pa_volume_api_ref(pa_volume_api *api) { -+ pa_assert(api); -+ -+ api->refcnt++; -+ -+ return api; -+} -+ -+void pa_volume_api_unref(pa_volume_api *api) { -+ pa_assert(api); -+ pa_assert(api->refcnt > 0); -+ -+ api->refcnt--; -+ -+ if (api->refcnt == 0) { -+ pa_assert_se(pa_shared_remove(api->core, "volume-api") >= 0); -+ volume_api_free(api); -+ } -+} -+ -+void pa_volume_api_add_binding_target_type(pa_volume_api *api, pa_binding_target_type *type) { -+ pa_assert(api); -+ pa_assert(type); -+ -+ pa_assert_se(pa_hashmap_put(api->binding_target_types, type->name, type) >= 0); -+ -+ pa_log_debug("Added binding target type %s.", type->name); -+ -+ pa_hook_fire(&api->hooks[PA_VOLUME_API_HOOK_BINDING_TARGET_TYPE_ADDED], type); -+} -+ -+void pa_volume_api_remove_binding_target_type(pa_volume_api *api, pa_binding_target_type *type) { -+ pa_assert(api); -+ pa_assert(type); -+ -+ pa_log_debug("Removing binding target type %s.", type->name); -+ -+ pa_hook_fire(&api->hooks[PA_VOLUME_API_HOOK_BINDING_TARGET_TYPE_REMOVED], type); -+ -+ pa_assert_se(pa_hashmap_remove(api->binding_target_types, type->name)); -+} -+ -+static void create_builtin_binding_target_types(pa_volume_api *api) { -+ pa_binding_target_type *type; -+ -+ pa_assert(api); -+ -+ type = pa_audio_group_create_binding_target_type(api); -+ pa_volume_api_add_binding_target_type(api, type); -+} -+ -+static void delete_builtin_binding_target_types(pa_volume_api *api) { -+ pa_binding_target_type *type; -+ -+ pa_assert(api); -+ -+ type = pa_hashmap_get(api->binding_target_types, PA_AUDIO_GROUP_BINDING_TARGET_TYPE); -+ pa_volume_api_remove_binding_target_type(api, type); -+} -+ -+static void create_objects_defer_event_cb(pa_mainloop_api *mainloop_api, pa_defer_event *event, void *userdata) { -+ pa_volume_api *volume_api = userdata; -+ -+ pa_assert(volume_api); -+ pa_assert(event == volume_api->create_objects_defer_event); -+ -+ mainloop_api->defer_free(event); -+ volume_api->create_objects_defer_event = NULL; -+ -+ volume_api->device_creator = pa_device_creator_new(volume_api); -+ volume_api->stream_creator = pa_stream_creator_new(volume_api); -+} -+ -+static pa_volume_api *volume_api_new(pa_core *core) { -+ pa_volume_api *api; -+ unsigned i; -+ -+ pa_assert(core); -+ -+ api = pa_xnew0(pa_volume_api, 1); -+ api->core = core; -+ api->refcnt = 1; -+ api->binding_target_types = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); -+ api->names = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, pa_xfree); -+ api->volume_controls = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); -+ api->mute_controls = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); -+ api->devices = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); -+ api->streams = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); -+ api->audio_groups = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); -+ -+ for (i = 0; i < PA_VOLUME_API_HOOK_MAX; i++) -+ pa_hook_init(&api->hooks[i], api); -+ -+ create_builtin_binding_target_types(api); -+ -+ /* We delay the object creation to ensure that policy modules have a chance -+ * to affect the initialization of the objects. If we created the objects -+ * immediately, policy modules wouldn't have a chance of connecting to the -+ * object creation hooks before the objects are created. */ -+ api->create_objects_defer_event = core->mainloop->defer_new(core->mainloop, create_objects_defer_event_cb, api); -+ -+ pa_log_debug("Created a pa_volume_api object."); -+ -+ return api; -+} -+ -+static void volume_api_free(pa_volume_api *api) { -+ unsigned i; -+ -+ pa_assert(api); -+ pa_assert(api->refcnt == 0); -+ -+ pa_log_debug("Freeing the pa_volume_api object."); -+ -+ if (api->stream_creator) -+ pa_stream_creator_free(api->stream_creator); -+ -+ if (api->device_creator) -+ pa_device_creator_free(api->device_creator); -+ -+ if (api->create_objects_defer_event) -+ api->core->mainloop->defer_free(api->create_objects_defer_event); -+ -+ if (api->binding_target_types) -+ delete_builtin_binding_target_types(api); -+ -+ for (i = 0; i < PA_VOLUME_API_HOOK_MAX; i++) -+ pa_hook_done(&api->hooks[i]); -+ -+ if (api->audio_groups) { -+ pa_assert(pa_hashmap_isempty(api->audio_groups)); -+ pa_hashmap_free(api->audio_groups); -+ } -+ -+ if (api->streams) { -+ pa_assert(pa_hashmap_isempty(api->streams)); -+ pa_hashmap_free(api->streams); -+ } -+ -+ if (api->devices) { -+ pa_assert(pa_hashmap_isempty(api->devices)); -+ pa_hashmap_free(api->devices); -+ } -+ -+ if (api->mute_controls) { -+ pa_assert(pa_hashmap_isempty(api->mute_controls)); -+ pa_hashmap_free(api->mute_controls); -+ } -+ -+ if (api->volume_controls) { -+ pa_assert(pa_hashmap_isempty(api->volume_controls)); -+ pa_hashmap_free(api->volume_controls); -+ } -+ -+ if (api->names) { -+ pa_assert(pa_hashmap_isempty(api->names)); -+ pa_hashmap_free(api->names); -+ } -+ -+ if (api->binding_target_types) { -+ pa_assert(pa_hashmap_isempty(api->binding_target_types)); -+ pa_hashmap_free(api->binding_target_types); -+ } -+ -+ pa_xfree(api); -+} -+ -+int pa_volume_api_register_name(pa_volume_api *api, const char *requested_name, bool fail_if_already_registered, -+ const char **registered_name) { -+ char *n; -+ -+ pa_assert(api); -+ pa_assert(requested_name); -+ pa_assert(registered_name); -+ -+ n = pa_xstrdup(requested_name); -+ -+ if (pa_hashmap_put(api->names, n, n) < 0) { -+ unsigned i = 1; -+ -+ pa_xfree(n); -+ -+ if (fail_if_already_registered) { -+ pa_log("Name %s already registered.", requested_name); -+ return -PA_ERR_EXIST; -+ } -+ -+ do { -+ i++; -+ n = pa_sprintf_malloc("%s.%u", requested_name, i); -+ } while (pa_hashmap_put(api->names, n, n) < 0); -+ } -+ -+ *registered_name = n; -+ -+ return 0; -+} -+ -+void pa_volume_api_unregister_name(pa_volume_api *api, const char *name) { -+ pa_assert(api); -+ pa_assert(name); -+ -+ pa_assert_se(pa_hashmap_remove_and_free(api->names, name) >= 0); -+} -+ -+uint32_t pa_volume_api_allocate_volume_control_index(pa_volume_api *api) { -+ uint32_t idx; -+ -+ pa_assert(api); -+ -+ idx = api->next_volume_control_index++; -+ -+ return idx; -+} -+ -+static void set_main_output_volume_control_internal(pa_volume_api *api, pa_volume_control *control) { -+ pa_volume_control *old_control; -+ -+ pa_assert(api); -+ -+ old_control = api->main_output_volume_control; -+ -+ if (control == old_control) -+ return; -+ -+ api->main_output_volume_control = control; -+ pa_log_debug("Main output volume control changed from %s to %s.", old_control ? old_control->name : "(unset)", -+ control ? control->name : "(unset)"); -+ pa_hook_fire(&api->hooks[PA_VOLUME_API_HOOK_MAIN_OUTPUT_VOLUME_CONTROL_CHANGED], api); -+} -+ -+static void set_main_input_volume_control_internal(pa_volume_api *api, pa_volume_control *control) { -+ pa_volume_control *old_control; -+ -+ pa_assert(api); -+ -+ old_control = api->main_input_volume_control; -+ -+ if (control == old_control) -+ return; -+ -+ api->main_input_volume_control = control; -+ pa_log_debug("Main input volume control changed from %s to %s.", old_control ? old_control->name : "(unset)", -+ control ? control->name : "(unset)"); -+ pa_hook_fire(&api->hooks[PA_VOLUME_API_HOOK_MAIN_INPUT_VOLUME_CONTROL_CHANGED], api); -+} -+ -+void pa_volume_api_add_volume_control(pa_volume_api *api, pa_volume_control *control) { -+ pa_assert(api); -+ pa_assert(control); -+ -+ pa_assert_se(pa_hashmap_put(api->volume_controls, (void *) control->name, control) >= 0); -+} -+ -+int pa_volume_api_remove_volume_control(pa_volume_api *api, pa_volume_control *control) { -+ pa_assert(api); -+ pa_assert(control); -+ -+ if (!pa_hashmap_remove(api->volume_controls, control->name)) -+ return -1; -+ -+ if (control == api->main_output_volume_control) -+ set_main_output_volume_control_internal(api, NULL); -+ -+ if (control == api->main_input_volume_control) -+ set_main_input_volume_control_internal(api, NULL); -+ -+ return 0; -+} -+ -+pa_volume_control *pa_volume_api_get_volume_control_by_index(pa_volume_api *api, uint32_t idx) { -+ pa_volume_control *control; -+ void *state; -+ -+ pa_assert(api); -+ -+ PA_HASHMAP_FOREACH(control, api->volume_controls, state) { -+ if (control->index == idx) -+ return control; -+ } -+ -+ return NULL; -+} -+ -+uint32_t pa_volume_api_allocate_mute_control_index(pa_volume_api *api) { -+ uint32_t idx; -+ -+ pa_assert(api); -+ -+ idx = api->next_mute_control_index++; -+ -+ return idx; -+} -+ -+static void set_main_output_mute_control_internal(pa_volume_api *api, pa_mute_control *control) { -+ pa_mute_control *old_control; -+ -+ pa_assert(api); -+ -+ old_control = api->main_output_mute_control; -+ -+ if (control == old_control) -+ return; -+ -+ api->main_output_mute_control = control; -+ pa_log_debug("Main output mute control changed from %s to %s.", old_control ? old_control->name : "(unset)", -+ control ? control->name : "(unset)"); -+ pa_hook_fire(&api->hooks[PA_VOLUME_API_HOOK_MAIN_OUTPUT_MUTE_CONTROL_CHANGED], api); -+} -+ -+static void set_main_input_mute_control_internal(pa_volume_api *api, pa_mute_control *control) { -+ pa_mute_control *old_control; -+ -+ pa_assert(api); -+ -+ old_control = api->main_input_mute_control; -+ -+ if (control == old_control) -+ return; -+ -+ api->main_input_mute_control = control; -+ pa_log_debug("Main input mute control changed from %s to %s.", old_control ? old_control->name : "(unset)", -+ control ? control->name : "(unset)"); -+ pa_hook_fire(&api->hooks[PA_VOLUME_API_HOOK_MAIN_INPUT_MUTE_CONTROL_CHANGED], api); -+} -+ -+void pa_volume_api_add_mute_control(pa_volume_api *api, pa_mute_control *control) { -+ pa_assert(api); -+ pa_assert(control); -+ -+ pa_assert_se(pa_hashmap_put(api->mute_controls, (void *) control->name, control) >= 0); -+} -+ -+int pa_volume_api_remove_mute_control(pa_volume_api *api, pa_mute_control *control) { -+ pa_assert(api); -+ pa_assert(control); -+ -+ if (!pa_hashmap_remove(api->mute_controls, control->name)) -+ return -1; -+ -+ if (control == api->main_output_mute_control) -+ set_main_output_mute_control_internal(api, NULL); -+ -+ if (control == api->main_input_mute_control) -+ set_main_input_mute_control_internal(api, NULL); -+ -+ return 0; -+} -+ -+pa_mute_control *pa_volume_api_get_mute_control_by_index(pa_volume_api *api, uint32_t idx) { -+ pa_mute_control *control; -+ void *state; -+ -+ pa_assert(api); -+ -+ PA_HASHMAP_FOREACH(control, api->mute_controls, state) { -+ if (control->index == idx) -+ return control; -+ } -+ -+ return NULL; -+} -+ -+uint32_t pa_volume_api_allocate_device_index(pa_volume_api *api) { -+ uint32_t idx; -+ -+ pa_assert(api); -+ -+ idx = api->next_device_index++; -+ -+ return idx; -+} -+ -+void pa_volume_api_add_device(pa_volume_api *api, pa_device *device) { -+ pa_assert(api); -+ pa_assert(device); -+ -+ pa_assert_se(pa_hashmap_put(api->devices, (void *) device->name, device) >= 0); -+} -+ -+int pa_volume_api_remove_device(pa_volume_api *api, pa_device *device) { -+ pa_assert(api); -+ pa_assert(device); -+ -+ if (!pa_hashmap_remove(api->devices, device->name)) -+ return -1; -+ -+ return 0; -+} -+ -+pa_device *pa_volume_api_get_device_by_index(pa_volume_api *api, uint32_t idx) { -+ pa_device *device; -+ void *state; -+ -+ pa_assert(api); -+ -+ PA_HASHMAP_FOREACH(device, api->devices, state) { -+ if (device->index == idx) -+ return device; -+ } -+ -+ return NULL; -+} -+ -+uint32_t pa_volume_api_allocate_stream_index(pa_volume_api *api) { -+ uint32_t idx; -+ -+ pa_assert(api); -+ -+ idx = api->next_stream_index++; -+ -+ return idx; -+} -+ -+void pa_volume_api_add_stream(pa_volume_api *api, pas_stream *stream) { -+ pa_assert(api); -+ pa_assert(stream); -+ -+ pa_assert_se(pa_hashmap_put(api->streams, (void *) stream->name, stream) >= 0); -+} -+ -+int pa_volume_api_remove_stream(pa_volume_api *api, pas_stream *stream) { -+ pa_assert(api); -+ pa_assert(stream); -+ -+ if (!pa_hashmap_remove(api->streams, stream->name)) -+ return -1; -+ -+ return 0; -+} -+ -+pas_stream *pa_volume_api_get_stream_by_index(pa_volume_api *api, uint32_t idx) { -+ pas_stream *stream; -+ void *state; -+ -+ pa_assert(api); -+ -+ PA_HASHMAP_FOREACH(stream, api->streams, state) { -+ if (stream->index == idx) -+ return stream; -+ } -+ -+ return NULL; -+} -+ -+uint32_t pa_volume_api_allocate_audio_group_index(pa_volume_api *api) { -+ uint32_t idx; -+ -+ pa_assert(api); -+ -+ idx = api->next_audio_group_index++; -+ -+ return idx; -+} -+ -+void pa_volume_api_add_audio_group(pa_volume_api *api, pa_audio_group *group) { -+ pa_assert(api); -+ pa_assert(group); -+ -+ pa_assert_se(pa_hashmap_put(api->audio_groups, (void *) group->name, group) >= 0); -+} -+ -+int pa_volume_api_remove_audio_group(pa_volume_api *api, pa_audio_group *group) { -+ pa_assert(api); -+ pa_assert(group); -+ -+ if (!pa_hashmap_remove(api->audio_groups, group->name)) -+ return -1; -+ -+ return 0; -+} -+ -+pa_audio_group *pa_volume_api_get_audio_group_by_index(pa_volume_api *api, uint32_t idx) { -+ pa_audio_group *group; -+ void *state; -+ -+ pa_assert(api); -+ -+ PA_HASHMAP_FOREACH(group, api->audio_groups, state) { -+ if (group->index == idx) -+ return group; -+ } -+ -+ return NULL; -+} -+ -+void pa_volume_api_set_main_output_volume_control(pa_volume_api *api, pa_volume_control *control) { -+ pa_assert(api); -+ -+ if (api->main_output_volume_control_binding) { -+ pa_binding_free(api->main_output_volume_control_binding); -+ api->main_output_volume_control_binding = NULL; -+ } -+ -+ set_main_output_volume_control_internal(api, control); -+} -+ -+void pa_volume_api_set_main_input_volume_control(pa_volume_api *api, pa_volume_control *control) { -+ pa_assert(api); -+ -+ if (api->main_input_volume_control_binding) { -+ pa_binding_free(api->main_input_volume_control_binding); -+ api->main_input_volume_control_binding = NULL; -+ } -+ -+ set_main_input_volume_control_internal(api, control); -+} -+ -+void pa_volume_api_set_main_output_mute_control(pa_volume_api *api, pa_mute_control *control) { -+ pa_assert(api); -+ -+ if (api->main_output_mute_control_binding) { -+ pa_binding_free(api->main_output_mute_control_binding); -+ api->main_output_mute_control_binding = NULL; -+ } -+ -+ set_main_output_mute_control_internal(api, control); -+} -+ -+void pa_volume_api_set_main_input_mute_control(pa_volume_api *api, pa_mute_control *control) { -+ pa_assert(api); -+ -+ if (api->main_input_mute_control_binding) { -+ pa_binding_free(api->main_input_mute_control_binding); -+ api->main_input_mute_control_binding = NULL; -+ } -+ -+ set_main_input_mute_control_internal(api, control); -+} -+ -+void pa_volume_api_bind_main_output_volume_control(pa_volume_api *api, pa_binding_target_info *target_info) { -+ pa_binding_owner_info owner_info = { -+ .userdata = api, -+ .set_value = (pa_binding_set_value_cb_t) set_main_output_volume_control_internal, -+ }; -+ -+ pa_assert(api); -+ pa_assert(target_info); -+ -+ if (api->main_output_volume_control_binding) -+ pa_binding_free(api->main_output_volume_control_binding); -+ -+ api->main_output_volume_control_binding = pa_binding_new(api, &owner_info, target_info); -+} -+ -+void pa_volume_api_bind_main_input_volume_control(pa_volume_api *api, pa_binding_target_info *target_info) { -+ pa_binding_owner_info owner_info = { -+ .userdata = api, -+ .set_value = (pa_binding_set_value_cb_t) set_main_input_volume_control_internal, -+ }; -+ -+ pa_assert(api); -+ pa_assert(target_info); -+ -+ if (api->main_input_volume_control_binding) -+ pa_binding_free(api->main_input_volume_control_binding); -+ -+ api->main_input_volume_control_binding = pa_binding_new(api, &owner_info, target_info); -+} -+ -+void pa_volume_api_bind_main_output_mute_control(pa_volume_api *api, pa_binding_target_info *target_info) { -+ pa_binding_owner_info owner_info = { -+ .userdata = api, -+ .set_value = (pa_binding_set_value_cb_t) set_main_output_mute_control_internal, -+ }; -+ -+ pa_assert(api); -+ pa_assert(target_info); -+ -+ if (api->main_output_mute_control_binding) -+ pa_binding_free(api->main_output_mute_control_binding); -+ -+ api->main_output_mute_control_binding = pa_binding_new(api, &owner_info, target_info); -+} -+ -+void pa_volume_api_bind_main_input_mute_control(pa_volume_api *api, pa_binding_target_info *target_info) { -+ pa_binding_owner_info owner_info = { -+ .userdata = api, -+ .set_value = (pa_binding_set_value_cb_t) set_main_input_mute_control_internal, -+ }; -+ -+ pa_assert(api); -+ pa_assert(target_info); -+ -+ if (api->main_input_mute_control_binding) -+ pa_binding_free(api->main_input_mute_control_binding); -+ -+ api->main_input_mute_control_binding = pa_binding_new(api, &owner_info, target_info); -+} -diff --git a/src/modules/volume-api/volume-api.h b/src/modules/volume-api/volume-api.h -new file mode 100644 -index 0000000..73a1410 ---- /dev/null -+++ b/src/modules/volume-api/volume-api.h -@@ -0,0 +1,163 @@ -+#ifndef foovolumeapihfoo -+#define foovolumeapihfoo -+ -+/*** -+ This file is part of PulseAudio. -+ -+ Copyright 2014 Intel Corporation -+ -+ PulseAudio is free software; you can redistribute it and/or modify -+ it under the terms of the GNU Lesser General Public License as published -+ by the Free Software Foundation; either version 2.1 of the License, -+ or (at your option) any later version. -+ -+ PulseAudio 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 Lesser General Public License -+ along with PulseAudio; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ USA. -+***/ -+ -+#include -+ -+typedef struct pa_volume_api pa_volume_api; -+ -+/* Avoid circular dependencies... */ -+typedef struct pa_audio_group pa_audio_group; -+typedef struct pa_binding pa_binding; -+typedef struct pa_binding_target_info pa_binding_target_info; -+typedef struct pa_binding_target_type pa_binding_target_type; -+typedef struct pa_device pa_device; -+typedef struct pa_device_creator pa_device_creator; -+typedef struct pa_mute_control pa_mute_control; -+typedef struct pas_stream pas_stream; -+typedef struct pa_stream_creator pa_stream_creator; -+typedef struct pa_volume_control pa_volume_control; -+ -+enum { -+ PA_VOLUME_API_HOOK_BINDING_TARGET_TYPE_ADDED, -+ PA_VOLUME_API_HOOK_BINDING_TARGET_TYPE_REMOVED, -+ PA_VOLUME_API_HOOK_VOLUME_CONTROL_PUT, -+ PA_VOLUME_API_HOOK_VOLUME_CONTROL_UNLINK, -+ PA_VOLUME_API_HOOK_VOLUME_CONTROL_DESCRIPTION_CHANGED, -+ PA_VOLUME_API_HOOK_VOLUME_CONTROL_VOLUME_CHANGED, -+ PA_VOLUME_API_HOOK_MUTE_CONTROL_PUT, -+ PA_VOLUME_API_HOOK_MUTE_CONTROL_UNLINK, -+ PA_VOLUME_API_HOOK_MUTE_CONTROL_DESCRIPTION_CHANGED, -+ PA_VOLUME_API_HOOK_MUTE_CONTROL_MUTE_CHANGED, -+ PA_VOLUME_API_HOOK_DEVICE_PUT, -+ PA_VOLUME_API_HOOK_DEVICE_UNLINK, -+ PA_VOLUME_API_HOOK_DEVICE_DESCRIPTION_CHANGED, -+ PA_VOLUME_API_HOOK_DEVICE_VOLUME_CONTROL_CHANGED, -+ PA_VOLUME_API_HOOK_DEVICE_MUTE_CONTROL_CHANGED, -+ -+ /* Policy modules can use this to set the initial volume control for a -+ * stream. The hook callback should use pas_stream_set_volume_control() to -+ * set the volume control. The hook callback should not do anything if -+ * stream->volume_control is already non-NULL. */ -+ PA_VOLUME_API_HOOK_STREAM_SET_INITIAL_VOLUME_CONTROL, -+ -+ /* Policy modules can use this to set the initial mute control for a -+ * stream. The hook callback should use pas_stream_set_mute_control() to -+ * set the mute control. The hook callback should not do anything if -+ * stream->mute_control is already non-NULL. */ -+ PA_VOLUME_API_HOOK_STREAM_SET_INITIAL_MUTE_CONTROL, -+ -+ PA_VOLUME_API_HOOK_STREAM_PUT, -+ PA_VOLUME_API_HOOK_STREAM_UNLINK, -+ PA_VOLUME_API_HOOK_STREAM_DESCRIPTION_CHANGED, -+ PA_VOLUME_API_HOOK_STREAM_VOLUME_CONTROL_CHANGED, -+ PA_VOLUME_API_HOOK_STREAM_MUTE_CONTROL_CHANGED, -+ PA_VOLUME_API_HOOK_AUDIO_GROUP_PUT, -+ PA_VOLUME_API_HOOK_AUDIO_GROUP_UNLINK, -+ PA_VOLUME_API_HOOK_AUDIO_GROUP_VOLUME_CONTROL_CHANGED, -+ PA_VOLUME_API_HOOK_AUDIO_GROUP_MUTE_CONTROL_CHANGED, -+ PA_VOLUME_API_HOOK_MAIN_OUTPUT_VOLUME_CONTROL_CHANGED, -+ PA_VOLUME_API_HOOK_MAIN_INPUT_VOLUME_CONTROL_CHANGED, -+ PA_VOLUME_API_HOOK_MAIN_OUTPUT_MUTE_CONTROL_CHANGED, -+ PA_VOLUME_API_HOOK_MAIN_INPUT_MUTE_CONTROL_CHANGED, -+ PA_VOLUME_API_HOOK_MAX -+}; -+ -+struct pa_volume_api { -+ pa_core *core; -+ unsigned refcnt; -+ pa_hashmap *binding_target_types; /* name -> pa_binding_target_type */ -+ pa_hashmap *names; /* object name -> object name (hashmap-as-a-set) */ -+ pa_hashmap *volume_controls; /* name -> pa_volume_control */ -+ pa_hashmap *mute_controls; /* name -> pa_mute_control */ -+ pa_hashmap *devices; /* name -> pa_device */ -+ pa_hashmap *streams; /* name -> pas_stream */ -+ pa_hashmap *audio_groups; /* name -> pa_audio_group */ -+ pa_volume_control *main_output_volume_control; -+ pa_volume_control *main_input_volume_control; -+ pa_mute_control *main_output_mute_control; -+ pa_mute_control *main_input_mute_control; -+ -+ uint32_t next_volume_control_index; -+ uint32_t next_mute_control_index; -+ uint32_t next_device_index; -+ uint32_t next_stream_index; -+ uint32_t next_audio_group_index; -+ pa_binding *main_output_volume_control_binding; -+ pa_binding *main_input_volume_control_binding; -+ pa_binding *main_output_mute_control_binding; -+ pa_binding *main_input_mute_control_binding; -+ pa_hook hooks[PA_VOLUME_API_HOOK_MAX]; -+ pa_defer_event *create_objects_defer_event; -+ pa_device_creator *device_creator; -+ pa_stream_creator *stream_creator; -+}; -+ -+pa_volume_api *pa_volume_api_get(pa_core *core); -+pa_volume_api *pa_volume_api_ref(pa_volume_api *api); -+void pa_volume_api_unref(pa_volume_api *api); -+ -+void pa_volume_api_add_binding_target_type(pa_volume_api *api, pa_binding_target_type *type); -+void pa_volume_api_remove_binding_target_type(pa_volume_api *api, pa_binding_target_type *type); -+ -+/* If fail_if_already_registered is false, this function never fails. */ -+int pa_volume_api_register_name(pa_volume_api *api, const char *requested_name, bool fail_if_already_registered, -+ const char **registered_name); -+ -+void pa_volume_api_unregister_name(pa_volume_api *api, const char *name); -+ -+uint32_t pa_volume_api_allocate_volume_control_index(pa_volume_api *api); -+void pa_volume_api_add_volume_control(pa_volume_api *api, pa_volume_control *control); -+int pa_volume_api_remove_volume_control(pa_volume_api *api, pa_volume_control *control); -+pa_volume_control *pa_volume_api_get_volume_control_by_index(pa_volume_api *api, uint32_t idx); -+ -+uint32_t pa_volume_api_allocate_mute_control_index(pa_volume_api *api); -+void pa_volume_api_add_mute_control(pa_volume_api *api, pa_mute_control *control); -+int pa_volume_api_remove_mute_control(pa_volume_api *api, pa_mute_control *control); -+pa_mute_control *pa_volume_api_get_mute_control_by_index(pa_volume_api *api, uint32_t idx); -+ -+uint32_t pa_volume_api_allocate_device_index(pa_volume_api *api); -+void pa_volume_api_add_device(pa_volume_api *api, pa_device *device); -+int pa_volume_api_remove_device(pa_volume_api *api, pa_device *device); -+pa_device *pa_volume_api_get_device_by_index(pa_volume_api *api, uint32_t idx); -+ -+uint32_t pa_volume_api_allocate_stream_index(pa_volume_api *api); -+void pa_volume_api_add_stream(pa_volume_api *api, pas_stream *stream); -+int pa_volume_api_remove_stream(pa_volume_api *api, pas_stream *stream); -+pas_stream *pa_volume_api_get_stream_by_index(pa_volume_api *api, uint32_t idx); -+ -+uint32_t pa_volume_api_allocate_audio_group_index(pa_volume_api *api); -+void pa_volume_api_add_audio_group(pa_volume_api *api, pa_audio_group *group); -+int pa_volume_api_remove_audio_group(pa_volume_api *api, pa_audio_group *group); -+pa_audio_group *pa_volume_api_get_audio_group_by_index(pa_volume_api *api, uint32_t idx); -+ -+void pa_volume_api_set_main_output_volume_control(pa_volume_api *api, pa_volume_control *control); -+void pa_volume_api_set_main_input_volume_control(pa_volume_api *api, pa_volume_control *control); -+void pa_volume_api_set_main_output_mute_control(pa_volume_api *api, pa_mute_control *control); -+void pa_volume_api_set_main_input_mute_control(pa_volume_api *api, pa_mute_control *control); -+void pa_volume_api_bind_main_output_volume_control(pa_volume_api *api, pa_binding_target_info *target_info); -+void pa_volume_api_bind_main_input_volume_control(pa_volume_api *api, pa_binding_target_info *target_info); -+void pa_volume_api_bind_main_output_mute_control(pa_volume_api *api, pa_binding_target_info *target_info); -+void pa_volume_api_bind_main_input_mute_control(pa_volume_api *api, pa_binding_target_info *target_info); -+ -+#endif -diff --git a/src/modules/volume-api/volume-control.c b/src/modules/volume-api/volume-control.c -new file mode 100644 -index 0000000..c7f5dbb ---- /dev/null -+++ b/src/modules/volume-api/volume-control.c -@@ -0,0 +1,363 @@ -+/*** -+ This file is part of PulseAudio. -+ -+ Copyright 2014 Intel Corporation -+ -+ PulseAudio is free software; you can redistribute it and/or modify -+ it under the terms of the GNU Lesser General Public License as published -+ by the Free Software Foundation; either version 2.1 of the License, -+ or (at your option) any later version. -+ -+ PulseAudio 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 Lesser General Public License -+ along with PulseAudio; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ USA. -+***/ -+ -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ -+#include "volume-control.h" -+ -+#include -+#include -+#include -+ -+#include -+ -+pa_volume_control *pa_volume_control_new(pa_volume_api *api, const char *name, const char *description, bool convertible_to_dB, -+ bool channel_map_is_writable) { -+ pa_volume_control *control; -+ -+ pa_assert(api); -+ pa_assert(name); -+ pa_assert(description); -+ -+ control = pa_xnew0(pa_volume_control, 1); -+ control->volume_api = api; -+ control->index = pa_volume_api_allocate_volume_control_index(api); -+ pa_assert_se(pa_volume_api_register_name(api, name, false, &control->name) >= 0); -+ control->description = pa_xstrdup(description); -+ control->proplist = pa_proplist_new(); -+ pa_bvolume_init_invalid(&control->volume); -+ control->convertible_to_dB = convertible_to_dB; -+ control->channel_map_is_writable = channel_map_is_writable; -+ control->devices = pa_hashmap_new(NULL, NULL); -+ control->default_for_devices = pa_hashmap_new(NULL, NULL); -+ control->streams = pa_hashmap_new(NULL, NULL); -+ control->audio_groups = pa_hashmap_new(NULL, NULL); -+ -+ return control; -+} -+ -+void pa_volume_control_put(pa_volume_control *control, const pa_bvolume *initial_volume, -+ pa_volume_control_set_initial_volume_cb_t set_initial_volume_cb) { -+ const char *prop_key; -+ void *state = NULL; -+ char volume_str[PA_VOLUME_SNPRINT_VERBOSE_MAX]; -+ char balance_str[PA_BVOLUME_SNPRINT_BALANCE_MAX]; -+ -+ pa_assert(control); -+ pa_assert((initial_volume && pa_bvolume_valid(initial_volume, true, true)) || control->set_volume); -+ pa_assert((initial_volume && pa_channel_map_valid(&initial_volume->channel_map)) || control->channel_map_is_writable); -+ pa_assert(set_initial_volume_cb || !control->set_volume); -+ -+ if (initial_volume && pa_bvolume_valid(initial_volume, true, false)) -+ control->volume.volume = initial_volume->volume; -+ else -+ control->volume.volume = PA_VOLUME_NORM / 3; -+ -+ if (initial_volume && pa_bvolume_valid(initial_volume, false, true)) -+ pa_bvolume_copy_balance(&control->volume, initial_volume); -+ else if (initial_volume && pa_channel_map_valid(&initial_volume->channel_map)) -+ pa_bvolume_reset_balance(&control->volume, &initial_volume->channel_map); -+ else { -+ pa_channel_map_init_mono(&control->volume.channel_map); -+ pa_bvolume_reset_balance(&control->volume, &control->volume.channel_map); -+ } -+ -+ if (set_initial_volume_cb) -+ set_initial_volume_cb(control); -+ -+ pa_volume_api_add_volume_control(control->volume_api, control); -+ -+ control->linked = true; -+ -+ pa_log_debug("Created volume control #%u.", control->index); -+ pa_log_debug(" Name: %s", control->name); -+ pa_log_debug(" Description: %s", control->description); -+ pa_log_debug(" Properties:"); -+ -+ while ((prop_key = pa_proplist_iterate(control->proplist, &state))) -+ pa_log_debug(" %s = %s", prop_key, pa_strnull(pa_proplist_gets(control->proplist, prop_key))); -+ -+ pa_log_debug(" Volume: %s", pa_volume_snprint_verbose(volume_str, sizeof(volume_str), control->volume.volume, -+ control->convertible_to_dB)); -+ pa_log_debug(" Balance: %s", pa_bvolume_snprint_balance(balance_str, sizeof(balance_str), &control->volume)); -+ pa_log_debug(" Channel map is writable: %s", pa_yes_no(control->channel_map_is_writable)); -+ -+ pa_hook_fire(&control->volume_api->hooks[PA_VOLUME_API_HOOK_VOLUME_CONTROL_PUT], control); -+} -+ -+void pa_volume_control_unlink(pa_volume_control *control) { -+ pa_audio_group *group; -+ pa_device *device; -+ pas_stream *stream; -+ -+ pa_assert(control); -+ -+ if (control->unlinked) { -+ pa_log_debug("Unlinking volume control %s (already unlinked, this is a no-op).", control->name); -+ return; -+ } -+ -+ control->unlinked = true; -+ -+ pa_log_debug("Unlinking volume control %s.", control->name); -+ -+ if (control->linked) -+ pa_hook_fire(&control->volume_api->hooks[PA_VOLUME_API_HOOK_VOLUME_CONTROL_UNLINK], control); -+ -+ pa_volume_api_remove_volume_control(control->volume_api, control); -+ -+ while ((group = pa_hashmap_first(control->audio_groups))) -+ pa_audio_group_set_volume_control(group, NULL); -+ -+ while ((stream = pa_hashmap_first(control->streams))) -+ pas_stream_set_volume_control(stream, NULL); -+ -+ while ((device = pa_hashmap_first(control->default_for_devices))) -+ pa_device_set_default_volume_control(device, NULL); -+ -+ while ((device = pa_hashmap_first(control->devices))) { -+ /* Why do we have this assertion here? The concern is that if we call -+ * pa_device_set_volume_control() for some device that has the -+ * use_default_volume_control flag set, then that flag will be unset as -+ * a side effect, and we don't want that side effect. This assertion -+ * should be safe, because we just called -+ * pa_device_set_default_volume_control(NULL) for each device that this -+ * control was the default for, and that should ensure that we don't -+ * any more hold any references to devices that used to use this -+ * control as the default. */ -+ pa_assert(!device->use_default_volume_control); -+ pa_device_set_volume_control(device, NULL); -+ } -+} -+ -+void pa_volume_control_free(pa_volume_control *control) { -+ pa_assert(control); -+ -+ if (!control->unlinked) -+ pa_volume_control_unlink(control); -+ -+ if (control->audio_groups) { -+ pa_assert(pa_hashmap_isempty(control->audio_groups)); -+ pa_hashmap_free(control->audio_groups); -+ } -+ -+ if (control->streams) { -+ pa_assert(pa_hashmap_isempty(control->streams)); -+ pa_hashmap_free(control->streams); -+ } -+ -+ if (control->default_for_devices) { -+ pa_assert(pa_hashmap_isempty(control->default_for_devices)); -+ pa_hashmap_free(control->default_for_devices); -+ } -+ -+ if (control->devices) { -+ pa_assert(pa_hashmap_isempty(control->devices)); -+ pa_hashmap_free(control->devices); -+ } -+ -+ if (control->proplist) -+ pa_proplist_free(control->proplist); -+ -+ pa_xfree(control->description); -+ -+ if (control->name) -+ pa_volume_api_unregister_name(control->volume_api, control->name); -+ -+ pa_xfree(control); -+} -+ -+void pa_volume_control_set_owner_audio_group(pa_volume_control *control, pa_audio_group *group) { -+ pa_assert(control); -+ pa_assert(group); -+ -+ control->owner_audio_group = group; -+} -+ -+static void set_volume_internal(pa_volume_control *control, const pa_bvolume *volume, bool set_volume, bool set_balance) { -+ pa_bvolume old_volume; -+ bool volume_changed; -+ bool balance_changed; -+ -+ pa_assert(control); -+ pa_assert(volume); -+ -+ old_volume = control->volume; -+ volume_changed = !pa_bvolume_equal(volume, &old_volume, set_volume, false); -+ balance_changed = !pa_bvolume_equal(volume, &old_volume, false, set_balance); -+ -+ if (!volume_changed && !balance_changed) -+ return; -+ -+ if (volume_changed) -+ control->volume.volume = volume->volume; -+ -+ if (balance_changed) -+ pa_bvolume_copy_balance(&control->volume, volume); -+ -+ if (!control->linked || control->unlinked) -+ return; -+ -+ if (volume_changed) { -+ char old_volume_str[PA_VOLUME_SNPRINT_VERBOSE_MAX]; -+ char new_volume_str[PA_VOLUME_SNPRINT_VERBOSE_MAX]; -+ -+ pa_log_debug("The volume of volume control %s changed from %s to %s.", control->name, -+ pa_volume_snprint_verbose(old_volume_str, sizeof(old_volume_str), old_volume.volume, -+ control->convertible_to_dB), -+ pa_volume_snprint_verbose(new_volume_str, sizeof(new_volume_str), control->volume.volume, -+ control->convertible_to_dB)); -+ } -+ -+ if (balance_changed) { -+ char old_balance_str[PA_BVOLUME_SNPRINT_BALANCE_MAX]; -+ char new_balance_str[PA_BVOLUME_SNPRINT_BALANCE_MAX]; -+ -+ pa_log_debug("The balance of volume control %s changed from %s to %s.", control->name, -+ pa_bvolume_snprint_balance(old_balance_str, sizeof(old_balance_str), &control->volume), -+ pa_bvolume_snprint_balance(new_balance_str, sizeof(new_balance_str), &control->volume)); -+ } -+ -+ pa_hook_fire(&control->volume_api->hooks[PA_VOLUME_API_HOOK_VOLUME_CONTROL_VOLUME_CHANGED], control); -+} -+ -+int pa_volume_control_set_volume(pa_volume_control *control, const pa_bvolume *volume, bool set_volume, bool set_balance) { -+ pa_bvolume volume_local; -+ int r; -+ -+ pa_assert(control); -+ pa_assert(volume); -+ -+ volume_local = *volume; -+ -+ if (!control->set_volume) { -+ pa_log_info("Tried to set the volume of volume control %s, but the volume control doesn't support the operation.", -+ control->name); -+ return -PA_ERR_NOTSUPPORTED; -+ } -+ -+ if (set_balance -+ && !control->channel_map_is_writable -+ && !pa_channel_map_equal(&volume_local.channel_map, &control->volume.channel_map)) -+ pa_bvolume_remap(&volume_local, &control->volume.channel_map); -+ -+ if (pa_bvolume_equal(&volume_local, &control->volume, set_volume, set_balance)) -+ return 0; -+ -+ control->set_volume_in_progress = true; -+ r = control->set_volume(control, &volume_local, set_volume, set_balance); -+ control->set_volume_in_progress = false; -+ -+ if (r >= 0) -+ set_volume_internal(control, &volume_local, set_volume, set_balance); -+ -+ return r; -+} -+ -+void pa_volume_control_description_changed(pa_volume_control *control, const char *new_description) { -+ char *old_description; -+ -+ pa_assert(control); -+ pa_assert(new_description); -+ -+ old_description = control->description; -+ -+ if (pa_streq(new_description, old_description)) -+ return; -+ -+ control->description = pa_xstrdup(new_description); -+ pa_log_debug("The description of volume control %s changed from \"%s\" to \"%s\".", control->name, old_description, -+ new_description); -+ pa_xfree(old_description); -+ pa_hook_fire(&control->volume_api->hooks[PA_VOLUME_API_HOOK_VOLUME_CONTROL_DESCRIPTION_CHANGED], control); -+} -+ -+void pa_volume_control_volume_changed(pa_volume_control *control, const pa_bvolume *new_volume, bool volume_changed, -+ bool balance_changed) { -+ pa_assert(control); -+ pa_assert(new_volume); -+ -+ if (!control->linked) -+ return; -+ -+ if (control->set_volume_in_progress) -+ return; -+ -+ set_volume_internal(control, new_volume, volume_changed, balance_changed); -+} -+ -+void pa_volume_control_add_device(pa_volume_control *control, pa_device *device) { -+ pa_assert(control); -+ pa_assert(device); -+ -+ pa_assert_se(pa_hashmap_put(control->devices, device, device) >= 0); -+} -+ -+void pa_volume_control_remove_device(pa_volume_control *control, pa_device *device) { -+ pa_assert(control); -+ pa_assert(device); -+ -+ pa_assert_se(pa_hashmap_remove(control->devices, device)); -+} -+ -+void pa_volume_control_add_default_for_device(pa_volume_control *control, pa_device *device) { -+ pa_assert(control); -+ pa_assert(device); -+ -+ pa_assert_se(pa_hashmap_put(control->default_for_devices, device, device) >= 0); -+} -+ -+void pa_volume_control_remove_default_for_device(pa_volume_control *control, pa_device *device) { -+ pa_assert(control); -+ pa_assert(device); -+ -+ pa_assert_se(pa_hashmap_remove(control->default_for_devices, device)); -+} -+ -+void pa_volume_control_add_stream(pa_volume_control *control, pas_stream *stream) { -+ pa_assert(control); -+ pa_assert(stream); -+ -+ pa_assert_se(pa_hashmap_put(control->streams, stream, stream) >= 0); -+} -+ -+void pa_volume_control_remove_stream(pa_volume_control *control, pas_stream *stream) { -+ pa_assert(control); -+ pa_assert(stream); -+ -+ pa_assert_se(pa_hashmap_remove(control->streams, stream)); -+} -+ -+void pa_volume_control_add_audio_group(pa_volume_control *control, pa_audio_group *group) { -+ pa_assert(control); -+ pa_assert(group); -+ -+ pa_assert_se(pa_hashmap_put(control->audio_groups, group, group) >= 0); -+} -+ -+void pa_volume_control_remove_audio_group(pa_volume_control *control, pa_audio_group *group) { -+ pa_assert(control); -+ pa_assert(group); -+ -+ pa_assert_se(pa_hashmap_remove(control->audio_groups, group)); -+} -diff --git a/src/modules/volume-api/volume-control.h b/src/modules/volume-api/volume-control.h -new file mode 100644 -index 0000000..aaba758 ---- /dev/null -+++ b/src/modules/volume-api/volume-control.h -@@ -0,0 +1,112 @@ -+#ifndef foovolumecontrolhfoo -+#define foovolumecontrolhfoo -+ -+/*** -+ This file is part of PulseAudio. -+ -+ Copyright 2014 Intel Corporation -+ -+ PulseAudio is free software; you can redistribute it and/or modify -+ it under the terms of the GNU Lesser General Public License as published -+ by the Free Software Foundation; either version 2.1 of the License, -+ or (at your option) any later version. -+ -+ PulseAudio 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 Lesser General Public License -+ along with PulseAudio; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ USA. -+***/ -+ -+#include -+#include -+ -+typedef struct pa_volume_control pa_volume_control; -+ -+struct pa_volume_control { -+ pa_volume_api *volume_api; -+ uint32_t index; -+ const char *name; -+ char *description; -+ pa_proplist *proplist; -+ pa_bvolume volume; -+ bool convertible_to_dB; -+ bool channel_map_is_writable; -+ -+ /* If this volume control is the "own volume control" of an audio group, -+ * this is set to point to that group, otherwise this is NULL. */ -+ pa_audio_group *owner_audio_group; -+ -+ pa_hashmap *devices; /* pa_device -> pa_device (hashmap-as-a-set) */ -+ pa_hashmap *default_for_devices; /* pa_device -> pa_device (hashmap-as-a-set) */ -+ pa_hashmap *streams; /* pas_stream -> pas_stream (hashmap-as-a-set) */ -+ pa_hashmap *audio_groups; /* pa_audio_group -> pa_audio_group (hashmap-as-a-set) */ -+ -+ bool linked; -+ bool unlinked; -+ bool set_volume_in_progress; -+ -+ /* Called from pa_volume_control_set_volume(). The implementation is -+ * expected to return a negative error code on failure. May be NULL, if the -+ * volume control is read-only. */ -+ int (*set_volume)(pa_volume_control *control, const pa_bvolume *volume, bool set_volume, bool set_balance); -+ -+ void *userdata; -+}; -+ -+pa_volume_control *pa_volume_control_new(pa_volume_api *api, const char *name, const char *description, bool convertible_to_dB, -+ bool channel_map_is_writable); -+ -+typedef void (*pa_volume_control_set_initial_volume_cb_t)(pa_volume_control *control); -+ -+/* initial_volume is the preferred initial volume of the volume control -+ * implementation. It may be NULL or partially invalid, if the implementation -+ * doesn't care about the initial state of the volume control, as long as these -+ * two rules are followed: -+ * -+ * 1) Read-only volume controls must always specify fully valid initial -+ * volume. -+ * 2) Volume controls with read-only channel map must always specify a valid -+ * channel map in initial_volume. -+ * -+ * The implementation's initial volume preference may be overridden by policy, -+ * if the volume control isn't read-only. When the final initial volume is -+ * known, the implementation is notified via set_initial_volume_cb (the volume -+ * can be read from control->volume). set_initial_volume_cb may be NULL, if the -+ * volume control is read-only. */ -+void pa_volume_control_put(pa_volume_control *control, const pa_bvolume *initial_volume, -+ pa_volume_control_set_initial_volume_cb_t set_initial_volume_cb); -+ -+void pa_volume_control_unlink(pa_volume_control *control); -+void pa_volume_control_free(pa_volume_control *control); -+ -+/* Called by audio-group.c only. */ -+void pa_volume_control_set_owner_audio_group(pa_volume_control *control, pa_audio_group *group); -+ -+/* Called by clients and policy modules. */ -+int pa_volume_control_set_volume(pa_volume_control *control, const pa_bvolume *volume, bool set_volume, bool set_balance); -+ -+/* Called by the volume control implementation. */ -+void pa_volume_control_description_changed(pa_volume_control *control, const char *new_description); -+void pa_volume_control_volume_changed(pa_volume_control *control, const pa_bvolume *new_volume, bool volume_changed, -+ bool balance_changed); -+ -+/* Called from device.c only. */ -+void pa_volume_control_add_device(pa_volume_control *control, pa_device *device); -+void pa_volume_control_remove_device(pa_volume_control *control, pa_device *device); -+void pa_volume_control_add_default_for_device(pa_volume_control *control, pa_device *device); -+void pa_volume_control_remove_default_for_device(pa_volume_control *control, pa_device *device); -+ -+/* Called from sstream.c only. */ -+void pa_volume_control_add_stream(pa_volume_control *control, pas_stream *stream); -+void pa_volume_control_remove_stream(pa_volume_control *control, pas_stream *stream); -+ -+/* Called from audio-group.c only. */ -+void pa_volume_control_add_audio_group(pa_volume_control *control, pa_audio_group *group); -+void pa_volume_control_remove_audio_group(pa_volume_control *control, pa_audio_group *group); -+ -+#endif -diff --git a/src/pulse/ext-volume-api.c b/src/pulse/ext-volume-api.c -new file mode 100644 -index 0000000..8e93bce ---- /dev/null -+++ b/src/pulse/ext-volume-api.c -@@ -0,0 +1,275 @@ -+/*** -+ This file is part of PulseAudio. -+ -+ Copyright 2014 Intel Corporation -+ -+ PulseAudio is free software; you can redistribute it and/or modify -+ it under the terms of the GNU Lesser General Public License as published -+ by the Free Software Foundation; either version 2.1 of the License, -+ or (at your option) any later version. -+ -+ PulseAudio 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 Lesser General Public License -+ along with PulseAudio; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ USA. -+***/ -+ -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ -+#include "ext-volume-api.h" -+ -+#include -+#include -+#include -+ -+#include -+ -+int pa_ext_volume_api_balance_valid(double balance) { -+ return balance >= 0.0 && balance <= 1.0; -+} -+ -+int pa_ext_volume_api_bvolume_valid(const pa_ext_volume_api_bvolume *volume, int check_volume, int check_balance) { -+ unsigned channel; -+ -+ pa_assert(volume); -+ -+ if (check_volume && !PA_VOLUME_IS_VALID(volume->volume)) -+ return 0; -+ -+ if (!check_balance) -+ return 1; -+ -+ if (!pa_channel_map_valid(&volume->channel_map)) -+ return 0; -+ -+ for (channel = 0; channel < volume->channel_map.channels; channel++) { -+ if (!pa_ext_volume_api_balance_valid(volume->balance[channel])) -+ return 0; -+ } -+ -+ return 1; -+} -+ -+void pa_ext_volume_api_bvolume_init_invalid(pa_ext_volume_api_bvolume *volume) { -+ unsigned i; -+ -+ pa_assert(volume); -+ -+ volume->volume = PA_VOLUME_INVALID; -+ -+ for (i = 0; i < PA_CHANNELS_MAX; i++) -+ volume->balance[i] = -1.0; -+ -+ pa_channel_map_init(&volume->channel_map); -+} -+ -+void pa_ext_volume_api_bvolume_init_mono(pa_ext_volume_api_bvolume *bvolume, pa_volume_t volume) { -+ pa_assert(bvolume); -+ pa_assert(PA_VOLUME_IS_VALID(volume)); -+ -+ bvolume->volume = volume; -+ bvolume->balance[0] = 1.0; -+ pa_channel_map_init_mono(&bvolume->channel_map); -+} -+ -+int pa_ext_volume_api_bvolume_equal(const pa_ext_volume_api_bvolume *a, const pa_ext_volume_api_bvolume *b, -+ int check_volume, int check_balance) { -+ unsigned i; -+ -+ pa_assert(a); -+ pa_assert(b); -+ -+ if (check_volume && a->volume != b->volume) -+ return 0; -+ -+ if (!check_balance) -+ return 1; -+ -+ if (!pa_channel_map_equal(&a->channel_map, &b->channel_map)) -+ return 0; -+ -+ for (i = 0; i < a->channel_map.channels; i++) { -+ if (fabs(a->balance[i] - b->balance[i]) > 0.00001) -+ return 0; -+ } -+ -+ return 1; -+} -+ -+void pa_ext_volume_api_bvolume_from_cvolume(pa_ext_volume_api_bvolume *bvolume, const pa_cvolume *cvolume, -+ const pa_channel_map *map) { -+ unsigned i; -+ -+ pa_assert(bvolume); -+ pa_assert(cvolume); -+ pa_assert(map); -+ pa_assert(cvolume->channels == map->channels); -+ -+ bvolume->volume = pa_cvolume_max(cvolume); -+ bvolume->channel_map = *map; -+ -+ for (i = 0; i < map->channels; i++) { -+ if (bvolume->volume != PA_VOLUME_MUTED) -+ bvolume->balance[i] = ((double) cvolume->values[i]) / ((double) bvolume->volume); -+ else -+ bvolume->balance[i] = 1.0; -+ } -+} -+ -+void pa_ext_volume_api_bvolume_to_cvolume(const pa_ext_volume_api_bvolume *bvolume, pa_cvolume *cvolume) { -+ unsigned i; -+ -+ pa_assert(bvolume); -+ pa_assert(cvolume); -+ pa_assert(pa_ext_volume_api_bvolume_valid(bvolume, true, true)); -+ -+ cvolume->channels = bvolume->channel_map.channels; -+ -+ for (i = 0; i < bvolume->channel_map.channels; i++) -+ cvolume->values[i] = bvolume->volume * bvolume->balance[i]; -+} -+ -+void pa_ext_volume_api_bvolume_copy_balance(pa_ext_volume_api_bvolume *to, -+ const pa_ext_volume_api_bvolume *from) { -+ pa_assert(to); -+ pa_assert(from); -+ -+ memcpy(to->balance, from->balance, sizeof(from->balance)); -+ to->channel_map = from->channel_map; -+} -+ -+void pa_ext_volume_api_bvolume_reset_balance(pa_ext_volume_api_bvolume *volume, const pa_channel_map *map) { -+ unsigned i; -+ -+ pa_assert(volume); -+ pa_assert(map); -+ pa_assert(pa_channel_map_valid(map)); -+ -+ for (i = 0; i < map->channels; i++) -+ volume->balance[i] = 1.0; -+ -+ volume->channel_map = *map; -+} -+ -+void pa_ext_volume_api_bvolume_remap(pa_ext_volume_api_bvolume *volume, const pa_channel_map *to) { -+ unsigned i; -+ pa_cvolume cvolume; -+ -+ pa_assert(volume); -+ pa_assert(to); -+ pa_assert(pa_ext_volume_api_bvolume_valid(volume, false, true)); -+ pa_assert(pa_channel_map_valid(to)); -+ -+ cvolume.channels = volume->channel_map.channels; -+ -+ for (i = 0; i < cvolume.channels; i++) -+ cvolume.values[i] = volume->balance[i] * (double) PA_VOLUME_NORM; -+ -+ pa_cvolume_remap(&cvolume, &volume->channel_map, to); -+ -+ for (i = 0; i < to->channels; i++) -+ volume->balance[i] = (double) cvolume.values[i] / (double) PA_VOLUME_NORM; -+ -+ volume->channel_map = *to; -+} -+ -+double pa_ext_volume_api_bvolume_get_left_right_balance(const pa_ext_volume_api_bvolume *volume) { -+ pa_ext_volume_api_bvolume bvolume; -+ pa_cvolume cvolume; -+ double ret; -+ -+ pa_assert(volume); -+ -+ bvolume.volume = PA_VOLUME_NORM; -+ pa_ext_volume_api_bvolume_copy_balance(&bvolume, volume); -+ pa_ext_volume_api_bvolume_to_cvolume(&bvolume, &cvolume); -+ ret = pa_cvolume_get_balance(&cvolume, &volume->channel_map); -+ -+ return ret; -+} -+ -+void pa_ext_volume_api_bvolume_set_left_right_balance(pa_ext_volume_api_bvolume *volume, double balance) { -+ pa_cvolume cvolume; -+ pa_volume_t old_volume; -+ -+ pa_assert(volume); -+ -+ if (!pa_channel_map_can_balance(&volume->channel_map)) -+ return; -+ -+ pa_cvolume_reset(&cvolume, volume->channel_map.channels); -+ pa_cvolume_set_balance(&cvolume, &volume->channel_map, balance); -+ old_volume = volume->volume; -+ pa_ext_volume_api_bvolume_from_cvolume(volume, &cvolume, &volume->channel_map); -+ volume->volume = old_volume; -+} -+ -+double pa_ext_volume_api_bvolume_get_rear_front_balance(const pa_ext_volume_api_bvolume *volume) { -+ pa_ext_volume_api_bvolume bvolume; -+ pa_cvolume cvolume; -+ double ret; -+ -+ pa_assert(volume); -+ -+ bvolume.volume = PA_VOLUME_NORM; -+ pa_ext_volume_api_bvolume_copy_balance(&bvolume, volume); -+ pa_ext_volume_api_bvolume_to_cvolume(&bvolume, &cvolume); -+ ret = pa_cvolume_get_fade(&cvolume, &volume->channel_map); -+ -+ return ret; -+} -+ -+void pa_ext_volume_api_bvolume_set_rear_front_balance(pa_ext_volume_api_bvolume *volume, double balance) { -+ pa_cvolume cvolume; -+ pa_volume_t old_volume; -+ -+ pa_assert(volume); -+ -+ if (!pa_channel_map_can_fade(&volume->channel_map)) -+ return; -+ -+ pa_cvolume_reset(&cvolume, volume->channel_map.channels); -+ pa_cvolume_set_fade(&cvolume, &volume->channel_map, balance); -+ old_volume = volume->volume; -+ pa_ext_volume_api_bvolume_from_cvolume(volume, &cvolume, &volume->channel_map); -+ volume->volume = old_volume; -+} -+ -+char *pa_ext_volume_api_bvolume_snprint_balance(char *buf, size_t buf_len, -+ const pa_ext_volume_api_bvolume *volume) { -+ char *e; -+ unsigned channel; -+ bool first = true; -+ -+ pa_assert(buf); -+ pa_assert(buf_len > 0); -+ pa_assert(volume); -+ -+ pa_init_i18n(); -+ -+ if (!pa_ext_volume_api_bvolume_valid(volume, true, true)) { -+ pa_snprintf(buf, buf_len, _("(invalid)")); -+ return buf; -+ } -+ -+ *(e = buf) = 0; -+ -+ for (channel = 0; channel < volume->channel_map.channels && buf_len > 1; channel++) { -+ buf_len -= pa_snprintf(e, buf_len, "%s%s: %u%%", -+ first ? "" : ", ", -+ pa_channel_position_to_string(volume->channel_map.map[channel]), -+ (unsigned) (volume->balance[channel] * 100 + 0.5)); -+ -+ e = strchr(e, 0); -+ first = false; -+ } -+ -+ return buf; -+} -diff --git a/src/pulse/ext-volume-api.h b/src/pulse/ext-volume-api.h -new file mode 100644 -index 0000000..36b7748 ---- /dev/null -+++ b/src/pulse/ext-volume-api.h -@@ -0,0 +1,68 @@ -+#ifndef fooextvolumeapihfoo -+#define fooextvolumeapihfoo -+ -+/*** -+ This file is part of PulseAudio. -+ -+ Copyright 2014 Intel Corporation -+ -+ PulseAudio is free software; you can redistribute it and/or modify -+ it under the terms of the GNU Lesser General Public License as published -+ by the Free Software Foundation; either version 2.1 of the License, -+ or (at your option) any later version. -+ -+ PulseAudio 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 Lesser General Public License -+ along with PulseAudio; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ USA. -+***/ -+ -+#include -+#include -+#include -+ -+/* This API is temporary, and has no stability guarantees whatsoever. Think -+ * twice before making anything that relies on this API. This is undocumented -+ * for a reason. */ -+ -+PA_C_DECL_BEGIN -+ -+typedef struct pa_ext_volume_api_bvolume pa_ext_volume_api_bvolume; -+ -+struct pa_ext_volume_api_bvolume { -+ pa_volume_t volume; -+ double balance[PA_CHANNELS_MAX]; -+ pa_channel_map channel_map; -+}; -+ -+int pa_ext_volume_api_balance_valid(double balance) PA_GCC_CONST; -+int pa_ext_volume_api_bvolume_valid(const pa_ext_volume_api_bvolume *volume, int check_volume, int check_balance) -+ PA_GCC_PURE; -+void pa_ext_volume_api_bvolume_init_invalid(pa_ext_volume_api_bvolume *volume); -+void pa_ext_volume_api_bvolume_init_mono(pa_ext_volume_api_bvolume *bvolume, pa_volume_t volume); -+int pa_ext_volume_api_bvolume_equal(const pa_ext_volume_api_bvolume *a, const pa_ext_volume_api_bvolume *b, -+ int check_volume, int check_balance) PA_GCC_PURE; -+void pa_ext_volume_api_bvolume_from_cvolume(pa_ext_volume_api_bvolume *bvolume, const pa_cvolume *cvolume, -+ const pa_channel_map *map); -+void pa_ext_volume_api_bvolume_to_cvolume(const pa_ext_volume_api_bvolume *bvolume, pa_cvolume *cvolume); -+void pa_ext_volume_api_bvolume_copy_balance(pa_ext_volume_api_bvolume *to, -+ const pa_ext_volume_api_bvolume *from); -+void pa_ext_volume_api_bvolume_reset_balance(pa_ext_volume_api_bvolume *volume, const pa_channel_map *map); -+void pa_ext_volume_api_bvolume_remap(pa_ext_volume_api_bvolume *volume, const pa_channel_map *to); -+double pa_ext_volume_api_bvolume_get_left_right_balance(const pa_ext_volume_api_bvolume *volume) PA_GCC_PURE; -+void pa_ext_volume_api_bvolume_set_left_right_balance(pa_ext_volume_api_bvolume *volume, double balance); -+double pa_ext_volume_api_bvolume_get_rear_front_balance(const pa_ext_volume_api_bvolume *volume) PA_GCC_PURE; -+void pa_ext_volume_api_bvolume_set_rear_front_balance(pa_ext_volume_api_bvolume *volume, double balance); -+ -+#define PA_EXT_VOLUME_API_BVOLUME_SNPRINT_BALANCE_MAX 500 -+char *pa_ext_volume_api_bvolume_snprint_balance(char *buf, size_t buf_size, -+ const pa_ext_volume_api_bvolume *volume); -+ -+PA_C_DECL_END -+ -+#endif --- -2.1.4 - ---- a/po/POTFILES.in 2016-04-13 17:40:00.818008672 +0200 -+++ b/po/POTFILES.in 2016-04-13 17:40:30.885008622 +0200 -@@ -198,3 +198,5 @@ - src/utils/padsp.c - src/utils/pasuspender.c - src/utils/pax11publish.c -+src/modules/volume-api/device-creator.c -+src/pulse/ext-volume-api.c diff --git a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0031-Add-module-main-volume-policy.patch b/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0031-Add-module-main-volume-policy.patch deleted file mode 100644 index 216ed21e9..000000000 --- a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0031-Add-module-main-volume-policy.patch +++ /dev/null @@ -1,1418 +0,0 @@ -From cfb39f18569679f59c9b6283c47e8d90ddd9763d Mon Sep 17 00:00:00 2001 -From: Tanu Kaskinen -Date: Wed, 21 May 2014 14:13:41 +0300 -Subject: [PATCH] Add module-main-volume-policy - -Change-Id: I787141b43cafb652aa752c64ae28b6b7aa052d8e -Signed-off-by: Jaska Uimonen ---- - Makefile.am | 3 + - src/Makefile.am | 15 + - src/daemon/default.pa.in | 4 + - .../main-volume-policy/main-volume-context.c | 325 ++++++++++++ - .../main-volume-policy/main-volume-context.h | 75 +++ - .../main-volume-policy/main-volume-policy.c | 213 ++++++++ - .../main-volume-policy.conf.example | 20 + - .../main-volume-policy/main-volume-policy.h | 72 +++ - .../main-volume-policy/module-main-volume-policy.c | 556 +++++++++++++++++++++ - 9 files changed, 1283 insertions(+) - create mode 100644 src/modules/main-volume-policy/main-volume-context.c - create mode 100644 src/modules/main-volume-policy/main-volume-context.h - create mode 100644 src/modules/main-volume-policy/main-volume-policy.c - create mode 100644 src/modules/main-volume-policy/main-volume-policy.conf.example - create mode 100644 src/modules/main-volume-policy/main-volume-policy.h - create mode 100644 src/modules/main-volume-policy/module-main-volume-policy.c - -diff --git a/Makefile.am b/Makefile.am -index cf4a648..646b7fc 100644 ---- a/Makefile.am 2016-04-13 15:14:28.942023245 +0200 -+++ b/Makefile.am 2016-04-13 15:16:32.691023039 +0200 -@@ -60,6 +60,9 @@ - moduledevvolumeapi_DATA = src/modules/volume-api/*.h - moduledevvolumeapidir = $(includedir)/pulsemodule/modules/volume-api - -+moduledevmainvolumepolicy_DATA = $(top_srcdir)/src/modules/main-volume-policy/*.h -+moduledevmainvolumepolicydir = $(includedir)/pulsemodule/modules/main-volume-policy -+ - if HAVE_GLIB20 - pkgconfig_DATA += \ - libpulse-mainloop-glib.pc - libpulse-mainloop-glib.pc -diff --git a/src/Makefile.am b/src/Makefile.am -index a6bb319..8fa60ec 100644 ---- a/src/Makefile.am -+++ b/src/Makefile.am -@@ -1050,7 +1050,8 @@ - libprotocol-simple.la \ - libprotocol-http.la \ - libprotocol-native.la \ -- libvolume-api.la -+ libvolume-api.la \ -+ libmain-volume-policy.la - - if HAVE_WEBRTC - modlibexec_LTLIBRARIES += libwebrtc-util.la -@@ -1051,6 +1052,12 @@ libcli_la_SOURCES = pulsecore/cli.c pulsecore/cli.h - libcli_la_LDFLAGS = $(AM_LDFLAGS) -avoid-version - libcli_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINOR@.la libpulsecommon-@PA_MAJORMINOR@.la libpulse.la - -+libmain_volume_policy_la_SOURCES = \ -+ modules/main-volume-policy/main-volume-context.c modules/main-volume-policy/main-volume-context.h \ -+ modules/main-volume-policy/main-volume-policy.c modules/main-volume-policy/main-volume-policy.h -+libmain_volume_policy_la_LDFLAGS = $(AM_LDFLAGS) -avoid-version -+libmain_volume_policy_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINOR@.la libpulsecommon-@PA_MAJORMINOR@.la libpulse.la libvolume-api.la -+ - libprotocol_cli_la_SOURCES = pulsecore/protocol-cli.c pulsecore/protocol-cli.h - libprotocol_cli_la_LDFLAGS = $(AM_LDFLAGS) -avoid-version - libprotocol_cli_la_LIBADD = $(AM_LIBADD) libpulsecore-@PA_MAJORMINOR@.la libpulsecommon-@PA_MAJORMINOR@.la libpulse.la libcli.la -@@ -1136,6 +1136,7 @@ endif - modlibexec_LTLIBRARIES += \ - module-cli.la \ - module-cli-protocol-tcp.la \ -+ module-main-volume-policy.la \ - module-simple-protocol-tcp.la \ - module-null-sink.la \ - module-null-source.la \ -@@ -1426,6 +1434,7 @@ SYMDEF_FILES = \ - module-cli-symdef.h \ - module-cli-protocol-tcp-symdef.h \ - module-cli-protocol-unix-symdef.h \ -+ module-main-volume-policy-symdef.h \ - module-pipe-sink-symdef.h \ - module-pipe-source-symdef.h \ - module-simple-protocol-tcp-symdef.h \ -@@ -1575,6 +1584,12 @@ module_cli_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_CLI $(AM_ - module_cli_protocol_unix_la_LDFLAGS = $(MODULE_LDFLAGS) - module_cli_protocol_unix_la_LIBADD = $(MODULE_LIBADD) libprotocol-cli.la - -+# Main volume and mute policy -+ -+module_main_volume_policy_la_SOURCES = modules/main-volume-policy/module-main-volume-policy.c -+module_main_volume_policy_la_LDFLAGS = $(MODULE_LDFLAGS) -+module_main_volume_policy_la_LIBADD = $(MODULE_LIBADD) libmain-volume-policy.la libvolume-api.la -+ - # HTTP protocol - - module_http_protocol_tcp_la_SOURCES = modules/module-protocol-stub.c -diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in -index 7cf52a4..f70804c 100755 ---- a/src/daemon/default.pa.in -+++ b/src/daemon/default.pa.in -@@ -188,6 +188,10 @@ - #.endif - ])dnl - -+.ifexists module-main-volume-policy -+load-module module-main-volume-policy -+.endif -+ - ### Make some devices default - #set-default-sink output - #set-default-source input -diff --git a/src/modules/main-volume-policy/main-volume-context.c b/src/modules/main-volume-policy/main-volume-context.c -new file mode 100644 -index 0000000..7ac35c6 ---- /dev/null -+++ b/src/modules/main-volume-policy/main-volume-context.c -@@ -0,0 +1,325 @@ -+/*** -+ This file is part of PulseAudio. -+ -+ Copyright 2014 Intel Corporation -+ -+ PulseAudio is free software; you can redistribute it and/or modify -+ it under the terms of the GNU Lesser General Public License as published -+ by the Free Software Foundation; either version 2.1 of the License, -+ or (at your option) any later version. -+ -+ PulseAudio 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 Lesser General Public License -+ along with PulseAudio; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ USA. -+***/ -+ -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ -+#include "main-volume-context.h" -+ -+#include -+#include -+ -+int pa_main_volume_context_new(pa_main_volume_policy *policy, const char *name, const char *description, -+ pa_main_volume_context **context) { -+ pa_main_volume_context *context_local; -+ int r; -+ -+ pa_assert(policy); -+ pa_assert(name); -+ pa_assert(description); -+ pa_assert(context); -+ -+ context_local = pa_xnew0(struct pa_main_volume_context, 1); -+ context_local->main_volume_policy = policy; -+ context_local->index = pa_main_volume_policy_allocate_main_volume_context_index(policy); -+ -+ r = pa_main_volume_policy_register_name(policy, name, true, &context_local->name); -+ if (r < 0) -+ goto fail; -+ -+ context_local->description = pa_xstrdup(description); -+ -+ *context = context_local; -+ -+ return 0; -+ -+fail: -+ pa_main_volume_context_free(context_local); -+ -+ return r; -+} -+ -+void pa_main_volume_context_put(pa_main_volume_context *context) { -+ pa_assert(context); -+ -+ pa_main_volume_policy_add_main_volume_context(context->main_volume_policy, context); -+ -+ context->linked = true; -+ -+ pa_log_debug("Created main volume context #%u.", context->index); -+ pa_log_debug(" Name: %s", context->name); -+ pa_log_debug(" Description: %s", context->description); -+ pa_log_debug(" Main output volume control: %s", -+ context->main_output_volume_control ? context->main_output_volume_control->name : "(unset)"); -+ pa_log_debug(" Main input volume control: %s", -+ context->main_input_volume_control ? context->main_input_volume_control->name : "(unset)"); -+ pa_log_debug(" Main output mute control: %s", -+ context->main_output_mute_control ? context->main_output_mute_control->name : "(unset)"); -+ pa_log_debug(" Main input mute control: %s", -+ context->main_input_mute_control ? context->main_input_mute_control->name : "(unset)"); -+ -+ pa_hook_fire(&context->main_volume_policy->hooks[PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_PUT], context); -+} -+ -+void pa_main_volume_context_unlink(pa_main_volume_context *context) { -+ pa_assert(context); -+ -+ if (context->unlinked) { -+ pa_log_debug("Unlinking main volume context %s (already unlinked, this is a no-op).", context->name); -+ return; -+ } -+ -+ context->unlinked = true; -+ -+ pa_log_debug("Unlinking main volume context %s.", context->name); -+ -+ if (context->linked) -+ pa_hook_fire(&context->main_volume_policy->hooks[PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_UNLINK], context); -+ -+ if (context->main_input_mute_control_binding) { -+ pa_binding_free(context->main_input_mute_control_binding); -+ context->main_input_mute_control_binding = NULL; -+ } -+ -+ if (context->main_output_mute_control_binding) { -+ pa_binding_free(context->main_output_mute_control_binding); -+ context->main_output_mute_control_binding = NULL; -+ } -+ -+ if (context->main_input_volume_control_binding) { -+ pa_binding_free(context->main_input_volume_control_binding); -+ context->main_input_volume_control_binding = NULL; -+ } -+ -+ if (context->main_output_volume_control_binding) { -+ pa_binding_free(context->main_output_volume_control_binding); -+ context->main_output_volume_control_binding = NULL; -+ } -+ -+ context->main_input_mute_control = NULL; -+ context->main_output_mute_control = NULL; -+ context->main_input_volume_control = NULL; -+ context->main_output_volume_control = NULL; -+ -+ pa_main_volume_policy_remove_main_volume_context(context->main_volume_policy, context); -+} -+ -+void pa_main_volume_context_free(pa_main_volume_context *context) { -+ pa_assert(context); -+ -+ if (!context->unlinked) -+ pa_main_volume_context_unlink(context); -+ -+ pa_xfree(context->description); -+ -+ if (context->name) -+ pa_main_volume_policy_unregister_name(context->main_volume_policy, context->name); -+ -+ pa_xfree(context); -+} -+ -+const char *pa_main_volume_context_get_name(pa_main_volume_context *context) { -+ pa_assert(context); -+ -+ return context->name; -+} -+ -+static void set_main_output_volume_control_internal(pa_main_volume_context *context, pa_volume_control *control) { -+ pa_volume_control *old_control; -+ -+ pa_assert(context); -+ -+ old_control = context->main_output_volume_control; -+ -+ if (control == old_control) -+ return; -+ -+ context->main_output_volume_control = control; -+ -+ if (!context->linked || context->unlinked) -+ return; -+ -+ pa_log_debug("The main output volume control of main volume context %s changed from %s to %s.", context->name, -+ old_control ? old_control->name : "(unset)", control ? control->name : "(unset)"); -+ -+ pa_hook_fire(&context->main_volume_policy->hooks -+ [PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_MAIN_OUTPUT_VOLUME_CONTROL_CHANGED], -+ context); -+} -+ -+void pa_main_volume_context_bind_main_output_volume_control(pa_main_volume_context *context, -+ pa_binding_target_info *target_info) { -+ pa_binding_owner_info owner_info = { -+ .userdata = context, -+ .set_value = (pa_binding_set_value_cb_t) set_main_output_volume_control_internal, -+ }; -+ -+ pa_assert(context); -+ pa_assert(target_info); -+ -+ if (context->main_output_volume_control_binding) -+ pa_binding_free(context->main_output_volume_control_binding); -+ -+ context->main_output_volume_control_binding = pa_binding_new(context->main_volume_policy->volume_api, &owner_info, -+ target_info); -+} -+ -+static void set_main_input_volume_control_internal(pa_main_volume_context *context, pa_volume_control *control) { -+ pa_volume_control *old_control; -+ -+ pa_assert(context); -+ -+ old_control = context->main_input_volume_control; -+ -+ if (control == old_control) -+ return; -+ -+ context->main_input_volume_control = control; -+ -+ if (!context->linked || context->unlinked) -+ return; -+ -+ pa_log_debug("The main input volume control of main volume context %s changed from %s to %s.", context->name, -+ old_control ? old_control->name : "(unset)", control ? control->name : "(unset)"); -+ -+ pa_hook_fire(&context->main_volume_policy->hooks -+ [PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_MAIN_INPUT_VOLUME_CONTROL_CHANGED], -+ context); -+} -+ -+void pa_main_volume_context_bind_main_input_volume_control(pa_main_volume_context *context, -+ pa_binding_target_info *target_info) { -+ pa_binding_owner_info owner_info = { -+ .userdata = context, -+ .set_value = (pa_binding_set_value_cb_t) set_main_input_volume_control_internal, -+ }; -+ -+ pa_assert(context); -+ pa_assert(target_info); -+ -+ if (context->main_input_volume_control_binding) -+ pa_binding_free(context->main_input_volume_control_binding); -+ -+ context->main_input_volume_control_binding = pa_binding_new(context->main_volume_policy->volume_api, &owner_info, -+ target_info); -+} -+ -+static void set_main_output_mute_control_internal(pa_main_volume_context *context, pa_mute_control *control) { -+ pa_mute_control *old_control; -+ -+ pa_assert(context); -+ -+ old_control = context->main_output_mute_control; -+ -+ if (control == old_control) -+ return; -+ -+ context->main_output_mute_control = control; -+ -+ if (!context->linked || context->unlinked) -+ return; -+ -+ pa_log_debug("The main output mute control of main volume context %s changed from %s to %s.", context->name, -+ old_control ? old_control->name : "(unset)", control ? control->name : "(unset)"); -+ -+ pa_hook_fire(&context->main_volume_policy->hooks -+ [PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_MAIN_OUTPUT_MUTE_CONTROL_CHANGED], -+ context); -+} -+ -+void pa_main_volume_context_bind_main_output_mute_control(pa_main_volume_context *context, -+ pa_binding_target_info *target_info) { -+ pa_binding_owner_info owner_info = { -+ .userdata = context, -+ .set_value = (pa_binding_set_value_cb_t) set_main_output_mute_control_internal, -+ }; -+ -+ pa_assert(context); -+ pa_assert(target_info); -+ -+ if (context->main_output_mute_control_binding) -+ pa_binding_free(context->main_output_mute_control_binding); -+ -+ context->main_output_mute_control_binding = pa_binding_new(context->main_volume_policy->volume_api, &owner_info, -+ target_info); -+} -+ -+static void set_main_input_mute_control_internal(pa_main_volume_context *context, pa_mute_control *control) { -+ pa_mute_control *old_control; -+ -+ pa_assert(context); -+ -+ old_control = context->main_input_mute_control; -+ -+ if (control == old_control) -+ return; -+ -+ context->main_input_mute_control = control; -+ -+ if (!context->linked || context->unlinked) -+ return; -+ -+ pa_log_debug("The main input mute control of main volume context %s changed from %s to %s.", context->name, -+ old_control ? old_control->name : "(unset)", control ? control->name : "(unset)"); -+ -+ pa_hook_fire(&context->main_volume_policy->hooks -+ [PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_MAIN_INPUT_MUTE_CONTROL_CHANGED], -+ context); -+} -+ -+void pa_main_volume_context_bind_main_input_mute_control(pa_main_volume_context *context, -+ pa_binding_target_info *target_info) { -+ pa_binding_owner_info owner_info = { -+ .userdata = context, -+ .set_value = (pa_binding_set_value_cb_t) set_main_input_mute_control_internal, -+ }; -+ -+ pa_assert(context); -+ pa_assert(target_info); -+ -+ if (context->main_input_mute_control_binding) -+ pa_binding_free(context->main_input_mute_control_binding); -+ -+ context->main_input_mute_control_binding = pa_binding_new(context->main_volume_policy->volume_api, &owner_info, -+ target_info); -+} -+ -+pa_binding_target_type *pa_main_volume_context_create_binding_target_type(pa_main_volume_policy *policy) { -+ pa_binding_target_type *type; -+ -+ pa_assert(policy); -+ -+ type = pa_binding_target_type_new(PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_TYPE, policy->main_volume_contexts, -+ &policy->hooks[PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_PUT], -+ &policy->hooks[PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_UNLINK], -+ (pa_binding_target_type_get_name_cb_t) pa_main_volume_context_get_name); -+ pa_binding_target_type_add_field(type, PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_OUTPUT_VOLUME_CONTROL, -+ PA_BINDING_CALCULATE_FIELD_OFFSET(pa_main_volume_context, main_output_volume_control)); -+ pa_binding_target_type_add_field(type, PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_INPUT_VOLUME_CONTROL, -+ PA_BINDING_CALCULATE_FIELD_OFFSET(pa_main_volume_context, main_input_volume_control)); -+ pa_binding_target_type_add_field(type, PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_OUTPUT_MUTE_CONTROL, -+ PA_BINDING_CALCULATE_FIELD_OFFSET(pa_main_volume_context, main_output_mute_control)); -+ pa_binding_target_type_add_field(type, PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_INPUT_MUTE_CONTROL, -+ PA_BINDING_CALCULATE_FIELD_OFFSET(pa_main_volume_context, main_input_mute_control)); -+ -+ return type; -+} -diff --git a/src/modules/main-volume-policy/main-volume-context.h b/src/modules/main-volume-policy/main-volume-context.h -new file mode 100644 -index 0000000..4a0a6f7 ---- /dev/null -+++ b/src/modules/main-volume-policy/main-volume-context.h -@@ -0,0 +1,75 @@ -+#ifndef foomainvolumecontexthfoo -+#define foomainvolumecontexthfoo -+ -+/*** -+ This file is part of PulseAudio. -+ -+ Copyright 2014 Intel Corporation -+ -+ PulseAudio is free software; you can redistribute it and/or modify -+ it under the terms of the GNU Lesser General Public License as published -+ by the Free Software Foundation; either version 2.1 of the License, -+ or (at your option) any later version. -+ -+ PulseAudio 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 Lesser General Public License -+ along with PulseAudio; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ USA. -+***/ -+ -+#include -+ -+#include -+ -+typedef struct pa_main_volume_context pa_main_volume_context; -+ -+#define PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_TYPE "MainVolumeContext" -+#define PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_OUTPUT_VOLUME_CONTROL "main_output_volume_control" -+#define PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_INPUT_VOLUME_CONTROL "main_input_volume_control" -+#define PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_OUTPUT_MUTE_CONTROL "main_output_mute_control" -+#define PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_INPUT_MUTE_CONTROL "main_input_mute_control" -+ -+struct pa_main_volume_context { -+ pa_main_volume_policy *main_volume_policy; -+ uint32_t index; -+ const char *name; -+ char *description; -+ pa_volume_control *main_output_volume_control; -+ pa_volume_control *main_input_volume_control; -+ pa_mute_control *main_output_mute_control; -+ pa_mute_control *main_input_mute_control; -+ -+ pa_binding *main_output_volume_control_binding; -+ pa_binding *main_input_volume_control_binding; -+ pa_binding *main_output_mute_control_binding; -+ pa_binding *main_input_mute_control_binding; -+ -+ bool linked; -+ bool unlinked; -+}; -+ -+int pa_main_volume_context_new(pa_main_volume_policy *policy, const char *name, const char *description, -+ pa_main_volume_context **context); -+void pa_main_volume_context_put(pa_main_volume_context *context); -+void pa_main_volume_context_unlink(pa_main_volume_context *context); -+void pa_main_volume_context_free(pa_main_volume_context *context); -+ -+const char *pa_main_volume_context_get_name(pa_main_volume_context *context); -+ -+void pa_main_volume_context_bind_main_output_volume_control(pa_main_volume_context *context, -+ pa_binding_target_info *target_info); -+void pa_main_volume_context_bind_main_input_volume_control(pa_main_volume_context *context, -+ pa_binding_target_info *target_info); -+void pa_main_volume_context_bind_main_output_mute_control(pa_main_volume_context *context, -+ pa_binding_target_info *target_info); -+void pa_main_volume_context_bind_main_input_mute_control(pa_main_volume_context *context, pa_binding_target_info *target_info); -+ -+/* Called from main-volume-policy.c only. */ -+pa_binding_target_type *pa_main_volume_context_create_binding_target_type(pa_main_volume_policy *policy); -+ -+#endif -diff --git a/src/modules/main-volume-policy/main-volume-policy.c b/src/modules/main-volume-policy/main-volume-policy.c -new file mode 100644 -index 0000000..b0b4ede ---- /dev/null -+++ b/src/modules/main-volume-policy/main-volume-policy.c -@@ -0,0 +1,213 @@ -+/*** -+ This file is part of PulseAudio. -+ -+ Copyright 2014 Intel Corporation -+ -+ PulseAudio is free software; you can redistribute it and/or modify -+ it under the terms of the GNU Lesser General Public License as published -+ by the Free Software Foundation; either version 2.1 of the License, -+ or (at your option) any later version. -+ -+ PulseAudio 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 Lesser General Public License -+ along with PulseAudio; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ USA. -+***/ -+ -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ -+#include "main-volume-policy.h" -+ -+#include -+ -+#include -+#include -+ -+static pa_main_volume_policy *main_volume_policy_new(pa_core *core); -+static void main_volume_policy_free(pa_main_volume_policy *policy); -+ -+pa_main_volume_policy *pa_main_volume_policy_get(pa_core *core) { -+ pa_main_volume_policy *policy; -+ -+ pa_assert(core); -+ -+ policy = pa_shared_get(core, "main-volume-policy"); -+ -+ if (policy) -+ pa_main_volume_policy_ref(policy); -+ else { -+ policy = main_volume_policy_new(core); -+ pa_assert_se(pa_shared_set(core, "main-volume-policy", policy) >= 0); -+ } -+ -+ return policy; -+} -+ -+pa_main_volume_policy *pa_main_volume_policy_ref(pa_main_volume_policy *policy) { -+ pa_assert(policy); -+ -+ policy->refcnt++; -+ -+ return policy; -+} -+ -+void pa_main_volume_policy_unref(pa_main_volume_policy *policy) { -+ pa_assert(policy); -+ pa_assert(policy->refcnt > 0); -+ -+ policy->refcnt--; -+ -+ if (policy->refcnt == 0) { -+ pa_assert_se(pa_shared_remove(policy->core, "main-volume-policy") >= 0); -+ main_volume_policy_free(policy); -+ } -+} -+ -+static pa_main_volume_policy *main_volume_policy_new(pa_core *core) { -+ pa_main_volume_policy *policy; -+ unsigned i; -+ -+ pa_assert(core); -+ -+ policy = pa_xnew0(pa_main_volume_policy, 1); -+ policy->core = core; -+ policy->refcnt = 1; -+ policy->volume_api = pa_volume_api_get(core); -+ policy->names = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, pa_xfree); -+ policy->main_volume_contexts = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); -+ -+ for (i = 0; i < PA_MAIN_VOLUME_POLICY_HOOK_MAX; i++) -+ pa_hook_init(&policy->hooks[i], policy); -+ -+ policy->main_volume_context_binding_target_type = pa_main_volume_context_create_binding_target_type(policy); -+ pa_volume_api_add_binding_target_type(policy->volume_api, policy->main_volume_context_binding_target_type); -+ -+ pa_log_debug("Created a pa_main_volume_policy object."); -+ -+ return policy; -+} -+ -+static void main_volume_policy_free(pa_main_volume_policy *policy) { -+ unsigned i; -+ -+ pa_assert(policy); -+ pa_assert(policy->refcnt == 0); -+ -+ pa_log_debug("Freeing the pa_main_volume_policy object."); -+ -+ if (policy->main_volume_context_binding_target_type) { -+ pa_volume_api_remove_binding_target_type(policy->volume_api, policy->main_volume_context_binding_target_type); -+ pa_binding_target_type_free(policy->main_volume_context_binding_target_type); -+ } -+ -+ for (i = 0; i < PA_MAIN_VOLUME_POLICY_HOOK_MAX; i++) -+ pa_hook_done(&policy->hooks[i]); -+ -+ if (policy->main_volume_contexts) { -+ pa_assert(pa_hashmap_isempty(policy->main_volume_contexts)); -+ pa_hashmap_free(policy->main_volume_contexts); -+ } -+ -+ if (policy->names) { -+ pa_assert(pa_hashmap_isempty(policy->names)); -+ pa_hashmap_free(policy->names); -+ } -+ -+ if (policy->volume_api) -+ pa_volume_api_unref(policy->volume_api); -+ -+ pa_xfree(policy); -+} -+ -+int pa_main_volume_policy_register_name(pa_main_volume_policy *policy, const char *requested_name, -+ bool fail_if_already_registered, const char **registered_name) { -+ char *n; -+ -+ pa_assert(policy); -+ pa_assert(requested_name); -+ pa_assert(registered_name); -+ -+ n = pa_xstrdup(requested_name); -+ -+ if (pa_hashmap_put(policy->names, n, n) < 0) { -+ unsigned i = 1; -+ -+ pa_xfree(n); -+ -+ if (fail_if_already_registered) { -+ pa_log("Name %s already registered.", requested_name); -+ return -PA_ERR_EXIST; -+ } -+ -+ do { -+ i++; -+ n = pa_sprintf_malloc("%s.%u", requested_name, i); -+ } while (pa_hashmap_put(policy->names, n, n) < 0); -+ } -+ -+ *registered_name = n; -+ -+ return 0; -+} -+ -+void pa_main_volume_policy_unregister_name(pa_main_volume_policy *policy, const char *name) { -+ pa_assert(policy); -+ pa_assert(name); -+ -+ pa_assert_se(pa_hashmap_remove_and_free(policy->names, name) >= 0); -+} -+ -+uint32_t pa_main_volume_policy_allocate_main_volume_context_index(pa_main_volume_policy *policy) { -+ uint32_t idx; -+ -+ pa_assert(policy); -+ -+ idx = policy->next_main_volume_context_index++; -+ -+ return idx; -+} -+ -+void pa_main_volume_policy_add_main_volume_context(pa_main_volume_policy *policy, pa_main_volume_context *context) { -+ pa_assert(policy); -+ pa_assert(context); -+ -+ pa_assert_se(pa_hashmap_put(policy->main_volume_contexts, (void *) context->name, context) >= 0); -+} -+ -+int pa_main_volume_policy_remove_main_volume_context(pa_main_volume_policy *policy, pa_main_volume_context *context) { -+ pa_assert(policy); -+ pa_assert(context); -+ -+ if (!pa_hashmap_remove(policy->main_volume_contexts, context->name)) -+ return -1; -+ -+ if (context == policy->active_main_volume_context) -+ pa_main_volume_policy_set_active_main_volume_context(policy, NULL); -+ -+ return 0; -+} -+ -+void pa_main_volume_policy_set_active_main_volume_context(pa_main_volume_policy *policy, pa_main_volume_context *context) { -+ pa_main_volume_context *old_context; -+ -+ pa_assert(policy); -+ -+ old_context = policy->active_main_volume_context; -+ -+ if (context == old_context) -+ return; -+ -+ policy->active_main_volume_context = context; -+ -+ pa_log_debug("The active main volume context changed from %s to %s.", old_context ? old_context->name : "(unset)", -+ context ? context->name : "(unset)"); -+ -+ pa_hook_fire(&policy->hooks[PA_MAIN_VOLUME_POLICY_HOOK_ACTIVE_MAIN_VOLUME_CONTEXT_CHANGED], NULL); -+} -diff --git a/src/modules/main-volume-policy/main-volume-policy.conf.example b/src/modules/main-volume-policy/main-volume-policy.conf.example -new file mode 100644 -index 0000000..a4a35d3 ---- /dev/null -+++ b/src/modules/main-volume-policy/main-volume-policy.conf.example -@@ -0,0 +1,20 @@ -+[General] -+output-volume-model = by-active-main-volume-context -+input-volume-model = by-active-main-volume-context -+output-mute-model = none -+input-mute-model = none -+main-volume-contexts = x-example-call-main-volume-context x-example-default-main-volume-context -+ -+[MainVolumeContext x-example-call-main-volume-context] -+description = Call main volume context -+main-output-volume-control = bind:AudioGroup:x-example-call-downlink-audio-group -+main-input-volume-control = bind:AudioGroup:x-example-call-uplink-audio-group -+main-output-mute-control = none -+main-input-mute-control = none -+ -+[MainVolumeContext x-example-default-main-volume-context] -+description = Default main volume context -+main-output-volume-control = bind:AudioGroup:x-example-default-output-audio-group -+main-input-volume-control = bind:AudioGroup:x-example-default-input-audio-group -+main-output-mute-control = none -+main-input-mute-control = none -diff --git a/src/modules/main-volume-policy/main-volume-policy.h b/src/modules/main-volume-policy/main-volume-policy.h -new file mode 100644 -index 0000000..5cd669e ---- /dev/null -+++ b/src/modules/main-volume-policy/main-volume-policy.h -@@ -0,0 +1,72 @@ -+#ifndef foomainvolumepolicyhfoo -+#define foomainvolumepolicyhfoo -+ -+/*** -+ This file is part of PulseAudio. -+ -+ Copyright 2014 Intel Corporation -+ -+ PulseAudio is free software; you can redistribute it and/or modify -+ it under the terms of the GNU Lesser General Public License as published -+ by the Free Software Foundation; either version 2.1 of the License, -+ or (at your option) any later version. -+ -+ PulseAudio 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 Lesser General Public License -+ along with PulseAudio; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ USA. -+***/ -+ -+#include -+#include -+ -+#include -+ -+typedef struct pa_main_volume_policy pa_main_volume_policy; -+ -+/* Avoid circular dependencies... */ -+typedef struct pa_main_volume_context pa_main_volume_context; -+ -+enum { -+ PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_PUT, -+ PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_UNLINK, -+ PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_MAIN_OUTPUT_VOLUME_CONTROL_CHANGED, -+ PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_MAIN_INPUT_VOLUME_CONTROL_CHANGED, -+ PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_MAIN_OUTPUT_MUTE_CONTROL_CHANGED, -+ PA_MAIN_VOLUME_POLICY_HOOK_MAIN_VOLUME_CONTEXT_MAIN_INPUT_MUTE_CONTROL_CHANGED, -+ PA_MAIN_VOLUME_POLICY_HOOK_ACTIVE_MAIN_VOLUME_CONTEXT_CHANGED, -+ PA_MAIN_VOLUME_POLICY_HOOK_MAX, -+}; -+ -+struct pa_main_volume_policy { -+ pa_core *core; -+ unsigned refcnt; -+ pa_volume_api *volume_api; -+ pa_hashmap *names; /* object name -> object name (hashmap-as-a-set) */ -+ pa_hashmap *main_volume_contexts; /* name -> pa_main_volume_context */ -+ pa_main_volume_context *active_main_volume_context; -+ -+ uint32_t next_main_volume_context_index; -+ pa_hook hooks[PA_MAIN_VOLUME_POLICY_HOOK_MAX]; -+ pa_binding_target_type *main_volume_context_binding_target_type; -+}; -+ -+pa_main_volume_policy *pa_main_volume_policy_get(pa_core *core); -+pa_main_volume_policy *pa_main_volume_policy_ref(pa_main_volume_policy *policy); -+void pa_main_volume_policy_unref(pa_main_volume_policy *policy); -+ -+int pa_main_volume_policy_register_name(pa_main_volume_policy *policy, const char *requested_name, -+ bool fail_if_already_registered, const char **registered_name); -+void pa_main_volume_policy_unregister_name(pa_main_volume_policy *policy, const char *name); -+ -+uint32_t pa_main_volume_policy_allocate_main_volume_context_index(pa_main_volume_policy *policy); -+void pa_main_volume_policy_add_main_volume_context(pa_main_volume_policy *policy, pa_main_volume_context *context); -+int pa_main_volume_policy_remove_main_volume_context(pa_main_volume_policy *policy, pa_main_volume_context *context); -+void pa_main_volume_policy_set_active_main_volume_context(pa_main_volume_policy *policy, pa_main_volume_context *context); -+ -+#endif -diff --git a/src/modules/main-volume-policy/module-main-volume-policy.c b/src/modules/main-volume-policy/module-main-volume-policy.c -new file mode 100644 -index 0000000..a14699d ---- /dev/null -+++ b/src/modules/main-volume-policy/module-main-volume-policy.c -@@ -0,0 +1,556 @@ -+/*** -+ This file is part of PulseAudio. -+ -+ Copyright 2014 Intel Corporation -+ -+ PulseAudio is free software; you can redistribute it and/or modify -+ it under the terms of the GNU Lesser General Public License as published -+ by the Free Software Foundation; either version 2.1 of the License, -+ or (at your option) any later version. -+ -+ PulseAudio 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 Lesser General Public License -+ along with PulseAudio; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ USA. -+***/ -+ -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ -+#include "module-main-volume-policy-symdef.h" -+ -+#include -+ -+#include -+#include -+ -+#include -+ -+#include -+#include -+#include -+ -+PA_MODULE_AUTHOR("Tanu Kaskinen"); -+PA_MODULE_DESCRIPTION(_("Main volume and mute policy")); -+PA_MODULE_VERSION(PACKAGE_VERSION); -+PA_MODULE_LOAD_ONCE(true); -+ -+enum control_type { -+ CONTROL_TYPE_VOLUME, -+ CONTROL_TYPE_MUTE, -+}; -+ -+enum model { -+ MODEL_NONE, -+ MODEL_BY_ACTIVE_MAIN_VOLUME_CONTEXT, -+}; -+ -+struct userdata { -+ pa_main_volume_policy *main_volume_policy; -+ enum model output_volume_model; -+ enum model input_volume_model; -+ enum model output_mute_model; -+ enum model input_mute_model; -+ pa_hashmap *contexts; /* name -> struct context */ -+ -+ pa_hook_slot *active_main_volume_context_changed_slot; -+ -+ /* The following fields are only used during initialization. */ -+ pa_hashmap *context_names; /* name -> name (hashmap-as-a-set) */ -+ pa_hashmap *unused_contexts; /* name -> struct context */ -+}; -+ -+struct context { -+ struct userdata *userdata; -+ char *name; -+ char *description; -+ pa_binding_target_info *main_output_volume_control_target_info; -+ pa_binding_target_info *main_input_volume_control_target_info; -+ pa_binding_target_info *main_output_mute_control_target_info; -+ pa_binding_target_info *main_input_mute_control_target_info; -+ pa_main_volume_context *main_volume_context; -+ -+ bool unlinked; -+}; -+ -+static void context_unlink(struct context *context); -+ -+static const char *model_to_string(enum model model) { -+ switch (model) { -+ case MODEL_NONE: -+ return "none"; -+ -+ case MODEL_BY_ACTIVE_MAIN_VOLUME_CONTEXT: -+ return "by-active-main-volume-context"; -+ } -+ -+ pa_assert_not_reached(); -+} -+ -+static int model_from_string(const char *str, enum model *model) { -+ pa_assert(str); -+ pa_assert(model); -+ -+ if (pa_streq(str, "none")) -+ *model = MODEL_NONE; -+ else if (pa_streq(str, "by-active-main-volume-context")) -+ *model = MODEL_BY_ACTIVE_MAIN_VOLUME_CONTEXT; -+ else -+ return -PA_ERR_INVALID; -+ -+ return 0; -+} -+ -+static struct context *context_new(struct userdata *u, const char *name) { -+ struct context *context; -+ -+ pa_assert(u); -+ pa_assert(name); -+ -+ context = pa_xnew0(struct context, 1); -+ context->userdata = u; -+ context->name = pa_xstrdup(name); -+ context->description = pa_xstrdup(name); -+ -+ return context; -+} -+ -+static int context_put(struct context *context) { -+ int r; -+ -+ pa_assert(context); -+ -+ r = pa_main_volume_context_new(context->userdata->main_volume_policy, context->name, context->description, -+ &context->main_volume_context); -+ if (r < 0) -+ goto fail; -+ -+ if (context->main_output_volume_control_target_info) -+ pa_main_volume_context_bind_main_output_volume_control(context->main_volume_context, -+ context->main_output_volume_control_target_info); -+ -+ if (context->main_input_volume_control_target_info) -+ pa_main_volume_context_bind_main_input_volume_control(context->main_volume_context, -+ context->main_input_volume_control_target_info); -+ -+ if (context->main_output_mute_control_target_info) -+ pa_main_volume_context_bind_main_output_mute_control(context->main_volume_context, -+ context->main_output_mute_control_target_info); -+ -+ if (context->main_input_mute_control_target_info) -+ pa_main_volume_context_bind_main_input_mute_control(context->main_volume_context, -+ context->main_input_mute_control_target_info); -+ -+ pa_main_volume_context_put(context->main_volume_context); -+ -+ return 0; -+ -+fail: -+ context_unlink(context); -+ -+ return r; -+} -+ -+static void context_unlink(struct context *context) { -+ pa_assert(context); -+ -+ if (context->unlinked) -+ return; -+ -+ context->unlinked = true; -+ -+ if (context->main_volume_context) { -+ pa_main_volume_context_free(context->main_volume_context); -+ context->main_volume_context = NULL; -+ } -+} -+ -+static void context_free(struct context *context) { -+ pa_assert(context); -+ -+ if (!context->unlinked) -+ context_unlink(context); -+ -+ if (context->main_input_mute_control_target_info) -+ pa_binding_target_info_free(context->main_input_mute_control_target_info); -+ -+ if (context->main_output_mute_control_target_info) -+ pa_binding_target_info_free(context->main_output_mute_control_target_info); -+ -+ if (context->main_input_volume_control_target_info) -+ pa_binding_target_info_free(context->main_input_volume_control_target_info); -+ -+ if (context->main_output_volume_control_target_info) -+ pa_binding_target_info_free(context->main_output_volume_control_target_info); -+ -+ pa_xfree(context->description); -+ pa_xfree(context->name); -+ pa_xfree(context); -+} -+ -+static void context_set_description(struct context *context, const char *description) { -+ pa_assert(context); -+ pa_assert(description); -+ -+ pa_xfree(context->description); -+ context->description = pa_xstrdup(description); -+} -+ -+static void context_set_main_control_target_info(struct context *context, enum control_type type, pa_direction_t direction, -+ pa_binding_target_info *info) { -+ pa_assert(context); -+ -+ switch (type) { -+ case CONTROL_TYPE_VOLUME: -+ if (direction == PA_DIRECTION_OUTPUT) { -+ if (context->main_output_volume_control_target_info) -+ pa_binding_target_info_free(context->main_output_volume_control_target_info); -+ -+ if (info) -+ context->main_output_volume_control_target_info = pa_binding_target_info_copy(info); -+ else -+ context->main_output_volume_control_target_info = NULL; -+ } else { -+ if (context->main_input_volume_control_target_info) -+ pa_binding_target_info_free(context->main_input_volume_control_target_info); -+ -+ if (info) -+ context->main_input_volume_control_target_info = pa_binding_target_info_copy(info); -+ else -+ context->main_input_volume_control_target_info = NULL; -+ } -+ break; -+ -+ case CONTROL_TYPE_MUTE: -+ if (direction == PA_DIRECTION_OUTPUT) { -+ if (context->main_output_mute_control_target_info) -+ pa_binding_target_info_free(context->main_output_mute_control_target_info); -+ -+ if (info) -+ context->main_output_mute_control_target_info = pa_binding_target_info_copy(info); -+ else -+ context->main_output_mute_control_target_info = NULL; -+ } else { -+ if (context->main_input_mute_control_target_info) -+ pa_binding_target_info_free(context->main_input_mute_control_target_info); -+ -+ if (info) -+ context->main_input_mute_control_target_info = pa_binding_target_info_copy(info); -+ else -+ context->main_input_mute_control_target_info = NULL; -+ } -+ break; -+ } -+} -+ -+static pa_hook_result_t active_main_volume_context_changed_cb(void *hook_data, void *call_data, void *userdata) { -+ struct userdata *u = userdata; -+ pa_main_volume_context *context; -+ pa_volume_api *api; -+ pa_binding_target_info *info = NULL; -+ -+ pa_assert(u); -+ -+ context = u->main_volume_policy->active_main_volume_context; -+ api = u->main_volume_policy->volume_api; -+ -+ if (u->output_volume_model == MODEL_BY_ACTIVE_MAIN_VOLUME_CONTEXT) { -+ if (context) { -+ info = pa_binding_target_info_new(PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_TYPE, context->name, -+ PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_OUTPUT_VOLUME_CONTROL); -+ pa_volume_api_bind_main_output_volume_control(api, info); -+ } else -+ pa_volume_api_set_main_output_volume_control(api, NULL); -+ } -+ -+ if (u->input_volume_model == MODEL_BY_ACTIVE_MAIN_VOLUME_CONTEXT) { -+ if (context) { -+ info = pa_binding_target_info_new(PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_TYPE, context->name, -+ PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_INPUT_VOLUME_CONTROL); -+ pa_volume_api_bind_main_input_volume_control(api, info); -+ } else -+ pa_volume_api_set_main_input_volume_control(api, NULL); -+ } -+ -+ if (u->output_mute_model == MODEL_BY_ACTIVE_MAIN_VOLUME_CONTEXT) { -+ if (context) { -+ info = pa_binding_target_info_new(PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_TYPE, context->name, -+ PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_OUTPUT_MUTE_CONTROL); -+ pa_volume_api_bind_main_output_mute_control(api, info); -+ } else -+ pa_volume_api_set_main_output_mute_control(api, NULL); -+ } -+ -+ if (u->input_mute_model == MODEL_BY_ACTIVE_MAIN_VOLUME_CONTEXT) { -+ if (context) { -+ info = pa_binding_target_info_new(PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_TYPE, context->name, -+ PA_MAIN_VOLUME_CONTEXT_BINDING_TARGET_FIELD_MAIN_INPUT_MUTE_CONTROL); -+ pa_volume_api_bind_main_input_mute_control(api, info); -+ } else -+ pa_volume_api_set_main_input_mute_control(api, NULL); -+ } -+ -+ if (info) -+ pa_binding_target_info_free(info); -+ -+ return PA_HOOK_OK; -+} -+ -+static int parse_model(pa_config_parser_state *state) { -+ int r; -+ -+ pa_assert(state); -+ -+ r = model_from_string(state->rvalue, state->data); -+ if (r < 0) -+ pa_log("[%s:%u] Failed to parse model: %s", state->filename, state->lineno, state->rvalue); -+ -+ return r; -+} -+ -+static int parse_main_volume_contexts(pa_config_parser_state *state) { -+ struct userdata *u; -+ char *name; -+ const char *split_state = NULL; -+ -+ pa_assert(state); -+ -+ u = state->userdata; -+ -+ while ((name = pa_split_spaces(state->rvalue, &split_state))) -+ pa_hashmap_put(u->context_names, name, name); -+ -+ return 0; -+} -+ -+static struct context *get_context(struct userdata *u, const char *section) { -+ const char *name; -+ struct context *context; -+ -+ pa_assert(u); -+ -+ if (!section) -+ return NULL; -+ -+ if (!pa_startswith(section, "MainVolumeContext ")) -+ return NULL; -+ -+ name = section + 18; -+ -+ context = pa_hashmap_get(u->unused_contexts, name); -+ if (!context) { -+ context = context_new(u, name); -+ pa_hashmap_put(u->unused_contexts, context->name, context); -+ } -+ -+ return context; -+} -+ -+static int parse_description(pa_config_parser_state *state) { -+ struct userdata *u; -+ struct context *context; -+ -+ pa_assert(state); -+ -+ u = state->userdata; -+ -+ context = get_context(u, state->section); -+ if (!context) { -+ pa_log("[%s:%u] Key \"%s\" not expected in section %s.", state->filename, state->lineno, state->lvalue, -+ pa_strnull(state->section)); -+ return -PA_ERR_INVALID; -+ } -+ -+ context_set_description(context, state->rvalue); -+ -+ return 0; -+} -+ -+static const char *get_target_field_name(enum control_type type) { -+ switch (type) { -+ case CONTROL_TYPE_VOLUME: -+ return "volume_control"; -+ -+ case CONTROL_TYPE_MUTE: -+ return "mute_control"; -+ } -+ -+ pa_assert_not_reached(); -+} -+ -+static int parse_main_control(pa_config_parser_state *state, enum control_type type, pa_direction_t direction) { -+ struct userdata *u; -+ struct context *context; -+ -+ pa_assert(state); -+ -+ u = state->userdata; -+ -+ context = get_context(u, state->section); -+ if (!context) { -+ pa_log("[%s:%u] Key \"%s\" not expected in section %s.", state->filename, state->lineno, state->lvalue, -+ pa_strnull(state->section)); -+ return -PA_ERR_INVALID; -+ } -+ -+ if (pa_streq(state->rvalue, "none")) -+ context_set_main_control_target_info(context, type, direction, NULL); -+ else if (pa_startswith(state->rvalue, "bind:")) { -+ int r; -+ pa_binding_target_info *info; -+ -+ r = pa_binding_target_info_new_from_string(state->rvalue, get_target_field_name(type), &info); -+ if (r < 0) { -+ pa_log("[%s:%u] Failed to parse binding target \"%s\".", state->filename, state->lineno, state->rvalue); -+ return r; -+ } -+ -+ context_set_main_control_target_info(context, type, direction, info); -+ pa_binding_target_info_free(info); -+ } else { -+ pa_log("[%s:%u] Failed to parse value \"%s\".", state->filename, state->lineno, state->rvalue); -+ return -PA_ERR_INVALID; -+ } -+ -+ return 0; -+} -+ -+static int parse_main_output_volume_control(pa_config_parser_state *state) { -+ pa_assert(state); -+ -+ return parse_main_control(state, CONTROL_TYPE_VOLUME, PA_DIRECTION_OUTPUT); -+} -+ -+static int parse_main_input_volume_control(pa_config_parser_state *state) { -+ pa_assert(state); -+ -+ return parse_main_control(state, CONTROL_TYPE_VOLUME, PA_DIRECTION_INPUT); -+} -+ -+static int parse_main_output_mute_control(pa_config_parser_state *state) { -+ pa_assert(state); -+ -+ return parse_main_control(state, CONTROL_TYPE_MUTE, PA_DIRECTION_OUTPUT); -+} -+ -+static int parse_main_input_mute_control(pa_config_parser_state *state) { -+ pa_assert(state); -+ -+ return parse_main_control(state, CONTROL_TYPE_MUTE, PA_DIRECTION_INPUT); -+} -+ -+static void finalize_config(struct userdata *u) { -+ const char *context_name; -+ void *state; -+ struct context *context; -+ -+ pa_assert(u); -+ -+ PA_HASHMAP_FOREACH(context_name, u->context_names, state) { -+ int r; -+ -+ context = pa_hashmap_remove(u->unused_contexts, context_name); -+ if (!context) -+ context = context_new(u, context_name); -+ -+ r = context_put(context); -+ if (r < 0) { -+ pa_log_warn("Failed to create main volume context %s.", context_name); -+ context_free(context); -+ continue; -+ } -+ -+ pa_assert_se(pa_hashmap_put(u->contexts, context->name, context) >= 0); -+ } -+ -+ PA_HASHMAP_FOREACH(context, u->unused_contexts, state) -+ pa_log_debug("Main volume context %s is not used.", context->name); -+ -+ pa_hashmap_free(u->unused_contexts); -+ u->unused_contexts = NULL; -+ -+ pa_hashmap_free(u->context_names); -+ u->context_names = NULL; -+} -+ -+int pa__init(pa_module *module) { -+ struct userdata *u; -+ FILE *f; -+ char *fn = NULL; -+ -+ pa_assert(module); -+ -+ u = module->userdata = pa_xnew0(struct userdata, 1); -+ u->main_volume_policy = pa_main_volume_policy_get(module->core); -+ u->output_volume_model = MODEL_NONE; -+ u->input_volume_model = MODEL_NONE; -+ u->output_mute_model = MODEL_NONE; -+ u->input_mute_model = MODEL_NONE; -+ u->contexts = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, -+ (pa_free_cb_t) context_free); -+ u->active_main_volume_context_changed_slot = -+ pa_hook_connect(&u->main_volume_policy->hooks[PA_MAIN_VOLUME_POLICY_HOOK_ACTIVE_MAIN_VOLUME_CONTEXT_CHANGED], -+ PA_HOOK_NORMAL, active_main_volume_context_changed_cb, u); -+ u->context_names = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, pa_xfree); -+ u->unused_contexts = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, -+ (pa_free_cb_t) context_free); -+ -+ f = pa_open_config_file(PA_DEFAULT_CONFIG_DIR PA_PATH_SEP "main-volume-policy.conf", "main-volume-policy.conf", NULL, &fn); -+ if (f) { -+ pa_config_item config_items[] = { -+ { "output-volume-model", parse_model, &u->output_volume_model, "General" }, -+ { "input-volume-model", parse_model, &u->input_volume_model, "General" }, -+ { "output-mute-model", parse_model, &u->output_mute_model, "General" }, -+ { "input-mute-model", parse_model, &u->input_mute_model, "General" }, -+ { "main-volume-contexts", parse_main_volume_contexts, NULL, "General" }, -+ { "description", parse_description, NULL, NULL }, -+ { "main-output-volume-control", parse_main_output_volume_control, NULL, NULL }, -+ { "main-input-volume-control", parse_main_input_volume_control, NULL, NULL }, -+ { "main-output-mute-control", parse_main_output_mute_control, NULL, NULL }, -+ { "main-input-mute-control", parse_main_input_mute_control, NULL, NULL }, -+ { NULL }, -+ }; -+ -+ pa_config_parse(fn, f, config_items, NULL, u); -+ pa_xfree(fn); -+ fn = NULL; -+ fclose(f); -+ f = NULL; -+ } -+ -+ finalize_config(u); -+ -+ pa_log_debug("Output volume model: %s", model_to_string(u->output_volume_model)); -+ pa_log_debug("Input volume model: %s", model_to_string(u->input_volume_model)); -+ pa_log_debug("Output mute model: %s", model_to_string(u->output_mute_model)); -+ pa_log_debug("Input mute model: %s", model_to_string(u->input_mute_model)); -+ -+ return 0; -+} -+ -+void pa__done(pa_module *module) { -+ struct userdata *u; -+ -+ pa_assert(module); -+ -+ u = module->userdata; -+ if (!u) -+ return; -+ -+ if (u->active_main_volume_context_changed_slot) -+ pa_hook_slot_free(u->active_main_volume_context_changed_slot); -+ -+ if (u->contexts) -+ pa_hashmap_free(u->contexts); -+ -+ if (u->main_volume_policy) -+ pa_main_volume_policy_unref(u->main_volume_policy); -+ -+ pa_xfree(u); -+} --- -2.1.4 - ---- a/po/POTFILES.in 2016-04-14 13:03:50.715006116 +0200 -+++ b/po/POTFILES.in 2016-04-14 13:04:23.097006062 +0200 -@@ -200,3 +200,4 @@ - src/utils/pax11publish.c - src/modules/volume-api/device-creator.c - src/pulse/ext-volume-api.c -+src/modules/main-volume-policy/module-main-volume-policy.c diff --git a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0039-main-volume-policy-adapt-to-pa6rev.patch b/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0039-main-volume-policy-adapt-to-pa6rev.patch deleted file mode 100644 index 4f2777112..000000000 --- a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio/0039-main-volume-policy-adapt-to-pa6rev.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/src/modules/main-volume-policy/module-main-volume-policy.c 2016-04-18 10:59:46.124086205 +0200 -+++ b/src/modules/main-volume-policy/module-main-volume-policy.c 2016-04-18 11:01:31.497089360 +0200 -@@ -517,7 +517,7 @@ - { NULL }, - }; - -- pa_config_parse(fn, f, config_items, NULL, u); -+ pa_config_parse(fn, f, config_items, NULL, false, u); - pa_xfree(fn); - fn = NULL; - fclose(f); diff --git a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio_%.bbappend b/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio_%.bbappend deleted file mode 100644 index a54ec60f1..000000000 --- a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio_%.bbappend +++ /dev/null @@ -1,28 +0,0 @@ -FILESEXTRAPATHS_append := ":${THISDIR}/${PN}" - -inherit systemd - -do_install_append() { - # Install pulseaudio systemd service - if ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'true', 'false', d)}; then - install -m 644 -p -D ${WORKDIR}/build/src/pulseaudio.service ${D}${systemd_user_unitdir}/pulseaudio.service - install -m 644 -p -D ${WORKDIR}/pulseaudio-${PV}/src/daemon/systemd/user/pulseaudio.socket ${D}${systemd_user_unitdir}/pulseaudio.socket - - # Execute these manually on behalf of systemctl script (from systemd-systemctl-native.bb) - # because it does not support systemd's user mode. - install -d ${D}${systemd_user_unitdir}/sockets.target.wants/ - ln -sf ${systemd_user_unitdir}/pulseaudio.socket ${D}${systemd_user_unitdir}/sockets.target.wants/ - - install -d ${D}${systemd_user_unitdir}/default.target.wants/ - ln -sf ${systemd_user_unitdir}/pulseaudio.service ${D}${systemd_user_unitdir}/default.target.wants/ - fi - mkdir -p ${D}/${bindir} - install -m 755 -p -D ${WORKDIR}/build/src/.libs/pacat ${D}/${bindir}/ -} - -FILES_${PN}-server += " \ - ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', '${systemd_user_unitdir}/pulseaudio.socket', '', d)} \ - ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', '${systemd_user_unitdir}/sockets.target.wants/pulseaudio.socket', '', d)} \ - ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', '${systemd_user_unitdir}/pulseaudio.service', '', d)} \ - ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', '${systemd_user_unitdir}/default.target.wants/pulseaudio.service', '', d)} \ -" diff --git a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio_10.0.bbappend b/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio_10.0.bbappend deleted file mode 100644 index f59ee89d5..000000000 --- a/meta-ivi-common/recipes-multimedia/pulseaudio/pulseaudio_10.0.bbappend +++ /dev/null @@ -1,15 +0,0 @@ -FILESEXTRAPATHS_prepend := "${THISDIR}/pulseaudio-10.0:" - -SRC_URI += " \ - file://0001-install-files-for-a-module-development.patch \ - file://0002-volume-ramp-additions-to-the-low-level-infra.patch \ - file://0003-volume-ramp-adding-volume-ramping-to-sink-input.patch \ - file://0004-sink-input-Code-cleanup-regarding-volume-ramping.patch \ - file://0005-sink-input-volume-Add-support-for-volume-ramp-factor.patch \ - file://0006-sink-input-Remove-pa_sink_input_set_volume_ramp.patch;apply=no \ - file://enable-ofono-hfp-backend.patch \ -" - -PACKAGES =+ " pulseaudio-module-dev" - -FILES_pulseaudio-module-dev = "${includedir}/pulsemodule/* ${libdir}/pkgconfig/pulseaudio-module-devel.pc" diff --git a/meta-ivi-common/recipes-support/.gitkeep b/meta-ivi-common/recipes-support/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/meta-ivi-common/recipes-test/aiostress/aiostress_0.22.bb b/meta-ivi-common/recipes-test/aiostress/aiostress_0.22.bb deleted file mode 100644 index 7803d74ed..000000000 --- a/meta-ivi-common/recipes-test/aiostress/aiostress_0.22.bb +++ /dev/null @@ -1,24 +0,0 @@ -SUMMARY = "Async IO testing utility" -DESCRIPTION = "aio-stress will open or create each file on the command line, and start a series of aio to it.\ -aio is done in a rotating loop. first file1 gets 8 requests, then file2, then file3 etc.\ -As each file finishes writing, it is switched to reads io buffers are aligned in case you want to do raw io" -HOMEPAGE = "https://oss.oracle.com/~mason/aio-stress/" -LICENSE = "GPLv2" - -S="${WORKDIR}" - -LIC_FILES_CHKSUM = "file://${S}/aio-stress.c;md5=ccb5d196a3736bbd835d582a4e2329c3" - -SRC_URI = "https://oss.oracle.com/~mason/aio-stress/aio-stress.c" -SRC_URI[md5sum] = "ccb5d196a3736bbd835d582a4e2329c3" -SRC_URI[sha256sum] = "3f4cffcc946fb717fff9d8fe932c7c2ee606efff198408d9fbe16955151445f7" - -do_compile () { - ${CC} -Wall -Wshadow -o aio-stress -lpthread -laio aio-stress.c -} - -do_install () { - install -d ${D}${bindir} - install -m 0755 aio-stress ${D}${bindir} -} - diff --git a/meta-ivi-common/recipes-test/blobsallad/blobsallad/0001-Makefile.patch b/meta-ivi-common/recipes-test/blobsallad/blobsallad/0001-Makefile.patch deleted file mode 100755 index 0ae56cee1..000000000 --- a/meta-ivi-common/recipes-test/blobsallad/blobsallad/0001-Makefile.patch +++ /dev/null @@ -1,53 +0,0 @@ ---- a/Makefile.orig 2016-04-01 15:50:20.636358716 +0200 -+++ b/Makefile 2016-04-01 15:51:58.916361191 +0200 -@@ -1,3 +1,9 @@ -+INCDIR = $(SDKROOT)/usr/include -+LIBDIR = $(SDKROOT)/usr/lib -+ -+EXTRA_CFLAGS=-I$(INCDIR) -+EXTRA_LDFLAGS=-Wl,-rpath-link=$(LIBDIR) -L$(LIBDIR) -+ - OBJECTS = bs_main.o \ - bs_vector.o \ - bs_pointmass.o \ -@@ -15,21 +21,21 @@ - bs_profiler.o \ - bs_rubberband.o - --CC = gcc -+#CC = gcc - - DISTDIR = blobsallad-src - --CFLAGS = `pkg-config --cflags cairo; sdl-config --cflags` --LIBS = `pkg-config --libs cairo; sdl-config --libs` -lm -lGL -lGLU -+EXTRA_CFLAGS += -I$(INCDIR)/cairo -I$(INCDIR)/SDL -D_GNU_SOURCE=1 -D_REENTRANT -+EXTRA_LDFLAGS += -lcairo -lSDL -lpthread -lm - - all: $(OBJECTS) -- $(CC) -g -o blobsallad $(OBJECTS) $(LIBS) -+ $(CC) -g -o blobsallad $(OBJECTS) $(EXTRA_LDFLAGS) - - map: -- gcc -o createmap create_testdata.c -Wall -g -lm -+ $(CC) -o createmap create_testdata.c -Wall -g -lm - - octree: -- gcc -o test_octree test_octree.c bs_octree.c bs_list.c bs_vector.c bs_vector_util.c bs_timer.c bs_array.c -Wall -O2 $(LIBS) $(CFLAGS) -+ $(CC) -o test_octree test_octree.c bs_octree.c bs_list.c bs_vector.c bs_vector_util.c bs_timer.c bs_array.c -Wall -O2 $(EXTRA_LDFLAGS) $(EXTRA_CFLAGS) - - GFX_OBJECTS = gfx_main.o \ - bs_gfx.o \ -@@ -41,10 +47,10 @@ - bs_list.o - - gfx: $(GFX_OBJECTS) -- gcc -o gfx_main -Wall -g $(GFX_OBJECTS) $(LIBS) -+ $(CC) -o gfx_main -Wall -g $(GFX_OBJECTS) $(EXTRA_LDFLAGS) - - .c.o: -- $(CC) -g -Wall $(CFLAGS) $ -c $< -+ $(CC) -g -Wall $(EXTRA_CFLAGS) $ -c $< - - clean: - rm -f *.o; rm -f blobsallad; diff --git a/meta-ivi-common/recipes-test/blobsallad/blobsallad/0002-auto.patch b/meta-ivi-common/recipes-test/blobsallad/blobsallad/0002-auto.patch deleted file mode 100755 index b61da2c1f..000000000 --- a/meta-ivi-common/recipes-test/blobsallad/blobsallad/0002-auto.patch +++ /dev/null @@ -1,95 +0,0 @@ ---- a/bs_main.c -+++ b/bs_main.c -@@ -11,6 +11,9 @@ - #include "bs_profiler.h" - #include "bs_rubberband.h" - -+static struct timeval beginTime; /* Time of the benchmark start */ -+static int cur_step; /* Current benchmark phase. Used to subsequently increase number of objects each 10 seconds */ -+ - typedef struct bs_main_data_st - { - bs_cairo_sdl_t *pCairoSdl; -@@ -113,7 +116,9 @@ - SDL_Event event; - SDL_UserEvent userevent; - bs_main_data_t *pMainData; -- -+ struct timeval curTime; -+ int hunsec; -+ - pMainData = (bs_main_data_t*) pUserData; - - userevent.type = SDL_USEREVENT; -@@ -121,6 +126,20 @@ - userevent.data1 = NULL; - userevent.data2 = NULL; - -+ gettimeofday(&curTime, NULL); -+ hunsec = curTime.tv_sec - beginTime.tv_sec; -+ -+ /* increase cur_step each 10 seconds */ -+ if (cur_step < hunsec / 10) { -+ printf("%d objects = %.2f fps\n", 1 << (cur_step + 1), pMainData->fps); -+ userevent.code = 2; /* add more objects */ -+ cur_step++; -+ } -+ -+ /* exit if requested number of objects is reached */ -+ if (cur_step == 4) -+ userevent.code = 3; -+ - event.type = SDL_USEREVENT; - event.user = userevent; - -@@ -152,14 +171,19 @@ - pMainData->newTimerInterval = 50; - pMainData->fps = 20.0; - pMainData->running = TRUE; -- -+ -+ cur_step = 0; -+ - bs_profiler_init(); - -+ gettimeofday(&beginTime, NULL); - gettimeofday(&startTime, NULL); - pMainData->lastFrameTimeStamp = startTime.tv_sec * 1000 + startTime.tv_usec / 1000; - - SDL_AddTimer(50, bs_main_sdl_timer_callback, pMainData); - -+ bs_blob_collective_split(pMainData->pCollective); -+ - for(;;) - { - SDL_WaitEvent(&event); -@@ -253,8 +277,7 @@ - break; - - case SDL_USEREVENT: -- if(event.user.code == 1) -- { -+ if (event.user.code == 1) { - gettimeofday(&startTime, NULL); - bs_main_update_simulation(pMainData); - bs_main_redraw(pMainData); -@@ -268,10 +291,15 @@ - usedTime = 50; - } - -- pMainData->newTimerInterval = usedTime; -- } -- break; -- -+ pMainData->newTimerInterval = usedTime; -+ } else if (event.user.code == 2) { -+ int i; -+ for (i = 0; i < (1 << cur_step); i++) -+ bs_blob_collective_split(pMainData->pCollective); -+ } else if (event.user.code == 3) { -+ exit(0); -+ } -+ break; - case SDL_QUIT: - exit(0); - break; diff --git a/meta-ivi-common/recipes-test/blobsallad/blobsallad/0003-printcleanup.patch b/meta-ivi-common/recipes-test/blobsallad/blobsallad/0003-printcleanup.patch deleted file mode 100755 index 630871dfd..000000000 --- a/meta-ivi-common/recipes-test/blobsallad/blobsallad/0003-printcleanup.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/bs_blob_collective.c -+++ b/bs_blob_collective.c -@@ -152,7 +152,7 @@ - - bs_list_unlink_p_cont(pCollective->pBlobs, bs_blob_collective_remove_blob_cb, findData.pMotherBlob); - -- printf("number of blobs: %d\n", bs_list_get_length(pCollective->pBlobs)); -+/* printf("number of blobs: %d\n", bs_list_get_length(pCollective->pBlobs)); */ - } - - typedef struct bs_blob_collective_join_find_smallest_st diff --git a/meta-ivi-common/recipes-test/blobsallad/blobsallad/0004-bs_main.c.patch b/meta-ivi-common/recipes-test/blobsallad/blobsallad/0004-bs_main.c.patch deleted file mode 100755 index ae15408de..000000000 --- a/meta-ivi-common/recipes-test/blobsallad/blobsallad/0004-bs_main.c.patch +++ /dev/null @@ -1,15 +0,0 @@ ---- a/bs_main.c -+++ b/bs_main.c -@@ -165,9 +165,9 @@ - //pMainData->pRubberband = bs_rubberband_create(2.5f, 3.0f); - pMainData->pEnv = bs_env_create(0.0f, 0.0f, 6.0f, 4.0f); - pMainData->pGravity = bs_vector_create(0.0f, 10.0f); -- pMainData->pCairoSdl = bs_cairo_sdl_create(600, 400); -- pMainData->width = 600.0; -- pMainData->height = 400.0; -+ pMainData->pCairoSdl = bs_cairo_sdl_create(1600, 1024); -+ pMainData->width = 1600.0; -+ pMainData->height = 1024.0; - pMainData->newTimerInterval = 50; - pMainData->fps = 20.0; - pMainData->running = TRUE; diff --git a/meta-ivi-common/recipes-test/blobsallad/blobsallad_2006-11-14-23-57.bb b/meta-ivi-common/recipes-test/blobsallad/blobsallad_2006-11-14-23-57.bb deleted file mode 100644 index 373d4ddc6..000000000 --- a/meta-ivi-common/recipes-test/blobsallad/blobsallad_2006-11-14-23-57.bb +++ /dev/null @@ -1,36 +0,0 @@ -DESCRIPTION = "" -HOMEPAGE = "http://blobsallad.se/" -LICENSE = "CLOSED" -LIC_FILES_CHKSUM = "" - -SRC_URI = " \ - http://blobsallad.se/src/blobsallad-src-${PV}.tar.gz \ - file://0001-Makefile.patch \ - file://0002-auto.patch \ - file://0003-printcleanup.patch \ - file://0004-bs_main.c.patch" - -SRC_URI[md5sum] = "a2e3342cbf0f3a4a9b110af2663bed36" -SRC_URI[sha256sum] = "cd6309df1929d3e6b7bce1dbecc751849aeaafe17c01e05fd2567dc4267faaa2" - -DEPENDS = "cairo virtual/libsdl" - -INSANE_SKIP_${PN} = "ldflags" - -S = "${WORKDIR}/blobsallad-src" - -do_configure () { - # Specify any needed configure commands here - : -} - -do_compile () { - # You will almost certainly need to add additional arguments here - oe_runmake SDKROOT=${STAGING_DIR_HOST} -} - -do_install () { - install -d ${D}${bindir} - install -m 0755 blobsallad ${D}${bindir} -} - diff --git a/meta-ivi-common/recipes-test/dung/dung_3.4.25-m2.bb b/meta-ivi-common/recipes-test/dung/dung_3.4.25-m2.bb deleted file mode 100644 index 28bf858a0..000000000 --- a/meta-ivi-common/recipes-test/dung/dung_3.4.25-m2.bb +++ /dev/null @@ -1,18 +0,0 @@ -SUMMARY = "Kernel test scripts" -LICENSE = "GPLv2" -LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6" - -SRC_URI = "git://gerrit.automotivelinux.org/gerrit/src/qa-test-misc;protocol=https;branch=${AGL_BRANCH}" -SRCREV = "e2472c7b1d061aef8bb05a4d7940fd8159c4a329" - -inherit allarch - -S = "${WORKDIR}/git/${PN}-${PV}" - -do_install () { - for subdir in arch_timer cmt common scifab sdhi.0; do - install -d -m 0755 ${D}/${datadir}/${PN}/$subdir - install -m 0755 -t ${D}/${datadir}/${PN}/$subdir ${S}/$subdir/* - done -} - diff --git a/meta-ivi-common/recipes-test/ebizzy/ebizzy_0.3.bb b/meta-ivi-common/recipes-test/ebizzy/ebizzy_0.3.bb deleted file mode 100644 index 08b0425c0..000000000 --- a/meta-ivi-common/recipes-test/ebizzy/ebizzy_0.3.bb +++ /dev/null @@ -1,20 +0,0 @@ -DESCRIPTION = "Benchmark tool that generates a workload resembling common web application server workloads" -HOMEPAGE = "http://ebizzy.sourceforge.net/" -LICENSE = "GPLv2" -LIC_FILES_CHKSUM = "file://LICENSE;md5=eb723b61539feef013de476e68b5c50a" - -SRC_URI = "http://downloads.sourceforge.net/project/ebizzy/ebizzy/${PV}/ebizzy-${PV}.tar.gz" -SRC_URI[md5sum] = "af038bc506066bb3d28db08aba62bc38" -SRC_URI[sha256sum] = "77286029d6348f3d9b3f04eae1feadb5ad1ad07b9f688f4d9f002960862467f2" - -INSANE_SKIP_${PN} = "ldflags" - -do_compile () { - ${CC} -Wall -Wshadow -lpthread -o ebizzy ebizzy.c -} - -do_install () { - install -d ${D}${bindir} - install -m 0755 ebizzy ${D}${bindir} -} - diff --git a/meta-ivi-common/recipes-test/ffsb/ffsb_6.0-rc2.bb b/meta-ivi-common/recipes-test/ffsb/ffsb_6.0-rc2.bb deleted file mode 100644 index 66db133e3..000000000 --- a/meta-ivi-common/recipes-test/ffsb/ffsb_6.0-rc2.bb +++ /dev/null @@ -1,14 +0,0 @@ -DESCRIPTION = "Flexible File System Benchmark" -HOMEPAGE = "https://sourceforge.net/projects/ffsb/" -LICENSE = "GPLv2" -LIC_FILES_CHKSUM = "file://LICENSE;md5=fd5d9bcabd8ed5a54a01ce8d183d592a" - -SRC_URI = "http://downloads.sourceforge.net/project/ffsb/ffsb/ffsb-${PV}/ffsb-${PV}.tar.bz2" -SRC_URI[md5sum] = "cabfc1021c2ec6c6b168fefc84210891" -SRC_URI[sha256sum] = "e5867692aae8c9bfbcdc774599022289c4d89c1d90f4dd7101fb9865ac773c71" - -inherit autotools - -# extra args to configure -EXTRA_OECONF = "" - diff --git a/meta-ivi-common/recipes-test/fontconfig/fontconfig_%.bbappend b/meta-ivi-common/recipes-test/fontconfig/fontconfig_%.bbappend deleted file mode 100644 index c4bebdc1f..000000000 --- a/meta-ivi-common/recipes-test/fontconfig/fontconfig_%.bbappend +++ /dev/null @@ -1,17 +0,0 @@ -PACKAGES =+ "fontconfig-test" - -do_install_append() { - install -m 755 -d ${D}/${datadir}/fontconfig-test - install -m 755 ${S}/test/run-test.sh ${D}/${datadir}/fontconfig-test/ - - sed -i -e "s/FCLIST=\.\.\/fc\-list\/fc\-list/FCLIST=\/usr\/bin\/fc\-list/g" -e "s/FCCACHE=\.\.\/fc\-cache\/fc\-cache/FCCACHE=\/usr\/bin\/fc\-cache/g" ${D}/${datadir}/fontconfig-test/run-test.sh - - for x in 4x6.pcf 8x16.pcf out.expected fonts.conf.in; do - install -m 644 ${S}/test/$x ${D}/${datadir}/fontconfig-test/ - done -} - -DEBIAN_NOAUTONAME_fontconfig-test = "1" -FILES_fontconfig-test = "${datadir}/fontconfig-test/*" - - diff --git a/meta-ivi-common/recipes-test/freetype/files/0001-Makefile-dont-build-gfx-demos.patch b/meta-ivi-common/recipes-test/freetype/files/0001-Makefile-dont-build-gfx-demos.patch deleted file mode 100644 index 1f3acf28e..000000000 --- a/meta-ivi-common/recipes-test/freetype/files/0001-Makefile-dont-build-gfx-demos.patch +++ /dev/null @@ -1,32 +0,0 @@ -diff -urN /tmp/ft2demos-2.6.orig/Makefile /tmp/ft2demos-2.6/Makefile ---- ft2demos-2.6.orig/Makefile 2015-06-07 07:34:19.000000000 +0000 -+++ ft2demos-2.6/Makefile 2016-06-17 14:25:37.640456725 +0000 -@@ -153,7 +153,8 @@ - - ifeq ($(PLATFORM),unix) - CC = $(CCraw) -- LINK_CMD = $(subst /,$(SEP),$(OBJ_BUILD)/libtool) \ -+ LIBTOOL = $(OBJ_BUILD)/libtool -+ LINK_CMD = $(subst /,$(SEP),$(LIBTOOL)) \ - --mode=link $(CC) \ - $(subst /,$(COMPILER_SEP),$(LDFLAGS)) - LINK_LIBS = $(subst /,$(COMPILER_SEP),$(FTLIB) $(EFENCE)) -@@ -279,12 +280,12 @@ - ttdebug - - # Comment out the next line if you don't have a graphics subsystem. -- EXES += ftdiff \ -- ftgamma \ -- ftgrid \ -- ftmulti \ -- ftstring \ -- ftview -+ # EXES += ftdiff \ -+ # ftgamma \ -+ # ftgrid \ -+ # ftmulti \ -+ # ftstring \ -+ # ftview - - # ftvalid requires ftgxval.c and ftotval.c - # diff --git a/meta-ivi-common/recipes-test/freetype/files/0001-ft2demos-Makefile-Do-not-hardcode-libtool-path.patch b/meta-ivi-common/recipes-test/freetype/files/0001-ft2demos-Makefile-Do-not-hardcode-libtool-path.patch deleted file mode 100644 index 7803ad7e0..000000000 --- a/meta-ivi-common/recipes-test/freetype/files/0001-ft2demos-Makefile-Do-not-hardcode-libtool-path.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 8c4f135619de929f9348b830a07a46a0c2c38e51 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jan-Simon=20M=C3=B6ller?= -Date: Fri, 7 Oct 2016 15:26:20 +0200 -Subject: [PATCH] Do not hardcode libtool path -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -It is already known and imported through config.mk. - -Signed-off-by: Jan-Simon Möller ---- - Makefile | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/Makefile b/Makefile -index a5d34bd..254aad4 100644 ---- a/Makefile -+++ b/Makefile -@@ -153,7 +153,6 @@ else - - ifeq ($(PLATFORM),unix) - CC = $(CCraw) -- LIBTOOL = $(OBJ_BUILD)/libtool - LINK_CMD = $(subst /,$(SEP),$(LIBTOOL)) \ - --mode=link $(CC) \ - $(subst /,$(COMPILER_SEP),$(LDFLAGS)) --- -2.1.4 - diff --git a/meta-ivi-common/recipes-test/freetype/freetype_2.8.bbappend b/meta-ivi-common/recipes-test/freetype/freetype_2.8.bbappend deleted file mode 100644 index 282ce784a..000000000 --- a/meta-ivi-common/recipes-test/freetype/freetype_2.8.bbappend +++ /dev/null @@ -1,32 +0,0 @@ -FILESEXTRAPATHS_prepend := "${THISDIR}/files:" - -SRC_URI =+ "${SOURCEFORGE_MIRROR}/freetype/ft2demos-${PV}.tar.bz2;name=ft2demos \ - file://0001-Makefile-dont-build-gfx-demos.patch;patchdir=../ft2demos-${PV} \ - file://0001-ft2demos-Makefile-Do-not-hardcode-libtool-path.patch;patchdir=../ft2demos-${PV} \ - " -SRC_URI[ft2demos.md5sum] = "61db5831e213acb843f0fc6d10186054" -SRC_URI[ft2demos.sha256sum] = "2b6ce0d36bcb43fcc8aac07a0287982d855571ee271c3803c768e501f9c1a233" - -PACKAGES =+ "${PN}-demos" - -B = "${S}" - -do_compile_append () { - - oe_runmake -C ${WORKDIR}/ft2demos-${PV} TOP_DIR=${WORKDIR}/${BPN}-${PV}/ -} - -do_install_append () { - install -d -m 0755 ${D}/${bindir} - for x in ftbench ftdump ftlint ftvalid ttdebug; do - install -m 0755 ${WORKDIR}/ft2demos-${PV}/bin/.libs/$x ${D}/${bindir} - done -} - -FILES_${PN}-demos = "\ - ${bindir}/ftbench \ - ${bindir}/ftdump \ - ${bindir}/ftlint \ - ${bindir}/ftvalid \ - ${bindir}/ttdebug \ -" diff --git a/meta-ivi-common/recipes-test/fsfuzzer/files/0001-fix_missing_header_sys_stat.patch b/meta-ivi-common/recipes-test/fsfuzzer/files/0001-fix_missing_header_sys_stat.patch deleted file mode 100644 index e834becf3..000000000 --- a/meta-ivi-common/recipes-test/fsfuzzer/files/0001-fix_missing_header_sys_stat.patch +++ /dev/null @@ -1,11 +0,0 @@ -diff -urN fsfuzzer-0.7.orig/fstest.c fsfuzzer-0.7/fstest.c ---- fsfuzzer-0.7.orig/fstest.c 2009-01-25 14:50:06.000000000 +0000 -+++ fsfuzzer-0.7/fstest.c 2016-06-16 17:49:27.264565819 +0000 -@@ -35,6 +35,7 @@ - #include - #include - #include -+#include - - #define LOGGIT 1 - #define CHECK_XATTR 1 diff --git a/meta-ivi-common/recipes-test/fsfuzzer/fsfuzzer_0.7.bb b/meta-ivi-common/recipes-test/fsfuzzer/fsfuzzer_0.7.bb deleted file mode 100644 index d2ddb59b1..000000000 --- a/meta-ivi-common/recipes-test/fsfuzzer/fsfuzzer_0.7.bb +++ /dev/null @@ -1,18 +0,0 @@ -SUMMARY = "The fsfuzzer is a filesystem fuzzer tool that does stress tests of various filesystems in a reproducible and logged way." -DESCRIPTION = "This tool creates initial (valid) filesystem images and then manipulates their binary format and structure for detecting flaws/bugs/design problems in the parsing/handling code for that particular filesystem. The program expects that you have a /media directory. It uses that one for mounting test images in." -HOMEPAGE = "https://www.ee.oulu.fi/research/ouspg/fsfuzzer" - -LICENSE = "GPLv2" -LIC_FILES_CHKSUM = "file://COPYING;md5=94d55d512a9ba36caa9b7df079bae19f" - -SRC_URI = "http://people.redhat.com/sgrubb/files/fsfuzzer-${PV}.tar.gz \ - file://0001-fix_missing_header_sys_stat.patch \ - " -SRC_URI[md5sum] = "d69ac4b67aaba52a889c9188eb456c15" -SRC_URI[sha256sum] = "094aa17c4f66c525a04e5db5ad444b4a561b6f8e310d0bd70b9ca421cdf0a434" - -inherit autotools - -# Specify any options you want to pass to the configure script using EXTRA_OECONF: -EXTRA_OECONF = "" - diff --git a/meta-ivi-common/recipes-test/glmark2/glmark2_%.bbappend b/meta-ivi-common/recipes-test/glmark2/glmark2_%.bbappend deleted file mode 100644 index a64e0506c..000000000 --- a/meta-ivi-common/recipes-test/glmark2/glmark2_%.bbappend +++ /dev/null @@ -1,2 +0,0 @@ -PACKAGECONFIG = "wayland-gles2" -PACKAGECONFIG[wayland-gles2] = ",,virtual/egl virtual/libgles2 wayland" diff --git a/meta-ivi-common/recipes-test/himeno/himeno_2.0.bb b/meta-ivi-common/recipes-test/himeno/himeno_2.0.bb deleted file mode 100644 index f890e23a4..000000000 --- a/meta-ivi-common/recipes-test/himeno/himeno_2.0.bb +++ /dev/null @@ -1,27 +0,0 @@ -DESCRIPTION = "Himeno Benchmark" -LICENSE = "LGPL-2.0" -URL = "http://accc.riken.jp/en/supercom/himenobmt/" - -SRC_URI = "http://accc.riken.jp/en/wp-content/uploads/sites/2/2015/07/himenobmt.c.zip" -SRC_URI[md5sum] = "8d8e837dfc3e00a3b322eb4ae3edd551" -SRC_URI[sha256sum] = "8780bfbdacb0d4dcab2931e65cadd69411731e3f2afcc1231d0743a036298077" - -LIC_FILES_CHKSUM = "file://himenoBMT.c;md5=8e8771ddc01c6d1a795e088e2d6dee78" - -# Upstream ZIP file contains an LZH archive, thus a 2 steps "unpack" is required. -# The LZH archive is unpacked after native tools dependency resolution, -# thus. after "configure" task in our case: - -DEPENDS = "p7zip-native" - -do_configure_append() { - 7z x -y -o${S} ${WORKDIR}/himenobmt.c.lzh - cd ${S} - sed -i -e 's/CC= gcc/#CC= gcc/' Makefile - sed -i -e 's/CFLAGS = /#CFLAGS = /' Makefile -} - -do_install () { - install -d ${D}${bindir} - install -m 0755 bmt ${D}${bindir} -} diff --git a/meta-ivi-common/recipes-test/interbench/files/interbench.c.patch b/meta-ivi-common/recipes-test/interbench/files/interbench.c.patch deleted file mode 100755 index c882739ba..000000000 --- a/meta-ivi-common/recipes-test/interbench/files/interbench.c.patch +++ /dev/null @@ -1,68 +0,0 @@ ---- interbench.c.orig 2009-10-30 23:14:59.000000000 -0500 -+++ interbench.c 2012-07-10 19:06:00.000000000 -0500 -@@ -71,6 +71,7 @@ struct user_data { - char datestamp[13]; - FILE *logfile; - } ud = { -+ .ram = 0, - .duration = 30, - .cpu_load = 4, - .log = 1, -@@ -652,6 +653,8 @@ void emulate_write(struct thread *th) - terminal_error("fopen"); - if (stat(name, &statbuf) == -1) - terminal_fileopen_error(fp, "stat"); -+ if (statbuf.st_blksize < MIN_BLK_SIZE) -+ statbuf.st_blksize = MIN_BLK_SIZE; - for (i = 0 ; i < mem; i++) { - if (fwrite(buf, statbuf.st_blksize, 1, fp) != 1) - terminal_fileopen_error(fp, "fwrite"); -@@ -1136,14 +1139,17 @@ void get_ram(void) - if(!(meminfo = fopen("/proc/meminfo", "r"))) - terminal_error("fopen"); - -- ud.ram = ud.swap = 0; -- while( !feof(meminfo) && !fscanf(meminfo, "MemTotal: %lu kB", &ud.ram) ) -- fgets(aux,sizeof(aux),meminfo); -+ if (!ud.ram) -+ { -+ while( !feof(meminfo) && !fscanf(meminfo, "MemTotal: %lu kB", &ud.ram) ) -+ fgets(aux,sizeof(aux),meminfo); -+ } -+ ud.swap = 0; - while( !feof(meminfo) && !fscanf(meminfo, "SwapTotal: %lu kB", &ud.swap) ) - fgets(aux,sizeof(aux),meminfo); - if (fclose(meminfo) == -1) - terminal_error("fclose"); -- -+ - if( !ud.ram || !ud.swap ) { - unsigned long i; - fprintf(stderr, "\nCould not get memory or swap size. "); -@@ -1399,6 +1405,7 @@ void usage(void) - fprintf(stderr, "\t[-h]\n\n"); - fprintf(stderr, " -l\tUse loops per sec (default: use saved benchmark)\n"); - fprintf(stderr, " -L\tUse cpu load of with burn load (default: 4)\n"); -+ fprintf(stderr, " -M\tForce RAM size to . Useful when disk is smaller than RAM.\n"); - fprintf(stderr, " -t\tSeconds to run each benchmark (default: 30)\n"); - fprintf(stderr, " -B\tNice the benchmarked thread to (default: 0)\n"); - fprintf(stderr, " -N\tNice the load thread to (default: 0)\n"); -@@ -1482,7 +1489,7 @@ int main(int argc, char **argv) - terminal_error("signal"); - #endif - -- while ((q = getopt(argc, argv, "hl:L:B:N:ut:bcnrC:I:m:w:x:W:X:")) != -1) { -+ while ((q = getopt(argc, argv, "hl:L:M:B:N:ut:bcnrC:I:m:w:x:W:X:")) != -1) { - switch (q) { - case 'h': - usage(); -@@ -1496,6 +1503,9 @@ int main(int argc, char **argv) - case 'L': - ud.cpu_load = atoi(optarg); - break; -+ case 'M': -+ ud.ram = atoi(optarg); -+ break; - case 'B': - ud.bench_nice = atoi(optarg); - break; diff --git a/meta-ivi-common/recipes-test/interbench/interbench_0.31.bb b/meta-ivi-common/recipes-test/interbench/interbench_0.31.bb deleted file mode 100644 index 3e6490374..000000000 --- a/meta-ivi-common/recipes-test/interbench/interbench_0.31.bb +++ /dev/null @@ -1,31 +0,0 @@ -DESCRIPTION = "The Linux interactivity benchmark" -HOMEPAGE = "http://users.tpg.com.au/ckolivas/interbench/" -LICENSE = "GPLv2" -LIC_FILES_CHKSUM = "file://COPYING;md5=393a5ca445f6965873eca0259a17f833" -SRC_URI = "http://ck.kolivas.org/apps/interbench/interbench-${PV}.tar.bz2" - -SRC_URI += "file://interbench.c.patch;striplevel=0" - -inherit autotools - -INSANE_SKIP_${PN} = "ldflags" - -B = "${S}" -EXTRA_OEMAKE = "CC='${CC}'" - -# upstream tarball contains x86_64 binaries, we need a clean source tree -do_compile() { - oe_runmake clean - oe_runmake -} - -do_install() { - install -d ${D}${bindir} ${D}${datadir}/doc/${PN}/ ${D}${mandir}/man8/ - install -m 0755 ${B}/interbench ${D}${bindir} - install -m 0644 ${S}/readme* ${D}${datadir}/doc/${PN}/ - install -m 0644 ${S}/interbench.8 ${D}${mandir}/man8/ -} - -SRC_URI[md5sum] = "832254d7fd1255c548ebea7b97f01015" -SRC_URI[sha256sum] = "89d438b28aef22d26e79812762a57a9f9344a8dd8826edebfe60dad48ee1c784" - diff --git a/meta-ivi-common/recipes-test/iperf/iperf-2.0.9/0001-fix-out-of-tree-config.patch b/meta-ivi-common/recipes-test/iperf/iperf-2.0.9/0001-fix-out-of-tree-config.patch deleted file mode 100644 index e8a029790..000000000 --- a/meta-ivi-common/recipes-test/iperf/iperf-2.0.9/0001-fix-out-of-tree-config.patch +++ /dev/null @@ -1,52 +0,0 @@ -iperf: fix out of tree configuration - -The configure step uses a package header to check for support of types/declares, -this package header encapsulates all the required system header for providing -the needed resources. When configured from an out of tree directory the package -header is not found due to the hard path. -We now make the path for package header relative to our 'srcdir' so it is -found appropriately. - -Signed-off-by: Awais Belal ---- -diff --git a/configure.ac b/configure.ac -index 2b3fd20..d420f9e 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -176,8 +176,8 @@ dnl Check for system services - - dnl check for multicast - if test "$ac_cv_multicast" != no; then -- AC_CHECK_TYPES(struct ip_mreq,,,[#include "compat/headers_slim.h"]) -- AC_CHECK_DECLS(IP_ADD_MEMBERSHIP,,,[#include "compat/headers_slim.h"]) -+ AC_CHECK_TYPES(struct ip_mreq,,,[#include "${srcdir}/compat/headers_slim.h"]) -+ AC_CHECK_DECLS(IP_ADD_MEMBERSHIP,,,[#include "${srcdir}/compat/headers_slim.h"]) - AC_MSG_CHECKING(for multicast support) - ac_cv_multicast=no - if test "$ac_cv_have_decl_IP_ADD_MEMBERSHIP" = yes; then -@@ -193,9 +193,9 @@ fi - - dnl check for IPv6 - if test "$ac_cv_have_ipv6" != no; then -- AC_CHECK_TYPES(struct sockaddr_storage,,,[#include "compat/headers_slim.h"]) -- AC_CHECK_TYPES(struct sockaddr_in6,,,[#include "compat/headers_slim.h"]) -- AC_CHECK_DECLS(AF_INET6,,,[#include "compat/headers_slim.h"]) -+ AC_CHECK_TYPES(struct sockaddr_storage,,,[#include "${srcdir}/compat/headers_slim.h"]) -+ AC_CHECK_TYPES(struct sockaddr_in6,,,[#include "${srcdir}/compat/headers_slim.h"]) -+ AC_CHECK_DECLS(AF_INET6,,,[#include "${srcdir}/compat/headers_slim.h"]) - AC_MSG_CHECKING(for IPv6 headers and structures) - ac_cv_have_ipv6=no - if test "$ac_cv_type_struct_sockaddr_storage" = yes; then -@@ -211,9 +211,9 @@ fi - - if test "$ac_cv_have_ipv6" = yes; then - if test "$ac_cv_multicast" = yes; then -- AC_CHECK_TYPES(struct ipv6_mreq,,,[#include "compat/headers_slim.h"]) -- AC_CHECK_DECLS(IPV6_ADD_MEMBERSHIP,,,[#include "compat/headers_slim.h"]) -- AC_CHECK_DECLS(IPV6_MULTICAST_HOPS,,,[#include "compat/headers_slim.h"]) -+ AC_CHECK_TYPES(struct ipv6_mreq,,,[#include "${srcdir}/compat/headers_slim.h"]) -+ AC_CHECK_DECLS(IPV6_ADD_MEMBERSHIP,,,[#include "${srcdir}/compat/headers_slim.h"]) -+ AC_CHECK_DECLS(IPV6_MULTICAST_HOPS,,,[#include "${srcdir}/compat/headers_slim.h"]) - AC_MSG_CHECKING(for IPv6 multicast support) - ac_cv_have_ipv6_multicast=no - if test "$ac_cv_type_struct_ipv6_mreq" = yes; then diff --git a/meta-ivi-common/recipes-test/iperf/iperf-2.0.9/0002-fix-bool-size-m4.patch b/meta-ivi-common/recipes-test/iperf/iperf-2.0.9/0002-fix-bool-size-m4.patch deleted file mode 100644 index 348e316ce..000000000 --- a/meta-ivi-common/recipes-test/iperf/iperf-2.0.9/0002-fix-bool-size-m4.patch +++ /dev/null @@ -1,16 +0,0 @@ ---- iperf-2.0.5/m4/dast.m4.orig 2016-06-15 11:42:03.945581785 -0400 -+++ iperf-2.0.5/m4/dast.m4 2016-06-15 11:42:11.053581641 -0400 -@@ -11,7 +11,12 @@ - - AC_DEFUN(DAST_CHECK_BOOL, [ - --AC_CHECK_SIZEOF(bool) -+if test "$ac_cv_header_stdbool_h" = yes; then -+ AC_CHECK_SIZEOF(bool,,[#include ]) -+else -+ AC_CHECK_SIZEOF(bool) -+fi -+ - if test "$ac_cv_sizeof_bool" = 0 ; then - AC_DEFINE(bool, int) - fi diff --git a/meta-ivi-common/recipes-test/iperf/iperf-2.0.9/iperf-2.0.5_ManPage.patch b/meta-ivi-common/recipes-test/iperf/iperf-2.0.9/iperf-2.0.5_ManPage.patch deleted file mode 100755 index 12e8f4631..000000000 --- a/meta-ivi-common/recipes-test/iperf/iperf-2.0.9/iperf-2.0.5_ManPage.patch +++ /dev/null @@ -1,8 +0,0 @@ -diff --git iperf-2.0.5/man/Makefile.am iperf-2.0.5/man/Makefile.am - index ed97bc6..728873f 100644 ---- iperf-2.0.5/man/Makefile.am -+++ iperf-2.0.5/man/Makefile.am -@@ -1,2 +1 @@ --man_MANS = iperf.1 --dist_man_MANS = $(man_MANS) -+dist_man_MANS = iperf.1 diff --git a/meta-ivi-common/recipes-test/iperf/iperf_2.0.9.bb b/meta-ivi-common/recipes-test/iperf/iperf_2.0.9.bb deleted file mode 100644 index f297f7f7f..000000000 --- a/meta-ivi-common/recipes-test/iperf/iperf_2.0.9.bb +++ /dev/null @@ -1,20 +0,0 @@ -DESCRIPTION = "Iperf is a tool to measure maximum TCP bandwidth, allowing the tuning of various parameters and UDP characteristics" -HOMEPAGE = "http://dast.nlanr.net/Projects/Iperf/" -SECTION = "console/network" -LICENSE = "BSD-2-Clause" -LIC_FILES_CHKSUM = "file://COPYING;md5=e8478eae9f479e39bc34975193360298" - -SRC_URI = " https://iperf.fr/download/source/${BP}-source.tar.gz \ - " - -SRC_URI[md5sum] = "1bb3a1d98b1973aee6e8f171933c0f61" -SRC_URI[sha256sum] = "a5350777b191e910334d3a107b5e5219b72ffa393da4186da1e0a4552aeeded6" - -S = "${WORKDIR}/${BP}" - -inherit autotools pkgconfig - -EXTRA_OECONF = "--exec-prefix=${STAGING_DIR_HOST}${layout_exec_prefix}" - -PACKAGECONFIG ??= "${@bb.utils.contains('DISTRO_FEATURES', 'ipv6', 'ipv6', '', d)}" -PACKAGECONFIG[ipv6] = "--enable-ipv6,--disable-ipv6," diff --git a/meta-ivi-common/recipes-test/ipv6connect/ipv6connect.bb b/meta-ivi-common/recipes-test/ipv6connect/ipv6connect.bb deleted file mode 100644 index a8b93716a..000000000 --- a/meta-ivi-common/recipes-test/ipv6connect/ipv6connect.bb +++ /dev/null @@ -1,24 +0,0 @@ -SUMMARY = "ipv6connect test" -HOMEPAGE = "https://chromium.googlesource.com/chromiumos/third_party/autotest/+/0.12.369.B/client/tests/ipv6connect" -LICENSE = "GPLv2" -LIC_FILES_CHKSUM = "file://${S}/${PN}/LICENSE;md5=b234ee4d69f5fce4486a80fdaf4a4263" - -SRC_URI = "git://gerrit.automotivelinux.org/gerrit/src/qa-test-misc;protocol=https;branch=${AGL_BRANCH}" -SRCREV = "b355b7e1f43a19938895964f314484ffd8a39542" - -inherit autotools - -INSANE_SKIP_${PN} = "ldflags" - -B = "${WORKDIR}/git/ipv6connect" -S = "${WORKDIR}/git" - -# configure script is not delivered, only a makefile. -do_configure() { - : -} - -do_install() { - install -d ${D}${bindir} - install -m 0755 ${B}/ipv6connect ${D}${bindir} -} diff --git a/meta-ivi-common/recipes-test/linpack/linpack.bb b/meta-ivi-common/recipes-test/linpack/linpack.bb deleted file mode 100644 index 84bed0ff6..000000000 --- a/meta-ivi-common/recipes-test/linpack/linpack.bb +++ /dev/null @@ -1,23 +0,0 @@ -SUMMARY = "Linpack benchmark" -LICENSE = "BSD" -LIC_FILES_CHKSUM = "file://${S}/${PN}/linpack.c;md5=076f1fd8d313056103f98d4253862eae" - -SRC_URI = "git://gerrit.automotivelinux.org/gerrit/src/qa-test-misc;protocol=https;branch=${AGL_BRANCH}" -SRCREV = "920cae73a918d1f516113b0ae967be3ecaba86ef" - -DEPENDS += "rsync-native" - -inherit autotools - -S = "${WORKDIR}/git" - -# configure script is not delivered, only a makefile. -do_configure() { - mkdir -p ${B} - rsync -a ${S}/${PN}/* ${B} -} - -do_install() { - install -d ${D}${bindir} - install -m 0755 ${B}/linpack ${D}${bindir} -} diff --git a/meta-ivi-common/recipes-test/linus-stress/linus-stress.bb b/meta-ivi-common/recipes-test/linus-stress/linus-stress.bb deleted file mode 100644 index 01b3cfce5..000000000 --- a/meta-ivi-common/recipes-test/linus-stress/linus-stress.bb +++ /dev/null @@ -1,23 +0,0 @@ -SUMMARY = "linus_stress test" -HOMEPAGE = "https://chromium.googlesource.com/chromiumos/third_party/autotest/+/master/client/tests/linus_stress" -LICENSE = "GPLv2" -LIC_FILES_CHKSUM = "file://${S}/linus_stress/LICENSE;md5=b234ee4d69f5fce4486a80fdaf4a4263" - -SRC_URI = "git://gerrit.automotivelinux.org/gerrit/src/qa-test-misc;protocol=https;branch=${AGL_BRANCH}" -SRCREV = "87cdfd4626c0cb47fc22f328867e49d6268df85c" - -inherit autotools -INSANE_SKIP_${PN} = "ldflags" - -B = "${WORKDIR}/git/linus_stress" -S = "${WORKDIR}/git" - -# configure script is not delivered, only a makefile. -do_configure() { - : -} - -do_install() { - install -d ${D}${bindir} - install -m 0755 ${B}/linus_stress ${D}${bindir} -} diff --git a/meta-ivi-common/recipes-test/packagegroups/packagegroup-ivi-common-test.bb b/meta-ivi-common/recipes-test/packagegroups/packagegroup-ivi-common-test.bb deleted file mode 100644 index 84a951bce..000000000 --- a/meta-ivi-common/recipes-test/packagegroups/packagegroup-ivi-common-test.bb +++ /dev/null @@ -1,51 +0,0 @@ -SUMMARY = "Utilities for testing of AGL" -DESCRIPTION = "A set of common packages required by testing AGL for Quality Assurance" - -LICENSE = "MIT" - -inherit packagegroup - -PACKAGES = "\ - packagegroup-ivi-common-test \ - packagegroup-ivi-common-test-ltp \ - " - -ALLOW_EMPTY_${PN} = "1" - -RDEPENDS_${PN} += "\ - bc \ - blobsallad \ - dbench \ - ebizzy \ - ffsb \ - interbench \ - iozone3 \ - iperf \ - ipv6connect \ - linpack \ - linus-stress \ - lmbench \ - ltp \ - nbench-byte \ - packagegroup-ivi-common-test-ltp \ - rt-tests \ - stress \ - " -# to be added, but needs LICENSE_FLAGS_WHITELIST="non-commercial" -# netperf - -# FTBS, SPEC-316 -# himeno -# FTBS, SPEC-1384 -# trinity - - -# Packages for shell commands which are required by LTP -# readelf, logrotate, vsftpd, crontab, sar, arp, ftp, -# host, rcp, rlogin, rsh, tcpdump, expect, iptables, dnsmasq, -# pgrep -RDEPENDS_packagegroup-ivi-common-test-ltp += " \ - initscripts-functions bind-utils binutils \ - cronie dnsmasq expect inetutils-ftp inetutils-rsh \ - iptables logrotate net-tools sysstat tcpdump vsftpd \ - " diff --git a/meta-ivi-common/recipes-test/trinity/trinity_git.bb b/meta-ivi-common/recipes-test/trinity/trinity_git.bb deleted file mode 100644 index f0f09a855..000000000 --- a/meta-ivi-common/recipes-test/trinity/trinity_git.bb +++ /dev/null @@ -1,42 +0,0 @@ -SUMMARY = "a Linux System call fuzz teste." -DESCRIPTION = "Trinity, a Linux System call fuzz tester." -HOMEPAGE = "http://codemonkey.org.uk/projects/trinity/" -LICENSE = "GPLv2" -LIC_FILES_CHKSUM = "file://${S}/COPYING;md5=96094d47cfbd2cc45eb46ce0fc423c04" - -COMPATIBLE_HOST = "(x86_64|arm|aarch64).*-linux" - -PV = "1.5" -SRCREV = "edc2e693e298e0372010a361354c4a79a3cd93f3" -SRC_URI = "git://github.com/kernelslacker/trinity.git;protocol=https;nobranch=1 \ - " - -S = "${WORKDIR}/git" - -inherit useradd - -USERADD_PACKAGES = "${PN}" -USERADD_PARAM_${PN} = "--system --create-home --shell /bin/sh ${PN} " - -do_configure () { - ./configure.sh -} - -# workaround random build failures -do_compile () { - ${MAKE} -} - -do_install () { - oe_runmake install DESTDIR=${D}/usr - install -o ${PN} -d -m 0755 ${D}/${datadir}/${PN} - install -o ${PN} -m 0755 ${S}/scripts/test-all-syscalls-parallel.sh ${D}/${datadir}/${PN} - install -o ${PN} -m 0755 ${S}/scripts/test-all-syscalls-sequentially.sh ${D}/${datadir}/${PN} - install -o ${PN} -m 0755 ${S}/scripts/test-multi.sh ${D}/${datadir}/${PN} - install -o ${PN} -m 0755 ${S}/scripts/test-vm.sh ${D}/${datadir}/${PN} -} - -PACKAGES =+ "${PN}-example" - -FILES_${PN} = "${bindir}/trinity" -FILES_${PN}-example = "${datadir}/${PN}" diff --git a/templates/base/00_local.conf.agl.inc b/templates/base/00_local.conf.agl.inc index 1cfd90557..30fc68f7d 100644 --- a/templates/base/00_local.conf.agl.inc +++ b/templates/base/00_local.conf.agl.inc @@ -6,3 +6,6 @@ DISTRO = "poky-agl" #see meta-agl/meta-agl/conf/include/base-agl.inc require conf/include/base-agl.inc + +#see meta-agl/meta-app-framework/conf/include/agl-appfw-smack.inc +require conf/include/agl-appfw-smack.inc diff --git a/templates/base/bblayers.conf.sample b/templates/base/bblayers.conf.sample index d86954698..0c3114f8c 100644 --- a/templates/base/bblayers.conf.sample +++ b/templates/base/bblayers.conf.sample @@ -24,12 +24,19 @@ YOCTO_LAYERS = " \ # with some automotive tools/libraries #----------------------------------------------------- AGL_CORE_LAYERS = " \ - ${METADIR}/meta-agl/meta-ivi-common \ - ${METADIR}/meta-agl/meta-agl \ + ${METADIR}/meta-agl/meta-agl-profile-core \ ${METADIR}/meta-agl/meta-agl-distro \ ${METADIR}/meta-agl/meta-agl-bsp \ " +AGL_APPFW_LAYERS = " \ + ${METADIR}/meta-security \ + ${METADIR}/meta-openembedded/meta-perl \ + ${METADIR}/meta-agl/meta-security \ + ${METADIR}/meta-agl/meta-app-framework \ + " + + # These are the direct dependencies of the AGL CORE Layers #--------------------------------------------------------- AGL_CORE_DEPENDENCY_LAYERS = " \ @@ -40,18 +47,29 @@ AGL_CORE_DEPENDENCY_LAYERS = " \ ${METADIR}/meta-openembedded/meta-filesystems \ " +# temporary ... to avoid build breakage. To move to upper layers. +AGL_TEMP_GFX_LAYERS = " \ + ${METADIR}/meta-agl/meta-agl-profile-graphical \ + ${METADIR}/meta-agl/meta-agl-profile-demo \ + " + + #################### # Combine the layers BBLAYERS ?= " \ ${AGL_CORE_DEPENDENCY_LAYERS} \ ${AGL_CORE_LAYERS} \ + ${AGL_APPFW_LAYERS} \ + ${AGL_TEMP_GFX_LAYERS} \ ${YOCTO_LAYERS} \ " BBLAYERS_NON_REMOVABLE ?= " \ ${METADIR}/poky/meta \ ${METADIR}/poky/meta-poky \ - ${METADIR}//meta-agl/meta-agl \ + ${METADIR}/meta-agl/meta-agl-profile-core \ + ${METADIR}/meta-agl/meta-agl-distro \ " + diff --git a/templates/feature/agl-appfw-smack/50_bblayers.conf.inc b/templates/feature/agl-appfw-smack/50_bblayers.conf.inc deleted file mode 100644 index 7f5f24eb5..000000000 --- a/templates/feature/agl-appfw-smack/50_bblayers.conf.inc +++ /dev/null @@ -1,7 +0,0 @@ -BBLAYERS =+ " \ - ${METADIR}/meta-security \ - ${METADIR}/meta-openembedded/meta-perl \ - ${METADIR}/meta-agl/meta-security \ - ${METADIR}/meta-agl/meta-app-framework \ - " - diff --git a/templates/feature/agl-appfw-smack/50_local.conf.inc b/templates/feature/agl-appfw-smack/50_local.conf.inc index 0a11f07c2..e69de29bb 100644 --- a/templates/feature/agl-appfw-smack/50_local.conf.inc +++ b/templates/feature/agl-appfw-smack/50_local.conf.inc @@ -1,2 +0,0 @@ -#see meta-agl/meta-app-framework/conf/include/agl-appfw-smack.inc -require conf/include/agl-appfw-smack.inc diff --git a/templates/feature/agl-ci-change-features-nogfx/included.dep b/templates/feature/agl-ci-change-features-nogfx/included.dep index 49f5dd12d..56b4cd1a9 100644 --- a/templates/feature/agl-ci-change-features-nogfx/included.dep +++ b/templates/feature/agl-ci-change-features-nogfx/included.dep @@ -1 +1 @@ -agl-devel agl-netboot agl-appfw-smack \ No newline at end of file +agl-devel agl-netboot \ No newline at end of file diff --git a/templates/feature/agl-ci-change-features/included.dep b/templates/feature/agl-ci-change-features/included.dep index fdd01e6a8..280452454 100644 --- a/templates/feature/agl-ci-change-features/included.dep +++ b/templates/feature/agl-ci-change-features/included.dep @@ -1 +1 @@ -agl-demo agl-devel agl-netboot agl-appfw-smack +agl-demo agl-devel agl-netboot diff --git a/templates/feature/agl-ci-snapshot-features-nogfx/included.dep b/templates/feature/agl-ci-snapshot-features-nogfx/included.dep index 00e77831a..c2e48284f 100644 --- a/templates/feature/agl-ci-snapshot-features-nogfx/included.dep +++ b/templates/feature/agl-ci-snapshot-features-nogfx/included.dep @@ -1 +1 @@ -agl-devel agl-netboot agl-appfw-smack agl-archiver +agl-devel agl-netboot agl-archiver diff --git a/templates/feature/agl-ci-snapshot-features/included.dep b/templates/feature/agl-ci-snapshot-features/included.dep index 219beeec4..c382e609c 100644 --- a/templates/feature/agl-ci-snapshot-features/included.dep +++ b/templates/feature/agl-ci-snapshot-features/included.dep @@ -1 +1 @@ -agl-demo agl-devel agl-netboot agl-appfw-smack agl-archiver +agl-demo agl-devel agl-netboot agl-archiver -- cgit 1.2.3-korg