summaryrefslogtreecommitdiffstats
path: root/meta-agl-devel
diff options
context:
space:
mode:
authorToshikazuOhiwa <toshikazu_ohiwa@mail.toyota.co.jp>2020-03-30 09:24:26 +0900
committerToshikazuOhiwa <toshikazu_ohiwa@mail.toyota.co.jp>2020-03-30 09:24:26 +0900
commit5b80bfd7bffd4c20d80b7c70a7130529e9a755dd (patch)
treeb4bb18dcd1487dbf1ea8127e5671b7bb2eded033 /meta-agl-devel
parent706ad73eb02caf8532deaf5d38995bd258725cb8 (diff)
agl-basesystem
Diffstat (limited to 'meta-agl-devel')
-rw-r--r--meta-agl-devel/.gitreview5
-rw-r--r--meta-agl-devel/ATTIC/agl-audio-4a-framework/50_bblayers.conf.inc5
-rw-r--r--meta-agl-devel/ATTIC/agl-audio-4a-framework/50_local.conf.inc2
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/README.md3
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/classes/afb-system-cmake.bbclass6
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/classes/afb-system.bbclass1
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/conf/include/agl-audio-4a-framework.inc24
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/conf/layer.conf23
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/meta-agl-demo/recipes-multimedia/4a-mixer/4a-mixer_git.bb27
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-connectivity/bluez-alsa/bluez-alsa/0001-build-and-link-with-a-shared-library.patch853
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-connectivity/bluez-alsa/bluez-alsa/0002-log-add-calling-function-name.patch26
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-connectivity/bluez-alsa/bluez-alsa/0003-dbus-request-a-name-on-startup.patch153
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-connectivity/bluez-alsa/bluez-alsa/0004-bluealsa-pcm-bump-the-trigger-after-pcm-prepare.patch35
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-connectivity/bluez-alsa/bluez-alsa_git.bbappend19
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-core/packagegroups/packagegroup-agl-audio.bb24
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-kernel/snd-avirt/files/0001-snd-avirt-backport-kernel-4.12-api.patch40
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-kernel/snd-avirt/files/0002-snd-avirt-backport-kernel-4.9-api.patch63
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-kernel/snd-avirt/snd-avirt.bb14
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-kernel/snd-avirt/snd-avirt.bbappend22
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-alsa-core/4a-alsa-core_git.bb25
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-config/4a-hal-config.bb24
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-config/files/asound.conf.template3
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-device-config/4a-hal-device-config-alternatives.README3
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-device-config/4a-hal-device-config-alternatives.bbexample57
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-device-config/4a-hal-device-config.README4
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-device-config/4a-hal-device-config.bb58
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-device-config/4a-hal-vendor-config.README3
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-device-config/4a-hal-vendor-config.bbexample46
-rwxr-xr-xmeta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-device-config/files/deploy-hal-udev.sh4
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-device-config/files/udev-sample-rule.rules1
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-generic/4a-hal-generic_git.bb30
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-unicens/4a-hal-unicens_git.bb32
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-softmixer/4a-softmixer_git.bb25
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-tools/4a-tools_git.bb22
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/agl-service-audio-4a/agl-service-audio-4a_git.bb58
-rwxr-xr-xmeta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/agl-service-audio-4a/files/4a_wait_bt.sh83
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/alsa/alsa-plugins_%.bbappend7
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/libavirt/libavirt_git.bb19
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/pulseaudio/files/default.pa.4a77
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/pulseaudio/pulseaudio-module-4a-client_git.bb20
-rw-r--r--meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/pulseaudio/pulseaudio_%.bbappend7
-rw-r--r--meta-agl-devel/README.md86
-rw-r--r--meta-agl-devel/docs/devguides-book.yml13
-rwxr-xr-xmeta-agl-devel/meta-agl-devel.md139
-rw-r--r--meta-agl-devel/meta-audio-soundmanager-framework/COPYING.MIT17
-rw-r--r--meta-agl-devel/meta-audio-soundmanager-framework/README.md18
-rw-r--r--meta-agl-devel/meta-audio-soundmanager-framework/conf/layer.conf12
-rw-r--r--meta-agl-devel/meta-audio-soundmanager-framework/recipes-extended/dlt-daemon/dlt-daemon/0001-Fix-build-with-systemd-209.patch30
-rw-r--r--meta-agl-devel/meta-audio-soundmanager-framework/recipes-extended/dlt-daemon/dlt-daemon/0002-Don-t-execute-processes-as-a-specific-user.patch81
-rw-r--r--meta-agl-devel/meta-audio-soundmanager-framework/recipes-extended/dlt-daemon/dlt-daemon/0003-systemd-unit-type-should-be-in-lowercase-so-use-Type.patch98
-rw-r--r--meta-agl-devel/meta-audio-soundmanager-framework/recipes-extended/dlt-daemon/dlt-daemon/0004-Modify-systemd-config-directory.patch24
-rw-r--r--meta-agl-devel/meta-audio-soundmanager-framework/recipes-extended/dlt-daemon/dlt-daemon_2.11.1.bb54
-rw-r--r--meta-agl-devel/meta-audio-soundmanager-framework/recipes-extended/dlt-daemon/dlt-daemon_2.15.0.bb52
-rw-r--r--meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/agl-service-audio-soundmanager/agl-service-audio-soundmanager_1.0.bb20
-rw-r--r--meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config-soundmanager/audiomanager-plugins-config-soundmanager/amcp_dbus.conf20
-rw-r--r--meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config-soundmanager/audiomanager-plugins-config-soundmanager/amrp_dbus.conf21
-rw-r--r--meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config-soundmanager/audiomanager-plugins-config-soundmanager/configuration.xml516
-rw-r--r--meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config-soundmanager/audiomanager-plugins-config-soundmanager/customtypes.xsd63
-rw-r--r--meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config-soundmanager/audiomanager-plugins-config-soundmanager/soundmanager-dbus.conf20
-rw-r--r--meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config-soundmanager/audiomanager-plugins-config-soundmanager_7.4.bb40
-rw-r--r--meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config/audiomanager-plugins-config/amcp_dbus.conf20
-rw-r--r--meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config/audiomanager-plugins-config/amrp_dbus.conf21
-rw-r--r--meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config/audiomanager-plugins-config/configuration.xml522
-rw-r--r--meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config/audiomanager-plugins-config/customtypes.xsd63
-rw-r--r--meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config/audiomanager-plugins-config/org.genivi.audiomanager.routing.pulseaudio.conf35
-rw-r--r--meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config/audiomanager-plugins-config_7.4.bb40
-rw-r--r--meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins/audiomanager-plugins_git.bb60
-rw-r--r--meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager/audiomanager/0001-Fix-duplicated-command-line-arg-t.patch25
-rw-r--r--meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager/audiomanager/audiomanager.service17
-rw-r--r--meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager/audiomanager_7.4.bb56
-rw-r--r--meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/libsoundmanager/libsoundmanager_0.9.bb16
-rwxr-xr-xmeta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/module-router/module-router_git.bb31
-rw-r--r--meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/pulseaudio-config-module-router/files/20-module-router.pa3
-rw-r--r--meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/pulseaudio-config-module-router/pulseaudio-config-module-router_1.0.bb13
-rw-r--r--meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/pulseaudio-config-soundmanager/files/soundmanager.pa3
-rw-r--r--meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/pulseaudio-config-soundmanager/pulseaudio-config-soundmanager_1.0.bb12
-rw-r--r--meta-agl-devel/meta-audio-soundmanager-framework/recipes-packagegroup/packagegroups/packagegroup-agl-audio-soundmanager.bb18
-rw-r--r--meta-agl-devel/meta-audio-soundmanager-framework/recipes-platform/packagegroups/packagegroup-agl-demo.bbappend4
-rw-r--r--meta-agl-devel/meta-gstrecorder-rcar-gen3/conf/include/agl_gstrecorder.inc1
-rw-r--r--meta-agl-devel/meta-gstrecorder-rcar-gen3/conf/layer.conf12
-rw-r--r--meta-agl-devel/meta-gstrecorder-rcar-gen3/recipes-graphics/wayland/weston/0001-remoting-Fix-remoting-gbm-dependency.patch41
-rw-r--r--meta-agl-devel/meta-gstrecorder-rcar-gen3/recipes-graphics/wayland/weston/0002-main-change-remoting-initialization-timing.patch39
-rw-r--r--meta-agl-devel/meta-gstrecorder-rcar-gen3/recipes-graphics/wayland/weston_6.0.0.bbappend12
-rw-r--r--meta-agl-devel/meta-html5-framework/conf/layer.conf12
-rw-r--r--meta-agl-devel/meta-html5-framework/recipes-platform/images/agl-demo-platform-crosssdk.bbappend3
-rw-r--r--meta-agl-devel/meta-html5-framework/recipes-platform/images/agl-demo-platform.bbappend3
-rw-r--r--meta-agl-devel/meta-html5-framework/recipes-platform/packagegroups/packagegroup-agl-demo-platform-html5.bb26
-rw-r--r--meta-agl-devel/meta-html5-framework/recipes-wam/chromium/chromium-browser-service.bb19
-rw-r--r--meta-agl-devel/meta-html5-framework/recipes-wam/chromium/chromium68/v8-qemu-wrapper.patch40
-rw-r--r--meta-agl-devel/meta-html5-framework/recipes-wam/chromium/chromium68_git.bb404
-rw-r--r--meta-agl-devel/meta-html5-framework/recipes-wam/chromium/gn-utils.inc157
-rw-r--r--meta-agl-devel/meta-html5-framework/recipes-wam/wam/files/WebAppMgr.env202
-rw-r--r--meta-agl-devel/meta-html5-framework/recipes-wam/wam/files/WebAppMgr@.service36
-rw-r--r--meta-agl-devel/meta-html5-framework/recipes-wam/wam/wam-tinyproxy_git.bb20
-rw-r--r--meta-agl-devel/meta-html5-framework/recipes-wam/wam/wam_git.bb51
-rw-r--r--meta-agl-devel/meta-oem-extra-libs/conf/layer.conf17
-rw-r--r--meta-agl-devel/meta-oem-extra-libs/recipes-connectivity/libwebsockets/libwebsockets_%.bbappend1
-rw-r--r--meta-agl-devel/meta-oem-extra-libs/recipes-connectivity/libwebsockets/libwebsockets_2.1.0.bb28
-rw-r--r--meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/files/CVE-2013-4420.patch113
-rw-r--r--meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/files/no_maxpathlen.patch491
-rw-r--r--meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/files/no_static_buffers.patch82
-rw-r--r--meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/files/no_strip.patch24
-rw-r--r--meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/files/oldgnu_prefix.patch21
-rw-r--r--meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/files/series7
-rw-r--r--meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/files/testsuite.patch50
-rw-r--r--meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/files/th_get_size-unsigned-int.patch52
-rw-r--r--meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/libtar_1.2.20.bb31
-rw-r--r--meta-agl-devel/meta-oem-extra-libs/recipes-core/packagegroups/nativesdk-packagegroup-sdk-host.bbappend1
-rw-r--r--meta-agl-devel/meta-oem-extra-libs/recipes-core/packagegroups/packagegroup-ivi-common-core-os-commonlibs.bbappend53
-rw-r--r--meta-agl-devel/meta-oem-extra-libs/recipes-devtools/bsdiff/bsdiff_git.bb19
-rw-r--r--meta-agl-devel/meta-oem-extra-libs/recipes-support/imagemagick/imagemagick_%.bbappend2
-rwxr-xr-xmeta-agl-devel/meta-oem-extra-libs/recipes-support/libdatrie/libdatrie_0.2.9.bb28
-rwxr-xr-xmeta-agl-devel/meta-oem-extra-libs/recipes-support/libthai/libthai_0.1.20.bb13
-rw-r--r--meta-agl-devel/meta-oem-extra-libs/recipes-support/mongoose/README.md10
-rw-r--r--meta-agl-devel/meta-oem-extra-libs/recipes-support/mongoose/mongoose_6.6.bb76
-rw-r--r--meta-agl-devel/meta-pipewire/conf/include/agl-pipewire.inc3
-rw-r--r--meta-agl-devel/meta-pipewire/conf/layer.conf12
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-connectivity/bluez-alsa/bluez-alsa/0001-utils-add-a-gstreamer-helper-application-for-interco.patch464
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-connectivity/bluez-alsa/bluez-alsa/bluealsa-gst-helper@.service18
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-connectivity/bluez-alsa/bluez-alsa_git.bbappend35
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-core/packagegroups/packagegroup-pipewire.bb17
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-multimedia/agl-service-audiomixer/agl-service-audiomixer_git.bb16
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire-conf-agl/client.env10
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire-conf-agl/pipewire.conf10
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire-conf-agl/server.env12
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire-conf-agl_git.bb40
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire.inc117
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0001-spa-include-install-missing-headers.patch41
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0002-extensions-implement-Endpoint-ClientEndpoint-interfa.patch1563
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0003-pipewire-cli-add-support-for-printing-endpoint-info-.patch149
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0004-pipewire-cli-add-command-to-modify-endpoint-control-.patch124
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0005-arm-build-with-mno-unaligned-access.patch30
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0006-logger-print-timestamps-on-logged-messages.patch52
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0007-alsa-make-corrections-on-the-timeout-based-on-how-fa.patch130
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0008-audio-dsp-allow-mode-to-be-set-with-a-property.patch45
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0009-audioconvert-do-setup-internal-links-and-buffers-als.patch55
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0010-gst-Implement-new-pwaudio-src-sink-elements-based-on.patch1249
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0011-gst-pwaudioringbuffer-make-the-buffer-size-sensitive.patch60
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0012-gst-pwaudioringbuffer-request-pause-play-on-the-appr.patch76
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0013-gst-pwaudioringbuffer-wait-only-for-STREAM_STATE_CON.patch35
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0014-gst-pwaudiosink-set-the-default-latency-time-buffer-.patch37
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0015-audioconvert-fmtconvert-assume-F32-on-the-other-port.patch44
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0016-gst-pwaudioringbuffer-set-node.latency-to-get-schedu.patch41
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0017-connection-move-remaining-data-and-fds.patch61
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0018-protocol-improve-flushing.patch222
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/pipewire@.service24
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/pipewire@.socket19
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/smack-pipewire8
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire_git.bb29
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire_git.bbappend30
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/wireplumber.conf.in55
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl_git.bb69
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber_git.bb36
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-security/security-manager/security-manager/0001-Adapt-smack-rules-to-allow-connections-to-pipewire.patch25
-rw-r--r--meta-agl-devel/meta-pipewire/recipes-security/security-manager/security-manager_%.bbappend2
-rw-r--r--meta-agl-devel/meta-speech-framework/conf/include/agl-speech-framework.inc2
-rw-r--r--meta-agl-devel/meta-speech-framework/conf/include/agl-voiceagent-alexa.inc6
-rw-r--r--meta-agl-devel/meta-speech-framework/conf/layer.conf27
-rw-r--r--meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-service/0001-remove-library-dependency-copying.patch30
-rw-r--r--meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-service/0002-update-config.xml.in.patch31
-rw-r--r--meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-service/0003-update-audio-device-configuration.patch197
-rw-r--r--meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-service/0004-update-config-and-database-paths.patch124
-rw-r--r--meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-service_git.bb41
-rw-r--r--meta-agl-devel/meta-speech-framework/meta-aac/recipes-modules/aac-module-gstreamer/aac-module-gstreamer.bbappend9
-rw-r--r--meta-agl-devel/meta-speech-framework/meta-aac/recipes-modules/aac-module-gstreamer/aac-module-gstreamer/0001-gstreamer-implement-pipewire-integration.patch94
-rw-r--r--meta-agl-devel/meta-speech-framework/recipes-apis/agl-service-voice-high-capabilities/agl-service-voice-high-capabilities_git.bb19
-rw-r--r--meta-agl-devel/meta-speech-framework/recipes-apis/agl-service-voice-high/agl-service-voice-high_git.bb17
-rw-r--r--meta-agl-devel/meta-speech-framework/recipes-platform/packagegroups/packagegroup-agl-core-services.bbappend7
-rw-r--r--meta-agl-devel/templates/feature/agl-audio-soundmanager-framework/50_bblayers.conf.inc5
-rw-r--r--meta-agl-devel/templates/feature/agl-audio-soundmanager-framework/50_local.conf.inc6
-rw-r--r--meta-agl-devel/templates/feature/agl-audio-soundmanager-framework/README_feature_agl-audio-soundmanager-framework.md9
-rw-r--r--meta-agl-devel/templates/feature/agl-gstrecorder/50_bblayers.conf.inc5
-rw-r--r--meta-agl-devel/templates/feature/agl-gstrecorder/50_local.conf.inc3
-rwxr-xr-xmeta-agl-devel/templates/feature/agl-gstrecorder/50_setupwarning.sh14
-rw-r--r--meta-agl-devel/templates/feature/agl-gstrecorder/README_feature_agl-gstrecorder.md9
-rw-r--r--meta-agl-devel/templates/feature/agl-html5-framework/50_bblayers.conf.inc5
-rw-r--r--meta-agl-devel/templates/feature/agl-html5-framework/README_feature_agl-html5-framework.md9
-rw-r--r--meta-agl-devel/templates/feature/agl-oem-extra-libs/50_bblayers.conf.inc5
-rw-r--r--meta-agl-devel/templates/feature/agl-oem-extra-libs/README_feature_agl-oem-extra-libs.md9
-rw-r--r--meta-agl-devel/templates/feature/agl-pipewire/50_bblayers.conf.inc5
-rw-r--r--meta-agl-devel/templates/feature/agl-pipewire/50_local.conf.inc2
-rw-r--r--meta-agl-devel/templates/feature/agl-pipewire/README_feature_agl-pipewire.md9
-rw-r--r--meta-agl-devel/templates/feature/agl-speech-framework/50_bblayers.conf.inc5
-rw-r--r--meta-agl-devel/templates/feature/agl-speech-framework/50_local.conf.inc2
-rw-r--r--meta-agl-devel/templates/feature/agl-speech-framework/README_feature_agl-speech-framework.md9
-rw-r--r--meta-agl-devel/templates/feature/agl-voiceagent-alexa/50_bblayers.conf.inc10
-rw-r--r--meta-agl-devel/templates/feature/agl-voiceagent-alexa/50_local.conf.inc2
-rw-r--r--meta-agl-devel/templates/feature/agl-voiceagent-alexa/README_feature_agl-voiceagent-alexa.md8
-rw-r--r--meta-agl-devel/templates/feature/agl-voiceagent-alexa/included.dep1
189 files changed, 12234 insertions, 0 deletions
diff --git a/meta-agl-devel/.gitreview b/meta-agl-devel/.gitreview
new file mode 100644
index 00000000..e2b97232
--- /dev/null
+++ b/meta-agl-devel/.gitreview
@@ -0,0 +1,5 @@
+[gerrit]
+host=gerrit.automotivelinux.org
+port=29418
+project=AGL/meta-agl-devel
+defaultbranch=halibut
diff --git a/meta-agl-devel/ATTIC/agl-audio-4a-framework/50_bblayers.conf.inc b/meta-agl-devel/ATTIC/agl-audio-4a-framework/50_bblayers.conf.inc
new file mode 100644
index 00000000..a4889083
--- /dev/null
+++ b/meta-agl-devel/ATTIC/agl-audio-4a-framework/50_bblayers.conf.inc
@@ -0,0 +1,5 @@
+
+BBLAYERS =+ " \
+ ${METADIR}/meta-agl-devel/meta-audio-4a-framework \
+ "
+
diff --git a/meta-agl-devel/ATTIC/agl-audio-4a-framework/50_local.conf.inc b/meta-agl-devel/ATTIC/agl-audio-4a-framework/50_local.conf.inc
new file mode 100644
index 00000000..91d4c863
--- /dev/null
+++ b/meta-agl-devel/ATTIC/agl-audio-4a-framework/50_local.conf.inc
@@ -0,0 +1,2 @@
+#see meta-agl-devel/meta-audio-4a-framework/conf/include/agl-audio-4a-framework.inc
+require conf/include/agl-audio-4a-framework.inc
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/README.md b/meta-agl-devel/ATTIC/meta-audio-4a-framework/README.md
new file mode 100644
index 00000000..37dd360a
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/README.md
@@ -0,0 +1,3 @@
+Collection of recipes for first integration of 4A (Advanced AGL Audio Architecture).
+
+This layer should disappear and recipes merged into meta-agl.
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/classes/afb-system-cmake.bbclass b/meta-agl-devel/ATTIC/meta-audio-4a-framework/classes/afb-system-cmake.bbclass
new file mode 100644
index 00000000..67ad7260
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/classes/afb-system-cmake.bbclass
@@ -0,0 +1,6 @@
+inherit afb-system
+
+DEPENDS += "alsa-lib json-c systemd af-binder cmake-apps-module-native"
+inherit cmake pkgconfig
+
+EXTRA_OECMAKE_append = " -DCMAKE_INSTALL_PREFIX=${INSTALL_PREFIX}"
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/classes/afb-system.bbclass b/meta-agl-devel/ATTIC/meta-audio-4a-framework/classes/afb-system.bbclass
new file mode 100644
index 00000000..b553d621
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/classes/afb-system.bbclass
@@ -0,0 +1 @@
+INSTALL_PREFIX = "${libexecdir}/agl"
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/conf/include/agl-audio-4a-framework.inc b/meta-agl-devel/ATTIC/meta-audio-4a-framework/conf/include/agl-audio-4a-framework.inc
new file mode 100644
index 00000000..12711f66
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/conf/include/agl-audio-4a-framework.inc
@@ -0,0 +1,24 @@
+# In order to enable the audio-4a-framework features ,
+# enables the following line:
+#
+DISTRO_FEATURES_append = " agl-audio-4a-framework "
+
+# asound.conf is provided by the 4a-hal-config (and not by asound.state)
+#VIRTUAL-RUNTIME_alsa-state = "4a-hal-config"
+VIRTUAL_RUNTIME_alsa-state = ""
+# additionally there is a bug in alsa-utils-alsactl where it pulls in alsa-state directly
+RRECOMMENDS_pn-alsa-utils-alsactl = "VIRTUAL-RUNTIME_alsa-state"
+
+# why should a config package have -dev ... I'll leave that answer to you.
+PACKAGES_pn-alsa-state_remove = "alsa-state-dev"
+PACKAGES_pn-alsa-state_remove = "alsa-states-dev"
+PACKAGES_pn-alsa-state = "alsa-state alsa-states"
+
+PREFERRED_PROVIDER_virtual/mixer ?= "4a-mixer"
+PREFERRED_RPROVIDER_virtual/mixer ?= "4a-mixer"
+
+PREFERRED_VERSION_alsa-lib = "1.1.6"
+PREFERRED_VERSION_alsa-plugins = "1.1.6"
+PREFERRED_VERSION_alsa-tools = "1.1.6"
+PREFERRED_VERSION_alsa-utils = "1.1.6"
+PREFERRED_VERSION_alsa-utils-scripts = "1.1.6"
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/conf/layer.conf b/meta-agl-devel/ATTIC/meta-audio-4a-framework/conf/layer.conf
new file mode 100644
index 00000000..dc190b66
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/conf/layer.conf
@@ -0,0 +1,23 @@
+# We have a conf and classes directory, add to BBPATH
+BBPATH .= ":${LAYERDIR}"
+
+# Fix for SPEC-1588
+# Let us add layer-specific bbappends which are only applied when that
+# layer is included in our configuration -
+# e.g. only add layers if a bsp is present.
+# This is based on the BBFILE_COLLECTIONS name of the layer.
+BBFILES += "${@' '.join('${LAYERDIR}/meta-%s/recipes*/*/*.bbappend' % layer \
+ for layer in BBFILE_COLLECTIONS.split())}"
+BBFILES += "${@' '.join('${LAYERDIR}/meta-%s/recipes*/*/*.bb' % layer \
+ for layer in BBFILE_COLLECTIONS.split())}"
+
+
+# We have recipes-* directories, add to BBFILES
+BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
+ ${LAYERDIR}/recipes-*/*/*.bbappend"
+
+BBFILE_COLLECTIONS += "4a-framework"
+BBFILE_PATTERN_4a-framework = "^${LAYERDIR}/"
+BBFILE_PRIORITY_4a-framework = "8"
+
+LAYERSERIES_COMPAT_4a-framework = "thud"
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/meta-agl-demo/recipes-multimedia/4a-mixer/4a-mixer_git.bb b/meta-agl-devel/ATTIC/meta-audio-4a-framework/meta-agl-demo/recipes-multimedia/4a-mixer/4a-mixer_git.bb
new file mode 100644
index 00000000..f87d4d20
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/meta-agl-demo/recipes-multimedia/4a-mixer/4a-mixer_git.bb
@@ -0,0 +1,27 @@
+SUMMARY = "Mixer for CES2017 AGL Demonstration"
+DESCRIPTION = "AGL HMI application for control of PulseAudio mixer elements"
+HOMEPAGE = "https://gerrit.automotivelinux.org/gerrit/#/admin/projects/apps/mixer"
+SECTION = "apps"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=ae6497158920d9524cf208c09cc4c984"
+
+SRC_URI = "gitsm://gerrit.automotivelinux.org/gerrit/apps/mixer;protocol=https;branch=${AGL_BRANCH}"
+SRCREV = "${AGL_APP_REVISION}"
+
+PV = "1.0+git${SRCPV}"
+S = "${WORKDIR}/git"
+
+# build-time dependencies
+DEPENDS += "qtquickcontrols2 \
+ qtwebsockets \
+ qtaglextras \
+ libafb-helpers-qt \
+"
+
+PROVIDES += "virtual/mixer"
+RPROVIDES_${PN} += "virtual/mixer"
+
+inherit cmake_qt5 aglwgt
+
+OECMAKE_CXX_FLAGS_append = " ${@bb.utils.contains('DISTRO_FEATURES', 'agl-devel', '' , '-DQT_NO_DEBUG_OUTPUT', d)}"
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-connectivity/bluez-alsa/bluez-alsa/0001-build-and-link-with-a-shared-library.patch b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-connectivity/bluez-alsa/bluez-alsa/0001-build-and-link-with-a-shared-library.patch
new file mode 100644
index 00000000..53ee3ad0
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-connectivity/bluez-alsa/bluez-alsa/0001-build-and-link-with-a-shared-library.patch
@@ -0,0 +1,853 @@
+From 7625b67a687b7a365d9d758a86ed05e84b2b3a61 Mon Sep 17 00:00:00 2001
+From: Thierry Bultel <thierry.bultel@iot.bzh>
+Date: Mon, 3 Dec 2018 14:29:07 +0100
+Subject: [PATCH 1/3] build and link with a shared library
+
+Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
+---
+ configure.ac | 4 +-
+ includes/bluealsa/bluealsa.h | 21 ++++++
+ {src/shared => includes/bluealsa}/ctl-client.h | 2 +-
+ {src/shared => includes/bluealsa}/ctl-proto.h | 0
+ {src/shared => includes/bluealsa}/defs.h | 0
+ {src/shared => includes/bluealsa}/ffb.h | 0
+ {src/shared => includes/bluealsa}/log.h | 0
+ {src/shared => includes/bluealsa}/rt.h | 0
+ src/Makefile.am | 11 ++-
+ src/asound/Makefile.am | 15 ++--
+ src/asound/bluealsa-ctl.c | 6 +-
+ src/asound/bluealsa-pcm.c | 10 +--
+ src/at.c | 4 +-
+ src/bluealsa.h | 2 +-
+ src/bluealsalib/Makefile.am | 50 ++++++++++++++
+ src/bluealsalib/bluealsa.pc.in | 12 ++++
+ src/bluez-a2dp.c | 2 +-
+ src/bluez.c | 2 +-
+ src/ctl.c | 4 +-
+ src/ctl.h | 2 +-
+ src/io.c | 8 +--
+ src/main.c | 4 +-
+ src/ofono.c | 2 +-
+ src/rfcomm.c | 4 +-
+ src/shared/ctl-client.c | 4 +-
+ src/shared/ffb.c | 2 +-
+ src/shared/log.c | 4 +-
+ src/shared/rt.c | 2 +-
+ src/transport.c | 2 +-
+ src/utils.c | 2 +-
+ test/Makefile.am | 10 ++-
+ test/server-mock.c | 3 -
+ test/test-at.c | 1 -
+ test/test-bluealsalib.c | 96 ++++++++++++++++++++++++++
+ test/test-io.c | 3 -
+ test/test-utils.c | 8 +--
+ utils/Makefile.am | 11 ++-
+ utils/aplay.c | 8 +--
+ utils/rfcomm.c | 4 +-
+ 39 files changed, 252 insertions(+), 73 deletions(-)
+ create mode 100644 includes/bluealsa/bluealsa.h
+ rename {src/shared => includes/bluealsa}/ctl-client.h (98%)
+ rename {src/shared => includes/bluealsa}/ctl-proto.h (100%)
+ rename {src/shared => includes/bluealsa}/defs.h (100%)
+ rename {src/shared => includes/bluealsa}/ffb.h (100%)
+ rename {src/shared => includes/bluealsa}/log.h (100%)
+ rename {src/shared => includes/bluealsa}/rt.h (100%)
+ create mode 100644 src/bluealsalib/Makefile.am
+ create mode 100644 src/bluealsalib/bluealsa.pc.in
+ create mode 100644 test/test-bluealsalib.c
+
+diff --git a/configure.ac b/configure.ac
+index 0bb9452..6323d60 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -152,8 +152,10 @@ AC_CONFIG_FILES([
+ Makefile
+ src/Makefile
+ src/asound/Makefile
++ src/bluealsalib/Makefile
+ utils/Makefile
+- test/Makefile])
++ test/Makefile
++ src/bluealsalib/bluealsa.pc])
+ AC_OUTPUT
+
+ # warn user that alsa-lib thread-safety makes troubles
+diff --git a/includes/bluealsa/bluealsa.h b/includes/bluealsa/bluealsa.h
+new file mode 100644
+index 0000000..062856a
+--- /dev/null
++++ b/includes/bluealsa/bluealsa.h
+@@ -0,0 +1,21 @@
++/*
++ * BlueALSA - bluealsa.h
++ * Copyright (c) 2018 Thierry Bultel
++ *
++ * This file is a part of bluez-alsa.
++ *
++ * This project is licensed under the terms of the MIT license.
++ *
++ */
++
++#ifndef BLUEALSA_H
++#define BLUEALSA_H
++
++#include <bluealsa/ctl-client.h>
++#include <bluealsa/defs.h>
++
++typedef int (*transport_update_cb) (struct ba_msg_transport *transports);
++
++extern int bluelsa_register_transport_update_cb(const char * interfance, transport_update_cb cb);
++
++#endif
+diff --git a/src/shared/ctl-client.h b/includes/bluealsa/ctl-client.h
+similarity index 98%
+rename from src/shared/ctl-client.h
+rename to includes/bluealsa/ctl-client.h
+index 3dc93a6..b8af154 100644
+--- a/src/shared/ctl-client.h
++++ b/includes/bluealsa/ctl-client.h
+@@ -12,7 +12,7 @@
+ #define BLUEALSA_SHARED_CTLCLIENT_H_
+
+ #include <stdbool.h>
+-#include "shared/ctl-proto.h"
++#include <bluealsa/ctl-proto.h>
+
+ int bluealsa_open(const char *interface);
+
+diff --git a/src/shared/ctl-proto.h b/includes/bluealsa/ctl-proto.h
+similarity index 100%
+rename from src/shared/ctl-proto.h
+rename to includes/bluealsa/ctl-proto.h
+diff --git a/src/shared/defs.h b/includes/bluealsa/defs.h
+similarity index 100%
+rename from src/shared/defs.h
+rename to includes/bluealsa/defs.h
+diff --git a/src/shared/ffb.h b/includes/bluealsa/ffb.h
+similarity index 100%
+rename from src/shared/ffb.h
+rename to includes/bluealsa/ffb.h
+diff --git a/src/shared/log.h b/includes/bluealsa/log.h
+similarity index 100%
+rename from src/shared/log.h
+rename to includes/bluealsa/log.h
+diff --git a/src/shared/rt.h b/includes/bluealsa/rt.h
+similarity index 100%
+rename from src/shared/rt.h
+rename to includes/bluealsa/rt.h
+diff --git a/src/Makefile.am b/src/Makefile.am
+index fb1241d..5626ae5 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -2,12 +2,9 @@
+ # Copyright (c) 2016-2018 Arkadiusz Bokowy
+
+ bin_PROGRAMS = bluealsa
+-SUBDIRS = asound
++SUBDIRS = bluealsalib asound
+
+ bluealsa_SOURCES = \
+- shared/ffb.c \
+- shared/log.c \
+- shared/rt.c \
+ at.c \
+ bluealsa.c \
+ bluez.c \
+@@ -34,7 +31,8 @@ AM_CFLAGS = \
+ @APTX_CFLAGS@ \
+ @LDAC_CFLAGS@ \
+ @LDAC_ABR_CFLAGS@ \
+- @SBC_CFLAGS@
++ @SBC_CFLAGS@ \
++ -I$(top_srcdir)/includes
+
+ LDADD = \
+ @BLUEZ_LIBS@ \
+@@ -44,4 +42,5 @@ LDADD = \
+ @APTX_LIBS@ \
+ @LDAC_LIBS@ \
+ @LDAC_ABR_LIBS@ \
+- @SBC_LIBS@
++ @SBC_LIBS@ \
++ bluealsalib/libbluealsa.la
+diff --git a/src/asound/Makefile.am b/src/asound/Makefile.am
+index 923d884..24618f1 100644
+--- a/src/asound/Makefile.am
++++ b/src/asound/Makefile.am
+@@ -5,32 +5,35 @@ EXTRA_DIST = 20-bluealsa.conf
+
+ asound_module_ctl_LTLIBRARIES = libasound_module_ctl_bluealsa.la
+ asound_module_pcm_LTLIBRARIES = libasound_module_pcm_bluealsa.la
++
+ asound_module_conf_DATA = 20-bluealsa.conf
+
+ libasound_module_ctl_bluealsa_la_SOURCES = \
+- ../shared/ctl-client.c \
+- ../shared/log.c \
+ bluealsa-ctl.c
++
+ libasound_module_pcm_bluealsa_la_SOURCES = \
+- ../shared/ctl-client.c \
+- ../shared/log.c \
+- ../shared/rt.c \
+ bluealsa-pcm.c
+
+ asound_module_ctldir = @ALSA_PLUGIN_DIR@
+ asound_module_pcmdir = @ALSA_PLUGIN_DIR@
++
+ asound_module_confdir = @ALSA_CONF_DIR@
+
+ AM_CFLAGS = \
+ -I$(top_srcdir)/src \
++ -I$(top_srcdir)/includes \
+ @ALSA_CFLAGS@ \
+ @BLUEZ_CFLAGS@ \
+ @GLIB2_CFLAGS@
+
+-AM_LDFLAGS = -module -avoid-version
++AM_LDFLAGS = \
++ -module \
++ -avoid-version \
++ ../bluealsalib/libbluealsa.la
+
+ libasound_module_ctl_bluealsa_la_LIBADD = \
+ @ALSA_LIBS@
++
+ libasound_module_pcm_bluealsa_la_LIBADD = \
+ @ALSA_LIBS@ \
+ @BLUEZ_LIBS@
+diff --git a/src/asound/bluealsa-ctl.c b/src/asound/bluealsa-ctl.c
+index f4a0181..1b9d124 100644
+--- a/src/asound/bluealsa-ctl.c
++++ b/src/asound/bluealsa-ctl.c
+@@ -19,9 +19,9 @@
+ #include <alsa/asoundlib.h>
+ #include <alsa/control_external.h>
+
+-#include "shared/ctl-client.h"
+-#include "shared/ctl-proto.h"
+-#include "shared/log.h"
++#include <bluealsa/ctl-client.h>
++#include <bluealsa/ctl-proto.h>
++#include <bluealsa/log.h>
+
+
+ enum ctl_elem_type {
+diff --git a/src/asound/bluealsa-pcm.c b/src/asound/bluealsa-pcm.c
+index 258aebd..42cb61d 100644
+--- a/src/asound/bluealsa-pcm.c
++++ b/src/asound/bluealsa-pcm.c
+@@ -23,11 +23,11 @@
+ #include <alsa/asoundlib.h>
+ #include <alsa/pcm_external.h>
+
+-#include "shared/ctl-client.h"
+-#include "shared/ctl-proto.h"
+-#include "shared/defs.h"
+-#include "shared/log.h"
+-#include "shared/rt.h"
++#include <bluealsa/ctl-client.h>
++#include <bluealsa/ctl-proto.h>
++#include <bluealsa/defs.h>
++#include <bluealsa/log.h>
++#include <bluealsa/rt.h>
+
+
+ struct bluealsa_pcm {
+diff --git a/src/at.c b/src/at.c
+index e3d1703..bda2255 100644
+--- a/src/at.c
++++ b/src/at.c
+@@ -16,8 +16,8 @@
+ #include <stdio.h>
+ #include <string.h>
+
+-#include "shared/defs.h"
+-#include "shared/log.h"
++#include <bluealsa/defs.h>
++#include <bluealsa/log.h>
+
+
+ /**
+diff --git a/src/bluealsa.h b/src/bluealsa.h
+index 7968ba9..7eee34f 100644
+--- a/src/bluealsa.h
++++ b/src/bluealsa.h
+@@ -27,7 +27,7 @@
+ #include "bluez.h"
+ #include "bluez-a2dp.h"
+ #include "transport.h"
+-#include "shared/ctl-proto.h"
++#include <bluealsa/ctl-proto.h>
+
+ struct ba_config {
+
+diff --git a/src/bluealsalib/Makefile.am b/src/bluealsalib/Makefile.am
+new file mode 100644
+index 0000000..11d9e00
+--- /dev/null
++++ b/src/bluealsalib/Makefile.am
+@@ -0,0 +1,50 @@
++# BlueALSA - Makefile.am
++# Copyright (c) 2018 Thiery Bultel (thierry.bultel@iot.bzh)
++
++bluealsalib_LTLIBRARIES = libbluealsa.la
++
++libbluealsa_la_SOURCES = \
++ ../shared/ctl-client.c \
++ ../shared/ffb.c \
++ ../shared/log.c \
++ ../shared/rt.c
++
++EXTRA_DIST=bluealsa.pc.in
++
++pkgconfigdir = $(libdir)/pkgconfig
++pkgconfig_DATA = bluealsa.pc
++
++AM_CFLAGS = \
++ -I$(top_srcdir)/src \
++ -I$(top_srcdir)/includes \
++ @ALSA_CFLAGS@ \
++ @BLUEZ_CFLAGS@ \
++ @GLIB2_CFLAGS@
++
++libbluealsa_la_LIBADD = \
++ @ALSA_LIBS@ \
++ @BLUEZ_LIBS@
++
++libbluealsa_la_LDFLAGS = \
++ $(AM_LDFLAGS) \
++ -version-info 1:0:0
++
++bluealsalibdir = $(libdir)
++
++# install path for published headers
++bluealsalibincludedir=$(includedir)/bluealsa
++
++bluealsalib_headers_dir=../../includes/bluealsa
++
++bluealsalib_headers = \
++ $(bluealsalib_headers_dir)/bluealsa.h \
++ $(bluealsalib_headers_dir)/ctl-client.h \
++ $(bluealsalib_headers_dir)/ctl-proto.h \
++ $(bluealsalib_headers_dir)/defs.h \
++ $(bluealsalib_headers_dir)/ffb.h \
++ $(bluealsalib_headers_dir)/log.h \
++ $(bluealsalib_headers_dir)/rt.h
++
++libbluealsa_la_SOURCES += $(bluealsalib_headers)
++
++bluealsalibinclude_HEADERS = $(bluealsalib_headers)
+diff --git a/src/bluealsalib/bluealsa.pc.in b/src/bluealsalib/bluealsa.pc.in
+new file mode 100644
+index 0000000..93c3c4a
+--- /dev/null
++++ b/src/bluealsalib/bluealsa.pc.in
+@@ -0,0 +1,12 @@
++prefix=@prefix@
++exec_prefix=@exec_prefix@
++libdir=@libdir@
++includedir=@includedir@
++
++Name: alsa
++Description: Bluez-Alsa - Library
++Version: @VERSION@
++Requires:
++Libs: -L${libdir} -lbluealsa
++#Libs.private: @ALSA_DEPLIBS@
++Cflags: -I${includedir}/bluealsa
+diff --git a/src/bluez-a2dp.c b/src/bluez-a2dp.c
+index 5f81e6e..4c7b07b 100644
+--- a/src/bluez-a2dp.c
++++ b/src/bluez-a2dp.c
+@@ -13,7 +13,7 @@
+ #endif
+
+ #include "bluez-a2dp.h"
+-#include "shared/defs.h"
++#include <bluealsa/defs.h>
+
+ static const a2dp_sbc_t a2dp_sbc = {
+ .frequency =
+diff --git a/src/bluez.c b/src/bluez.c
+index 537f0fe..591fdce 100644
+--- a/src/bluez.c
++++ b/src/bluez.c
+@@ -24,7 +24,7 @@
+ #include "ctl.h"
+ #include "transport.h"
+ #include "utils.h"
+-#include "shared/log.h"
++#include <bluealsa/log.h>
+
+
+ /**
+diff --git a/src/ctl.c b/src/ctl.c
+index ae2b812..dd3ab45 100644
+--- a/src/ctl.c
++++ b/src/ctl.c
+@@ -32,8 +32,8 @@
+ #include "hfp.h"
+ #include "transport.h"
+ #include "utils.h"
+-#include "shared/defs.h"
+-#include "shared/log.h"
++#include <bluealsa/defs.h>
++#include <bluealsa/log.h>
+
+ /* Special PCM type for internal usage only. */
+ #define BA_PCM_TYPE_RFCOMM 0x1F
+diff --git a/src/ctl.h b/src/ctl.h
+index 0e3c46b..593a9fd 100644
+--- a/src/ctl.h
++++ b/src/ctl.h
+@@ -11,7 +11,7 @@
+ #ifndef BLUEALSA_CTL_H_
+ #define BLUEALSA_CTL_H_
+
+-#include "shared/ctl-proto.h"
++#include <bluealsa/ctl-proto.h>
+
+ /* Indexes of special file descriptors in the poll array. */
+ #define CTL_IDX_SRV 0
+diff --git a/src/io.c b/src/io.c
+index b3d7ac9..f81eeb0 100644
+--- a/src/io.c
++++ b/src/io.c
+@@ -44,10 +44,10 @@
+ #include "bluealsa.h"
+ #include "transport.h"
+ #include "utils.h"
+-#include "shared/defs.h"
+-#include "shared/ffb.h"
+-#include "shared/log.h"
+-#include "shared/rt.h"
++#include <bluealsa/defs.h>
++#include <bluealsa/ffb.h>
++#include <bluealsa/log.h>
++#include <bluealsa/rt.h>
+
+
+ /**
+diff --git a/src/main.c b/src/main.c
+index 35e6702..9cef402 100644
+--- a/src/main.c
++++ b/src/main.c
+@@ -37,8 +37,8 @@
+ #endif
+ #include "transport.h"
+ #include "utils.h"
+-#include "shared/defs.h"
+-#include "shared/log.h"
++#include <bluealsa/defs.h>
++#include <bluealsa/log.h>
+
+
+ static char *get_a2dp_codecs(
+diff --git a/src/ofono.c b/src/ofono.c
+index 902d099..bfd4e39 100644
+--- a/src/ofono.c
++++ b/src/ofono.c
+@@ -27,7 +27,7 @@
+ #include "ctl.h"
+ #include "ofono-iface.h"
+ #include "transport.h"
+-#include "shared/log.h"
++#include <bluealsa/log.h>
+
+ #define OFONO_FAKE_DEV_ID 0xffff
+
+diff --git a/src/rfcomm.c b/src/rfcomm.c
+index a86ae61..2d76725 100644
+--- a/src/rfcomm.c
++++ b/src/rfcomm.c
+@@ -17,11 +17,11 @@
+ #include <string.h>
+ #include <unistd.h>
+
++#include <bluealsa/defs.h>
+ #include "bluealsa.h"
+ #include "ctl.h"
+ #include "utils.h"
+-#include "shared/defs.h"
+-#include "shared/log.h"
++#include <bluealsa/log.h>
+
+
+ /**
+diff --git a/src/shared/ctl-client.c b/src/shared/ctl-client.c
+index 6cf9402..2da9a54 100644
+--- a/src/shared/ctl-client.c
++++ b/src/shared/ctl-client.c
+@@ -8,7 +8,7 @@
+ *
+ */
+
+-#include "shared/ctl-client.h"
++#include <bluealsa/ctl-client.h>
+
+ #include <errno.h>
+ #include <fcntl.h>
+@@ -19,7 +19,7 @@
+ #include <sys/types.h>
+ #include <sys/un.h>
+
+-#include "shared/log.h"
++#include <bluealsa/log.h>
+
+
+ /**
+diff --git a/src/shared/ffb.c b/src/shared/ffb.c
+index b31d7d1..ab50f4a 100644
+--- a/src/shared/ffb.c
++++ b/src/shared/ffb.c
+@@ -8,7 +8,7 @@
+ *
+ */
+
+-#include "shared/ffb.h"
++#include "../../includes/bluealsa/ffb.h"
+
+
+ /**
+diff --git a/src/shared/log.c b/src/shared/log.c
+index 65f0fea..884540c 100644
+--- a/src/shared/log.c
++++ b/src/shared/log.c
+@@ -8,7 +8,7 @@
+ *
+ */
+
+-#include "shared/log.h"
++#include <bluealsa/log.h>
+
+ #include <pthread.h>
+ #include <stdarg.h>
+@@ -17,7 +17,7 @@
+ #include <string.h>
+ #include <syslog.h>
+
+-#include "shared/rt.h"
++#include <bluealsa/rt.h>
+
+
+ /* internal logging identifier */
+diff --git a/src/shared/rt.c b/src/shared/rt.c
+index edcbebc..40bd721 100644
+--- a/src/shared/rt.c
++++ b/src/shared/rt.c
+@@ -8,7 +8,7 @@
+ *
+ */
+
+-#include "shared/rt.h"
++#include <bluealsa/rt.h>
+
+ #include <stdlib.h>
+
+diff --git a/src/transport.c b/src/transport.c
+index 7253925..1617dd1 100644
+--- a/src/transport.c
++++ b/src/transport.c
+@@ -34,7 +34,7 @@
+ #include "io.h"
+ #include "rfcomm.h"
+ #include "utils.h"
+-#include "shared/log.h"
++#include <bluealsa/log.h>
+
+
+ static const char *transport_type_to_string(enum ba_transport_type type) {
+diff --git a/src/utils.c b/src/utils.c
+index 70d069e..27459d2 100644
+--- a/src/utils.c
++++ b/src/utils.c
+@@ -24,7 +24,7 @@
+
+ #include "a2dp-codecs.h"
+ #include "bluez.h"
+-#include "shared/log.h"
++#include <bluealsa/log.h>
+
+
+ /**
+diff --git a/test/Makefile.am b/test/Makefile.am
+index 104dc63..8f7b2eb 100644
+--- a/test/Makefile.am
++++ b/test/Makefile.am
+@@ -6,7 +6,8 @@ TESTS = \
+ test-ctl \
+ test-io \
+ test-pcm \
+- test-utils
++ test-utils \
++ test-bluealsalib
+
+ check_PROGRAMS = \
+ server-mock \
+@@ -14,7 +15,8 @@ check_PROGRAMS = \
+ test-ctl \
+ test-io \
+ test-pcm \
+- test-utils
++ test-utils \
++ test-bluealsalib
+
+ check_LTLIBRARIES = \
+ aloader.la
+@@ -25,6 +27,7 @@ aloader_la_LDFLAGS = \
+
+ AM_CFLAGS = \
+ -I$(top_srcdir)/src \
++ -I$(top_srcdir)/includes \
+ @AAC_CFLAGS@ \
+ @ALSA_CFLAGS@ \
+ @APTX_CFLAGS@ \
+@@ -46,4 +49,5 @@ LDADD = \
+ @GLIB2_LIBS@ \
+ @LDAC_ABR_LIBS@ \
+ @LDAC_LIBS@ \
+- @SBC_LIBS@
++ @SBC_LIBS@ \
++ ../src/bluealsalib/libbluealsa.la
+diff --git a/test/server-mock.c b/test/server-mock.c
+index 8c3a90e..c88fa35 100644
+--- a/test/server-mock.c
++++ b/test/server-mock.c
+@@ -31,9 +31,6 @@
+ #include "../src/rfcomm.c"
+ #include "../src/transport.c"
+ #include "../src/utils.c"
+-#include "../src/shared/ffb.c"
+-#include "../src/shared/log.c"
+-#include "../src/shared/rt.c"
+
+ static const a2dp_sbc_t cconfig = {
+ .frequency = SBC_SAMPLING_FREQ_44100,
+diff --git a/test/test-at.c b/test/test-at.c
+index 8cff264..a847c22 100644
+--- a/test/test-at.c
++++ b/test/test-at.c
+@@ -11,7 +11,6 @@
+ #include <check.h>
+
+ #include "../src/at.c"
+-#include "../src/shared/log.c"
+
+ START_TEST(test_at_build) {
+
+diff --git a/test/test-bluealsalib.c b/test/test-bluealsalib.c
+new file mode 100644
+index 0000000..d5fa3ff
+--- /dev/null
++++ b/test/test-bluealsalib.c
+@@ -0,0 +1,96 @@
++/*
++ * test-bluealsalib.c
++ * Copyright (c) 2018 Thierry Bultel
++ *
++ * This file is a part of bluez-alsa.
++ *
++ * This project is licensed under the terms of the MIT license.
++ *
++ */
++
++// TODO monitor all available interfaces
++const char * ba_interface = "hci0";
++
++#include <bluealsa/bluealsa.h>
++#include <bluealsa/log.h>
++#include <pthread.h>
++#include <errno.h>
++#include <poll.h>
++
++
++static void * monitor_thread_entry(void* arg) {
++ debug("...");
++
++ int ba_fd, ba_event_fd;
++ enum ba_event transport_mask = BA_EVENT_TRANSPORT_ADDED | BA_EVENT_TRANSPORT_CHANGED|BA_EVENT_TRANSPORT_REMOVED;
++
++ if ((ba_fd = bluealsa_open(ba_interface)) == -1) {
++ error("BlueALSA connection failed: %s", strerror(errno));
++ goto fail;
++ }
++
++ if ((ba_event_fd = bluealsa_open(ba_interface)) == -1) {
++ error("BlueALSA connection failed: %s", strerror(errno));
++ goto fail;
++ }
++
++ if (bluealsa_subscribe(ba_event_fd, transport_mask) == -1) {
++ error("BlueALSA subscription failed: %s", strerror(errno));
++ goto fail;
++ }
++
++goto init;
++
++ while (true) {
++
++ struct ba_msg_event event;
++ struct ba_msg_transport *transports;
++ ssize_t ret;
++ size_t i;
++
++ struct pollfd pfds[] = {{ ba_event_fd, POLLIN, 0 }};
++ if (poll(pfds, ARRAYSIZE(pfds), -1) == -1 && errno == EINTR)
++ continue;
++
++ while ((ret = recv(ba_event_fd, &event, sizeof(event), MSG_DONTWAIT)) == -1 && errno == EINTR)
++ continue;
++ if (ret != sizeof(event)) {
++ error("Couldn't read event: %s", strerror(ret == -1 ? errno : EBADMSG));
++ goto fail;
++ }
++
++init:
++ debug("Fetching available transports");
++ if ((ret = bluealsa_get_transports(ba_fd, &transports)) == -1) {
++ error("Couldn't get transports: %s", strerror(errno));
++ goto fail;
++ }
++
++ debug("Got %d transports", ret);
++
++ for (int ix=0; ix<ret; ix++) {
++ char addr[18];
++ struct ba_msg_transport * transport = &transports[ix];
++ ba2str(&transport->addr, addr);
++ info("Transport %d: type %d, dev %s", ix, transport->type, addr);
++ }
++
++ }
++
++fail:
++ info("exit");
++ return NULL;
++}
++
++int main(int argc, char * argv[]) {
++ printf("%s... !\n", argv[0]);
++
++ pthread_t monitor;
++ if (pthread_create(&monitor, NULL, monitor_thread_entry, NULL) == -1) {
++ debug("failed to create the monitor thread");
++ goto fail;
++ }
++ pthread_join(monitor, NULL);
++fail:
++ return 0;
++}
+diff --git a/test/test-io.c b/test/test-io.c
+index d913d2f..8ebb1d8 100644
+--- a/test/test-io.c
++++ b/test/test-io.c
+@@ -21,9 +21,6 @@
+ #include "../src/rfcomm.c"
+ #include "../src/transport.c"
+ #include "../src/utils.c"
+-#include "../src/shared/ffb.c"
+-#include "../src/shared/log.c"
+-#include "../src/shared/rt.c"
+
+ static const a2dp_sbc_t config_sbc_44100_stereo = {
+ .frequency = SBC_SAMPLING_FREQ_44100,
+diff --git a/test/test-utils.c b/test/test-utils.c
+index b704b42..46475f1 100644
+--- a/test/test-utils.c
++++ b/test/test-utils.c
+@@ -10,11 +10,11 @@
+
+ #include <check.h>
+
++#include <bluealsa/defs.h>
++#include <bluealsa/ffb.h>
++#include <bluealsa/rt.h>
++
+ #include "../src/utils.c"
+-#include "../src/shared/defs.h"
+-#include "../src/shared/ffb.c"
+-#include "../src/shared/log.c"
+-#include "../src/shared/rt.c"
+
+ START_TEST(test_dbus_profile_object_path) {
+
+diff --git a/utils/Makefile.am b/utils/Makefile.am
+index 256689a..a6d132c 100644
+--- a/utils/Makefile.am
++++ b/utils/Makefile.am
+@@ -6,32 +6,31 @@ bin_PROGRAMS =
+ if ENABLE_APLAY
+ bin_PROGRAMS += bluealsa-aplay
+ bluealsa_aplay_SOURCES = \
+- ../src/shared/ctl-client.c \
+- ../src/shared/ffb.c \
+- ../src/shared/log.c \
+ aplay.c
+ bluealsa_aplay_CFLAGS = \
+ -I$(top_srcdir)/src \
++ -I$(top_srcdir)/includes \
+ @ALSA_CFLAGS@ \
+ @BLUEZ_CFLAGS@ \
+ @GIO2_CFLAGS@
+ bluealsa_aplay_LDADD = \
+ @ALSA_LIBS@ \
+ @BLUEZ_LIBS@ \
+- @GIO2_LIBS@
++ @GIO2_LIBS@ \
++ ../src/bluealsalib/libbluealsa.la
+ endif
+
+ if ENABLE_RFCOMM
+ bin_PROGRAMS += bluealsa-rfcomm
+ bluealsa_rfcomm_SOURCES = \
+- ../src/shared/ctl-client.c \
+- ../src/shared/log.c \
+ rfcomm.c
+ bluealsa_rfcomm_CFLAGS = \
+ -I$(top_srcdir)/src \
++ -I$(top_srcdir)/includes \
+ @BLUEZ_CFLAGS@
+ bluealsa_rfcomm_LDADD = \
+ @BLUEZ_LIBS@ \
++ ../src/bluealsalib/libbluealsa.la \
+ -lreadline
+ endif
+
+diff --git a/utils/aplay.c b/utils/aplay.c
+index f792ce6..4b1372e 100644
+--- a/utils/aplay.c
++++ b/utils/aplay.c
+@@ -25,10 +25,10 @@
+ #include <alsa/asoundlib.h>
+ #include <gio/gio.h>
+
+-#include "shared/ctl-client.h"
+-#include "shared/defs.h"
+-#include "shared/ffb.h"
+-#include "shared/log.h"
++#include <bluealsa/ctl-client.h>
++#include <bluealsa/defs.h>
++#include <bluealsa/ffb.h>
++#include <bluealsa/log.h>
+
+ struct pcm_worker {
+ struct ba_msg_transport transport;
+diff --git a/utils/rfcomm.c b/utils/rfcomm.c
+index cc31f46..38e3b30 100644
+--- a/utils/rfcomm.c
++++ b/utils/rfcomm.c
+@@ -24,8 +24,8 @@
+ #include <readline/readline.h>
+ #include <readline/history.h>
+
+-#include "shared/ctl-client.h"
+-#include "shared/log.h"
++#include <bluealsa/ctl-client.h>
++#include <bluealsa/log.h>
+
+ static char *strtrim(char *str) {
+ while (isspace(*str))
+--
+2.16.4
+
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-connectivity/bluez-alsa/bluez-alsa/0002-log-add-calling-function-name.patch b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-connectivity/bluez-alsa/bluez-alsa/0002-log-add-calling-function-name.patch
new file mode 100644
index 00000000..8ed7e0b6
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-connectivity/bluez-alsa/bluez-alsa/0002-log-add-calling-function-name.patch
@@ -0,0 +1,26 @@
+From 3a7400da79678e749381306e33163ca2c005cb3b Mon Sep 17 00:00:00 2001
+From: Thierry Bultel <thierry.bultel@iot.bzh>
+Date: Mon, 3 Dec 2018 14:31:31 +0100
+Subject: [PATCH 2/3] log: add calling function name
+
+Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
+---
+ includes/bluealsa/log.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/includes/bluealsa/log.h b/includes/bluealsa/log.h
+index 39663fb..6d4cec3 100644
+--- a/includes/bluealsa/log.h
++++ b/includes/bluealsa/log.h
+@@ -31,7 +31,7 @@ void info(const char *format, ...) __attribute__ ((format(printf, 1, 2)));
+
+ #if DEBUG
+ void _debug(const char *format, ...) __attribute__ ((format(printf, 1, 2)));
+-# define debug(M, ARGS ...) _debug("%s:%d: " M, __FILE__, __LINE__, ## ARGS)
++# define debug(M, ARGS ...) _debug("%s:%d:%s: " M, __FILE__, __LINE__,__func__, ## ARGS)
+ #else
+ # define debug(M, ARGS ...) do {} while (0)
+ #endif
+--
+2.16.4
+
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-connectivity/bluez-alsa/bluez-alsa/0003-dbus-request-a-name-on-startup.patch b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-connectivity/bluez-alsa/bluez-alsa/0003-dbus-request-a-name-on-startup.patch
new file mode 100644
index 00000000..1ef59296
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-connectivity/bluez-alsa/bluez-alsa/0003-dbus-request-a-name-on-startup.patch
@@ -0,0 +1,153 @@
+From 4c14fffbd20a6dd9e6ceca1eb1726ceaafab7410 Mon Sep 17 00:00:00 2001
+From: Thierry Bultel <thierry.bultel@iot.bzh>
+Date: Fri, 18 Jan 2019 11:45:29 +0100
+Subject: [PATCH 3/3] dbus: request a name on startup
+
+When the service thread is ready, ask a name to dbus
+The advantage of doing that is that client applications
+can check dbus for bluez-alsa presence, without having
+to implement any kinf of polling logic. Also, this
+way, they can be notified on the service exit, to
+perform any needed cleanup.
+Since there must be an instance of bluealsa daemon
+per hci device, the dbus name will be
+'org.bluez-alsa.hci0', 'org.bluez-alsa.hci1' ...
+and so on.
+
+Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
+---
+ configure.ac | 10 ++++++++++
+ src/Makefile.am | 3 +++
+ src/bluez-alsa.conf | 14 ++++++++++++++
+ src/main.c | 32 ++++++++++++++++++++++++++++++++
+ 4 files changed, 59 insertions(+)
+ create mode 100644 src/bluez-alsa.conf
+
+diff --git a/configure.ac b/configure.ac
+index 6323d60..d4ec7d4 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -130,6 +130,16 @@ AC_ARG_WITH([alsaconfdir],
+ [alsaconfdir="$sysconfdir/alsa/conf.d"],
+ [alsaconfdir="$datadir/alsa/alsa.conf.d"])])
+
++AC_ARG_WITH(dbusconfdir, AC_HELP_STRING([--with-dbusconfdir=PATH],
++ [path to D-Bus config directory]), [path_dbusconf=${withval}],
++ [path_dbusconf="`$PKG_CONFIG --variable=sysconfdir dbus-1`"])
++if (test -z "${path_dbusconf}"); then
++ DBUS_CONFDIR="${sysconfdir}/dbus-1/system.d"
++else
++ DBUS_CONFDIR="${path_dbusconf}/dbus-1/system.d"
++fi
++AC_SUBST(DBUS_CONFDIR)
++
+ test "x$prefix" = xNONE && prefix=$ac_default_prefix
+ test "x$exec_prefix" = xNONE && exec_prefix=$prefix
+
+diff --git a/src/Makefile.am b/src/Makefile.am
+index 5626ae5..c501f2e 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -23,6 +23,9 @@ bluealsa_SOURCES += \
+ ofono-iface.c
+ endif
+
++dbusconfdir = @DBUS_CONFDIR@
++dist_dbusconf_DATA = bluez-alsa.conf
++
+ AM_CFLAGS = \
+ @BLUEZ_CFLAGS@ \
+ @GLIB2_CFLAGS@ \
+diff --git a/src/bluez-alsa.conf b/src/bluez-alsa.conf
+new file mode 100644
+index 0000000..6b999d6
+--- /dev/null
++++ b/src/bluez-alsa.conf
+@@ -0,0 +1,14 @@
++<!-- This configuration file specifies the required security policies
++ for bluez-alsa core daemon to work. -->
++
++<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
++ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
++<busconfig>
++
++ <!-- ../system.conf have denied everything, so we just punch some holes -->
++
++ <policy user="root">
++ <allow own_prefix="org.bluez-alsa"/>
++ </policy>
++
++</busconfig>
+diff --git a/src/main.c b/src/main.c
+index 9cef402..9183978 100644
+--- a/src/main.c
++++ b/src/main.c
+@@ -12,6 +12,7 @@
+ # include "config.h"
+ #endif
+
++#define _GNU_SOURCE
+ #include <errno.h>
+ #include <getopt.h>
+ #include <signal.h>
+@@ -58,6 +59,20 @@ static char *get_a2dp_codecs(
+ return g_strjoinv(", ", (char **)tmp);
+ }
+
++static void name_acquired_handler(
++ GDBusConnection *connection,
++ const gchar *name,
++ gpointer user_data) {
++ debug("Acquired name: %s", name);
++}
++
++static void name_lost_handler(
++ GDBusConnection *connection,
++ const gchar *name,
++ gpointer user_data) {
++ debug("Lost name: %s", name);
++}
++
+ static GMainLoop *loop = NULL;
+ static void main_loop_stop(int sig) {
+ /* Call to this handler restores the default action, so on the
+@@ -318,6 +333,7 @@ int main(int argc, char **argv) {
+ GError *err;
+
+ err = NULL;
++
+ address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, NULL);
+ if ((config.dbus = g_dbus_connection_new_for_address_sync(address,
+ G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
+@@ -336,6 +352,19 @@ int main(int argc, char **argv) {
+ ofono_register();
+ #endif
+
++ char * name_on_bus = NULL;
++ asprintf(&name_on_bus, "org.bluez-alsa.%s", config.hci_dev.name);
++
++ guint g_dbusid;
++ g_dbusid = g_bus_own_name_on_connection(config.dbus,
++ name_on_bus,
++ G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
++ G_BUS_NAME_OWNER_FLAGS_REPLACE,
++ name_acquired_handler,
++ name_lost_handler,
++ NULL,
++ NULL);
++
+ /* In order to receive EPIPE while writing to the pipe whose reading end
+ * is closed, the SIGPIPE signal has to be handled. For more information
+ * see the io_thread_write_pcm() function. */
+@@ -359,5 +388,8 @@ int main(int argc, char **argv) {
+ bluealsa_ctl_free();
+ bluealsa_config_free();
+
++ g_bus_unown_name (g_dbusid);
++ free(name_on_bus);
++
+ return EXIT_SUCCESS;
+ }
+--
+2.16.4
+
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-connectivity/bluez-alsa/bluez-alsa/0004-bluealsa-pcm-bump-the-trigger-after-pcm-prepare.patch b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-connectivity/bluez-alsa/bluez-alsa/0004-bluealsa-pcm-bump-the-trigger-after-pcm-prepare.patch
new file mode 100644
index 00000000..7befe733
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-connectivity/bluez-alsa/bluez-alsa/0004-bluealsa-pcm-bump-the-trigger-after-pcm-prepare.patch
@@ -0,0 +1,35 @@
+From ba292e82928a6a0ea663039ba2d5c030c4cfa80d Mon Sep 17 00:00:00 2001
+From: Thierry Bultel <thierry.bultel@iot.bzh>
+Date: Fri, 8 Feb 2019 10:21:55 +0100
+Subject: [PATCH] bluealsa-pcm: bump the trigger after pcm prepare
+
+When a sound application recovers from a EPIPE by calling
+snd_pcm_prepare, and goes immediately after to a call to poll,
+it would be stuck forever unless the internal event trigger
+is bumped.
+
+Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
+---
+ src/asound/bluealsa-pcm.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/src/asound/bluealsa-pcm.c b/src/asound/bluealsa-pcm.c
+index 42cb61d..4ccbf0d 100644
+--- a/src/asound/bluealsa-pcm.c
++++ b/src/asound/bluealsa-pcm.c
+@@ -351,6 +351,12 @@ static int bluealsa_prepare(snd_pcm_ioplug_t *io) {
+ pcm->io_ptr = 0;
+
+ debug("Prepared: %d", pcm->fd);
++
++ /* When the sound application calls poll just after snd_pcm_prepare,
++ * it would block forever unless the internal trigger is bumped
++ * */
++ eventfd_write(pcm->event_fd, 1);
++
+ return 0;
+ }
+
+--
+2.16.4
+
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-connectivity/bluez-alsa/bluez-alsa_git.bbappend b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-connectivity/bluez-alsa/bluez-alsa_git.bbappend
new file mode 100644
index 00000000..ece43824
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-connectivity/bluez-alsa/bluez-alsa_git.bbappend
@@ -0,0 +1,19 @@
+# This brings some mandatory patches for the softmixer and hal-manager.
+#
+# - patch 1 makes a communication library for hal-manager to get
+# the list of audio transports from bluez-alsa
+# - patch 2 makes the "debug" macro always display the caller name
+# - patch 3 asks dbus for a name like 'org.bluez-alsa.hciX' where hciX
+# - patch 4 is a bug fix
+# name of the HCI interface that the bluealsa daemon instance is handling
+#
+# Notice that patch 2 will very likely be replaced by a full dbus interface
+# in the future.
+#
+
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += "file://0001-build-and-link-with-a-shared-library.patch"
+SRC_URI += "file://0002-log-add-calling-function-name.patch"
+SRC_URI += "file://0003-dbus-request-a-name-on-startup.patch"
+SRC_URI += "file://0004-bluealsa-pcm-bump-the-trigger-after-pcm-prepare.patch"
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-core/packagegroups/packagegroup-agl-audio.bb b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-core/packagegroups/packagegroup-agl-audio.bb
new file mode 100644
index 00000000..bc236ff6
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-core/packagegroups/packagegroup-agl-audio.bb
@@ -0,0 +1,24 @@
+SUMMARY = "AGL Audio packages"
+DESCRIPTION = "The set of packages required by the AGL Audio"
+LICENSE = "MIT"
+
+inherit packagegroup
+
+PACKAGES = "\
+ packagegroup-agl-audio \
+ "
+
+RDEPENDS_${PN} += "\
+ 4a-alsa-core \
+ agl-service-audio-4a \
+ VIRTUAL-RUNTIME_alsa-state \
+ agl-service-unicens \
+ bluez-alsa \
+ 4a-softmixer \
+ 4a-hal-generic \
+ 4a-hal-unicens \
+ snd-avirt \
+ ${@bb.utils.contains('DISTRO_FEATURES', 'agl-devel', '4a-tools', '' , d)} \
+"
+# FIXME: Disable for now due to compilation issues against PulseAudio 12.x
+# ${@bb.utils.contains('DISTRO_FEATURES', 'pulseaudio', 'pulseaudio-module-4a-client', '' , d)}
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-kernel/snd-avirt/files/0001-snd-avirt-backport-kernel-4.12-api.patch b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-kernel/snd-avirt/files/0001-snd-avirt-backport-kernel-4.12-api.patch
new file mode 100644
index 00000000..fa737cb4
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-kernel/snd-avirt/files/0001-snd-avirt-backport-kernel-4.12-api.patch
@@ -0,0 +1,40 @@
+From 2fc07fedd17650f64f9bfcdb8682b55dad75cccd Mon Sep 17 00:00:00 2001
+From: Mark Farrugia <mark.farrugia@fiberdyne.com.au>
+Date: Mon, 8 Apr 2019 16:38:13 +1000
+Subject: [PATCH] 0001-snd-avirt-backport-kernel-4.12-api
+
+---
+ core.c | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+diff --git a/core.c b/core.c
+index c2e32c5..2bb6616 100644
+--- a/core.c
++++ b/core.c
+@@ -219,9 +219,8 @@ int snd_avirt_stream_try_complete(struct snd_avirt_stream *stream)
+ /* Set PCM ops for the Audio Path*/
+ PCM_OPS_SET(pcm_ops_ap, &stream->pcm_ops, pointer);
+ PCM_OPS_SET(pcm_ops_ap, &stream->pcm_ops, get_time_info);
+- PCM_OPS_SET(pcm_ops_ap, &stream->pcm_ops, fill_silence);
+- PCM_OPS_SET(pcm_ops_ap, &stream->pcm_ops, copy_user);
+- PCM_OPS_SET(pcm_ops_ap, &stream->pcm_ops, copy_kernel);
++ PCM_OPS_SET(pcm_ops_ap, &stream->pcm_ops, silence);
++ PCM_OPS_SET(pcm_ops_ap, &stream->pcm_ops, copy);
+ PCM_OPS_SET(pcm_ops_ap, &stream->pcm_ops, mmap);
+ PCM_OPS_SET(pcm_ops_ap, &stream->pcm_ops, ack);
+
+@@ -331,9 +330,9 @@ snd_avirt_route_endpoint_copy(struct snd_pcm_substream *substream,
+
+ switch (endpoint) {
+ case SND_AVIRT_ROUTE_SOURCE:
+- return endpoint_ap->pcm_capture_ops->copy_kernel;
++ return endpoint_ap->pcm_capture_ops->copy;
+ case SND_AVIRT_ROUTE_SINK:
+- return endpoint_ap->pcm_playback_ops->copy_kernel;
++ return endpoint_ap->pcm_playback_ops->copy;
+ }
+
+ return NULL;
+--
+2.17.1
+
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-kernel/snd-avirt/files/0002-snd-avirt-backport-kernel-4.9-api.patch b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-kernel/snd-avirt/files/0002-snd-avirt-backport-kernel-4.9-api.patch
new file mode 100644
index 00000000..fa944da0
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-kernel/snd-avirt/files/0002-snd-avirt-backport-kernel-4.9-api.patch
@@ -0,0 +1,63 @@
+From fe7fc04e4f685c72b4f971ca0e23b10d683cffe0 Mon Sep 17 00:00:00 2001
+From: Mark Farrugia <mark.farrugia@fiberdyne.com.au>
+Date: Fri, 16 Nov 2018 16:10:12 +1100
+Subject: [PATCH] snd-avirt-backport-kernel-4.9-api
+
+---
+ dummy/dummy.c | 6 +++---
+ loopback/loopback.c | 6 +++---
+ 2 files changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/dummy/dummy.c b/dummy/dummy.c
+index f683b92..c37be09 100644
+--- a/dummy/dummy.c
++++ b/dummy/dummy.c
+@@ -125,9 +125,9 @@ static int dummy_systimer_prepare(struct snd_pcm_substream *substream)
+ return 0;
+ }
+
+-static void dummy_systimer_callback(struct timer_list *t)
++static void dummy_systimer_callback(unsigned long data)
+ {
+- struct dummy_systimer_pcm *dpcm = from_timer(dpcm, t, timer);
++ struct dummy_systimer_pcm *dpcm = (struct dummy_systimer_pcm *)data;
+ unsigned long flags;
+ int elapsed = 0;
+
+@@ -162,7 +162,7 @@ static int dummy_systimer_create(struct snd_pcm_substream *substream)
+ if (!dpcm)
+ return -ENOMEM;
+ substream->runtime->private_data = dpcm;
+- timer_setup(&dpcm->timer, dummy_systimer_callback, 0);
++ setup_timer(&dpcm->timer, dummy_systimer_callback, (unsigned long)dpcm);
+ spin_lock_init(&dpcm->lock);
+ dpcm->substream = substream;
+ return 0;
+diff --git a/loopback/loopback.c b/loopback/loopback.c
+index 4181392..6667a69 100644
+--- a/loopback/loopback.c
++++ b/loopback/loopback.c
+@@ -498,9 +498,9 @@ unlock:
+ return running;
+ }
+
+-static void loopback_timer_function(struct timer_list *t)
++static void loopback_timer_function(unsigned long data)
+ {
+- struct loopback_pcm *dpcm = from_timer(dpcm, t, timer);
++ struct loopback_pcm *dpcm = (struct loopback_pcm *)data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dpcm->cable->lock, flags);
+@@ -652,7 +652,7 @@ static int loopback_open(struct snd_pcm_substream *substream)
+ }
+ dpcm->loopback = loopback;
+ dpcm->substream = substream;
+- timer_setup(&dpcm->timer, loopback_timer_function, 0);
++ setup_timer(&dpcm->timer, loopback_timer_function, (unsigned long)dpcm);
+
+ cable = loopback->cables[substream->pcm->device];
+ if (!cable) {
+--
+2.17.1
+
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-kernel/snd-avirt/snd-avirt.bb b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-kernel/snd-avirt/snd-avirt.bb
new file mode 100644
index 00000000..006f9c51
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-kernel/snd-avirt/snd-avirt.bb
@@ -0,0 +1,14 @@
+DESCRIPTION = "Build SND_AVIRT driver"
+LICENSE = "GPLv2"
+LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6"
+
+inherit module
+
+PV = "0.1"
+
+SRC_URI = "git://gerrit.automotivelinux.org/gerrit/src/avirt;protocol=https;branch=${AGL_BRANCH}"
+
+S = "${WORKDIR}/git"
+SRCREV = "12c6dc3159cc14cb3456d6d504398ba779538fb3"
+
+KERNEL_MODULE_AUTOLOAD += "snd-avirt-core snd-avirt-ap-loopback"
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-kernel/snd-avirt/snd-avirt.bbappend b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-kernel/snd-avirt/snd-avirt.bbappend
new file mode 100644
index 00000000..3c9fea0e
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-kernel/snd-avirt/snd-avirt.bbappend
@@ -0,0 +1,22 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
+
+def prep_version (d) :
+ KV = d.getVar('KERNEL_VERSION', True)
+ if not KV :
+ return "4.12"
+ else:
+ return KV
+
+ORIG_KERN_VER = "${@prep_version(d)}"
+
+VANILLA_KERNEL_VERSION = "${@str(ORIG_KERN_VER.split("-")[0].split(".")[0]+ORIG_KERN_VER.split("-")[0].split(".")[1])}"
+
+APPLY_0001 = "${@str('no' if ${VANILLA_KERNEL_VERSION} > 412 else 'yes')}"
+APPLY_0002 = "${@str('no' if ${VANILLA_KERNEL_VERSION} > 49 else 'yes')}"
+
+SRC_URI_append = " \
+ file://0001-snd-avirt-backport-kernel-4.12-api.patch;apply=${APPLY_0001} \
+ file://0002-snd-avirt-backport-kernel-4.9-api.patch;apply=${APPLY_0002} \
+ "
+# Make sure we can expose KERNEL_VERSION ...
+do_patch[depends] += "virtual/kernel:do_populate_sysroot"
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-alsa-core/4a-alsa-core_git.bb b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-alsa-core/4a-alsa-core_git.bb
new file mode 100644
index 00000000..b94eff21
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-alsa-core/4a-alsa-core_git.bb
@@ -0,0 +1,25 @@
+SUMMARY = "4A - Low Level Alsa Binding"
+DESCRIPTION = "Low Level Alsa Binding for 4A (AGL Advanced Audio Agent)"
+HOMEPAGE = "https://git.automotivelinux.org/src/4a-alsa-core/"
+SECTION = "apps"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
+
+SRC_URI = "gitsm://gerrit.automotivelinux.org/gerrit/src/4a-alsa-core;protocol=https;branch=${AGL_BRANCH}"
+SRCREV = "9b71be04ea600189e390bb111624ad5c2d248a4c"
+
+DEPENDS += "libafb-helpers"
+
+PV = "0.1+git${SRCPV}"
+S = "${WORKDIR}/git"
+
+inherit afb-system-cmake
+
+# FIXME: Remove once CMake+ninja issues are resolved
+OECMAKE_GENERATOR = "Unix Makefiles"
+
+FILES_${PN}-dev += "${INSTALL_PREFIX}/4a-alsa-core/htdocs"
+
+FILES_${PN} += "${INSTALL_PREFIX}/4a-alsa-core"
+FILES_${PN} += "${INSTALL_PREFIX}/lib"
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-config/4a-hal-config.bb b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-config/4a-hal-config.bb
new file mode 100644
index 00000000..fc648a1d
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-config/4a-hal-config.bb
@@ -0,0 +1,24 @@
+SUMMARY = "4A - HAL Configuration"
+DESCRIPTION = "Configuration files for HALs used in 4A (AGL Advanced Audio Agent)"
+HOMEPAGE = "https://git.automotivelinux.org/src/4a-hal-reference/"
+SECTION = "apps"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
+
+SRC_URI = "file://asound.conf.template \
+ "
+
+PV = "0.1"
+
+RPROVIDES_${PN} += "VIRTUAL-RUNTIME_alsa-state"
+
+inherit afb-system
+
+do_install () {
+ install -d ${D}/${sysconfdir}
+ install -m 0755 ${WORKDIR}/asound.conf.template ${D}/${sysconfdir}/asound.conf
+ sed -i "s|@INSTALL_PREFIX@|${INSTALL_PREFIX}|g" ${D}/${sysconfdir}/asound.conf
+}
+
+FILES_${PN} += "${sysconfdir}/asound.conf"
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-config/files/asound.conf.template b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-config/files/asound.conf.template
new file mode 100644
index 00000000..5a265db0
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-config/files/asound.conf.template
@@ -0,0 +1,3 @@
+#
+#4A pcm configuration is now dynamic, please check hal configuration files in @INSTALL_PREFIX@/4a-hal/etc
+#
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-device-config/4a-hal-device-config-alternatives.README b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-device-config/4a-hal-device-config-alternatives.README
new file mode 100644
index 00000000..689f9bf8
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-device-config/4a-hal-device-config-alternatives.README
@@ -0,0 +1,3 @@
+This is a sample on how the update-alternative system can be used to select
+the highest priority hal given.
+Downside ... always only one file is possible in the etc folder. No HAL_LIST.
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-device-config/4a-hal-device-config-alternatives.bbexample b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-device-config/4a-hal-device-config-alternatives.bbexample
new file mode 100644
index 00000000..3bafc3bb
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-device-config/4a-hal-device-config-alternatives.bbexample
@@ -0,0 +1,57 @@
+SUMMARY = "4A - Generic HAL device configuration"
+DESCRIPTION = "Generic HAL device configuration in 4A (AGL Advanced Audio Agent)"
+HOMEPAGE = "https://git.automotivelinux.org/src/4a-hal-configs/"
+SECTION = "apps"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=86d3f3a95c324c9479bd8986968f4327"
+
+SRC_URI = "gitsm://gerrit.automotivelinux.org/gerrit/src/4a-hal-configs;protocol=https;branch=${AGL_BRANCH}"
+SRCREV = "45f205076573a858348c10a52d31382f31deaf55"
+
+PV = "0.1+git${SRCPV}"
+S = "${WORKDIR}/git"
+
+# The package is machine-specific due to variable config content
+PACKAGE_ARCH = "${MACHINE_ARCH}"
+
+inherit afb-system update-alternative
+# This defines INSTALL_PREFIX = "/usr/libexec/agl/"
+
+# no configure needed
+do_configure[noexec] = "1"
+# no compile needed
+do_compile[noexec] = "1"
+
+
+# when no specific HAL is defined, use a generic usb one
+4A_DEFAULT_HAL ??= "2ch-generic-usb"
+
+# for specific machines, activate only known HAL
+4A_DEFAULT_HAL_m3ulcb ?= "rcar-m3"
+# Downside: only one file at a time!
+4A_DEFAULT_HAL_h3ulcb ?= "rcar-m3"
+4A_DEFAULT_HAL_intel-corei7-64 ?= "intel-minnow"
+4A_DEFAULT_HAL_qemux86-64 ?= "intel-qemu"
+
+# Due to bug SPEC-1610, default hal for RPI3 is not active yet
+# 4A_DEFAULT_HAL_raspberrypi3 ?= "raspberry-pi-3"
+
+do_install () {
+ # get pkgdir for 4a-hal
+ PKGDIR=${D}/${INSTALL_PREFIX}/4a-hal
+
+ install -d -m 0755 ${PKGDIR}/etc.available
+ cp -ar ${S}/*/*.json ${PKGDIR}/etc.available/
+ chown -R root:root ${PKGDIR}/
+}
+
+# we define a '4a-default-hal' alternative with a low default priority
+# you can deploy your own hal with a higher prio
+ALTERNATIVE_${PN} = "4a-default-hal"
+ALTERNATIVE_PRIORITY = "10"
+ALTERNATIVE_LINK_NAME[4a-default-hal] = "${INSTALL_PREFIX}/4a-hal/etc/4a-default-hal.json"
+ALTERNATIVE_TARGET[4a-default-hal] = "${INSTALL_PREFIX}/4a-hal/etc.available/hal-4a-${4A_DEFAULT_HAL}.json"
+
+
+RPROVIDES_${PN} += "virtual/4a-default-hal" \ No newline at end of file
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-device-config/4a-hal-device-config.README b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-device-config/4a-hal-device-config.README
new file mode 100644
index 00000000..602486a4
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-device-config/4a-hal-device-config.README
@@ -0,0 +1,4 @@
+To keep it simple.
+
+Just expose 4A_HAL_LIST as-is to conf/local.conf so the user can actually choose any json file.
+
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-device-config/4a-hal-device-config.bb b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-device-config/4a-hal-device-config.bb
new file mode 100644
index 00000000..e504c3da
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-device-config/4a-hal-device-config.bb
@@ -0,0 +1,58 @@
+SUMMARY = "4A - Generic HAL device configuration"
+DESCRIPTION = "Generic HAL device configuration in 4A (AGL Advanced Audio Agent)"
+HOMEPAGE = "https://git.automotivelinux.org/src/4a-hal-configs/"
+SECTION = "apps"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=86d3f3a95c324c9479bd8986968f4327"
+
+SRC_URI = "gitsm://gerrit.automotivelinux.org/gerrit/src/4a-hal-configs;protocol=https;branch=${AGL_BRANCH}"
+SRCREV = "fdf0e3c4c67ceb5ddc77c9c1f27d85c1be2055a6"
+
+PV = "0.1+git${SRCPV}"
+S = "${WORKDIR}/git"
+
+# The package is machine-specific due to variable config content
+PACKAGE_ARCH = "${MACHINE_ARCH}"
+
+inherit afb-system
+# This defines INSTALL_PREFIX = "/usr/libexec/agl/"
+
+# no configure needed
+do_configure[noexec] = "1"
+
+# no compile needed
+do_compile[noexec] = "1"
+
+# when no specific HAL is defined, use a generic usb one
+4A_HAL_LIST ??= "2ch-generic-usb"
+
+# for specific machines, activate only known HALs
+4A_HAL_LIST_m3ulcb ?= "rcar-m3 rcar-m3kf"
+4A_HAL_LIST_h3ulcb ?= "rcar-m3 rcar-m3kf"
+4A_HAL_LIST_intel-corei7-64 ?= "intel-minnow intel-upsquared-hdmi"
+4A_HAL_LIST_qemux86-64 ?= "intel-qemu"
+
+# Due to bug SPEC-1610, default hal for RPI3 is not active yet
+# 4A_HAL_LIST_raspberrypi3 ?= "raspberry-pi-3"
+
+do_install () {
+
+ # get pkgdir for 4a-hal
+ PKGDIR=${D}/${INSTALL_PREFIX}/4a-hal
+
+ install -d -m 0755 ${PKGDIR}
+ install -d -m 0755 ${PKGDIR}/etc
+ install -d -m 0755 ${PKGDIR}/etc.available
+
+ cp -ar ${S}/*/*.json ${PKGDIR}/etc.available/
+ chown -R root:root ${PKGDIR}/etc.available
+
+ for x in ${4A_HAL_LIST}; do
+ hal=hal-4a-$x.json
+ cp -v $PKGDIR/etc.available/${hal} $PKGDIR/etc/
+ done
+}
+
+
+RPROVIDES_${PN} += "virtual/4a-default-hal"
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-device-config/4a-hal-vendor-config.README b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-device-config/4a-hal-vendor-config.README
new file mode 100644
index 00000000..29531ccd
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-device-config/4a-hal-vendor-config.README
@@ -0,0 +1,3 @@
+This is a sample how a vendor can:
+- inject his own hal (as file hal-4a-myhal.json)
+- set PREFERRED_RPROVIDER_virtual/4a-default-hal = "4a-hal-vendor-config" on conf/local.conf
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-device-config/4a-hal-vendor-config.bbexample b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-device-config/4a-hal-vendor-config.bbexample
new file mode 100644
index 00000000..105ab1fa
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-device-config/4a-hal-vendor-config.bbexample
@@ -0,0 +1,46 @@
+SUMMARY = "4A - Vendor HAL device configuration"
+DESCRIPTION = "Vendor HAL device configuration in 4A (AGL Advanced Audio Agent)"
+HOMEPAGE = "https://example.com/"
+SECTION = "apps"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=86d3f3a95c324c9479bd8986968f4327"
+
+SRC_URI = "file://hal-4a-myhal.json"
+
+PV = "0.1"
+S = "${WORKDIR}/"
+
+# The package is machine-specific due to variable config content
+PACKAGE_ARCH = "${MACHINE_ARCH}"
+
+inherit afb-system
+# This defines INSTALL_PREFIX = "/usr/libexec/agl/"
+
+# no configure needed
+do_configure[noexec] = "1"
+
+# no compile needed
+do_compile[noexec] = "1"
+
+# use our local hal
+4A_HAL_LIST = "myhal"
+
+do_install () {
+
+ # get pkgdir for 4a-hal
+ PKGDIR=${D}/${INSTALL_PREFIX}/4a-hal
+
+ install -d -m 0755 ${PKGDIR}/etc.available
+
+ cp -ar ${S}/*.json ${PKGDIR}/etc.available/
+ chown -R root:root ${PKGDIR}/etc.available
+
+ for x in ${4A_HAL_LIST}; do
+ hal=hal-4a-$x.json
+ cp -v $PKGDIR/etc.available/${hal} $PKGDIR/etc/
+ done
+}
+
+
+RPROVIDES_${PN} += "virtual/4a-default-hal" \ No newline at end of file
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-device-config/files/deploy-hal-udev.sh b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-device-config/files/deploy-hal-udev.sh
new file mode 100755
index 00000000..f031d58b
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-device-config/files/deploy-hal-udev.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+rm /usr/libexec/agl/4a-hal/etc/*
+cp /usr/libexec/agl/4a-hal/etc.available/$i /usr/libexec/agl/4a-hal/etc/
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-device-config/files/udev-sample-rule.rules b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-device-config/files/udev-sample-rule.rules
new file mode 100644
index 00000000..d2d16a17
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-device-config/files/udev-sample-rule.rules
@@ -0,0 +1 @@
+ACTION=="add", SUBSYSTEM=="usb", SOMEOTHERMATCH="bar", RUN+="/usr/bin/deploy-hal-udev.sh hal-4a-greenbox.json"
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-generic/4a-hal-generic_git.bb b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-generic/4a-hal-generic_git.bb
new file mode 100644
index 00000000..8b20b83d
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-generic/4a-hal-generic_git.bb
@@ -0,0 +1,30 @@
+SUMMARY = "4A - Generic HAL"
+DESCRIPTION = "Generic HAL in 4A (AGL Advanced Audio Agent)"
+HOMEPAGE = "https://git.automotivelinux.org/src/4a-hal-generic/"
+SECTION = "apps"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=86d3f3a95c324c9479bd8986968f4327"
+
+SRC_URI = "gitsm://gerrit.automotivelinux.org/gerrit/src/4a-hal-generic;protocol=https;branch=${AGL_BRANCH}"
+SRCREV = "0c4921b83a13bcb96bf03fb0e7a0733c3e202474"
+
+DEPENDS += "lua bluez-alsa liburcu libafb-helpers libappcontroller"
+
+PV = "0.1+git${SRCPV}"
+S = "${WORKDIR}/git"
+
+inherit afb-system-cmake
+
+# FIXME: Remove once CMake+ninja issues are resolved
+OECMAKE_GENERATOR = "Unix Makefiles"
+
+do_install_append () {
+ # get pkgdir - note that '4a-hal' comes from project ${project_git_repo}/conf.d/cmake/config.cmake
+ PKGDIR=${D}/${INSTALL_PREFIX}/4a-hal
+
+ # transition: provided by separate package
+ rm -rf $PKGDIR/etc
+}
+
+RDEPENDS_${PN} += "virtual/4a-default-hal bluez-alsa"
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-unicens/4a-hal-unicens_git.bb b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-unicens/4a-hal-unicens_git.bb
new file mode 100644
index 00000000..058d20bb
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-hal-unicens/4a-hal-unicens_git.bb
@@ -0,0 +1,32 @@
+SUMMARY = "4A - Unicens (MOST) Binding"
+DESCRIPTION = "Unicens binding (MOST audio network support) for 4A (AGL Advanced Audio Agent)"
+HOMEPAGE = "https://git.automotivelinux.org/src/4a-hal-unicens/"
+SECTION = "apps"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e385f6075dcdf3ad6ff0056fca58a129"
+
+DEPENDS += "lua libafb-helpers libappcontroller"
+
+SRC_URI = "gitsm://gerrit.automotivelinux.org/gerrit/src/4a-hal-unicens;protocol=https;branch=${AGL_BRANCH}"
+SRCREV = "9228c9da5b85f0fdd6b01f0309e57b846618be63"
+
+
+PV = "0.1+git${SRCPV}"
+S = "${WORKDIR}/git"
+
+inherit afb-system-cmake
+
+# FIXME: Remove once CMake+ninja issues are resolved
+OECMAKE_GENERATOR = "Unix Makefiles"
+
+do_install_append () {
+ # installation folder for this plugin is '4a-hal'
+ # get pkgdir - note that '4a-hal' comes from project ${project_git_repo}/conf.d/cmake/config.cmake
+ PKGDIR=${D}/${INSTALL_PREFIX}/4a-hal
+
+ # transition: provided by separate package
+ rm -rf $PKGDIR/etc
+}
+
+
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-softmixer/4a-softmixer_git.bb b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-softmixer/4a-softmixer_git.bb
new file mode 100644
index 00000000..908809b6
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-softmixer/4a-softmixer_git.bb
@@ -0,0 +1,25 @@
+SUMMARY = "4A - Softmixer"
+DESCRIPTION = "4A Softmixer (AGL Advanced Audio Agent)"
+HOMEPAGE = "https://git.automotivelinux.org/src/4a-softmixer/"
+SECTION = "apps"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=86d3f3a95c324c9479bd8986968f4327"
+
+SRC_URI = "gitsm://gerrit.automotivelinux.org/gerrit/src/4a-softmixer.git;protocol=https;branch=${AGL_BRANCH}"
+SRCREV = "1a75612274f883aed09d198575582abdc0c9fe0f"
+
+DEPENDS += "lua liburcu libafb-helpers libappcontroller libavirt"
+
+PV = "0.1+git${SRCPV}"
+S = "${WORKDIR}/git"
+
+inherit afb-system-cmake
+
+# FIXME: Remove once CMake+ninja issues are resolved
+OECMAKE_GENERATOR = "Unix Makefiles"
+
+#FIXME :
+#FILES_${PN}-dev += "${INSTALL_PREFIX}/4a-softmixer/htdocs"
+#FILES_${PN} += "${INSTALL_PREFIX}/afb-aaaa"
+#FILES_${PN} += "${INSTALL_PREFIX}/lib"
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-tools/4a-tools_git.bb b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-tools/4a-tools_git.bb
new file mode 100644
index 00000000..ae1117ad
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/4a-tools/4a-tools_git.bb
@@ -0,0 +1,22 @@
+SUMMARY = "4A - Tools"
+DESCRIPTION = "Tools, utilities, scripts and data related to 4A"
+HOMEPAGE = "https://github.com/iotbzh/4a-tools/"
+SECTION = "apps"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=86d3f3a95c324c9479bd8986968f4327"
+
+SRC_URI = "gitsm://github.com/iotbzh/4a-tools;protocol=https;branch=${AGL_BRANCH}"
+SRCREV = "flounder_5.99.2"
+#SRCREV = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+
+PV = "0.1+git${SRCPV}"
+S = "${WORKDIR}/git"
+
+
+do_install() {
+ oe_runmake install DESTDIR=${D}${prefix}
+}
+
+RDEPENDS_${PN} += "bash python3-websockets"
+FILES_${PN} += "${datadir}/4a/media/*"
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/agl-service-audio-4a/agl-service-audio-4a_git.bb b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/agl-service-audio-4a/agl-service-audio-4a_git.bb
new file mode 100644
index 00000000..014fe119
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/agl-service-audio-4a/agl-service-audio-4a_git.bb
@@ -0,0 +1,58 @@
+SUMMARY = "4A - High Level Audio API Service"
+DESCRIPTION = "High Level Audio API service used in 4A (AGL Advanced Audio Agent)"
+HOMEPAGE = "https://git.automotivelinux.org/apps/agl-service-audio-4a/"
+SECTION = "apps"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
+
+SRC_URI = "git://gerrit.automotivelinux.org/gerrit/apps/agl-service-audio-4a;protocol=https;branch=${AGL_BRANCH}"
+SRCREV = "${AGL_APP_REVISION}"
+
+PV = "0.1+git${SRCPV}"
+S = "${WORKDIR}/git"
+
+inherit cmake aglwgt pkgconfig
+
+DEPENDS += "alsa-lib json-c systemd af-binder glib-2.0 lua libappcontroller"
+
+do_aglwgt_deploy_append() {
+ cat <<'EOF' >${D}/${sysconfdir}/agl-postinsts/99_4A_service_patch.sh
+N=600
+svcfile="/usr/local/lib/systemd/*/afm-service-agl-service-audio-4a*.service"
+set -x
+echo "-- TMP 4A INSTALL FIX from meta-agl/meta-app-framework/recipes-multimedia/agl-service-audio-4a/agl-service-audio-4a_git.bb - MUST BE REMOVED !!!"
+while ! ls $svcfile > /dev/null; do
+ if [ $N = 0 ]; then echo "-- TMP 4A INSTALL NOT FIXED"; exit 0; fi
+ echo .
+ sleep 0.2
+ N=$(expr $N - 1)
+done
+sed -i '/\[Unit\]/ a Before=pulseaudio.service' $svcfile;
+sed -i '/\[Unit\]/ a ConditionPathExistsGlob=/dev/snd/control*' $svcfile;
+sed -i '/ExecStartPre=/ a Environment=LIBASOUND_THREAD_SAFE=0' $svcfile;
+
+sed -i -e 's|/usr/bin/afb-daemon\>|& --ldpath=/usr/libexec/agl/4a-alsa-core/lib:/usr/libexec/agl/4a-hal/lib:/usr/libexec/agl/smixer/lib|' $svcfile
+
+# binder name matters: it must match "afbd-4a-*" => the config file (controller json file) that will be searched will be "policy-4a-*.json"
+sed -i -e 's|--name afbd-agl-\(.*\)|--name afbd-4a-\1|' $svcfile
+
+# workaround for SPEC-1762
+sed -i -e 's|/usr/bin/afb-daemon\>|/usr/bin/4a_wait_bt.sh &|' $svcfile
+
+echo "-- TMP 4A INSTALL FIX END"
+
+EOF
+ chmod a+x ${D}/${sysconfdir}/agl-postinsts/99_4A_service_patch.sh
+}
+
+##############################################
+# workaround for SPEC-1762/SPEC-1763
+RDEPENDS_${PN} += "bash"
+SRC_URI += "file://4a_wait_bt.sh"
+do_install_append() {
+ install -d ${D}${bindir}
+ install -m 0755 ${WORKDIR}/4a_wait_bt.sh ${D}${bindir}/
+}
+#
+##############################################
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/agl-service-audio-4a/files/4a_wait_bt.sh b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/agl-service-audio-4a/files/4a_wait_bt.sh
new file mode 100755
index 00000000..9dec4350
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/agl-service-audio-4a/files/4a_wait_bt.sh
@@ -0,0 +1,83 @@
+#!/bin/bash
+
+###############################################################
+# This is a workaround for SPEC-1762/SPEC-1763
+#
+# THIS SCRIPT MUST BE REMOVED ONCE THE ABOVE ISSUES ARE SOLVED
+#
+# Source recipe is:
+#
+# meta-audio-4a-framework/
+# recipes-multimedia/
+# agl-service-audio-4a/
+# agl-service-audio-4a_git.bb
+#
+# Signed-off-by: Stephane Desneux <stephane.desneux@iot.bzh>
+###############################################################
+
+# time from script startup
+LIMIT=20
+ts0=0
+function ts() { echo $(( $(date +%s) - ts0 )); }
+ts0=$(ts)
+function havetime() { [[ $(ts) -le ${1:-$LIMIT} ]] || return 1; }
+
+function waitloop() {
+ # ensure bt modules are loaded (delay: 5s)
+ while havetime 4; do
+ [[ -d /sys/module/bluetooth ]] && {
+ echo "bluetooth kernel module detected"
+ break
+ }
+ echo "waiting for bluetooth kernel module to be up"
+ sleep 0.2
+ done
+ havetime 4 || { echo "TIMEOUT REACHED"; return 1; }
+
+ # check that we have at least one controller
+ HCIDEV=
+ while havetime 8; do
+ echo "detecting hci devices..."
+ for x in $(ls /sys/class/bluetooth/hci* 2>/dev/null); do
+ [[ -z "$HCIDEV" ]] && HCIDEV=$(basename $x)
+ done
+ [[ -n "$HCIDEV" ]] && {
+ echo "found HCI controller: $HCIDEV"
+ break
+ }
+ sleep 0.2
+ done
+ havetime 8 || { echo "TIMEOUT REACHED"; return 1; }
+
+ # wait for controller to be up and running
+ while havetime 15; do
+ state=$(hciconfig $HCIDEV | grep -A 2 ^hci0 | tail -1)
+ [[ $state =~ UP ]] && [[ $state =~ RUNNING ]] && {
+ echo "HCI controller $HCIDEV state: $state"
+ break
+ }
+ echo "HCI controller $HCIDEV state: $state ... waiting for UP RUNNING"
+ sleep 0.2
+ done
+ havetime 15 || { echo "TIMEOUT REACHED"; return 1; }
+ echo "HCI device up and running after $(ts) seconds"
+
+ # wait for bluetooth-service to return something
+ while havetime; do
+ res=$(afb-client-demo -d unix:/run/user/$UID/apis/ws/Bluetooth-Manager adapter_state true)
+ [[ "$res" =~ \"response\":(.*)}$ ]] && res=${BASH_REMATCH[1]}
+ [[ "$res" =~ \"powered\":true ]] && {
+ echo "Bluetooth-Manager/power: $res"
+ break
+ }
+ echo "Bluetooth-Manager/power: not ready yet ($res)"
+ sleep 0.2
+ done
+ echo "Bluetooth-Manager ready after $(ts) seconds"
+
+ echo "4A now starting..."
+}
+
+waitloop 2>&1 | sed 's/^/4AWAITBT /' >&2
+exec "$@"
+
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/alsa/alsa-plugins_%.bbappend b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/alsa/alsa-plugins_%.bbappend
new file mode 100644
index 00000000..5109a314
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/alsa/alsa-plugins_%.bbappend
@@ -0,0 +1,7 @@
+# Remove PulseAudio plugin configuration files
+
+do_install_append() {
+ rm -f ${D}${datadir}/alsa/alsa.conf.d/*pulseaudio*
+}
+
+FILES_${PN}-pulseaudio-conf = "${datadir}/alsa/alsa.conf.d"
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/libavirt/libavirt_git.bb b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/libavirt/libavirt_git.bb
new file mode 100644
index 00000000..6d224e4e
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/libavirt/libavirt_git.bb
@@ -0,0 +1,19 @@
+SUMMARY = "AVIRT user-space library"
+DESCRIPTION = "ALSA Virtual Dynamic Sound Driver (AVIRT) user-space library for dynamic sound stream creation."
+HOMEPAGE = "https://git.automotivelinux.org/src/libavirt/"
+SECTION = "libs/multimedia"
+
+LICENSE = "GPL-2.0"
+LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6"
+
+SRC_URI = "git://gerrit.automotivelinux.org/gerrit/src/libavirt;protocol=https;branch=${AGL_BRANCH}"
+SRCREV = "379ea3c132f53eb6f5cf26d1c8a5ca335eb32a2e"
+
+PV = "0.1+git${SRCPV}"
+S = "${WORKDIR}/git"
+
+DEPENDS = "alsa-lib"
+
+inherit cmake
+
+ALLOW_EMPTY_${PN} = "1"
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/pulseaudio/files/default.pa.4a b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/pulseaudio/files/default.pa.4a
new file mode 100644
index 00000000..0efdacc2
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/pulseaudio/files/default.pa.4a
@@ -0,0 +1,77 @@
+#!/usr/bin/pulseaudio -nF
+#
+# This file is part of PulseAudio.
+#
+# 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 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, see <http://www.gnu.org/licenses/>.
+
+# This startup script is used only if PulseAudio is started per-user
+# (i.e. not in system mode)
+
+.fail
+
+### Automatically augment property information from .desktop files
+### stored in /usr/share/application
+load-module module-augment-properties
+
+### Load several protocols
+.ifexists module-esound-protocol-unix.so
+load-module module-esound-protocol-unix
+.endif
+load-module module-native-protocol-unix
+
+### Network access (may be configured with paprefs, so leave this commented
+### here if you plan to use paprefs)
+#load-module module-esound-protocol-tcp
+#load-module module-native-protocol-tcp
+
+### Load the RTP receiver module (also configured via paprefs, see above)
+#load-module module-rtp-recv
+
+### Load the RTP sender module (also configured via paprefs, see above)
+#load-module module-null-sink sink_name=rtp format=s16be channels=2 rate=44100 sink_properties="device.description='RTP Multicast Sink'"
+#load-module module-rtp-send source=rtp.monitor
+
+.ifexists module-4a-client.so
+load-module module-null-sink sink_name=aaaa_null_sink sink_properties="device.description='4A Null Output'"
+set-default-sink aaaa_null_sink
+load-module module-4a-client
+.else
+load-module module-udev-detect
+.endif
+
+### Automatically move streams to the default sink if the sink they are
+### connected to dies, similar for sources
+load-module module-rescue-streams
+
+### Make sure we always have a sink around, even if it is a null sink.
+load-module module-always-sink
+
+### Automatically suspend sinks/sources that become idle for too long
+load-module module-suspend-on-idle
+
+### If autoexit on idle is enabled we want to make sure we only quit
+### when no local session needs us anymore.
+.ifexists module-console-kit.so
+load-module module-console-kit
+.endif
+.ifexists module-systemd-login.so
+load-module module-systemd-login
+.endif
+
+### Modules to allow autoloading of filters (such as echo cancellation)
+### on demand. module-filter-heuristics tries to determine what filters
+### make sense, and module-filter-apply does the heavy-lifting of
+### loading modules and rerouting streams.
+load-module module-filter-heuristics
+load-module module-filter-apply
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/pulseaudio/pulseaudio-module-4a-client_git.bb b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/pulseaudio/pulseaudio-module-4a-client_git.bb
new file mode 100644
index 00000000..b5e9e011
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/pulseaudio/pulseaudio-module-4a-client_git.bb
@@ -0,0 +1,20 @@
+SUMMARY = "pulseaudio 4A client module"
+DESCRIPTION = "pulseaudio module to work with 4A (AGL Advanced Audio Agent)"
+HOMEPAGE = "https://git.automotivelinux.org/src/pulseaudio-module-4a"
+SECTION = "plugins"
+
+LICENSE = "LGPL-2.1+"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=4fbd65380cdd255951079008b364516c"
+
+SRC_URI = "gitsm://gerrit.automotivelinux.org/gerrit/src/pulseaudio-module-4a.git;protocol=https;branch=${AGL_BRANCH}"
+SRCREV = "9cd72ed153f6615ed826b048e1c344bf4640bd2b"
+
+PV = "0.1+git${SRCPV}"
+S = "${WORKDIR}/git"
+
+inherit cmake pkgconfig
+
+DEPENDS += "af-binder systemd json-c pulseaudio"
+RDEPENDS_${PN} = "pulseaudio-module-alsa-sink"
+
+FILES_${PN} += "${libdir}/pulse-*/modules/module-4a-client.so"
diff --git a/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/pulseaudio/pulseaudio_%.bbappend b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/pulseaudio/pulseaudio_%.bbappend
new file mode 100644
index 00000000..d8a84990
--- /dev/null
+++ b/meta-agl-devel/ATTIC/meta-audio-4a-framework/recipes-multimedia/pulseaudio/pulseaudio_%.bbappend
@@ -0,0 +1,7 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
+
+SRC_URI += "file://default.pa.4a"
+
+do_install_append () {
+ cp ${WORKDIR}/default.pa.4a ${D}${sysconfdir}/pulse/default.pa
+}
diff --git a/meta-agl-devel/README.md b/meta-agl-devel/README.md
new file mode 100644
index 00000000..1a5b4861
--- /dev/null
+++ b/meta-agl-devel/README.md
@@ -0,0 +1,86 @@
+meta-agl-devel layer
+======================================================
+
+The meta-agl-devel layer is intended to contain components that are under
+testing/development or software packages that OEMs need but to not exist
+in AGL.
+
+Here below you can find more information about the components of this layer.
+
+Virtualization support (meta-egvirt)
+======================================================
+
+meta-egvirt is the Virtualization Expert Group (EG-VIRT) layer, targeting to enable
+virtualization support in AGL.
+
+For more information, see the README.md file included in the layer, or alternatively
+visit the EG\_VIRT wiki page at: https://wiki.automotivelinux.org/eg-virt
+
+The OEM needs library for AGL
+======================================================
+
+There are some software package that the OEM needs, but not exist in the AGL source.
+This layer is add OEM needs library for AGL.
+
+The software packages list:
+ * boost
+ * fixesproto
+ * imagemagick
+ * iptables
+ * Xorg-macros
+ * zlib
+ * eglibc = glibc
+ * libcurl
+ * libgif
+ * libneon
+ * mongoose
+ * fuse
+ * protocol buffers
+ * bsdiff
+ * module-init-tools
+ * libcroco
+ * libtiff
+ * librsvg
+ * libpcap
+
+Quick start guide
+-----------------
+To Add these library by add the feature 'agl-oem-extra-libs'
+
+1. Before build you need prepare agl layers:
+ * You can read it at meta-agl/README-AGL.md
+
+2. build the agl-demo-platform with 'agl-oem-extra-libs':
+
+```bash
+source meta-agl/scripts/aglsetup.sh -m qemux86-64 agl-demo [agl-appfw-smack] [agl-devel] [agl-netboot] agl-oem-extra-libs
+```
+
+3. Build agl-demo-platform
+
+```bash
+bitbake agl-demo-platform
+```
+
+Supported Machines
+------------------
+
+Reference hardware:
+
+* QEMU (x86-64) - emulated machine: qemux86-64
+
+HMI Framework
+======================================================
+Quick start guide
+-----------------
+To Add HMI Framework, it is necessary to add 'hmi-framework' at source command as same as agl-oem-extra-libs
+
+1. Before build you need prepare agl layers:
+ * You can read it at meta-agl/README-AGL.md
+
+2. build the agl-demo-platform with 'hmi-framework':
+
+```bash
+source meta-agl/scripts/aglsetup.sh -m m3ulcb agl-demo [agl-appfw-smack] [agl-devel] [agl-netboot] hmi-framework
+```
+
diff --git a/meta-agl-devel/docs/devguides-book.yml b/meta-agl-devel/docs/devguides-book.yml
new file mode 100644
index 00000000..e7a44b3b
--- /dev/null
+++ b/meta-agl-devel/docs/devguides-book.yml
@@ -0,0 +1,13 @@
+type: books
+books:
+-
+ id: meta-agl-devel
+ title: Meta AGL Devel
+ description: Meta AGL Devel documentation
+ keywords:
+ author: "AGL"
+ version: master
+ chapters:
+ - url: ../meta-agl-devel.md
+ destination: meta-agl-devel.md
+ name: meta-agl-devel
diff --git a/meta-agl-devel/meta-agl-devel.md b/meta-agl-devel/meta-agl-devel.md
new file mode 100755
index 00000000..473a4fe5
--- /dev/null
+++ b/meta-agl-devel/meta-agl-devel.md
@@ -0,0 +1,139 @@
+## Introduction
+
+The `meta-agl-devel` layer contains components that are being tested or
+still in development.
+The layer also contains software packages that Original Equipment
+Manufacturers (OEMs) need but are not included in the AGL software.
+
+## Sub-Layers
+
+The `meta-agl-devel` layer contains the following files and sub-layers:
+
+```
+.
+├── meta-agl-telemetry
+├── meta-audio-4a-framework
+├── meta-audio-soundmanager-framework
+├── meta-egvirt
+├── meta-gstrecorder-rcar-gen3
+├── meta-hmi-framework
+├── meta-oem-extra-libs
+├── README.md
+├── templates
+```
+
+The following list provides a summary of these sub-layers:
+
+* `meta-agl-telemetry`: Provides the smallest AGL image.
+ The image is designed to be used when a device requires restricted
+ scope of responsibilites (e.g. collecting vehicle telemetry).
+
+* `meta-audio-4a-framework`: A collection of recipes used for the
+ first integration of 4A (i.e. Advanced AGL Audio Architecture).
+
+* `meta-pipewire`: A collection of recipes used for the integration
+ of the pipewire sound system.
+
+* `meta-audio-soundmanager-framework`: Supports the Soundmanager
+ Audio Framework features, which maps to the `agl-audio-soundmanager-framework`
+ AGL feature.
+
+* `meta-egvirt`: The AGL Virtualization Expert Group (EG-VIRT) layer.
+ This layer supports the design, test, implementation, and assessment
+ of virtualization technologies (e.g. containers, hypervisors, system
+ partitioners, and so forth) aimed at AGL ARMv8 and Intel platforms.
+
+* `meta-gstrecorder-rcar-gen3`: Supports streaming audio and video for
+ the Pro and Premier board kits (e.g.
+ [Renesas R-Car Starter Kit Pro Board](https://www.elinux.org/R-Car/Boards/M3SK)
+ and
+ [Renesas R-Car Starter Kit Premier Board](https://www.elinux.org/R-Car/Boards/H3SK)).
+
+* `meta-hmi-framework`: Provides AGL's Human Machine Interface (HMI) framework
+ through resource management consisting of sounds, windows, and input control.
+ For more information, see the
+ [HMI-Framework Page](https://wiki.automotivelinux.org/hmiframework) of the
+ AGL Wiki.
+
+* `meta-oem-extra-libs`: Provides libraries and software packages needed by
+ OEMs but not provided by the AGL software.
+
+* `templates`: Feature templates that support the `meta-agl-devel` layer.
+
+## Additional Sub-Layer Information
+
+This section provides additional information for the `meta-egvirt`,
+`meta-oem-extra-libs`, and `meta-hmi-framework` layers.
+
+### Virtualization Support
+
+The `meta-egvirt` layer enables virtualization support in AGL.
+The AGL Virtualization Expert (EG-VIRT) group is responsible
+for design and implementation of AGL virtualization solutions
+(.e.g the Virtualization platform architecture of AGL).
+You can read about EG-VERT's efforts on the
+"[Virtualization Expert Group's](https://wiki.automotivelinux.org/eg-virt)"
+page of the AGL wiki.
+
+Additionally, you can learn more about virtualization as it applies to AGL
+by reading
+"[The Automotive Grade Linux Software Defined Connected Car Architecture](https://www.automotivelinux.org/wp-content/uploads/sites/4/2018/06/agl_software_defined_car_jun18.pdf)"
+whitepaper.
+
+### OEM Extra Libraries
+
+The `meta-oem-extra-libs` layer provides additional software packages many OEMs need
+but are not part of the AGL source.
+Following is the list of packages this layer provides:
+
+ * boost
+ * fixesproto
+ * imagemagick
+ * iptables
+ * Xorg-macros
+ * zlib
+ * eglibc = glibc
+ * libcurl
+ * libgif
+ * libneon
+ * mongoose
+ * fuse
+ * protocol buffers
+ * bsdiff
+ * module-init-tools
+ * libcroco
+ * libtiff
+ * librsvg
+ * libpcap
+
+To add these packages to your library, you need to include the
+`agl-oem-extra-libs` AGL feature when you initialize your build
+environment using the `aglsetup.sh` script.
+
+For information on how to use the `aglsetup.sh` script to initialize
+your build environment, see the
+"[Initializing Your Build Environment](../getting_started/reference/getting-started/image-workflow-initialize-build-environment.html)"
+section.
+
+Once you have included the AGL feature, you can build your image.
+
+### HMI Framework
+
+The `meta-hmi-framework` layer supports the Human-Machine Interface (HMI) Framework.
+The HMI-Framework is the User Interface (UI) to control the Infotainment System.
+Work continues to close the gap between the user experience of a smart phone
+and the Infotainment System in a vehicle, for example.
+
+You can find more out about HMI Framework progress on the
+"[HMI Framework](https://wiki.automotivelinux.org/hmiframework)" page on the AGL Wiki.
+
+To add HMI Framework support to your image, you need to include the
+`hmi-framework` AGL feature when you initialize your build
+environment using the `aglsetup.sh` script.
+
+For information on how to use the `aglsetup.sh` script to initialize
+your build environment, see the
+"[Initializing Your Build Environment](../getting_started/reference/getting-started/image-workflow-initialize-build-environment.html)"
+section.
+
+Once you have included the AGL feature, you can build your image.
diff --git a/meta-agl-devel/meta-audio-soundmanager-framework/COPYING.MIT b/meta-agl-devel/meta-audio-soundmanager-framework/COPYING.MIT
new file mode 100644
index 00000000..89de3547
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/COPYING.MIT
@@ -0,0 +1,17 @@
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/meta-agl-devel/meta-audio-soundmanager-framework/README.md b/meta-agl-devel/meta-audio-soundmanager-framework/README.md
new file mode 100644
index 00000000..751a3c2d
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/README.md
@@ -0,0 +1,18 @@
+This README file contains information on the contents of the
+soundmanager layer.
+
+Please see the corresponding sections below for details.
+
+How to enable the framework
+=================
+In order to enable the soundmanager audio framework features,
+please add the feature of "agl-audio-soundmanager-framework"
+in the source command which enables bitbake.
+
+$ source meta-agl/scripts/aglsetup.sh -m <machine> agl-demo agl-audio-soundmanager-framework
+
+
+Reference
+=================
+http://docs.automotivelinux.org/docs/apis_services/en/dev/reference/hmi-framework/3_3-SoundManager-Guide.html
+
diff --git a/meta-agl-devel/meta-audio-soundmanager-framework/conf/layer.conf b/meta-agl-devel/meta-audio-soundmanager-framework/conf/layer.conf
new file mode 100644
index 00000000..121a1f13
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/conf/layer.conf
@@ -0,0 +1,12 @@
+# 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 += "audio-soundmanager-framework"
+BBFILE_PATTERN_audio-soundmanager-framework = "^${LAYERDIR}/"
+BBFILE_PRIORITY_audio-soundmanager-framework = "6"
+
+LAYERSERIES_COMPAT_audio-soundmanager-framework = "thud"
diff --git a/meta-agl-devel/meta-audio-soundmanager-framework/recipes-extended/dlt-daemon/dlt-daemon/0001-Fix-build-with-systemd-209.patch b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-extended/dlt-daemon/dlt-daemon/0001-Fix-build-with-systemd-209.patch
new file mode 100644
index 00000000..5bf6bf88
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/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?= <erik.boto@pelagicore.com>
+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ö <erik.boto@pelagicore.com>
+---
+ 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-devel/meta-audio-soundmanager-framework/recipes-extended/dlt-daemon/dlt-daemon/0002-Don-t-execute-processes-as-a-specific-user.patch b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-extended/dlt-daemon/dlt-daemon/0002-Don-t-execute-processes-as-a-specific-user.patch
new file mode 100644
index 00000000..16884799
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/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 <andrei.gherzan@windriver.com>
+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 <andrei.gherzan@windriver.com>
+---
+ 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-devel/meta-audio-soundmanager-framework/recipes-extended/dlt-daemon/dlt-daemon/0003-systemd-unit-type-should-be-in-lowercase-so-use-Type.patch b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-extended/dlt-daemon/dlt-daemon/0003-systemd-unit-type-should-be-in-lowercase-so-use-Type.patch
new file mode 100644
index 00000000..691a5002
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/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 <andrei.gherzan@windriver.com>
+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 <andrei.gherzan@windriver.com>
+---
+ 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-devel/meta-audio-soundmanager-framework/recipes-extended/dlt-daemon/dlt-daemon/0004-Modify-systemd-config-directory.patch b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-extended/dlt-daemon/dlt-daemon/0004-Modify-systemd-config-directory.patch
new file mode 100644
index 00000000..685dfcdd
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/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 <andrei.gherzan@windriver.com>
+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 <andrei.gherzan@windriver.com>
+---
+ 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-devel/meta-audio-soundmanager-framework/recipes-extended/dlt-daemon/dlt-daemon_2.11.1.bb b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-extended/dlt-daemon/dlt-daemon_2.11.1.bb
new file mode 100644
index 00000000..b521bca9
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/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-devel/meta-audio-soundmanager-framework/recipes-extended/dlt-daemon/dlt-daemon_2.15.0.bb b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-extended/dlt-daemon/dlt-daemon_2.15.0.bb
new file mode 100644
index 00000000..dbc87c9a
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/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-devel/meta-audio-soundmanager-framework/recipes-multimedia/agl-service-audio-soundmanager/agl-service-audio-soundmanager_1.0.bb b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/agl-service-audio-soundmanager/agl-service-audio-soundmanager_1.0.bb
new file mode 100644
index 00000000..a10e825e
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/agl-service-audio-soundmanager/agl-service-audio-soundmanager_1.0.bb
@@ -0,0 +1,20 @@
+SUMMARY = "Sound Manager binding"
+DESCRIPTION = "Sound Manager is the service binding to communicate \
+ with Genivi Audio Manager. Genivi Audio Manager is \
+ the policy manager for sound. It controls volume \
+ and routing according to various situations. \
+ "
+HOMEPAGE = "https://wiki.automotivelinux.org/soundmanager"
+SECTION = "multimedia"
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=ae6497158920d9524cf208c09cc4c984"
+
+DEPENDS = "dbus glib-2.0 af-binder json-c"
+RDEPENDS_${PN} = "audiomanager audiomanager-plugins"
+
+inherit cmake aglwgt
+
+SRC_URI = "git://gerrit.automotivelinux.org/gerrit/apps/agl-service-soundmanager;protocol=https;branch=${AGL_BRANCH}"
+SRCREV = "5106b9d03108792b2594b553e00c149945ac6f97"
+S = "${WORKDIR}/git"
+PV = "1.0+git${SRCPV}"
diff --git a/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config-soundmanager/audiomanager-plugins-config-soundmanager/amcp_dbus.conf b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config-soundmanager/audiomanager-plugins-config-soundmanager/amcp_dbus.conf
new file mode 100644
index 00000000..49544d5e
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config-soundmanager/audiomanager-plugins-config-soundmanager/amcp_dbus.conf
@@ -0,0 +1,20 @@
+<!-- This configuration file specifies the required security policies
+to use the audiomanager command d-bus plugin interface. -->
+
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+ <!-- ../system.conf have denied everything, so we just punch some holes -->
+ <policy user="root">
+ <allow own="org.genivi.audiomanager"/>
+ <allow own="org.genivi.audiomanager.command"/>
+ <allow send_destination="org.genivi.audiomanager"/>
+ <allow send_destination="org.genivi.audiomanager.command"/>
+ </policy>
+ <policy at_console="true">
+ <allow send_destination="org.genivi.audiomanager"/>
+ </policy>
+ <policy context="default">
+ <allow send_destination="org.genivi.audiomanager"/>
+ </policy>
+</busconfig>
diff --git a/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config-soundmanager/audiomanager-plugins-config-soundmanager/amrp_dbus.conf b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config-soundmanager/audiomanager-plugins-config-soundmanager/amrp_dbus.conf
new file mode 100644
index 00000000..6832d305
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config-soundmanager/audiomanager-plugins-config-soundmanager/amrp_dbus.conf
@@ -0,0 +1,21 @@
+<!-- This configuration file specifies the required security policies
+to use the audiomanager routing d-bus plugin interface. -->
+
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+ <!-- ../system.conf have denied everything, so we just punch some holes -->
+ <policy user="root">
+ <allow own="org.genivi.audiomanager"/>
+ <allow own="org.genivi.audiomanager.routing"/>
+ <allow send_destination="org.genivi.audiomanager"/>
+ <allow send_destination="org.genivi.audiomanager.routing"/>
+ </policy>
+ <policy at_console="true">
+ <allow send_destination="org.genivi.audiomanager"/>
+ </policy>
+ <policy context="default">
+ <allow send_destination="org.genivi.audiomanager"/>
+ </policy>
+</busconfig>
+
diff --git a/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config-soundmanager/audiomanager-plugins-config-soundmanager/configuration.xml b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config-soundmanager/audiomanager-plugins-config-soundmanager/configuration.xml
new file mode 100644
index 00000000..3dc69c12
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config-soundmanager/audiomanager-plugins-config-soundmanager/configuration.xml
@@ -0,0 +1,516 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<c:configuration xmlns:c="controller" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="controller audiomanagertypes.xsd ">
+ <listSources>
+ <source>
+ <id>0</id>
+ <domainName>UNKNOWN</domainName>
+ <name>SourceTemplate</name>
+ <volume>0</volume>
+ <visible>TRUE</visible>
+ <className>UNKNOWN</className>
+ <sourceState>SS_OFF</sourceState>
+ <connectionFormat>CF_GENIVI_STEREO</connectionFormat>
+ <connectionFormat>CF_GENIVI_MONO</connectionFormat>
+ <interruptState>IS_OFF</interruptState>
+ <availability>
+ <availability>A_AVAILABLE</availability>
+ <availabilityReason>AR_UNKNOWN</availabilityReason>
+ </availability>
+ <soundProperty>
+ <type>SP_GENIVI_TREBLE</type>
+ <value minValue="0" maxValue="10">5</value>
+ </soundProperty>
+ <soundProperty>
+ <type>SP_GENIVI_MID</type>
+ <value minValue="0" maxValue="10">5</value>
+ </soundProperty>
+ <soundProperty>
+ <type>SP_GENIVI_BASS</type>
+ <value minValue="0" maxValue="10">5</value>
+ </soundProperty>
+ <mainSoundProperty>
+ <type>MSP_GENIVI_TREBLE</type>
+ <value minValue="0" maxValue="10">5</value>
+ </mainSoundProperty>
+ <mainSoundProperty>
+ <type>MSP_GENIVI_MID</type>
+ <value minValue="0" maxValue="10">5</value>
+ </mainSoundProperty>
+ <mainSoundProperty>
+ <type>MSP_GENIVI_BASS</type>
+ <value minValue="0" maxValue="10">5</value>
+ </mainSoundProperty>
+ <registrationType>REG_TEMPLATE</registrationType>
+ <isVolumeSupported>TRUE</isVolumeSupported>
+ <priority>1</priority>
+ <listMainSoundPropertiesToSoundProperties>
+ <mapEntry>MSP_UNKNOWN,SP_UNKNOWN</mapEntry>
+ <mapEntry>MSP_GENIVI_TREBLE,SP_GENIVI_TREBLE</mapEntry>
+ </listMainSoundPropertiesToSoundProperties>
+ </source>
+ <source baseName="SourceTemplate">
+ <id>0</id>
+ <domainName>SoundManager</domainName>
+ <name>mediaplayer</name>
+ <className>BASE</className>
+ <registrationType>REG_ROUTER</registrationType>
+ </source>
+ <source baseName="SourceTemplate">
+ <id>2</id>
+ <domainName>SoundManager</domainName>
+ <name>ALSA#Playback</name>
+ <className>BASE</className>
+ <registrationType>REG_ROUTER</registrationType>
+ </source>
+ <source baseName="SourceTemplate">
+ <id>3</id>
+ <domainName>SoundManager</domainName>
+ <name>music</name>
+ <className>BASE</className>
+ <registrationType>REG_ROUTER</registrationType>
+ </source>
+ <source baseName="SourceTemplate">
+ <id>4</id>
+ <domainName>SoundManager</domainName>
+ <name>Navi</name>
+ <className>INT</className>
+ <registrationType>REG_ROUTER</registrationType>
+ </source>
+ <source baseName="SourceTemplate">
+ <id>5</id>
+ <domainName>SoundManager</domainName>
+ <name>phone</name>
+ <className>PHONE</className>
+ <registrationType>REG_ROUTER</registrationType>
+ </source>
+ <source baseName="SourceTemplate">
+ <id>0</id>
+ <domainName>SoundManager</domainName>
+ <name>radio</name>
+ <className>BASE</className>
+ <registrationType>REG_ROUTER</registrationType>
+ </source>
+ </listSources>
+ <listSinks>
+ <sink>
+ <id>0</id>
+ <domainName>UNKNOWN</domainName>
+ <name>SinkTemplate</name>
+ <volume>0</volume>
+ <visible>TRUE</visible>
+ <mainVolume>100</mainVolume>
+ <className>BASE</className>
+ <muteState>MS_UNMUTED</muteState>
+ <connectionFormat>CF_GENIVI_STEREO</connectionFormat>
+ <connectionFormat>CF_GENIVI_MONO</connectionFormat>
+ <availability>
+ <availability>A_AVAILABLE</availability>
+ <availabilityReason>AR_GENIVI_NEWMEDIA</availabilityReason>
+ </availability>
+ <soundProperty>
+ <type>SP_GENIVI_TREBLE</type>
+ <value minValue="0" maxValue="10">5</value>
+ </soundProperty>
+ <soundProperty>
+ <type>SP_GENIVI_MID</type>
+ <value minValue="0" maxValue="10">5</value>
+ </soundProperty>
+ <soundProperty>
+ <type>SP_GENIVI_BASS</type>
+ <value minValue="0" maxValue="10">5</value>
+ </soundProperty>
+ <mainSoundProperty>
+ <type>MSP_GENIVI_TREBLE</type>
+ <value minValue="0" maxValue="10">5</value>
+ </mainSoundProperty>
+ <mainSoundProperty>
+ <type>MSP_GENIVI_MID</type>
+ <value minValue="0" maxValue="10">5</value>
+ </mainSoundProperty>
+ <mainSoundProperty>
+ <type>MSP_GENIVI_BASS</type>
+ <value minValue="0" maxValue="10">5</value>
+ </mainSoundProperty>
+ <registrationType>REG_TEMPLATE</registrationType>
+ <isVolumeSupported>TRUE</isVolumeSupported>
+ <priority>1</priority>
+ <listMainVolumesToNormalizedVolumes>
+ <tableEntry>0,0.0</tableEntry>
+ <tableEntry>1,0.01</tableEntry>
+ <tableEntry>2,0.02</tableEntry>
+ <tableEntry>3,0.03</tableEntry>
+ <tableEntry>4,0.04</tableEntry>
+ <tableEntry>5,0.05</tableEntry>
+ <tableEntry>6,0.06</tableEntry>
+ <tableEntry>7,0.07</tableEntry>
+ <tableEntry>8,0.08</tableEntry>
+ <tableEntry>9,0.09</tableEntry>
+ <tableEntry>10,0.1</tableEntry>
+ <tableEntry>11,0.11</tableEntry>
+ <tableEntry>12,0.12</tableEntry>
+ <tableEntry>14,0.14</tableEntry>
+ <tableEntry>15,0.15</tableEntry>
+ <tableEntry>17,0.17</tableEntry>
+ <tableEntry>20,0.2</tableEntry>
+ <tableEntry>22,0.22</tableEntry>
+ <tableEntry>25,0.25</tableEntry>
+ <tableEntry>28,0.28</tableEntry>
+ <tableEntry>31,0.31</tableEntry>
+ <tableEntry>35,0.35</tableEntry>
+ <tableEntry>40,0.4</tableEntry>
+ <tableEntry>45,0.45</tableEntry>
+ <tableEntry>50,0.5</tableEntry>
+ <tableEntry>56,0.56</tableEntry>
+ <tableEntry>62,0.62</tableEntry>
+ <tableEntry>70,0.7</tableEntry>
+ <tableEntry>80,0.8</tableEntry>
+ <tableEntry>90,0.9</tableEntry>
+ <tableEntry>100,1.0</tableEntry>
+ </listMainVolumesToNormalizedVolumes>
+ <listNormalizedVolumesToDecibelVolumes>
+ <tableEntry>0.0,-192.0</tableEntry>
+ <tableEntry>0.01,-40.0</tableEntry>
+ <tableEntry>0.02,-34.0</tableEntry>
+ <tableEntry>0.03,-30.0</tableEntry>
+ <tableEntry>0.04,-27.0</tableEntry>
+ <tableEntry>0.05,-26.0</tableEntry>
+ <tableEntry>0.06,-24.0</tableEntry>
+ <tableEntry>0.07,-23.0</tableEntry>
+ <tableEntry>0.08,-22.0</tableEntry>
+ <tableEntry>0.09,-21.0</tableEntry>
+ <tableEntry>0.1,-20.0</tableEntry>
+ <tableEntry>0.11,-19.0</tableEntry>
+ <tableEntry>0.12,-18.0</tableEntry>
+ <tableEntry>0.14,-17.0</tableEntry>
+ <tableEntry>0.15,-16.0</tableEntry>
+ <tableEntry>0.17,-15.0</tableEntry>
+ <tableEntry>0.2,-14.0</tableEntry>
+ <tableEntry>0.22,-13.0</tableEntry>
+ <tableEntry>0.25,-12.0</tableEntry>
+ <tableEntry>0.28,-11.0</tableEntry>
+ <tableEntry>0.31,-10.0</tableEntry>
+ <tableEntry>0.35,-9.0</tableEntry>
+ <tableEntry>0.4,-8.0</tableEntry>
+ <tableEntry>0.45,-7.0</tableEntry>
+ <tableEntry>0.5,-6.0</tableEntry>
+ <tableEntry>0.56,-5.0</tableEntry>
+ <tableEntry>0.62,-4.0</tableEntry>
+ <tableEntry>0.7,-3.0</tableEntry>
+ <tableEntry>0.8,-2.0</tableEntry>
+ <tableEntry>0.9,-1.0</tableEntry>
+ <tableEntry>1.0,0.0</tableEntry>
+ </listNormalizedVolumesToDecibelVolumes>
+ <listMainSoundPropertiesToSoundProperties>
+ <mapEntry>MSP_UNKNOWN,SP_UNKNOWN</mapEntry>
+ <mapEntry>MSP_GENIVI_TREBLE,SP_GENIVI_TREBLE</mapEntry>
+ </listMainSoundPropertiesToSoundProperties>
+ </sink>
+ <sink baseName="SinkTemplate">
+ <id>1</id>
+ <domainName>SoundManager</domainName>
+ <name>rsnd-dai.0-ak4642-hifi#Analog#Stereo</name>
+ <className>BASE</className>
+ <registrationType>REG_CONTROLLER</registrationType>
+ </sink>
+ <sink baseName="SinkTemplate">
+ <id>2</id>
+ <domainName>SoundManager</domainName>
+ <name>Microchip#MOST:0#Multichannel</name>
+ <className>BASE</className>
+ <registrationType>REG_CONTROLLER</registrationType>
+ </sink>
+ </listSinks>
+ <listGateways>
+ <!-- This is a single domain example, therefore no gateway is present -->
+ </listGateways>
+ <listDomains>
+ <domain>
+ <id>0</id>
+ <name>SoundManager</name>
+ <busName>org.genivi.audiomanager</busName>
+ <nodeName>SoundManager</nodeName>
+ <early>FALSE</early>
+ <complete>TRUE</complete>
+ <state>DS_CONTROLLED</state>
+ <registrationType>REG_ROUTER</registrationType>
+ </domain>
+ </listDomains>
+ <listClasses>
+ <class>
+ <name>BASE</name>
+ <type>C_PLAYBACK</type>
+ <priority>1</priority>
+ <topology>Microchip#MOST:0#Multichannel^rsnd-dai.0-ak4642-hifi#Analog#Stereo=mediaplayer^music^ALSA#Playback^radio</topology>
+ </class>
+ <class>
+ <name>INT</name>
+ <type>C_PLAYBACK</type>
+ <priority>2</priority>
+ <topology>Microchip#MOST:0#Multichannel^rsnd-dai.0-ak4642-hifi#Analog#Stereo=Navi</topology>
+ </class>
+ <class>
+ <name>PHONE</name>
+ <type>C_PLAYBACK</type>
+ <priority>3</priority>
+ <topology>Microchip#MOST:0#Multichannel^rsnd-dai.0-ak4642-hifi#Analog#Stereo=phone</topology>
+ </class>
+ </listClasses>
+ <listPolicies>
+ <!--Connect Policy Start-->
+ <!--BASE Policy-->
+ <policy>
+ <trigger>USER_CONNECTION_REQUEST</trigger>
+ <process>
+ <condition>name(CLASS, REQUESTING) EQ "BASE"</condition>
+ <condition>connectionState(CONNECTIONOFCLASS, REQUESTING, OTHERS) INC CS_CONNECTED</condition>
+ <action>
+ <type>ACTION_DISCONNECT</type>
+ <param>
+ <className>"BASE"</className>
+ <connectionState>CS_CONNECTED</connectionState>
+ </param>
+ </action>
+ </process>
+ </policy>
+ <!--INT policy-->
+ <policy>
+ <trigger>USER_CONNECTION_REQUEST</trigger>
+ <process>
+ <condition>name(CLASS, REQUESTING) EQ "INT"</condition>
+ <action>
+ <type>ACTION_LIMIT</type>
+ <param>
+ <className>"BASE"</className>
+ <volume>-1000</volume>
+ <pattern>01</pattern>
+ </param>
+ </action>
+ </process>
+ <process>
+ <condition>name(CLASS, REQUESTING) EQ "INT"</condition>
+ <condition>connectionState(CONNECTIONOFCLASS, REQUESTING, OTHERS) INC CS_CONNECTED</condition>
+ <condition>priority(CONNECTIONOFCLASS, REQUESTING, OTHERS) LT priority(CONNECTION, REQUESTING)</condition>
+ <action>
+ <type>ACTION_PUSH</type>
+ <param>
+ <className>"INT"</className>
+ <order>O_NEWEST</order>
+ </param>
+ </action>
+ <break>TRUE</break>
+ </process>
+ <process>
+ <condition>name(CLASS, REQUESTING) EQ "INT"</condition>
+ <condition>connectionState(CONNECTIONOFCLASS, REQUESTING, OTHERS) INC CS_CONNECTED</condition>
+ <action>
+ <type>ACTION_PUSH</type>
+ <param>
+ <className>"INT"</className>
+ <order>O_OLDEST</order>
+ </param>
+ </action>
+ </process>
+ <process>
+ <condition>name(CLASS, REQUESTING) EQ "INT"</condition>
+ <condition>connectionState(CONNECTIONOFCLASS, "PHONE") INC CS_CONNECTED</condition>
+ <action>
+ <type>ACTION_MUTE</type>
+ <param>
+ <className>REQUESTING</className>
+ </param>
+ </action>
+ <action>
+ <type>ACTION_CONNECT</type>
+ <param>
+ <className>REQUESTING</className>
+ </param>
+ </action>
+ <break>TRUE</break>
+ </process>
+ </policy>
+ <!--PHONE policy-->
+ <policy>
+ <trigger>USER_CONNECTION_REQUEST</trigger>
+ <process>
+ <condition>name(CLASS, REQUESTING) EQ "PHONE"</condition>
+ <action>
+ <type>ACTION_LIMIT</type>
+ <param>
+ <className>"BASE"</className>
+ <volume>-1000</volume>
+ <pattern>02</pattern>
+ </param>
+ </action>
+ </process>
+ <process>
+ <condition>name(CLASS, REQUESTING) EQ "PHONE"</condition>
+ <condition>connectionState(CONNECTIONOFCLASS, "INT") INC CS_CONNECTED</condition>
+ <action>
+ <type>ACTION_MUTE</type>
+ <param>
+ <className>"INT"</className>
+ </param>
+ </action>
+ </process>
+ <process>
+ <condition>name(SINK, REQUESTING) EQ "AMP"</condition>
+ <action>
+ <type>ACTION_CONNECT</type>
+ <param>
+ <className>REQUESTING</className>
+ <timeOut>5000</timeOut>
+ </param>
+ </action>
+ <break>TRUE</break>
+ </process>
+ </policy>
+ <!--Connect policy end-->
+ <!--Disconnect policy start-->
+ <policy>
+ <trigger>USER_DISCONNECTION_REQUEST</trigger>
+ <process>
+ <action>
+ <type>ACTION_DISCONNECT</type>
+ <param>
+ <sourceName>REQUESTING</sourceName>
+ <sinkName>REQUESTING</sinkName>
+ </param>
+ </action>
+ </process>
+ <process>
+ <condition>name(CLASS, REQUESTING) EQ "INT"</condition>
+ <action>
+ <type>ACTION_UNLIMIT</type>
+ <param>
+ <className>"BASE"</className>
+ <pattern>01</pattern>
+ </param>
+ </action>
+ </process>
+ <process>
+ <condition>name(CLASS, REQUESTING) EQ "INT"</condition>
+ <condition>connectionState(CONNECTIONOFCLASS, REQUESTING, OTHERS) INC CS_CONNECTED</condition>
+ <action>
+ <type>ACTION_POP</type>
+ <param>
+ <className>"INT"</className>
+ <order>O_OLDEST</order>
+ </param>
+ </action>
+ </process>
+ <process>
+ <condition>name(CLASS, REQUESTING) EQ "PHONE"</condition>
+ <condition>connectionState(CONNECTIONOFCLASS, "INT") INC CS_CONNECTED</condition>
+ <action>
+ <type>ACTION_UNMUTE</type>
+ <param>
+ <className>"INT"</className>
+ </param>
+ </action>
+ </process>
+ <process>
+ <condition>name(CLASS, REQUESTING) EQ "PHONE"</condition>
+ <action>
+ <type>ACTION_UNLIMIT</type>
+ <param>
+ <className>"BASE"</className>
+ <pattern>02</pattern>
+ </param>
+ </action>
+ </process>
+ <process>
+ <condition>name(CLASS, REQUESTING) EQ "BASE"</condition>
+ <condition>connectionState(CONNECTIONOFCLASS, "BASE") INC CS_SUSPENDED</condition>
+ <action>
+ <type>ACTION_RESUME</type>
+ <param>
+ <className>"BASE"</className>
+ <connectionState>CS_SUSPENDED</connectionState>
+ </param>
+ </action>
+ </process>
+ </policy>
+ <!-- default volume policy start -->
+ <policy>
+ <trigger>USER_SET_VOLUME</trigger>
+ <process>
+ <action>
+ <type>ACTION_SET_VOLUME</type>
+ <param>
+ <sinkName>REQUESTING</sinkName>
+ </param>
+ </action>
+ </process>
+ </policy>
+ <!-- default volume policy end -->
+ <!-- default mute policy start -->
+ <policy>
+ <trigger>USER_SET_SINK_MUTE_STATE</trigger>
+ <process>
+ <condition>muteState(USER,REQUESTING) EQ MS_MUTED</condition>
+ <action>
+ <type>ACTION_MUTE</type>
+ <param>
+ <sinkName>REQUESTING</sinkName>
+ </param>
+ </action>
+ </process>
+ <process>
+ <condition>muteState(USER,REQUESTING) EQ MS_UNMUTED</condition>
+ <action>
+ <type>ACTION_UNMUTE</type>
+ <param>
+ <sinkName>REQUESTING</sinkName>
+ </param>
+ </action>
+ </process>
+ </policy>
+ <!-- default mute policy end -->
+ <!-- default set sink sound property policy start -->
+ <policy>
+ <trigger>USER_SET_SINK_MAIN_SOUND_PROPERTY</trigger>
+ <process>
+ <action>
+ <type>ACTION_SET_PROPERTY</type>
+ <param>
+ <sinkName>REQUESTING</sinkName>
+ </param>
+ </action>
+ </process>
+ </policy>
+ <!-- default set sink sound property policy end -->
+ <!-- default set source sound property policy start -->
+ <policy>
+ <trigger>USER_SET_SOURCE_MAIN_SOUND_PROPERTY</trigger>
+ <process>
+ <action>
+ <type>ACTION_SET_PROPERTY</type>
+ <param>
+ <sourceName>REQUESTING</sourceName>
+ </param>
+ </action>
+ </process>
+ </policy>
+ <!-- default set source sound property policy end -->
+ <!-- default connect policy start -->
+ <policy>
+ <trigger>USER_CONNECTION_REQUEST</trigger>
+ <process>
+ <action>
+ <type>ACTION_CONNECT</type>
+ <param>
+ <className>REQUESTING</className>
+ <timeOut>5000</timeOut>
+ </param>
+ </action>
+ </process>
+ </policy>
+ <!-- default connect policy end -->
+ </listPolicies>
+ <listSystemProperties>
+ <systemProperty>
+ <type>SYP_DEBUG_LOG</type>
+ <value>5</value>
+ </systemProperty>
+ </listSystemProperties>
+</c:configuration>
diff --git a/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config-soundmanager/audiomanager-plugins-config-soundmanager/customtypes.xsd b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config-soundmanager/audiomanager-plugins-config-soundmanager/customtypes.xsd
new file mode 100644
index 00000000..2604fb71
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config-soundmanager/audiomanager-plugins-config-soundmanager/customtypes.xsd
@@ -0,0 +1,63 @@
+<?xml version="1.0"?>
+<xsd:schema targetNamespace="controller" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:c="controller">
+ <xsd:simpleType name="am_CustomAvailabilityReason_t">
+ <xsd:annotation>
+ <xsd:documentation>This enumeration list the source/sink availability change reason. </xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:string">
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="am_CustomSoundPropertyType_t">
+ <xsd:annotation>
+ <xsd:documentation>This enumeration list the source and sink sound property. The sound properties of Genivi Audio manager can be extended to include project specific properties. Three sound properties like volume persistence, connection persistence and volume support are extended.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:string">
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="am_CustomConnectionFormat_t">
+ <xsd:annotation>
+ <xsd:documentation>This enumeration lists the connection format for the source and sinks.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:string">
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="am_CustomNotificationType_t">
+ <xsd:annotation>
+ <xsd:documentation>This enumeration contains the type of notification possible.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:string">
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="am_CustomSystemPropertyType_t">
+ <xsd:annotation>
+ <xsd:documentation>This enumeration lists the system properties.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="SYP_DEBUG_LOG">
+ <xsd:annotation>
+ <xsd:documentation>1 </xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="am_CustomRampType_t">
+ <xsd:restriction base="xsd:string">
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="am_CustomMainSoundPropertyType_t">
+ <xsd:annotation>
+ <xsd:documentation>This enumeration lists the Main Properties for source and sinks.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:string">
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="am_SourceID_e">
+ <xsd:restriction base="xsd:string">
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="am_SinkID_e">
+ <xsd:restriction base="xsd:string">
+ </xsd:restriction>
+ </xsd:simpleType>
+</xsd:schema>
diff --git a/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config-soundmanager/audiomanager-plugins-config-soundmanager/soundmanager-dbus.conf b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config-soundmanager/audiomanager-plugins-config-soundmanager/soundmanager-dbus.conf
new file mode 100644
index 00000000..9b5aadb7
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config-soundmanager/audiomanager-plugins-config-soundmanager/soundmanager-dbus.conf
@@ -0,0 +1,20 @@
+<!-- This configuration file specifies the required security policies
+to use the audiomanager command d-bus plugin interface. -->
+
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+ <!-- ../system.conf have denied everything, so we just punch some holes -->
+ <policy user="root">
+ <allow own="org.genivi.audiomanager.routing.soundmanager"/>
+ <allow send_destination="org.genivi.audiomanager.routing.soundmanager"/>
+ <allow send_interface="org.genivi.audiomanager.routing.soundmanager"/>
+ <allow receive_sender="org.genivi.audiomanager.routing.soundmanager"/>
+ </policy>
+ <policy at_console="true">
+ <allow send_destination="org.genivi.audiomanager.routing.soundmanager"/>
+ </policy>
+ <policy context="default">
+ <allow send_destination="org.genivi.audiomanager.routing.soundmanager"/>
+ </policy>
+</busconfig>
diff --git a/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config-soundmanager/audiomanager-plugins-config-soundmanager_7.4.bb b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config-soundmanager/audiomanager-plugins-config-soundmanager_7.4.bb
new file mode 100644
index 00000000..7a1b05a6
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config-soundmanager/audiomanager-plugins-config-soundmanager_7.4.bb
@@ -0,0 +1,40 @@
+DESCRIPTION = "Configurations for Audiomanager Plugins with Sound Manager"
+HOMEPAGE = ""
+LICENSE = "MPLv2"
+SECTION = "multimedia"
+
+LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MPL-2.0;md5=815ca599c9df247a0c7f619bab123dad"
+RDEPENDS_${PN} = "libxml2 zlib dbus-lib"
+
+SRC_URI = " \
+ file://amcp_dbus.conf \
+ file://amrp_dbus.conf \
+ file://configuration.xml \
+ file://customtypes.xsd \
+ file://soundmanager-dbus.conf \
+"
+
+FILES_${PN} = " \
+ ${sysconfdir}/dbus-1/system.d/amcp_dbus.conf \
+ ${sysconfdir}/dbus-1/system.d/amrp_dbus.conf \
+ ${sysconfdir}/dbus-1/system.d/soundmanager-dbus.conf \
+ ${sysconfdir}/audiomanager/control/configuration.xml \
+ ${sysconfdir}/audiomanager/control/customtypes.xsd \
+"
+
+FILES_${PN}-dbg += " \
+ /usr/lib/audiomanager/command/.debug \
+ /usr/lib/audiomanager/routing/.debug \
+"
+
+do_install() {
+ install -d ${D}${sysconfdir}/dbus-1/system.d
+ install -m 644 ${WORKDIR}/amcp_dbus.conf ${D}${sysconfdir}/dbus-1/system.d/
+ install -m 644 ${WORKDIR}/amrp_dbus.conf ${D}${sysconfdir}/dbus-1/system.d/
+ install -m 644 ${WORKDIR}/soundmanager-dbus.conf ${D}${sysconfdir}/dbus-1/system.d/
+ install -d ${D}${sysconfdir}/audiomanager/control
+ install -m 644 ${WORKDIR}/configuration.xml ${D}${sysconfdir}/audiomanager/control/
+ install -m 644 ${WORKDIR}/customtypes.xsd ${D}${sysconfdir}/audiomanager/control/
+}
+
+RPROVIDES_${PN} += "virtual/audiomanager-plugins-config"
diff --git a/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config/audiomanager-plugins-config/amcp_dbus.conf b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config/audiomanager-plugins-config/amcp_dbus.conf
new file mode 100644
index 00000000..49544d5e
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config/audiomanager-plugins-config/amcp_dbus.conf
@@ -0,0 +1,20 @@
+<!-- This configuration file specifies the required security policies
+to use the audiomanager command d-bus plugin interface. -->
+
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+ <!-- ../system.conf have denied everything, so we just punch some holes -->
+ <policy user="root">
+ <allow own="org.genivi.audiomanager"/>
+ <allow own="org.genivi.audiomanager.command"/>
+ <allow send_destination="org.genivi.audiomanager"/>
+ <allow send_destination="org.genivi.audiomanager.command"/>
+ </policy>
+ <policy at_console="true">
+ <allow send_destination="org.genivi.audiomanager"/>
+ </policy>
+ <policy context="default">
+ <allow send_destination="org.genivi.audiomanager"/>
+ </policy>
+</busconfig>
diff --git a/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config/audiomanager-plugins-config/amrp_dbus.conf b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config/audiomanager-plugins-config/amrp_dbus.conf
new file mode 100644
index 00000000..6832d305
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config/audiomanager-plugins-config/amrp_dbus.conf
@@ -0,0 +1,21 @@
+<!-- This configuration file specifies the required security policies
+to use the audiomanager routing d-bus plugin interface. -->
+
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+ <!-- ../system.conf have denied everything, so we just punch some holes -->
+ <policy user="root">
+ <allow own="org.genivi.audiomanager"/>
+ <allow own="org.genivi.audiomanager.routing"/>
+ <allow send_destination="org.genivi.audiomanager"/>
+ <allow send_destination="org.genivi.audiomanager.routing"/>
+ </policy>
+ <policy at_console="true">
+ <allow send_destination="org.genivi.audiomanager"/>
+ </policy>
+ <policy context="default">
+ <allow send_destination="org.genivi.audiomanager"/>
+ </policy>
+</busconfig>
+
diff --git a/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config/audiomanager-plugins-config/configuration.xml b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config/audiomanager-plugins-config/configuration.xml
new file mode 100644
index 00000000..9e2d05ee
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config/audiomanager-plugins-config/configuration.xml
@@ -0,0 +1,522 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<c:configuration xmlns:c="controller" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="controller audiomanagertypes.xsd ">
+ <listSources>
+ <source>
+ <id>0</id>
+ <domainName>UNKNOWN</domainName>
+ <name>SourceTemplate</name>
+ <volume>0</volume>
+ <visible>TRUE</visible>
+ <className>UNKNOWN</className>
+ <sourceState>SS_OFF</sourceState>
+ <connectionFormat>CF_GENIVI_STEREO</connectionFormat>
+ <connectionFormat>CF_GENIVI_MONO</connectionFormat>
+ <interruptState>IS_OFF</interruptState>
+ <availability>
+ <availability>A_AVAILABLE</availability>
+ <availabilityReason>AR_UNKNOWN</availabilityReason>
+ </availability>
+ <soundProperty>
+ <type>SP_GENIVI_TREBLE</type>
+ <value minValue="0" maxValue="10">5</value>
+ </soundProperty>
+ <soundProperty>
+ <type>SP_GENIVI_MID</type>
+ <value minValue="0" maxValue="10">5</value>
+ </soundProperty>
+ <soundProperty>
+ <type>SP_GENIVI_BASS</type>
+ <value minValue="0" maxValue="10">5</value>
+ </soundProperty>
+ <mainSoundProperty>
+ <type>MSP_GENIVI_TREBLE</type>
+ <value minValue="0" maxValue="10">5</value>
+ </mainSoundProperty>
+ <mainSoundProperty>
+ <type>MSP_GENIVI_MID</type>
+ <value minValue="0" maxValue="10">5</value>
+ </mainSoundProperty>
+ <mainSoundProperty>
+ <type>MSP_GENIVI_BASS</type>
+ <value minValue="0" maxValue="10">5</value>
+ </mainSoundProperty>
+ <registrationType>REG_TEMPLATE</registrationType>
+ <isVolumeSupported>TRUE</isVolumeSupported>
+ <priority>1</priority>
+ <listMainSoundPropertiesToSoundProperties>
+ <mapEntry>MSP_UNKNOWN,SP_UNKNOWN</mapEntry>
+ <mapEntry>MSP_GENIVI_TREBLE,SP_GENIVI_TREBLE</mapEntry>
+ </listMainSoundPropertiesToSoundProperties>
+ </source>
+ <source baseName="SourceTemplate">
+ <id>1</id>
+ <domainName>PulseAudio</domainName>
+ <name>mediaplayer</name>
+ <className>BASE</className>
+ <registrationType>REG_ROUTER</registrationType>
+ </source>
+ <source baseName="SourceTemplate">
+ <id>2</id>
+ <domainName>PulseAudio</domainName>
+ <name>ALSA#Playback</name>
+ <className>BASE</className>
+ <registrationType>REG_ROUTER</registrationType>
+ </source>
+ <source baseName="SourceTemplate">
+ <id>3</id>
+ <domainName>PulseAudio</domainName>
+ <name>music</name>
+ <className>BASE</className>
+ <registrationType>REG_ROUTER</registrationType>
+ </source>
+ <source baseName="SourceTemplate">
+ <id>4</id>
+ <domainName>PulseAudio</domainName>
+ <name>Navi</name>
+ <className>INT</className>
+ <registrationType>REG_ROUTER</registrationType>
+ </source>
+ <source baseName="SourceTemplate">
+ <id>5</id>
+ <domainName>PulseAudio</domainName>
+ <name>phone</name>
+ <className>PHONE</className>
+ <registrationType>REG_ROUTER</registrationType>
+ </source>
+ </listSources>
+ <listSinks>
+ <sink>
+ <id>0</id>
+ <domainName>UNKNOWN</domainName>
+ <name>SinkTemplate</name>
+ <volume>0</volume>
+ <visible>TRUE</visible>
+ <mainVolume>100</mainVolume>
+ <className>BASE</className>
+ <muteState>MS_UNMUTED</muteState>
+ <connectionFormat>CF_GENIVI_STEREO</connectionFormat>
+ <connectionFormat>CF_GENIVI_MONO</connectionFormat>
+ <availability>
+ <availability>A_AVAILABLE</availability>
+ <availabilityReason>AR_GENIVI_NEWMEDIA</availabilityReason>
+ </availability>
+ <soundProperty>
+ <type>SP_GENIVI_TREBLE</type>
+ <value minValue="0" maxValue="10">5</value>
+ </soundProperty>
+ <soundProperty>
+ <type>SP_GENIVI_MID</type>
+ <value minValue="0" maxValue="10">5</value>
+ </soundProperty>
+ <soundProperty>
+ <type>SP_GENIVI_BASS</type>
+ <value minValue="0" maxValue="10">5</value>
+ </soundProperty>
+ <mainSoundProperty>
+ <type>MSP_GENIVI_TREBLE</type>
+ <value minValue="0" maxValue="10">5</value>
+ </mainSoundProperty>
+ <mainSoundProperty>
+ <type>MSP_GENIVI_MID</type>
+ <value minValue="0" maxValue="10">5</value>
+ </mainSoundProperty>
+ <mainSoundProperty>
+ <type>MSP_GENIVI_BASS</type>
+ <value minValue="0" maxValue="10">5</value>
+ </mainSoundProperty>
+ <registrationType>REG_TEMPLATE</registrationType>
+ <isVolumeSupported>TRUE</isVolumeSupported>
+ <priority>1</priority>
+ <listMainVolumesToNormalizedVolumes>
+ <tableEntry>0,0.0</tableEntry>
+ <tableEntry>1,0.01</tableEntry>
+ <tableEntry>2,0.02</tableEntry>
+ <tableEntry>3,0.03</tableEntry>
+ <tableEntry>4,0.04</tableEntry>
+ <tableEntry>5,0.05</tableEntry>
+ <tableEntry>6,0.06</tableEntry>
+ <tableEntry>7,0.07</tableEntry>
+ <tableEntry>8,0.08</tableEntry>
+ <tableEntry>9,0.09</tableEntry>
+ <tableEntry>10,0.1</tableEntry>
+ <tableEntry>11,0.11</tableEntry>
+ <tableEntry>12,0.12</tableEntry>
+ <tableEntry>14,0.14</tableEntry>
+ <tableEntry>15,0.15</tableEntry>
+ <tableEntry>17,0.17</tableEntry>
+ <tableEntry>20,0.2</tableEntry>
+ <tableEntry>22,0.22</tableEntry>
+ <tableEntry>25,0.25</tableEntry>
+ <tableEntry>28,0.28</tableEntry>
+ <tableEntry>31,0.31</tableEntry>
+ <tableEntry>35,0.35</tableEntry>
+ <tableEntry>40,0.4</tableEntry>
+ <tableEntry>45,0.45</tableEntry>
+ <tableEntry>50,0.5</tableEntry>
+ <tableEntry>56,0.56</tableEntry>
+ <tableEntry>62,0.62</tableEntry>
+ <tableEntry>70,0.7</tableEntry>
+ <tableEntry>80,0.8</tableEntry>
+ <tableEntry>90,0.9</tableEntry>
+ <tableEntry>100,1.0</tableEntry>
+ </listMainVolumesToNormalizedVolumes>
+ <listNormalizedVolumesToDecibelVolumes>
+ <tableEntry>0.0,-192.0</tableEntry>
+ <tableEntry>0.01,-40.0</tableEntry>
+ <tableEntry>0.02,-34.0</tableEntry>
+ <tableEntry>0.03,-30.0</tableEntry>
+ <tableEntry>0.04,-27.0</tableEntry>
+ <tableEntry>0.05,-26.0</tableEntry>
+ <tableEntry>0.06,-24.0</tableEntry>
+ <tableEntry>0.07,-23.0</tableEntry>
+ <tableEntry>0.08,-22.0</tableEntry>
+ <tableEntry>0.09,-21.0</tableEntry>
+ <tableEntry>0.1,-20.0</tableEntry>
+ <tableEntry>0.11,-19.0</tableEntry>
+ <tableEntry>0.12,-18.0</tableEntry>
+ <tableEntry>0.14,-17.0</tableEntry>
+ <tableEntry>0.15,-16.0</tableEntry>
+ <tableEntry>0.17,-15.0</tableEntry>
+ <tableEntry>0.2,-14.0</tableEntry>
+ <tableEntry>0.22,-13.0</tableEntry>
+ <tableEntry>0.25,-12.0</tableEntry>
+ <tableEntry>0.28,-11.0</tableEntry>
+ <tableEntry>0.31,-10.0</tableEntry>
+ <tableEntry>0.35,-9.0</tableEntry>
+ <tableEntry>0.4,-8.0</tableEntry>
+ <tableEntry>0.45,-7.0</tableEntry>
+ <tableEntry>0.5,-6.0</tableEntry>
+ <tableEntry>0.56,-5.0</tableEntry>
+ <tableEntry>0.62,-4.0</tableEntry>
+ <tableEntry>0.7,-3.0</tableEntry>
+ <tableEntry>0.8,-2.0</tableEntry>
+ <tableEntry>0.9,-1.0</tableEntry>
+ <tableEntry>1.0,0.0</tableEntry>
+ </listNormalizedVolumesToDecibelVolumes>
+ <listMainSoundPropertiesToSoundProperties>
+ <mapEntry>MSP_UNKNOWN,SP_UNKNOWN</mapEntry>
+ <mapEntry>MSP_GENIVI_TREBLE,SP_GENIVI_TREBLE</mapEntry>
+ </listMainSoundPropertiesToSoundProperties>
+ </sink>
+ <sink baseName="SinkTemplate">
+ <id>1</id>
+ <domainName>PulseAudio</domainName>
+ <name>rsnd-dai.0-ak4642-hifi#Analog#Stereo</name>
+ <className>BASE</className>
+ <registrationType>REG_ROUTER</registrationType>
+ </sink>
+ <sink baseName="SinkTemplate">
+ <id>2</id>
+ <domainName>PulseAudio</domainName>
+ <name>Microchip#MOST:0#Multichannel</name>
+ <className>BASE</className>
+ <registrationType>REG_ROUTER</registrationType>
+ </sink>
+ </listSinks>
+ <listGateways>
+ <!-- This is a single domain example, therefore no gateway is present -->
+ </listGateways>
+ <listDomains>
+ <domain>
+ <id>0</id>
+ <name>PulseAudio</name>
+ <busName>org.genivi.audiomanager</busName>
+ <nodeName>pulseaudio</nodeName>
+ <early>FALSE</early>
+ <complete>TRUE</complete>
+ <state>DS_CONTROLLED</state>
+ <registrationType>REG_ROUTER</registrationType>
+ </domain>
+ </listDomains>
+ <listClasses>
+ <class>
+ <name>BASE</name>
+ <type>C_PLAYBACK</type>
+ <priority>1</priority>
+ <topology>Microchip#MOST:0#Multichannel^rsnd-dai.0-ak4642-hifi#Analog#Stereo=mediaplayer^music^ALSA#Playback</topology>
+ </class>
+ <class>
+ <name>INT</name>
+ <type>C_PLAYBACK</type>
+ <priority>2</priority>
+ <topology>Microchip#MOST:0#Multichannel^rsnd-dai.0-ak4642-hifi#Analog#Stereo=Navi</topology>
+ </class>
+ <class>
+ <name>PHONE</name>
+ <type>C_PLAYBACK</type>
+ <priority>3</priority>
+ <topology>Microchip#MOST:0#Multichannel^rsnd-dai.0-ak4642-hifi#Analog#Stereo=phone</topology>
+ </class>
+ </listClasses>
+ <listPolicies>
+<!--Connect Policy Start-->
+<!--BASE Policy-->
+ <policy>
+ <trigger>USER_CONNECTION_REQUEST</trigger>
+ <process>
+ <condition>name(CLASS, REQUESTING) EQ "BASE"</condition>
+ <condition>connectionState(CONNECTIONOFCLASS, REQUESTING, OTHERS) INC CS_CONNECTED</condition>
+ <action>
+ <type>ACTION_SUSPEND</type>
+ <param>
+ <className>"BASE"</className>
+ <connectionState>CS_CONNECTED</connectionState>
+ </param>
+ </action>
+ </process>
+ </policy>
+<!--INT policy-->
+ <policy>
+ <trigger>USER_CONNECTION_REQUEST</trigger>
+ <process>
+ <condition>name(CLASS, REQUESTING) EQ "INT"</condition>
+ <action>
+ <type>ACTION_LIMIT</type>
+ <param>
+ <className>"BASE"</className>
+ <volume>-1000</volume>
+ <pattern>01</pattern>
+ </param>
+ </action>
+ </process>
+ <process>
+ <condition>name(CLASS, REQUESTING) EQ "INT"</condition>
+ <condition>connectionState(CONNECTIONOFCLASS, REQUESTING, OTHERS) INC CS_CONNECTED</condition>
+ <condition>priority(CONNECTIONOFCLASS, REQUESTING, OTHERS) LT priority(CONNECTION, REQUESTING)</condition>
+ <action>
+ <type>ACTION_PUSH</type>
+ <param>
+ <className>"INT"</className>
+ <order>O_NEWEST</order>
+ </param>
+ </action>
+ <break>TRUE</break>
+ </process>
+ <process>
+ <condition>name(CLASS, REQUESTING) EQ "INT"</condition>
+ <condition>connectionState(CONNECTIONOFCLASS, REQUESTING, OTHERS) INC CS_CONNECTED</condition>
+ <action>
+ <type>ACTION_PUSH</type>
+ <param>
+ <className>"INT"</className>
+ <order>O_OLDEST</order>
+ </param>
+ </action>
+ </process>
+ <process>
+ <condition>name(CLASS, REQUESTING) EQ "INT"</condition>
+ <condition>connectionState(CONNECTIONOFCLASS, "PHONE") INC CS_CONNECTED</condition>
+ <action>
+ <type>ACTION_MUTE</type>
+ <param>
+ <className>REQUESTING</className>
+ </param>
+ </action>
+ <action>
+ <type>ACTION_CONNECT</type>
+ <param>
+ <className>REQUESTING</className>
+ </param>
+ </action>
+ <break>TRUE</break>
+ </process>
+ </policy>
+<!--PHONE policy-->
+ <policy>
+ <trigger>USER_CONNECTION_REQUEST</trigger>
+ <process>
+ <condition>name(CLASS, REQUESTING) EQ "PHONE"</condition>
+ <action>
+ <type>ACTION_LIMIT</type>
+ <param>
+ <className>"BASE"</className>
+ <volume>-1000</volume>
+ <pattern>02</pattern>
+ </param>
+ </action>
+ </process>
+ <process>
+ <condition>name(CLASS, REQUESTING) EQ "PHONE"</condition>
+ <condition>connectionState(CONNECTIONOFCLASS, "INT") INC CS_CONNECTED</condition>
+ <action>
+ <type>ACTION_MUTE</type>
+ <param>
+ <className>"INT"</className>
+ </param>
+ </action>
+ </process>
+ <process>
+ <condition>name(SINK, REQUESTING) EQ "AMP"</condition>
+ <action>
+ <type>ACTION_CONNECT</type>
+ <param>
+ <className>REQUESTING</className>
+ <timeOut>5000</timeOut>
+ </param>
+ </action>
+ <break>TRUE</break>
+ </process>
+ </policy>
+<!--Connect policy end-->
+<!--Disconnect policy start-->
+ <policy>
+ <trigger>USER_DISCONNECTION_REQUEST</trigger>
+ <process>
+ <action>
+ <type>ACTION_DISCONNECT</type>
+ <param>
+ <sourceName>REQUESTING</sourceName>
+ <sinkName>REQUESTING</sinkName>
+ </param>
+ </action>
+ </process>
+ <process>
+ <condition>name(CLASS, REQUESTING) EQ "INT"</condition>
+ <action>
+ <type>ACTION_UNLIMIT</type>
+ <param>
+ <className>"BASE"</className>
+ <pattern>01</pattern>
+ </param>
+ </action>
+ </process>
+ <process>
+ <condition>name(CLASS, REQUESTING) EQ "INT"</condition>
+ <condition>connectionState(CONNECTIONOFCLASS, REQUESTING, OTHERS) INC CS_CONNECTED</condition>
+ <action>
+ <type>ACTION_POP</type>
+ <param>
+ <className>"INT"</className>
+ <order>O_OLDEST</order>
+ </param>
+ </action>
+ </process>
+ <process>
+ <condition>name(CLASS, REQUESTING) EQ "PHONE"</condition>
+ <condition>connectionState(CONNECTIONOFCLASS, "INT") INC CS_CONNECTED</condition>
+ <action>
+ <type>ACTION_UNMUTE</type>
+ <param>
+ <className>"INT"</className>
+ </param>
+ </action>
+ </process>
+ <process>
+ <condition>name(CLASS, REQUESTING) EQ "PHONE"</condition>
+ <action>
+ <type>ACTION_UNLIMIT</type>
+ <param>
+ <className>"BASE"</className>
+ <pattern>02</pattern>
+ </param>
+ </action>
+ </process>
+ <process>
+ <condition>name(CLASS, REQUESTING) EQ "BASE"</condition>
+ <condition>connectionState(CONNECTIONOFCLASS, "BASE") INC CS_SUSPENDED</condition>
+ <action>
+ <type>ACTION_RESUME</type>
+ <param>
+ <className>"BASE"</className>
+ <connectionState>CS_SUSPENDED</connectionState>
+ </param>
+ </action>
+ </process>
+ </policy>
+<!-- default volume policy start -->
+ <policy>
+ <trigger>USER_SET_VOLUME</trigger>
+ <process>
+ <action>
+ <type>ACTION_SET_VOLUME</type>
+ <param>
+ <sinkName>REQUESTING</sinkName>
+ </param>
+ </action>
+ </process>
+ </policy>
+<!-- default volume policy end -->
+<!-- default mute policy start -->
+ <policy>
+ <trigger>USER_SET_SINK_MUTE_STATE</trigger>
+ <process>
+ <condition>muteState(USER,REQUESTING) EQ MS_MUTED</condition>
+ <action>
+ <type>ACTION_MUTE</type>
+ <param>
+ <sinkName>REQUESTING</sinkName>
+ </param>
+ </action>
+ </process>
+ <process>
+ <condition>muteState(USER,REQUESTING) EQ MS_UNMUTED</condition>
+ <action>
+ <type>ACTION_UNMUTE</type>
+ <param>
+ <sinkName>REQUESTING</sinkName>
+ </param>
+ </action>
+ </process>
+ </policy>
+<!-- default mute policy end -->
+<!-- default set sink sound property policy start -->
+ <policy>
+ <trigger>USER_SET_SINK_MAIN_SOUND_PROPERTY</trigger>
+ <process>
+ <action>
+ <type>ACTION_SET_PROPERTY</type>
+ <param>
+ <sinkName>REQUESTING</sinkName>
+ </param>
+ </action>
+ </process>
+ </policy>
+<!-- default set sink sound property policy end -->
+<!-- default set source sound property policy start -->
+ <policy>
+ <trigger>USER_SET_SOURCE_MAIN_SOUND_PROPERTY</trigger>
+ <process>
+ <action>
+ <type>ACTION_SET_PROPERTY</type>
+ <param>
+ <sourceName>REQUESTING</sourceName>
+ </param>
+ </action>
+ </process>
+ </policy>
+<!-- default set source sound property policy end -->
+<!-- default connect policy start -->
+ <policy>
+ <trigger>USER_CONNECTION_REQUEST</trigger>
+ <process>
+ <action>
+ <type>ACTION_MUTE</type>
+ <param>
+ <className>REQUESTING</className>
+ <timeOut>5000</timeOut>
+ </param>
+ </action>
+ <action>
+ <type>ACTION_CONNECT</type>
+ <param>
+ <className>REQUESTING</className>
+ <timeOut>5000</timeOut>
+ </param>
+ </action>
+ <action>
+ <type>ACTION_UNMUTE</type>
+ <param>
+ <className>REQUESTING</className>
+ </param>
+ </action>
+ </process>
+ </policy>
+<!-- default connect policy end -->
+ </listPolicies>
+ <listSystemProperties>
+ <systemProperty>
+ <type>SYP_DEBUG_LOG</type>
+ <value>5</value>
+ </systemProperty>
+ </listSystemProperties>
+</c:configuration>
diff --git a/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config/audiomanager-plugins-config/customtypes.xsd b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config/audiomanager-plugins-config/customtypes.xsd
new file mode 100644
index 00000000..2604fb71
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config/audiomanager-plugins-config/customtypes.xsd
@@ -0,0 +1,63 @@
+<?xml version="1.0"?>
+<xsd:schema targetNamespace="controller" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:c="controller">
+ <xsd:simpleType name="am_CustomAvailabilityReason_t">
+ <xsd:annotation>
+ <xsd:documentation>This enumeration list the source/sink availability change reason. </xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:string">
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="am_CustomSoundPropertyType_t">
+ <xsd:annotation>
+ <xsd:documentation>This enumeration list the source and sink sound property. The sound properties of Genivi Audio manager can be extended to include project specific properties. Three sound properties like volume persistence, connection persistence and volume support are extended.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:string">
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="am_CustomConnectionFormat_t">
+ <xsd:annotation>
+ <xsd:documentation>This enumeration lists the connection format for the source and sinks.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:string">
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="am_CustomNotificationType_t">
+ <xsd:annotation>
+ <xsd:documentation>This enumeration contains the type of notification possible.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:string">
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="am_CustomSystemPropertyType_t">
+ <xsd:annotation>
+ <xsd:documentation>This enumeration lists the system properties.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="SYP_DEBUG_LOG">
+ <xsd:annotation>
+ <xsd:documentation>1 </xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="am_CustomRampType_t">
+ <xsd:restriction base="xsd:string">
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="am_CustomMainSoundPropertyType_t">
+ <xsd:annotation>
+ <xsd:documentation>This enumeration lists the Main Properties for source and sinks.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:string">
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="am_SourceID_e">
+ <xsd:restriction base="xsd:string">
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="am_SinkID_e">
+ <xsd:restriction base="xsd:string">
+ </xsd:restriction>
+ </xsd:simpleType>
+</xsd:schema>
diff --git a/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config/audiomanager-plugins-config/org.genivi.audiomanager.routing.pulseaudio.conf b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config/audiomanager-plugins-config/org.genivi.audiomanager.routing.pulseaudio.conf
new file mode 100644
index 00000000..f77845a3
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config/audiomanager-plugins-config/org.genivi.audiomanager.routing.pulseaudio.conf
@@ -0,0 +1,35 @@
+<!-- This configuration file specifies the required security policies
+ for routing adapter for KP audio server to work. -->
+
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+
+ <!-- ../system.conf have denied everything, so we just punch some holes -->
+
+ <policy user="root">
+ <allow own="org.genivi.audiomanager.routing.pulseaudio"/>
+ <allow send_destination="org.genivi.audiomanager.routing.pulseaudio"/>
+ <allow send_interface="org.genivi.audiomanager.routing.pulseaudio"/>
+ <allow receive_sender="org.genivi.audiomanager.routing.pulseaudio"/>
+ </policy>
+
+ <policy user="adit">
+ <allow own="org.genivi.audiomanager.routing.pulseaudio"/>
+ <allow send_destination="org.genivi.audiomanager.routing.pulseaudio"/>
+ <allow send_interface="org.genivi.audiomanager.routing.pulseaudio"/>
+ <allow receive_sender="org.genivi.audiomanager.routing.pulseaudio"/>
+ </policy>
+
+ <policy at_console="true">
+ <allow own="org.genivi.audiomanager.routing.pulseaudio"/>
+ <allow send_destination="org.genivi.audiomanager.routing.pulseaudio"/>
+ <allow send_interface="org.genivi.audiomanager.routing.pulseaudio"/>
+ <allow receive_sender="org.genivi.audiomanager.routing.pulseaudio"/>
+ </policy>
+
+ <policy context="default">
+ <allow send_destination="org.genivi.audiomanager"/>
+ </policy>
+
+</busconfig>
diff --git a/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config/audiomanager-plugins-config_7.4.bb b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config/audiomanager-plugins-config_7.4.bb
new file mode 100644
index 00000000..59d68f9a
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins-config/audiomanager-plugins-config_7.4.bb
@@ -0,0 +1,40 @@
+DESCRIPTION = "Configurations for Audiomanager Plugins for AGL Demo"
+HOMEPAGE = ""
+LICENSE = "MPLv2"
+SECTION = "multimedia"
+
+LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MPL-2.0;md5=815ca599c9df247a0c7f619bab123dad"
+RDEPENDS_${PN} = "libxml2 zlib dbus-lib"
+
+SRC_URI = " \
+ file://amcp_dbus.conf \
+ file://amrp_dbus.conf \
+ file://configuration.xml \
+ file://customtypes.xsd \
+ file://org.genivi.audiomanager.routing.pulseaudio.conf \
+"
+
+FILES_${PN} = " \
+ ${sysconfdir}/dbus-1/system.d/amcp_dbus.conf \
+ ${sysconfdir}/dbus-1/system.d/amrp_dbus.conf \
+ ${sysconfdir}/dbus-1/system.d/org.genivi.audiomanager.routing.pulseaudio.conf \
+ ${sysconfdir}/audiomanager/control/configuration.xml \
+ ${sysconfdir}/audiomanager/control/customtypes.xsd \
+"
+
+FILES_${PN}-dbg += " \
+ /usr/lib/audiomanager/command/.debug \
+ /usr/lib/audiomanager/routing/.debug \
+"
+
+do_install() {
+ install -d ${D}${sysconfdir}/dbus-1/system.d
+ install -m 644 ${WORKDIR}/amcp_dbus.conf ${D}${sysconfdir}/dbus-1/system.d/
+ install -m 644 ${WORKDIR}/amrp_dbus.conf ${D}${sysconfdir}/dbus-1/system.d/
+ install -m 644 ${WORKDIR}/org.genivi.audiomanager.routing.pulseaudio.conf ${D}${sysconfdir}/dbus-1/system.d/
+ install -d ${D}${sysconfdir}/audiomanager/control
+ install -m 644 ${WORKDIR}/configuration.xml ${D}${sysconfdir}/audiomanager/control/
+ install -m 644 ${WORKDIR}/customtypes.xsd ${D}${sysconfdir}/audiomanager/control/
+}
+
+RPROVIDES_${PN} = "virtual/audiomanager-plugins-config"
diff --git a/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins/audiomanager-plugins_git.bb b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins/audiomanager-plugins_git.bb
new file mode 100644
index 00000000..9b099ebc
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager-plugins/audiomanager-plugins_git.bb
@@ -0,0 +1,60 @@
+DESCRIPTION = "GENIVI Audio Manager Plugins"
+HOMEPAGE = "http://projects.genivi.org/audio-manager/home"
+LICENSE = "MPLv2"
+SECTION = "multimedia"
+DEPENDS = "audiomanager libxml2 dbus pulseaudio"
+
+LIC_FILES_CHKSUM = "file://PluginControlInterfaceGeneric/LICENSE.txt;md5=815ca599c9df247a0c7f619bab123dad"
+
+SRC_URI = " \
+ git://github.com/tisogai/AudioManagerPlugins.git;protocol=https;branch=unknown_element_support \
+ "
+
+SRCREV = "bf5c5e8198b85e84363770150d5a02f553f43296"
+
+S = "${WORKDIR}/git"
+inherit cmake
+OECMAKE_CXX_FLAGS += "-std=c++11"
+EXTRA_OECMAKE = " \
+ -DWITH_COMMAND_INTERFACE_CAPI=OFF \
+ -DWITH_COMMAND_INTERFACE_DBUS=ON \
+ -DWITH_ROUTING_INTERFACE_ASYNC=OFF \
+ -DWITH_ROUTING_INTERFACE_CAPI=OFF \
+ -DWITH_ROUTING_INTERFACE_DBUS=ON \
+ -DWITH_TEST_CONTROLLER=OFF \
+ -DWITH_GENERIC_CONTROLLER=ON \
+ -DCONTROLLER_CONFIG_DIR="/etc/audiomanager/control" \
+"
+
+# NOTE: The specific product should have a separate customtypes.xsd
+# and should be appended to FILES_${PN} in product specific
+# audiomanager-generic-controller_git.bbappend
+FILES_${PN} = " \
+ ${libdir}/audiomanager/control/libPluginControlInterfaceGeneric.so \
+ ${sysconfdir}/audiomanager/control/audiomanagertypes.xsd \
+ ${libdir}/audiomanager/command/libPluginCommandInterfaceDbus.so \
+ ${libdir}/audiomanager/routing/libPluginRoutingInterfaceDbus.so \
+ /usr/share/audiomanager/audiomanager/CommandInterface.xml \
+ /usr/share/audiomanager/audiomanager/RoutingReceiver.xml \
+"
+
+# NOTE: The specific product should have a separate customtypes.h
+# and should be appended to FILES_${PN}-dev in product specific
+# audiomanager-generic-controller_git.bbappend
+FILES_${PN}-dev = " \
+ ${sysconfdir}/audiomanager/control/xsd2header.pl \
+"
+
+FILES_${PN}-dbg += " \
+ ${libdir}/audiomanager/control/.debug/libPluginControlInterfaceGeneric.so \
+ ${libdir}/audiomanager/command/.debug/libPluginCommandInterfaceDbus.so \
+ ${libdir}/audiomanager/routing/.debug/libPluginRoutingInterfaceDbus.so \
+"
+
+# remove example configurations
+do_install_append() {
+ rm -rf ${D}${sysconfdir}/audiomanager/control/*.xml
+ rm -rf ${D}${sysconfdir}/audiomanager/control/customtypes.xsd
+}
+
+RDEPENDS_${PN} = "virtual/audiomanager-plugins-config"
diff --git a/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager/audiomanager/0001-Fix-duplicated-command-line-arg-t.patch b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager/audiomanager/0001-Fix-duplicated-command-line-arg-t.patch
new file mode 100644
index 00000000..fcdf9c54
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/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)" <andre.magalhaes@collabora.co.uk>
+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<std::string> commandPluginDir("l","CommandPluginDir","path for l
+ TCLAP::ValueArg<std::string> databasePath ("p","databasePath","path for sqlite database (default is in memory)",false,":memory:","string");
+ TCLAP::ValueArg<unsigned int> telnetPort ("t","telnetport","The port that is used for telnet",false,DEFAULT_TELNETPORT,"int");
+ TCLAP::ValueArg<unsigned int> 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-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager/audiomanager/audiomanager.service b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager/audiomanager/audiomanager.service
new file mode 100644
index 00000000..2210a377
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/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-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager/audiomanager_7.4.bb b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/audiomanager/audiomanager_7.4.bb
new file mode 100644
index 00000000..15eb3625
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/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-devel/meta-audio-soundmanager-framework/recipes-multimedia/libsoundmanager/libsoundmanager_0.9.bb b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/libsoundmanager/libsoundmanager_0.9.bb
new file mode 100644
index 00000000..3040644d
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/libsoundmanager/libsoundmanager_0.9.bb
@@ -0,0 +1,16 @@
+SUMMARY = "Sound Manager client library for applications"
+DESCRIPTION = "Sound Manager client library for applications built with recipe"
+HOMEPAGE = "https://wiki.automotivelinux.org/soundmanager"
+SECTION = "multimedia"
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=ae6497158920d9524cf208c09cc4c984"
+
+DEPENDS = "af-binder json-c"
+RDEPENDS_${PN} = "agl-service-audio-soundmanager"
+
+inherit cmake
+
+SRC_URI = "git://gerrit.automotivelinux.org/gerrit/src/libsoundmanager.git;protocol=https;branch=${AGL_BRANCH}"
+SRCREV = "7322b823f40a5504baef9cdb69513e7dba306ed1"
+S = "${WORKDIR}/git"
+PV = "0.9+git${SRCPV}"
diff --git a/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/module-router/module-router_git.bb b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/module-router/module-router_git.bb
new file mode 100755
index 00000000..cd52b68a
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/module-router/module-router_git.bb
@@ -0,0 +1,31 @@
+DESCRIPTION = "Pulseaudio router module"
+HOMEPAGE = "https://github.com/tisogai/module-router"
+LICENSE = "LGPLv2"
+SECTION = "multimedia"
+DEPENDS = "pulseaudio"
+
+LIC_FILES_CHKSUM = "file://LICENSE;md5=fc178bcd425090939a8b634d1d6a9594"
+
+SRC_URI = " \
+ git://github.com/tisogai/module-router.git;protocol=https;branch=master \
+ "
+
+SRCREV = "8104a3174e6f54ace53066ab1797d9b9bd2bdf63"
+
+S = "${WORKDIR}/git"
+inherit cmake
+OECMAKE_CXX_FLAGS += "-std=c++11"
+
+# NOTE: The specific product should have a separate customtypes.xsd
+# and should be appended to FILES_${PN} in product specific
+# audiomanager-generic-controller_git.bbappend
+FILES_${PN} = " \
+ ${libdir}/pulse-*/modules/module-router.so \
+"
+
+
+FILES_${PN}-dbg += " \
+ ${libdir}/pulse-*/modules/.debug/module-router.so \
+"
+
+
diff --git a/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/pulseaudio-config-module-router/files/20-module-router.pa b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/pulseaudio-config-module-router/files/20-module-router.pa
new file mode 100644
index 00000000..4060feb4
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/pulseaudio-config-module-router/files/20-module-router.pa
@@ -0,0 +1,3 @@
+.ifexists module-router.so
+load-module module-router
+.endif
diff --git a/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/pulseaudio-config-module-router/pulseaudio-config-module-router_1.0.bb b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/pulseaudio-config-module-router/pulseaudio-config-module-router_1.0.bb
new file mode 100644
index 00000000..d7c2f68b
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/pulseaudio-config-module-router/pulseaudio-config-module-router_1.0.bb
@@ -0,0 +1,13 @@
+SUMMARY = "PulseAudio configuration to enable router module"
+LICENSE = "MIT"
+LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
+
+SRC_URI = "file://20-module-router.pa"
+
+do_install () {
+ install -d ${D}${sysconfdir}/pulse/default.d
+ install -m 0644 ${WORKDIR}/20-module-router.pa ${D}${sysconfdir}/pulse/default.d/
+}
+
+RDEPENDS_${PN} = "module-router"
+RPROVIDES_${PN} = "virtual/pulseaudio-config"
diff --git a/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/pulseaudio-config-soundmanager/files/soundmanager.pa b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/pulseaudio-config-soundmanager/files/soundmanager.pa
new file mode 100644
index 00000000..cb53f339
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/pulseaudio-config-soundmanager/files/soundmanager.pa
@@ -0,0 +1,3 @@
+.ifexists module-router.so
+unload-module module-router
+.endif
diff --git a/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/pulseaudio-config-soundmanager/pulseaudio-config-soundmanager_1.0.bb b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/pulseaudio-config-soundmanager/pulseaudio-config-soundmanager_1.0.bb
new file mode 100644
index 00000000..691cc66b
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-multimedia/pulseaudio-config-soundmanager/pulseaudio-config-soundmanager_1.0.bb
@@ -0,0 +1,12 @@
+SUMMARY = "PulseAudio configuration which doesn't load module-router"
+LICENSE = "MIT"
+LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
+
+SRC_URI = "file://soundmanager.pa"
+
+do_install () {
+ install -d ${D}${sysconfdir}/pulse/default.d
+ install -m 0644 ${WORKDIR}/soundmanager.pa ${D}${sysconfdir}/pulse/default.d/
+}
+
+RPROVIDES_${PN} += "virtual/pulseaudio-config"
diff --git a/meta-agl-devel/meta-audio-soundmanager-framework/recipes-packagegroup/packagegroups/packagegroup-agl-audio-soundmanager.bb b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-packagegroup/packagegroups/packagegroup-agl-audio-soundmanager.bb
new file mode 100644
index 00000000..093c6fc7
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-packagegroup/packagegroups/packagegroup-agl-audio-soundmanager.bb
@@ -0,0 +1,18 @@
+SUMMARY = "Sound Manager package groups"
+DESCRIPTION = "AGL sound manager package group based on Genivi Audio Manager"
+LICENSE = "MIT"
+
+inherit packagegroup
+
+PACKAGES = "\
+ packagegroup-agl-audio-soundmanager \
+ "
+
+RDEPENDS_${PN} += "\
+ agl-service-audio-soundmanager \
+ pulseaudio-config-soundmanager \
+ audiomanager-plugins-config-soundmanager \
+ libsoundmanager \
+"
+
+PROVIDES_${PN} += "virtual/audio-framework"
diff --git a/meta-agl-devel/meta-audio-soundmanager-framework/recipes-platform/packagegroups/packagegroup-agl-demo.bbappend b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-platform/packagegroups/packagegroup-agl-demo.bbappend
new file mode 100644
index 00000000..a69cfb80
--- /dev/null
+++ b/meta-agl-devel/meta-audio-soundmanager-framework/recipes-platform/packagegroups/packagegroup-agl-demo.bbappend
@@ -0,0 +1,4 @@
+
+RDEPENDS_${PN} += " \
+ audiomanager
+ "
diff --git a/meta-agl-devel/meta-gstrecorder-rcar-gen3/conf/include/agl_gstrecorder.inc b/meta-agl-devel/meta-gstrecorder-rcar-gen3/conf/include/agl_gstrecorder.inc
new file mode 100644
index 00000000..bd289b10
--- /dev/null
+++ b/meta-agl-devel/meta-gstrecorder-rcar-gen3/conf/include/agl_gstrecorder.inc
@@ -0,0 +1 @@
+DISTRO_FEATURES_append = " gst-record"
diff --git a/meta-agl-devel/meta-gstrecorder-rcar-gen3/conf/layer.conf b/meta-agl-devel/meta-gstrecorder-rcar-gen3/conf/layer.conf
new file mode 100644
index 00000000..fe4492a6
--- /dev/null
+++ b/meta-agl-devel/meta-gstrecorder-rcar-gen3/conf/layer.conf
@@ -0,0 +1,12 @@
+# 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 += "gstrecorder-rcar-gen3"
+BBFILE_PATTERN_gstrecorder-rcar-gen3 = "^${LAYERDIR}/"
+BBFILE_PRIORITY_gstrecorder-rcar-gen3 = "7"
+
+LAYERSERIES_COMPAT_gstrecorder-rcar-gen3 = "thud"
diff --git a/meta-agl-devel/meta-gstrecorder-rcar-gen3/recipes-graphics/wayland/weston/0001-remoting-Fix-remoting-gbm-dependency.patch b/meta-agl-devel/meta-gstrecorder-rcar-gen3/recipes-graphics/wayland/weston/0001-remoting-Fix-remoting-gbm-dependency.patch
new file mode 100644
index 00000000..a4334750
--- /dev/null
+++ b/meta-agl-devel/meta-gstrecorder-rcar-gen3/recipes-graphics/wayland/weston/0001-remoting-Fix-remoting-gbm-dependency.patch
@@ -0,0 +1,41 @@
+From edc292341e037f9646dd183dfc110ad850184a4d Mon Sep 17 00:00:00 2001
+From: Harunobu Kurokawa <harunobu.kurokawa.dn@renesas.com>
+Date: Fri, 7 Jun 2019 12:18:07 +0900
+Subject: [PATCH] remoting: Fix remoting gbm dependency
+
+Add missing dependency for gbm.
+
+Signed-off-by: Harunobu Kurokawa <harunobu.kurokawa.dn@renesas.com>
+---
+ configure.ac | 1 +
+ remoting/remoting-plugin.c | 2 +-
+ 2 files changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/configure.ac b/configure.ac
+index c05ad01..0483ecd 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -246,6 +246,7 @@ if test x$enable_remoting = xyes; then
+ if test x$enable_drm_compositor != xyes; then
+ AC_MSG_WARN([The remoting-plugin.so module requires the DRM backend.])
+ fi
++ PKG_CHECK_MODULES(REMOTING_GBM, [gbm])
+ PKG_CHECK_MODULES(REMOTING_GST, [gstreamer-1.0 gstreamer-allocators-1.0 gstreamer-app-1.0 gstreamer-video-1.0])
+ fi
+
+diff --git a/remoting/remoting-plugin.c b/remoting/remoting-plugin.c
+index e99d61e..f076825 100644
+--- a/remoting/remoting-plugin.c
++++ b/remoting/remoting-plugin.c
+@@ -36,7 +36,7 @@
+ #include <unistd.h>
+ #include <sys/types.h>
+ #include <fcntl.h>
+-#include <gbm.h>
++#include <gbm/gbm.h>
+
+ #include <gst/gst.h>
+ #include <gst/allocators/gstdmabuf.h>
+--
+2.7.4
+
diff --git a/meta-agl-devel/meta-gstrecorder-rcar-gen3/recipes-graphics/wayland/weston/0002-main-change-remoting-initialization-timing.patch b/meta-agl-devel/meta-gstrecorder-rcar-gen3/recipes-graphics/wayland/weston/0002-main-change-remoting-initialization-timing.patch
new file mode 100644
index 00000000..db5060d2
--- /dev/null
+++ b/meta-agl-devel/meta-gstrecorder-rcar-gen3/recipes-graphics/wayland/weston/0002-main-change-remoting-initialization-timing.patch
@@ -0,0 +1,39 @@
+From 0a0103f20437d9ed63b6cec500027a6d7bf6185f Mon Sep 17 00:00:00 2001
+From: Harunobu Kurokawa <harunobu.kurokawa.dn@renesas.com>
+Date: Mon, 20 May 2019 18:31:32 +0900
+Subject: [PATCH] main: change remoting initialization timing
+
+Signed-off-by: Tomohito Esaki <etom@igel.co.jp>
+Signed-off-by: Harunobu Kurokawa <harunobu.kurokawa.dn@renesas.com>
+---
+ compositor/main.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/compositor/main.c b/compositor/main.c
+index 248298e..de7190b 100644
+--- a/compositor/main.c
++++ b/compositor/main.c
+@@ -2018,9 +2018,6 @@ load_drm_backend(struct weston_compositor *c,
+ ret = weston_compositor_load_backend(c, WESTON_BACKEND_DRM,
+ &config.base);
+
+- /* remoting */
+- load_remoting(c, wc);
+-
+ free(config.gbm_format);
+ free(config.seat_id);
+
+@@ -2664,6 +2661,10 @@ int main(int argc, char *argv[])
+ if (wet.init_failed)
+ goto out;
+
++ /* remoting: only support on drm-backend */
++ if (strstr(backend, "drm-backend.so"))
++ load_remoting(wet.compositor, config);
++
+ if (idle_time < 0)
+ weston_config_section_get_int(section, "idle-time", &idle_time, -1);
+ if (idle_time < 0)
+--
+2.9.2
+
diff --git a/meta-agl-devel/meta-gstrecorder-rcar-gen3/recipes-graphics/wayland/weston_6.0.0.bbappend b/meta-agl-devel/meta-gstrecorder-rcar-gen3/recipes-graphics/wayland/weston_6.0.0.bbappend
new file mode 100644
index 00000000..72723ded
--- /dev/null
+++ b/meta-agl-devel/meta-gstrecorder-rcar-gen3/recipes-graphics/wayland/weston_6.0.0.bbappend
@@ -0,0 +1,12 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+DEPENDS_append = " gstreamer1.0-plugins-base"
+
+PACKAGECONFIG_append = " remoting"
+
+PACKAGECONFIG[remoting] = " --enable-remoting"
+
+SRC_URI_append = " \
+ file://0001-remoting-Fix-remoting-gbm-dependency.patch \
+ file://0002-main-change-remoting-initialization-timing.patch \
+"
diff --git a/meta-agl-devel/meta-html5-framework/conf/layer.conf b/meta-agl-devel/meta-html5-framework/conf/layer.conf
new file mode 100644
index 00000000..6673b564
--- /dev/null
+++ b/meta-agl-devel/meta-html5-framework/conf/layer.conf
@@ -0,0 +1,12 @@
+# 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 += "html5-framework"
+BBFILE_PATTERN_html5-framework = "^${LAYERDIR}/"
+BBFILE_PRIORITY_html5-framework = "80"
+
+LAYERSERIES_COMPAT_html5-framework = "thud"
diff --git a/meta-agl-devel/meta-html5-framework/recipes-platform/images/agl-demo-platform-crosssdk.bbappend b/meta-agl-devel/meta-html5-framework/recipes-platform/images/agl-demo-platform-crosssdk.bbappend
new file mode 100644
index 00000000..d5d978dd
--- /dev/null
+++ b/meta-agl-devel/meta-html5-framework/recipes-platform/images/agl-demo-platform-crosssdk.bbappend
@@ -0,0 +1,3 @@
+IMAGE_INSTALL_append += "\
+ packagegroup-agl-demo-platform-html5 \
+ "
diff --git a/meta-agl-devel/meta-html5-framework/recipes-platform/images/agl-demo-platform.bbappend b/meta-agl-devel/meta-html5-framework/recipes-platform/images/agl-demo-platform.bbappend
new file mode 100644
index 00000000..d5d978dd
--- /dev/null
+++ b/meta-agl-devel/meta-html5-framework/recipes-platform/images/agl-demo-platform.bbappend
@@ -0,0 +1,3 @@
+IMAGE_INSTALL_append += "\
+ packagegroup-agl-demo-platform-html5 \
+ "
diff --git a/meta-agl-devel/meta-html5-framework/recipes-platform/packagegroups/packagegroup-agl-demo-platform-html5.bb b/meta-agl-devel/meta-html5-framework/recipes-platform/packagegroups/packagegroup-agl-demo-platform-html5.bb
new file mode 100644
index 00000000..c4e3c0d7
--- /dev/null
+++ b/meta-agl-devel/meta-html5-framework/recipes-platform/packagegroups/packagegroup-agl-demo-platform-html5.bb
@@ -0,0 +1,26 @@
+SUMMARY = "The software for DEMO platform of AGL IVI profile"
+DESCRIPTION = "A set of packages belong to AGL Demo Platform"
+
+LICENSE = "MIT"
+
+inherit packagegroup
+
+PACKAGES = "\
+ packagegroup-agl-demo-platform-html5 \
+ "
+
+ALLOW_EMPTY_${PN} = "1"
+
+RDEPENDS_${PN} += "\
+ packagegroup-agl-image-ivi \
+ "
+
+# add packages for demo platform (include demo apps) here
+RDEPENDS_${PN} += " \
+ "
+
+# add packages for WAM
+RDEPENDS_${PN} += " \
+ chromium-browser-service \
+ wam \
+ "
diff --git a/meta-agl-devel/meta-html5-framework/recipes-wam/chromium/chromium-browser-service.bb b/meta-agl-devel/meta-html5-framework/recipes-wam/chromium/chromium-browser-service.bb
new file mode 100644
index 00000000..2686c7c8
--- /dev/null
+++ b/meta-agl-devel/meta-html5-framework/recipes-wam/chromium/chromium-browser-service.bb
@@ -0,0 +1,19 @@
+SUMMARY = "Chromium browser widget"
+DESCRIPTION = "Wgt packaging for running chromium installed browser"
+HOMEPAGE = "https://webosose.org"
+SECTION = "apps"
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
+
+SRC_URI = "gitsm://github.com/webosose/${PN}.git;branch=halibut;protocol=https"
+SRCREV = "7dabb46483ff6a3a4fa5cfe532b91412f185554d"
+
+PV = "1.0+git${SRCPV}"
+S = "${WORKDIR}/git"
+
+#build-time dependencies
+DEPENDS += "af-binder af-main-native chromium68"
+
+inherit cmake aglwgt
+
+RDEPENDS_${PN} += "chromium68-browser runxdg"
diff --git a/meta-agl-devel/meta-html5-framework/recipes-wam/chromium/chromium68/v8-qemu-wrapper.patch b/meta-agl-devel/meta-html5-framework/recipes-wam/chromium/chromium68/v8-qemu-wrapper.patch
new file mode 100644
index 00000000..485766b0
--- /dev/null
+++ b/meta-agl-devel/meta-html5-framework/recipes-wam/chromium/chromium68/v8-qemu-wrapper.patch
@@ -0,0 +1,40 @@
+Upstream-Status: Inappropriate [embedder specific]
+
+The patch below makes the V8 binaries run during the build be invoked through
+QEMU, as they are built for the target.
+
+Signed-off-by: Raphael Kubo da Costa <raphael.kubo.da.costa@intel.com>
+Signed-off-by: Maksim Sisov <msisov@igalia.com>
+
+Index: git/src/tools/v8_context_snapshot/BUILD.gn
+===================================================================
+--- git.orig/src/tools/v8_context_snapshot/BUILD.gn
++++ git/src/tools/v8_context_snapshot/BUILD.gn
+@@ -62,6 +62,7 @@ if (use_v8_context_snapshot) {
+ output_path = rebase_path(output_file, root_build_dir)
+
+ args = [
++ "./v8-qemu-wrapper.sh",
+ "./" + rebase_path(
+ get_label_info(
+ ":v8_context_snapshot_generator($v8_snapshot_toolchain)",
+Index: git/src/v8/BUILD.gn
+===================================================================
+--- git.orig/src/v8/BUILD.gn
++++ git/src/v8/BUILD.gn
+@@ -900,6 +900,7 @@ action("run_torque") {
+ }
+
+ args = [
++ "./v8-qemu-wrapper.sh",
+ "./" + rebase_path(get_label_info(":torque($v8_torque_toolchain)",
+ "root_out_dir") + "/torque",
+ root_build_dir),
+@@ -977,6 +978,7 @@ template("run_mksnapshot") {
+ data = []
+
+ args = [
++ "./v8-qemu-wrapper.sh",
+ "./" + rebase_path(get_label_info(":mksnapshot($v8_snapshot_toolchain)",
+ "root_out_dir") + "/mksnapshot",
+ root_build_dir),
diff --git a/meta-agl-devel/meta-html5-framework/recipes-wam/chromium/chromium68_git.bb b/meta-agl-devel/meta-html5-framework/recipes-wam/chromium/chromium68_git.bb
new file mode 100644
index 00000000..e23e53ee
--- /dev/null
+++ b/meta-agl-devel/meta-html5-framework/recipes-wam/chromium/chromium68_git.bb
@@ -0,0 +1,404 @@
+# Copyright (c) 2018 LG Electronics, Inc.
+
+SUMMARY = "Chromium webruntime for webOS"
+AUTHOR = "Lokesh Kumar Goel <lokeshkumar.goel@lge.com>"
+SECTION = "webos/apps"
+LICENSE = "Apache-2.0 & BSD-3-Clause & LGPL-2.0 & LGPL-2.1"
+LIC_FILES_CHKSUM = "\
+ file://src/LICENSE;md5=0fca02217a5d49a14dfe2d11837bb34d \
+ file://src/third_party/blink/renderer/core/LICENSE-LGPL-2;md5=36357ffde2b64ae177b2494445b79d21 \
+ file://src/third_party/blink/renderer/core/LICENSE-LGPL-2.1;md5=a778a33ef338abbaf8b8a7c36b6eec80 \
+"
+
+require gn-utils.inc
+
+inherit gettext qemu
+
+DEPENDS = "virtual/gettext wayland wayland-native pixman freetype glib-2.0 fontconfig openssl pango cairo icu libxkbcommon libexif dbus pciutils udev libcap alsa-lib virtual/egl elfutils-native libdrm atk gperf-native gconf nss nss-native nspr nspr-native bison-native qemu-native"
+
+PROVIDES = "${BROWSER_APPLICATION}"
+
+SRC_URI = "\
+ git://github.com/webosose/${PN};branch=@39.agl.guppy;protocol=https;rev=${SRCREV_chromium68} \
+ git://github.com/webosose/v8;destsuffix=git/src/v8;rev=${SRCREV_v8} \
+ file://v8-qemu-wrapper.patch \
+"
+SRCREV_chromium68 = "3169198da53cbb842e504e91473e021a6b07bcc0"
+SRCREV_v8 = "1e3af71f1ff3735e8a5b639c48dfca63a7b8a647"
+
+# we don't include SRCPV in PV, so we have to manually include SRCREVs in do_fetch vardeps
+do_fetch[vardeps] += "SRCREV_v8"
+SRCREV_FORMAT = "main_v8"
+
+S = "${WORKDIR}/git"
+
+SRC_DIR = "${S}/src"
+OUT_DIR = "${WORKDIR}/build"
+BUILD_TYPE = "Release"
+
+B = "${OUT_DIR}/${BUILD_TYPE}"
+
+WEBRUNTIME_BUILD_TARGET = "webos:weboswebruntime"
+BROWSER_APP_BUILD_TARGET = "chrome"
+BROWSER_APPLICATION = "chromium68-browser"
+BROWSER_APPLICATION_DIR = "/opt/chromium68"
+
+TARGET = "${WEBRUNTIME_BUILD_TARGET} ${BROWSER_APP_BUILD_TARGET}"
+
+# Skip do_install_append of webos_system_bus. It is not compatible with this component.
+WEBOS_SYSTEM_BUS_FILES_LOCATION = "${S}/files/sysbus"
+
+PACKAGECONFIG ?= "jumbo use-upstream-wayland"
+
+# Options to enable debug-webcore build.
+# Add the following line to local.conf (or local.dev.inc) to enable them:
+# PACKAGECONFIG_append_pn-chromium68 = " debug-webcore"
+# Other debug options are controlled by sections later in this file
+PACKAGECONFIG[debug-webcore] = "remove_webcore_debug_symbols=false,remove_webcore_debug_symbols=true"
+
+# Set a default value for jumbo file merge of 8. This should be good for build
+# servers and workstations with a big number of cores. In case build is
+# happening in a machine with less cores but still enough RAM a good value could
+# be 50.
+JUMBO_FILE_MERGE_LIMIT="8"
+PACKAGECONFIG[jumbo] = "use_jumbo_build=true jumbo_file_merge_limit=${JUMBO_FILE_MERGE_LIMIT}, use_jumbo_build=false"
+
+PACKAGECONFIG[lttng] = "use_lttng=true,use_lttng=false,lttng-ust,lttng-tools lttng-modules babeltrace"
+
+# Chromium can use v4l2 device for hardware accelerated video decoding on such boards as Renesas R-car M3, for example.
+# In case of R-car m3, additional patches are required for gstreamer and v4l2apps.
+# See https://github.com/igel-oss/meta-browser-hwdecode/tree/igalia-chromium71.
+PACKAGECONFIG[use-linux-v4l2] = "use_v4l2_codec=true use_v4lplugin=true use_linux_v4l2_only=true"
+
+PACKAGECONFIG[use-upstream-wayland] = " \
+ ozone_platform_wayland_external=false ozone_platform_wayland=true \
+ use_system_minigbm=true, \
+ ozone_platform_wayland_external=true ozone_platform_wayland=false \
+"
+
+GN_ARGS = "\
+ enable_memorymanager_webapi=false\
+ ffmpeg_branding=\"Chrome\"\
+ host_os=\"linux\"\
+ ozone_auto_platforms=false\
+ proprietary_codecs=true\
+ target_os=\"linux\"\
+ treat_warnings_as_errors=false\
+ is_agl=true\
+ use_cbe=true\
+ is_chrome_cbe=true\
+ use_cups=false\
+ use_custom_libcxx=false\
+ use_kerberos=false\
+ use_neva_media=false\
+ use_ozone=true\
+ use_xkbcommon=true\
+ use_pmlog=false\
+ use_system_debugger_abort=true\
+ use_webos_gpu_info_collector=false\
+ ${PACKAGECONFIG_CONFARGS}\
+"
+
+# From Chromium's BUILDCONFIG.gn:
+# Set to enable the official build level of optimization. This has nothing
+# to do with branding, but enables an additional level of optimization above
+# release (!is_debug). This might be better expressed as a tri-state
+# (debug, release, official) but for historical reasons there are two
+# separate flags.
+# See also: https://groups.google.com/a/chromium.org/d/msg/chromium-dev/hkcb6AOX5gE/PPT1ukWoBwAJ
+GN_ARGS += "is_debug=false is_official_build=true"
+
+# is_cfi default value is true for x86-64 builds with is_official_build=true.
+# As of M63, we explicitly need to set it to false, otherwise we fail the
+# following assertion in //build/config/sanitizers/sanitizers.gni:
+# assert(!is_cfi || is_clang,
+# "is_cfi requires setting is_clang = true in 'gn args'")
+GN_ARGS += "is_cfi=false"
+
+# By default, passing is_official_build=true to GN causes its symbol_level
+# variable to be set to "2". This means the compiler will be passed "-g2" and
+# we will end up with a very large chrome binary (around 5Gb as of M58)
+# regardless of whether DEBUG_BUILD has been set or not. In addition, binutils,
+# file and other utilities are unable to read a 32-bit binary this size, which
+# causes it not to be stripped.
+# The solution is two-fold:
+# 1. Make sure -g is not passed on 32-bit architectures via DEBUG_FLAGS. -g is
+# the same as -g2. -g1 generates an 800MB binary, which is a lot more
+# manageable.
+# 2. Explicitly pass symbol_level=0 to GN. This causes -g0 to be passed
+# instead, so that if DEBUG_BUILD is not set GN will not create a huge debug
+# binary anyway. Since our compiler flags are passed after GN's, -g0 does
+# not cause any issues if DEBUG_BUILD is set, as -g1 will be passed later.
+DEBUG_FLAGS_remove_arm = "-g"
+DEBUG_FLAGS_append_arm = "-g1"
+DEBUG_FLAGS_remove_x86 = "-g"
+DEBUG_FLAGS_append_x86 = "-g1"
+GN_ARGS += "symbol_level=0"
+
+# We do not want to use Chromium's own Debian-based sysroots, it is easier to
+# just let Chromium's build system assume we are not using a sysroot at all and
+# let Yocto handle everything.
+GN_ARGS += "use_sysroot=false"
+
+# Toolchains we will use for the build. We need to point to the toolchain file
+# we've created, set the right target architecture and make sure we are not
+# using Chromium's toolchain (bundled clang, bundled binutils etc).
+GN_ARGS += "\
+ custom_toolchain=\"//build/toolchain/yocto:yocto_target\" \
+ gold_path=\"\" \
+ host_toolchain=\"//build/toolchain/yocto:yocto_native\" \
+ is_clang=${@is_default_cc_clang(d)} \
+ clang_base_path=\"${@clang_install_path(d)}\" \
+ clang_use_chrome_plugins=false \
+ linux_use_bundled_binutils=false \
+ target_cpu=\"${@gn_target_arch_name(d)}\" \
+ v8_snapshot_toolchain=\"//build/toolchain/yocto:yocto_target\" \
+"
+
+# ARM builds need special additional flags (see ${S}/build/config/arm.gni).
+# If we do not pass |arm_arch| and friends to GN, it will deduce a value that
+# will then conflict with TUNE_CCARGS and CC.
+# Note that as of M61 in some corner cases parts of the build system disable
+# the "compiler_arm_fpu" GN config, whereas -mfpu is always passed via ${CC}.
+# We might want to rework that if there are issues in the future.
+def get_compiler_flag(params, param_name, d):
+ """Given a sequence of compiler arguments in |params|, returns the value of
+ an option |param_name| or an empty string if the option is not present."""
+ for param in params:
+ if param.startswith(param_name):
+ return param.split('=')[1]
+ return ''
+
+ARM_FLOAT_ABI = "${@bb.utils.contains('TUNE_FEATURES', 'callconvention-hard', 'hard', 'softfp', d)}"
+ARM_FPU = "${@get_compiler_flag(d.getVar('TUNE_CCARGS').split(), '-mfpu', d)}"
+ARM_TUNE = "${@get_compiler_flag(d.getVar('TUNE_CCARGS').split(), '-mcpu', d)}"
+ARM_VERSION_aarch64 = "8"
+ARM_VERSION_armv7a = "7"
+ARM_VERSION_armv7ve = "7"
+ARM_VERSION_armv6 = "6"
+
+# GN computes and defaults to it automatically where needed
+# forcing it from cmdline breaks build on places where it ends up
+# overriding what GN wants
+TUNE_CCARGS_remove = "-mthumb"
+
+GN_ARGS_append_arm = " \
+ arm_float_abi=\"${ARM_FLOAT_ABI}\" \
+ arm_fpu=\"${ARM_FPU}\" \
+ arm_tune=\"${ARM_TUNE}\" \
+ arm_version=${ARM_VERSION} \
+"
+# tcmalloc's atomicops-internals-arm-v6plus.h uses the "dmb" instruction that
+# is not available on (some?) ARMv6 models, which causes the build to fail.
+GN_ARGS_append_armv6 += 'use_allocator="none"'
+# The WebRTC code fails to build on ARMv6 when NEON is enabled.
+# https://bugs.chromium.org/p/webrtc/issues/detail?id=6574
+GN_ARGS_append_armv6 += 'arm_use_neon=false'
+
+# Disable glibc shims on musl
+# tcmalloc does not play well with musl as of M62 (and possibly earlier).
+# https://github.com/gperftools/gperftools/issues/693
+GN_ARGS_append_libc-musl = ' use_allocator_shim=false'
+
+# V8's JIT infrastructure requires binaries such as mksnapshot and
+# mkpeephole to be run in the host during the build. However, these
+# binaries must have the same bit-width as the target (e.g. a x86_64
+# host targeting ARMv6 needs to produce a 32-bit binary). Instead of
+# depending on a third Yocto toolchain, we just build those binaries
+# for the target and run them on the host with QEMU.
+python do_create_v8_qemu_wrapper () {
+ """Creates a small wrapper that invokes QEMU to run some target V8 binaries
+ on the host."""
+ qemu_libdirs = [d.expand('${STAGING_DIR_HOST}${libdir}'),
+ d.expand('${STAGING_DIR_HOST}${base_libdir}')]
+ qemu_cmd = qemu_wrapper_cmdline(d, d.getVar('STAGING_DIR_HOST', True),
+ qemu_libdirs)
+ wrapper_path = d.expand('${B}/v8-qemu-wrapper.sh')
+ with open(wrapper_path, 'w') as wrapper_file:
+ wrapper_file.write("""#!/bin/sh
+
+# This file has been generated automatically.
+# It invokes QEMU to run binaries built for the target in the host during the
+# build process.
+
+%s "$@"
+""" % qemu_cmd)
+ os.chmod(wrapper_path, 0o755)
+}
+do_create_v8_qemu_wrapper[dirs] = "${B}"
+addtask create_v8_qemu_wrapper after do_patch before do_configure
+
+python do_write_toolchain_file () {
+ """Writes a BUILD.gn file for Yocto detailing its toolchains."""
+ toolchain_dir = d.expand("${S}/src/build/toolchain/yocto")
+ bb.utils.mkdirhier(toolchain_dir)
+ toolchain_file = os.path.join(toolchain_dir, "BUILD.gn")
+ write_toolchain_file(d, toolchain_file)
+}
+addtask write_toolchain_file after do_patch before do_configure
+
+# More options to speed up the build
+GN_ARGS += "\
+ enable_nacl=false\
+ disable_ftp_support=true\
+ enable_print_preview=false\
+ enable_remoting=false\
+ use_glib=true\
+ use_gnome_keyring=false\
+ use_pulseaudio=false\
+"
+
+# Respect ld-is-gold in DISTRO_FEATURES when enabling gold
+# Similar patch applied in meta-browser
+# http://patchwork.openembedded.org/patch/77755/
+EXTRA_OEGN_GOLD = "${@bb.utils.contains('DISTRO_FEATURES', 'ld-is-gold', 'use_gold=true', 'use_gold=false', d)}"
+GN_ARGS += "${EXTRA_OEGN_GOLD}"
+
+# Doesn't build for armv[45]*
+COMPATIBLE_MACHINE = "(-)"
+COMPATIBLE_MACHINE_aarch64 = "(.*)"
+COMPATIBLE_MACHINE_armv6 = "(.*)"
+COMPATIBLE_MACHINE_armv7a = "(.*)"
+COMPATIBLE_MACHINE_armv7ve = "(.*)"
+COMPATIBLE_MACHINE_x86 = "(.*)"
+COMPATIBLE_MACHINE_x86-64 = "(.*)"
+
+#CHROMIUM_PLUGINS_PATH = "${libdir}"
+CBE_DATA_PATH = "${libdir}/cbe"
+CBE_DATA_LOCALES_PATH = "${CBE_DATA_PATH}/locales"
+
+# The text relocations are intentional -- see comments in [GF-52468]
+# TODO: check if we need INSANE_SKIP on ldflags
+INSANE_SKIP_${PN} = "textrel ldflags"
+
+
+do_compile[progress] = "outof:^\[(\d+)/(\d+)\]\s+"
+do_compile() {
+ if [ ! -f ${OUT_DIR}/${BUILD_TYPE}/build.ninja ]; then
+ do_configure
+ fi
+
+ export PATH="${S}/depot_tools:$PATH"
+ ${S}/depot_tools/ninja -v -C ${OUT_DIR}/${BUILD_TYPE} ${TARGET}
+}
+
+do_configure() {
+ configure_env
+}
+
+configure_env() {
+ export GYP_CHROMIUM_NO_ACTION=1
+ export PATH="${S}/depot_tools:$PATH"
+
+ GN_ARGS="${GN_ARGS}"
+ echo GN_ARGS is ${GN_ARGS}
+ echo BUILD_TARGETS are ${TARGET}
+ cd ${SRC_DIR}
+ gn gen ${OUT_DIR}/${BUILD_TYPE} --args="${GN_ARGS}"
+}
+
+WINDOW_SIZE ?= "1920,1080"
+
+configure_browser_settings() {
+ USER_AGENT="Mozilla/5.0 (Linux; NetCast; U) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/${CHROMIUM_VERSION} Safari/537.31"
+ echo "${USER_AGENT}" > ${D_DIR}/user_agent_conf
+ #We can replace below WINDOW_SIZE values from build configuration if available
+ #echo "${WINDOW_SIZE}" > ${D_DIR}/window_size_conf
+}
+
+install_chromium_browser() {
+ D_DIR=${D}${BROWSER_APPLICATION_DIR}
+ install -d ${D_DIR}
+
+ # Install browser files
+ if [ -e "${SRC_DIR}/webos/install" ]; then
+ cd ${OUT_DIR}/${BUILD_TYPE}
+ xargs --arg-file=${SRC_DIR}/webos/install/default_browser/binary.list cp -R --no-dereference --preserve=mode,links -v --target-directory=${D_DIR}
+ cd ${SRC_DIR}
+ xargs --arg-file=${SRC_DIR}/webos/install/default_browser/runtime.list cp -R --no-dereference --preserve=mode,links -v --target-directory=${D_DIR}
+ fi
+
+ # AGL does not have PMLOG
+ sed -i.bak s/PmLogCtl.*// ${D_DIR}/run_webbrowser
+
+ # To execute chromium in JAILER, Security Part needs permissions change
+ # run_webbrowser: Script file for launching chromium
+ chmod -v 755 ${D_DIR}/chrome
+ chmod -v 755 ${D_DIR}/kill_webbrowser
+ chmod -v 755 ${D_DIR}/run_webbrowser
+
+ configure_browser_settings
+}
+
+install_webruntime() {
+ install -d ${D}${libdir}
+ install -d ${D}${includedir}/${BPN}
+ install -d ${D}${CBE_DATA_PATH}
+ install -d ${D}${CBE_DATA_LOCALES_PATH}
+
+ # Install webos webview files
+ if [ -e "${SRC_DIR}/webos/install" ]; then
+ cd ${SRC_DIR}
+ xargs --arg-file=${SRC_DIR}/webos/install/weboswebruntime/staging_inc.list cp --parents --target-directory=${D}${includedir}/${BPN}
+
+ cd ${OUT_DIR}/${BUILD_TYPE}
+
+ cp libcbe.so ${D}${libdir}/
+ if [ "${WEBOS_LTTNG_ENABLED}" = "1" ]; then
+ # use bindir if building non-cbe
+ cp libchromium_lttng_provider.so ${D}${libdir}/
+ fi
+ xargs --arg-file=${SRC_DIR}/webos/install/weboswebruntime/binary.list cp --parents --target-directory=${D}${CBE_DATA_PATH}
+ cat ${SRC_DIR}/webos/install/weboswebruntime/data_locales.list | xargs -I{} install -m 755 -p {} ${D}${CBE_DATA_LOCALES_PATH}
+ fi
+
+ # move this to separate mksnapshot-cross recipe once we figure out how to build just cross mksnapshot from chromium repository
+ install -d ${D}${bindir_cross}
+ gzip -c ${OUT_DIR}/${BUILD_TYPE}/${MKSNAPSHOT_PATH}mksnapshot > ${D}${bindir_cross}/${HOST_SYS}-mksnapshot.gz
+}
+
+do_install() {
+ install_webruntime
+ install_chromium_browser
+}
+
+WEBOS_SYSTEM_BUS_DIRS_LEGACY_BROWSER_APPLICATION = " \
+ ${webos_sysbus_prvservicesdir}/${BROWSER_APPLICATION}.service \
+ ${webos_sysbus_pubservicesdir}/${BROWSER_APPLICATION}.service \
+ ${webos_sysbus_prvrolesdir}/${BROWSER_APPLICATION}.json \
+ ${webos_sysbus_pubrolesdir}/${BROWSER_APPLICATION}.json \
+"
+
+SYSROOT_DIRS_append = " ${bindir_cross}"
+
+PACKAGES_prepend = " \
+ ${PN}-cross-mksnapshot \
+ ${BROWSER_APPLICATION} \
+"
+
+FILES_${BROWSER_APPLICATION} += " \
+ ${BROWSER_APPLICATION_DIR} \
+ ${WEBOS_SYSTEM_BUS_DIRS_LEGACY_BROWSER_APPLICATION} \
+"
+
+RDEPENDS_${BROWSER_APPLICATION} += "${PN}"
+
+VIRTUAL-RUNTIME_gpu-libs ?= ""
+RDEPENDS_${PN} += "${VIRTUAL-RUNTIME_gpu-libs}"
+
+# The text relocations are intentional -- see comments in [GF-52468]
+# TODO: check if we need INSANE_SKIP on ldflags
+INSANE_SKIP_${BROWSER_APPLICATION} += "libdir ldflags textrel"
+
+FILES_${PN} = " \
+ ${libdir}/*.so \
+ ${CBE_DATA_PATH}/* \
+ ${libdir}/${BPN}/*.so \
+ ${WEBOS_SYSTEM_BUS_DIRS} \
+"
+
+FILES_${PN}-dev = " \
+ ${includedir} \
+"
+
+FILES_${PN}-cross-mksnapshot = "${bindir_cross}/${HOST_SYS}-mksnapshot.gz"
diff --git a/meta-agl-devel/meta-html5-framework/recipes-wam/chromium/gn-utils.inc b/meta-agl-devel/meta-html5-framework/recipes-wam/chromium/gn-utils.inc
new file mode 100644
index 00000000..0fd55a63
--- /dev/null
+++ b/meta-agl-devel/meta-html5-framework/recipes-wam/chromium/gn-utils.inc
@@ -0,0 +1,157 @@
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+# GN host architecture helpers.
+#
+# BUILD_ARCH's value corresponds to what uname returns as the machine name.
+# The mapping in gn_host_arch_name() tries to match several possible values
+# returned by the Linux kernel in uname(2) into the corresponding values GN
+# understands.
+def gn_host_arch_name(d):
+ """Returns a GN architecture name corresponding to the build host's machine
+ architecture."""
+ import re
+ arch_translations = {
+ r'aarch64.*': 'arm64',
+ r'arm.*': 'arm',
+ r'i[3456]86$': 'x86',
+ r'x86_64$': 'x64',
+ }
+ build_arch = d.getVar("BUILD_ARCH")
+ for arch_regexp, gn_arch_name in arch_translations.items():
+ if re.match(arch_regexp, build_arch):
+ return gn_arch_name
+ bb.fatal('Unsuported BUILD_ARCH value: "%s"' % build_arch)
+
+# GN target architecture helpers.
+#
+# Determining the target architecture is more difficult, as there are many
+# different values we can use on the Yocto side (e.g. TUNE_ARCH, TARGET_ARCH,
+# MACHINEOVERRIDES etc). What we do is define the mapping with regular,
+# non-Python variables with overrides that are generic enough (i.e. "x86"
+# instead of "i586") and then use gn_target_arch_name() to return the right
+# value with some validation.
+GN_TARGET_ARCH_NAME_aarch64 = "arm64"
+GN_TARGET_ARCH_NAME_arm = "arm"
+GN_TARGET_ARCH_NAME_x86 = "x86"
+GN_TARGET_ARCH_NAME_x86-64 = "x64"
+
+BUILD_CC_toolchain-clang = "clang"
+BUILD_CXX_toolchain-clang = "clang++"
+BUILD_LD_toolchain-clang = "clang"
+
+# knob for clang, when using meta-clang to provide clang and case where
+# clang happens to be default compiler for OE we should let it use clang
+def is_default_cc_clang(d):
+ """Return true if clang is default cross compiler."""
+ toolchain = d.getVar("TOOLCHAIN")
+ overrides = d.getVar("OVERRIDES")
+ if toolchain == "clang" and "toolchain-clang" in overrides.split(":"):
+ return "true"
+ return "false"
+
+def clang_install_path(d):
+ """Return clang compiler install path."""
+ return d.getVar("STAGING_BINDIR_NATIVE")
+
+def gn_target_arch_name(d):
+ """Returns a GN architecture name corresponding to the target machine's
+ architecture."""
+ name = d.getVar("GN_TARGET_ARCH_NAME")
+ if name is None:
+ bb.fatal('Unsupported target architecture. A valid override for the '
+ 'GN_TARGET_ARCH_NAME variable could not be found.')
+ return name
+
+def write_toolchain_file(d, file_path):
+ """Creates a complete GN toolchain file in |file_path|."""
+ import string
+ gcc_toolchain_tmpl = string.Template(
+ 'gcc_toolchain("${toolchain_name}") {\n'
+ ' cc = "${cc}"\n'
+ ' cxx = "${cxx}"\n'
+ ' ar = "${ar}"\n'
+ ' ld = cxx # GN expects a compiler, not a linker.\n'
+ ' nm = "${nm}"\n'
+ ' readelf = "${readelf}"\n'
+ ' extra_cflags = "${extra_cflags}"\n'
+ ' extra_cppflags = "${extra_cppflags}"\n'
+ ' extra_cxxflags = "${extra_cxxflags}"\n'
+ ' extra_ldflags = "${extra_ldflags}"\n'
+ ' toolchain_args = {\n'
+ ' current_cpu = "${current_cpu}"\n'
+ ' current_os = "linux"\n'
+ ' is_clang = false\n'
+ ' }\n'
+ '}\n'
+ )
+ clang_toolchain_tmpl = string.Template(
+ 'clang_toolchain("clang_${toolchain_name}") {\n'
+ ' extra_cflags = "${extra_cflags}"\n'
+ ' extra_cppflags = "${extra_cppflags}"\n'
+ ' extra_cxxflags = "${extra_cxxflags}"\n'
+ ' extra_ldflags = "${extra_ldflags}"\n'
+ ' toolchain_args = {\n'
+ ' current_cpu = "${current_cpu}"\n'
+ ' current_os = "linux"\n'
+ ' is_clang = true\n'
+ ' use_gold = true\n'
+ ' }\n'
+ '}\n'
+ )
+
+ native_toolchain = {
+ 'toolchain_name': 'yocto_native',
+ 'current_cpu': gn_host_arch_name(d),
+ 'cc': d.expand('${BUILD_CC}'),
+ 'cxx': d.expand('${BUILD_CXX}'),
+ 'ar': d.expand('${BUILD_AR}'),
+ 'nm': d.expand('${BUILD_NM}'),
+ 'readelf': d.expand('${BUILD_PREFIX}readelf'),
+ 'extra_cflags': d.expand('${BUILD_CFLAGS}'),
+ 'extra_cppflags': d.expand('${BUILD_CPPFLAGS}'),
+ 'extra_cxxflags': d.expand('${BUILD_CXXFLAGS}'),
+ 'extra_ldflags': d.expand('${BUILD_LDFLAGS}'),
+ }
+ target_toolchain = {
+ 'toolchain_name': 'yocto_target',
+ 'current_cpu': gn_target_arch_name(d),
+ 'cc': d.expand('${CC}'),
+ 'cxx': d.expand('${CXX}'),
+ 'ar': d.expand('${AR}'),
+ 'nm': d.expand('${NM}'),
+ 'readelf': d.expand('${TARGET_PREFIX}readelf'),
+ 'extra_cflags': d.expand('${TARGET_CFLAGS}'),
+ 'extra_cppflags': d.expand('${TARGET_CPPFLAGS}'),
+ 'extra_cxxflags': d.expand('${TARGET_CXXFLAGS}'),
+ 'extra_ldflags': d.expand('${TARGET_LDFLAGS}'),
+ 'strip': '',
+ }
+
+ with open(file_path, 'w') as toolchain_file:
+ toolchain_file.write(
+ '# This file has been generated automatically.\n'
+ '\n'
+ 'import("//build/config/sysroot.gni")\n'
+ 'import("//build/toolchain/gcc_toolchain.gni")\n'
+ '\n'
+ )
+ toolchain_file.write(gcc_toolchain_tmpl.substitute(native_toolchain))
+ toolchain_file.write(gcc_toolchain_tmpl.substitute(target_toolchain))
+ toolchain_file.write(clang_toolchain_tmpl.substitute(native_toolchain))
+ toolchain_file.write(clang_toolchain_tmpl.substitute(target_toolchain))
diff --git a/meta-agl-devel/meta-html5-framework/recipes-wam/wam/files/WebAppMgr.env b/meta-agl-devel/meta-html5-framework/recipes-wam/wam/files/WebAppMgr.env
new file mode 100644
index 00000000..c8ddc517
--- /dev/null
+++ b/meta-agl-devel/meta-html5-framework/recipes-wam/wam/files/WebAppMgr.env
@@ -0,0 +1,202 @@
+##### AGL: not set in WebAppMgr@.service
+#XDG_SESSION_ID="c2"
+
+##### AGL: set by WebAppMgr@.service (depends on user)
+#XDG_RUNTIME_DIR="/run/user/%i"
+
+# Set wam executable file path
+HOOK_SEGV=NO
+WAM_EXE_PATH="/usr/bin/WebAppMgr"
+
+# Set wam name for user-agent
+WAM_NAME="WebAppManager"
+
+# Only allow UTF8 encoding for luna-service messages.
+LS_ENABLE_UTF8=1
+
+# Set effective userid and groupid
+#WAM_UID="wam"
+#WAM_GID="compositor"
+
+# Set location of error page (will follow localization rules based on this path)
+#WAM_ERROR_PAGE="file:///usr/share/localization/wam/loaderror.html"
+
+# suspending javascript execution delay for page visibility
+WAM_SUSPEND_DELAY_IN_MS=250
+
+#if [ -e "etc/wam/make_shm.sh" ] ; then
+# /etc/wam/make_shm.sh
+#fi
+
+# Set user data directory for WebAppMgr
+##### AGL: set by WebAppMgr@.service (depends on user)
+#WAM_DATA_PATH="/home/%i/wamdata"
+
+# ensure that wam data directories exist
+#mkdir -p ${WAM_DATA_PATH}
+
+# set directories permission
+#chown ${WAM_UID}:${WAM_GID} ${WAM_DATA_PATH}
+
+# setup 50 Mb maximum for ApplicationCache
+WAM_APPCACHE_MAXSIZE=52428800
+
+# setup 10 Mb maximum for ApplicationCache per domain
+WAM_APPCACHE_DOMAINLIMIT=10485760
+
+# setup 50 Mb maximum for DiskCache
+WAM_DISKCACHE_MAXSIZE=52428800
+
+# setup 256 Kb maximum for resource buffer allocation
+WAM_RESOURCE_BUFFER_MAX_ALLOC_SIZE=262144
+
+# setup 1 Mb for resource buffer
+WAM_RESOURCE_BUFFER_SIZE=1048576
+
+# setup 200 seconds for watchdog timeout of render process
+WATCHDOG_RENDER_TIMEOUT=200
+
+# setup nubmer of raster threads to 1
+BLINK_NUM_RASTER_THREADS=2
+
+# use default tile width if not sed by recipe
+#if [ "$BLINK_NUM_RASTER_THREADS" = "WEBOS${BLINK_NUM_RASTER_THREADS#WEBOS}" ]; then
+BLINK_NUM_RASTER_THREADS=1
+#fi
+
+# setup 6 Mb maximum for the program GPU cache
+GPU_PROGRAM_CACHE_SIZE=6144
+
+# disable using enyo system app specfic optimization
+# currently used optimizations : inline caching off
+#USE_SYSTEM_APP_OPTIMIZATION="0"
+
+# Set location of NaCl modules
+#CHROMIUM_PATH="/usr/palm/applications/com.lge.app.chromium"
+#NACL_PLUGIN=${CHROMIUM_PATH}"/libppGoogleNaClPluginChrome.so"
+#NACL_IRT_LIBRARY=${CHROMIUM_PATH}"/nacl_irt_arm.nexe"
+#NACL_HELPER=${CHROMIUM_PATH}"/nacl_helper"
+#NACL_HELPER_BOOTSTRAP=${CHROMIUM_PATH}"/nacl_helper_bootstrap"
+
+# Set location of NPAPI plugins for all Apps including default Apps
+# This is for the flash plugin of Signage, webOS TV doesn't use it.
+#PRIVILEGED_PLUGIN_PATH=""
+
+# Set location of NPAPI plugins for NetCast Apps
+# NetCast Apps should access only the plugins in this path
+#NETCAST_PLUGIN_PATH="/usr/lib/BrowserPlugins"
+
+# Set location of NPAPI plugins for HbbTV app.
+#HBBTV_PLUGIN_PATH="/usr/lib/HbbtvPlugins"
+
+# Set InetTV player stored path
+#INETTV_HTML_PLAYER_PATH="/usr/share/inettv/inettv_player/index.html"
+
+# Set location of extra libraries
+#CDM_LIB_PATH="/usr/lib"
+
+# Set location of all NPAPI plugins
+NPAPI_PLUGIN_PATH=${HBBTV_PLUGIN_PATH}":"${NETCAST_PLUGIN_PATH}":"${PRIVILEGED_PLUGIN_PATH}
+
+#if [ -e "etc/wam/make_shm.sh" ] ; then
+# /etc/wam/make_shm.sh
+#fi
+
+# setup 8 Mb minimum codecache capacity
+JSC_minGlobalCodeCacheCapacity=8388608
+
+# Enable more explicit logging of timing with regards to rendering
+# export WAM2_ENABLE_DEBUG_RENDER_TIMING=1
+
+# enable Web Inspector and Tellurium if in developer mode
+TELLURIUM_NUB_PATH=/usr/palm/tellurium/telluriumnub.js
+ENABLE_INSPECTOR=1
+
+# Enable cursor by default
+ENABLE_CURSOR_BY_DEFAULT=1
+
+# Enable launch optimization
+ENABLE_LAUNCH_OPTIMIZATION=1
+
+# Set the duration(seconds) passed from last network activity (e.g. FMP Detector)
+# If set to a positive value, adjust a custom timeout for a network stable timer in FMPDetector
+NETWORK_STABLE_TIMEOUT=3
+
+# please keep it in alphabetical order
+#WAM_EXTRA_FLAGS=""
+#WAM_JS_FLAGS=""
+#WAM_COMMON_SWITCHES=" \
+# --application-cache-domain-limit=$WAM_APPCACHE_DOMAINLIMIT \
+# --application-cache-size=$WAM_APPCACHE_MAXSIZE \
+# --browser-subprocess-path=$WAM_EXE_PATH \
+# --disable-direct-npapi-requests \
+# --disable-extensions \
+# --disable-low-res-tiling \
+# --disable-new-video-renderer \
+# --disk-cache-size=$WAM_DISKCACHE_MAXSIZE \
+# --enable-aggressive-release-policy \
+# --enable-accelerated-plugin-rendering \
+# --accelerated-plugin-rendering-blacklist=device;drmAgent;sound;service \
+# --enable-gpu-rasterization \
+# --disable-gpu-rasterization-for-first-frame \
+# --enable-key-event-throttling \
+# --enable-threaded-compositing \
+# --enable-watchdog \
+# --hide-selection-handles \
+# --ignore-gpu-blacklist \
+# --ignore-netif=p2p \
+# --in-process-gpu \
+# --max-unused-resource-memory-usage-percentage=0 \
+# --network-stable-timeout=$NETWORK_STABLE_TIMEOUT \
+# --noerrdialogs \
+# --num-raster-threads=$BLINK_NUM_RASTER_THREADS \
+# --ozone-platform=wayland \
+# --remote-debugging-port=9998 \
+# --resource-buffer-max-allocation-size=$WAM_RESOURCE_BUFFER_MAX_ALLOC_SIZE \
+# --resource-buffer-size=$WAM_RESOURCE_BUFFER_SIZE \
+# --touch-events=disabled \
+# --ui-disable-opaque-shader-program \
+# --user-agent-suffix=SmartTV \
+# --user-data-dir=$WAM_DATA_PATH \
+# --enable-devtools-experiments \
+# --webos-wam \ "
+
+#WAM_LITE_SWITCHES=" --in-process-zygote "
+
+#export WAM_WEBOS_LITE=NO
+#if [ "${WAM_WEBOS_LITE}" = "YES" ] ; then
+# export WAM_SWITCHES=${WAM_COMMON_SWITCHES}${WAM_LITE_SWITCHES}
+# export SKIA_FONT_CACHE_SIZE=1
+# export SKIA_IMAGE_CACHE_SIZE=40
+# export SKIA_BACKGROUND_FONT_CACHE_SIZE=0
+#else
+# export WAM_SWITCHES=${WAM_COMMON_SWITCHES}
+# export SKIA_FONT_CACHE_SIZE=8
+# export SKIA_IMAGE_CACHE_SIZE=80
+# export SKIA_BACKGROUND_FONT_CACHE_SIZE=512
+#fi
+
+#export WAM_EXTRA_SKIA_CACHE_SWITCHES=" \
+# --skia-font-cache-size-mb=$SKIA_FONT_CACHE_SIZE \
+# --skia-image-cache-size-mb=$SKIA_IMAGE_CACHE_SIZE \
+# --skia-background-font-cache-size-kb=$SKIA_BACKGROUND_FONT_CACHE_SIZE \
+# "
+
+#export WAM_EXTRA_GPU_TUNING_SWITCHES=" \
+# --gpu-program-cache-size-kb=$GPU_PROGRAM_CACHE_SIZE \
+# "
+#export WAM_WATCHDOG_RENDER_TIMEOUT_SWITCHES=" \
+# --watchdog-render-timeout=$WATCHDOG_RENDER_TIMEOUT \
+# "
+
+#WEBOS_LOAD_ACCESSIBILITY_PLUGIN=1
+
+#WAM_V8_CODE_CACHE_SWITCHES=" --enable-local-resource-code-cache --disallow-code-cache-from-file-uris-with-query-string "
+
+# Load any special configuration from plugins
+#if [ -e "/etc/wam/plugins/conf.sh" ] ; then
+# . /etc/wam/plugins/conf.sh || true
+#fi
+
+#exec $WAM_EXE_PATH $WAM_SWITCHES $WAM_EXTRA_SKIA_CACHE_SWITCHES $WAM_EXTRA_GPU_TUNING_SWITCHES $WAM_WATCHDOG_RENDER_TIMEOUT_SWITCHES $WAM_EXTRA_FLAGS $WAM_V8_CODE_CACHE_SWITCHES --js-flags="$WAM_JS_FLAGS"
+
diff --git a/meta-agl-devel/meta-html5-framework/recipes-wam/wam/files/WebAppMgr@.service b/meta-agl-devel/meta-html5-framework/recipes-wam/wam/files/WebAppMgr@.service
new file mode 100644
index 00000000..09573a76
--- /dev/null
+++ b/meta-agl-devel/meta-html5-framework/recipes-wam/wam/files/WebAppMgr@.service
@@ -0,0 +1,36 @@
+# @@@LICENSE
+#
+# Copyright (c) 2017-2018 LG Electronics, Inc.
+#
+# Confidential computer software. Valid license from LG required for
+# possession, use or copying. Consistent with FAR 12.211 and 12.212,
+# Commercial Computer Software, Computer Software Documentation, and
+# Technical Data for Commercial Items are licensed to the U.S. Government
+# under vendor's standard commercial license.
+#
+# LICENSE@@@
+
+[Unit]
+Description="WebAppMgr is responsible for running web apps and manage their lifecycle"
+After=afm-service-homescreen-service--0.1--main@%i.service afm-service-windowmanager-service--0.1--main@%i.service
+Wants=afm-service-homescreen-service--0.1--main@%i.service afm-service-windowmanager-service--0.1--main@%i.service
+
+[Service]
+Type=simple
+User=%i
+Slice=user-%i.slice
+SmackProcessLabel=System
+SupplementaryGroups=audio display
+UMask=0077
+CapabilityBoundingSet=
+OOMScoreAdjust=-1000
+EnvironmentFile=-/etc/default/WebAppMgr.env
+Environment=XDG_RUNTIME_DIR=/run/user/%i
+Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/%i/bus
+Environment=WAM_DATA_PATH="/home/%i/wamdata"
+ExecStart=/usr/bin/WebAppMgr --no-sandbox --in-process-gpu --remote-debugging-port=9998 --user-data-dir="/home/%i/wamdata" --webos-wam
+Restart=on-failure
+RestartSec=50
+
+[Install]
+WantedBy=default.target
diff --git a/meta-agl-devel/meta-html5-framework/recipes-wam/wam/wam-tinyproxy_git.bb b/meta-agl-devel/meta-html5-framework/recipes-wam/wam/wam-tinyproxy_git.bb
new file mode 100644
index 00000000..25a6ed2d
--- /dev/null
+++ b/meta-agl-devel/meta-html5-framework/recipes-wam/wam/wam-tinyproxy_git.bb
@@ -0,0 +1,20 @@
+SUMMARY = "Lightweight http(s) proxy daemon"
+HOMEPAGE = "https://tinyproxy.github.io/"
+LICENSE = "GPLv2"
+LIC_FILES_CHKSUM = "file://COPYING;md5=751419260aa954499f7abaabaa882bbe"
+
+SRC_URI = "git://github.com/Igalia/${PN}.git;branch=wam-proxy;protocol=https"
+S = "${WORKDIR}/git"
+SRCREV = "ab1b5c5a53960afd91d50b1f11e339f653602de8"
+
+EXTRA_OECONF += " \
+ --enable-filter \
+ --enable-transparent \
+ --enable-reverse \
+ --enable-upstream \
+ --enable-xtinyproxy \
+ "
+
+inherit autotools
+
+FILES_${PN} += "${datadir}/tinyproxy/*"
diff --git a/meta-agl-devel/meta-html5-framework/recipes-wam/wam/wam_git.bb b/meta-agl-devel/meta-html5-framework/recipes-wam/wam/wam_git.bb
new file mode 100644
index 00000000..16737cab
--- /dev/null
+++ b/meta-agl-devel/meta-html5-framework/recipes-wam/wam/wam_git.bb
@@ -0,0 +1,51 @@
+SUMMARY = "WAM"
+AUTHOR = "Jani Hautakangas <jani.hautakangas@lge.com>"
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
+
+inherit cmake
+
+DEPENDS = "glib-2.0 jsoncpp boost chromium68 wayland-ivi-extension libhomescreen libwindowmanager"
+
+EXTRA_OECMAKE = "\
+ -DCMAKE_BUILD_TYPE=Release \
+ -DCMAKE_INSTALL_PREFIX=${prefix} \
+ -DPLATFORM_NAME=${@'${DISTRO}'.upper().replace('-', '_')} \
+ -DCHROMIUM_SRC_DIR=${STAGING_INCDIR}/chromium68"
+
+PR="r0"
+
+PROVIDES += "virtual/webruntime"
+RPROVIDES_${PN} += "virtual/webruntime"
+
+SRC_URI = "\
+ git://github.com/webosose/${PN}.git;branch=@6.agl.guppy;protocol=https \
+ file://WebAppMgr@.service \
+ file://WebAppMgr.env \
+"
+S = "${WORKDIR}/git"
+SRCREV = "8271e13578b92b192cef1d1ac6577bc3699518a4"
+
+do_install_append() {
+ install -d ${D}${sysconfdir}/wam
+ install -v -m 644 ${S}/files/launch/security_policy.conf ${D}${sysconfdir}/wam/security_policy.conf
+ install -d ${D}${systemd_system_unitdir}
+ install -v -m 644 ${WORKDIR}/WebAppMgr@.service ${D}${systemd_system_unitdir}/WebAppMgr@.service
+ install -d ${D}${sysconfdir}/default/
+ install -v -m 644 ${WORKDIR}/WebAppMgr.env ${D}${sysconfdir}/default/WebAppMgr.env
+ ln -snf WebAppMgr ${D}${bindir}/web-runtime
+ install -d ${D}${systemd_system_unitdir}/afm-user-session@.target.wants
+ ln -sf ../WebAppMgr@.service ${D}${systemd_system_unitdir}/afm-user-session@.target.wants/
+}
+
+RDEPENDS_${PN} += "wam-tinyproxy"
+FILES_${PN} += "${sysconfdir}/init ${sysconfdir}/wam ${libdir}/webappmanager/plugins/*.so ${systemd_system_unitdir}"
+
+CXXFLAGS_append_agl-devel = " -DAGL_DEVEL"
+
+do_install_append_agl-devel() {
+ # Enable remote inspector and dev mode
+ install -d ${D}${localstatedir}/agl-devel/preferences
+ touch ${D}${localstatedir}/agl-devel/preferences/debug_system_apps
+ touch ${D}${localstatedir}/agl-devel/preferences/devmode_enabled
+} \ No newline at end of file
diff --git a/meta-agl-devel/meta-oem-extra-libs/conf/layer.conf b/meta-agl-devel/meta-oem-extra-libs/conf/layer.conf
new file mode 100644
index 00000000..ebd705be
--- /dev/null
+++ b/meta-agl-devel/meta-oem-extra-libs/conf/layer.conf
@@ -0,0 +1,17 @@
+# 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 += "oem-extra-libs"
+BBFILE_PATTERN_oem-extra-libs = "^${LAYERDIR}/"
+BBFILE_PRIORITY_oem-extra-libs = "7"
+
+LAYERSERIES_COMPAT_oem-extra-libs = "thud"
+
+# Fixing build errors
+SECURITY_CFLAGS_pn-imagemagick = "${SECURITY_NO_PIE_CFLAGS}"
+SECURITY_CFLAGS_pn-protobuf = "${SECURITY_NO_PIE_CFLAGS}"
+
diff --git a/meta-agl-devel/meta-oem-extra-libs/recipes-connectivity/libwebsockets/libwebsockets_%.bbappend b/meta-agl-devel/meta-oem-extra-libs/recipes-connectivity/libwebsockets/libwebsockets_%.bbappend
new file mode 100644
index 00000000..d36c441d
--- /dev/null
+++ b/meta-agl-devel/meta-oem-extra-libs/recipes-connectivity/libwebsockets/libwebsockets_%.bbappend
@@ -0,0 +1 @@
+PACKAGECONFIG_remove = "libuv"
diff --git a/meta-agl-devel/meta-oem-extra-libs/recipes-connectivity/libwebsockets/libwebsockets_2.1.0.bb b/meta-agl-devel/meta-oem-extra-libs/recipes-connectivity/libwebsockets/libwebsockets_2.1.0.bb
new file mode 100644
index 00000000..93547998
--- /dev/null
+++ b/meta-agl-devel/meta-oem-extra-libs/recipes-connectivity/libwebsockets/libwebsockets_2.1.0.bb
@@ -0,0 +1,28 @@
+SUMMARY = "Canonical libwebsockets.org websocket library"
+HOMEPAGE = "https://libwebsockets.org/"
+LICENSE = "LGPL-2.1"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e3393a657830d4a118c5a6ed35ba53d0"
+
+DEPENDS = "zlib"
+
+SRC_URI = "https://github.com/warmcat/libwebsockets/archive/v${PV}.tar.gz"
+
+SRC_URI[md5sum] = "4df3be57dee43aeebd54a3ed56568f50"
+SRC_URI[sha256sum] = "bcc96aaa609daae4d3f7ab1ee480126709ef4f6a8bf9c85de40aae48e38cce66"
+
+inherit cmake pkgconfig
+
+PACKAGECONFIG ?= "libuv client server http2 ssl"
+PACKAGECONFIG[client] = "-DLWS_WITHOUT_CLIENT=OFF,-DLWS_WITHOUT_CLIENT=ON,"
+PACKAGECONFIG[http2] = "-DLWS_WITH_HTTP2=ON,-DLWS_WITH_HTTP2=OFF,"
+PACKAGECONFIG[ipv6] = "-DLWS_IPV6=ON,-DLWS_IPV6=OFF,"
+PACKAGECONFIG[libev] = "-DLWS_WITH_LIBEV=ON,-DLWS_WITH_LIBEV=OFF,libev"
+PACKAGECONFIG[libuv] = "-DLWS_WITH_LIBUV=ON,-DLWS_WITH_LIBUV=OFF,libuv"
+PACKAGECONFIG[server] = "-DLWS_WITHOUT_SERVER=OFF,-DLWS_WITHOUT_SERVER=ON,"
+PACKAGECONFIG[ssl] = "-DLWS_WITH_SSL=ON,-DLWS_WITH_SSL=OFF,openssl"
+PACKAGECONFIG[testapps] = "-DLWS_WITHOUT_TESTAPPS=OFF,-DLWS_WITHOUT_TESTAPPS=ON,"
+
+PACKAGES =+ "${PN}-testapps"
+
+FILES_${PN}-dev += "${libdir}/cmake"
+FILES_${PN}-testapps += "${datadir}/libwebsockets-test-server/*"
diff --git a/meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/files/CVE-2013-4420.patch b/meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/files/CVE-2013-4420.patch
new file mode 100644
index 00000000..477d130f
--- /dev/null
+++ b/meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/files/CVE-2013-4420.patch
@@ -0,0 +1,113 @@
+Author: Raphael Geissert <geissert@debian.org>
+Bug-Debian: https://bugs.debian.org/731860
+Description: Avoid directory traversal when extracting archives
+ by skipping over leading slashes and any prefix containing ".." components.
+Forwarded: yes
+
+--- a/lib/decode.c
++++ b/lib/decode.c
+@@ -22,13 +22,42 @@
+ # include <string.h>
+ #endif
+
++char *
++safer_name_suffix (char const *file_name)
++{
++ char const *p, *t;
++ p = t = file_name;
++ while (*p == '/') t = ++p;
++ while (*p)
++ {
++ while (p[0] == '.' && p[0] == p[1] && p[2] == '/')
++ {
++ p += 3;
++ t = p;
++ }
++ /* advance pointer past the next slash */
++ while (*p && (p++)[0] != '/');
++ }
++
++ if (!*t)
++ {
++ t = ".";
++ }
++
++ if (t != file_name)
++ {
++ /* TODO: warn somehow that the path was modified */
++ }
++ return (char*)t;
++}
++
+
+ /* determine full path name */
+ char *
+ th_get_pathname(TAR *t)
+ {
+ if (t->th_buf.gnu_longname)
+- return t->th_buf.gnu_longname;
++ return safer_name_suffix(t->th_buf.gnu_longname);
+
+ /* allocate the th_pathname buffer if not already */
+ if (t->th_pathname == NULL)
+@@ -51,7 +80,7 @@ th_get_pathname(TAR *t)
+ }
+
+ /* will be deallocated in tar_close() */
+- return t->th_pathname;
++ return safer_name_suffix(t->th_pathname);
+ }
+
+
+--- a/lib/extract.c
++++ b/lib/extract.c
+@@ -298,14 +298,14 @@ tar_extract_hardlink(TAR * t, char *real
+ if (mkdirhier(dirname(filename)) == -1)
+ return -1;
+ libtar_hashptr_reset(&hp);
+- if (libtar_hash_getkey(t->h, &hp, th_get_linkname(t),
++ if (libtar_hash_getkey(t->h, &hp, safer_name_suffix(th_get_linkname(t)),
+ (libtar_matchfunc_t)libtar_str_match) != 0)
+ {
+ lnp = (char *)libtar_hashptr_data(&hp);
+ linktgt = &lnp[strlen(lnp) + 1];
+ }
+ else
+- linktgt = th_get_linkname(t);
++ linktgt = safer_name_suffix(th_get_linkname(t));
+
+ #ifdef DEBUG
+ printf(" ==> extracting: %s (link to %s)\n", filename, linktgt);
+@@ -343,9 +343,9 @@ tar_extract_symlink(TAR *t, char *realna
+
+ #ifdef DEBUG
+ printf(" ==> extracting: %s (symlink to %s)\n",
+- filename, th_get_linkname(t));
++ filename, safer_name_suffix(th_get_linkname(t)));
+ #endif
+- if (symlink(th_get_linkname(t), filename) == -1)
++ if (symlink(safer_name_suffix(th_get_linkname(t)), filename) == -1)
+ {
+ #ifdef DEBUG
+ perror("symlink()");
+--- a/lib/internal.h
++++ b/lib/internal.h
+@@ -21,3 +21,4 @@
+ #define TLS_THREAD
+ #endif
+
++char* safer_name_suffix(char const*);
+--- a/lib/output.c
++++ b/lib/output.c
+@@ -123,9 +123,9 @@ th_print_long_ls(TAR *t)
+ else
+ printf(" link to ");
+ if ((t->options & TAR_GNU) && t->th_buf.gnu_longlink != NULL)
+- printf("%s", t->th_buf.gnu_longlink);
++ printf("%s", safer_name_suffix(t->th_buf.gnu_longlink));
+ else
+- printf("%.100s", t->th_buf.linkname);
++ printf("%.100s", safer_name_suffix(t->th_buf.linkname));
+ }
+
+ putchar('\n');
diff --git a/meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/files/no_maxpathlen.patch b/meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/files/no_maxpathlen.patch
new file mode 100644
index 00000000..104dc4cd
--- /dev/null
+++ b/meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/files/no_maxpathlen.patch
@@ -0,0 +1,491 @@
+Author: Svante Signell <svante.signell@telia.com>
+Author: Petter Reinholdtsen <pere@hungry.com>
+Author: Magnus Holmgren <magnus@debian.org>
+Bug-Debian: http://bugs.debian.org/657116
+Description: Fix FTBFS on Hurd by dynamically allocating path names.
+ Depends on no_static_buffers.patch, which introduced the th_pathname field.
+
+--- a/compat/basename.c
++++ b/compat/basename.c
+@@ -34,13 +34,25 @@ static char rcsid[] = "$OpenBSD: basenam
+ #include <errno.h>
+ #include <string.h>
+ #include <sys/param.h>
++#include <stdlib.h>
+
+ char *
+ openbsd_basename(path)
+ const char *path;
+ {
+- static char bname[MAXPATHLEN];
++ static char *bname = NULL;
++ static size_t allocated = 0;
+ register const char *endp, *startp;
++ int len = 0;
++
++ if (!allocated) {
++ allocated = 64;
++ bname = malloc(allocated);
++ if (!bname) {
++ allocated = 0;
++ return NULL;
++ }
++ }
+
+ /* Empty or NULL string gets treated as "." */
+ if (path == NULL || *path == '\0') {
+@@ -64,11 +76,19 @@ openbsd_basename(path)
+ while (startp > path && *(startp - 1) != '/')
+ startp--;
+
+- if (endp - startp + 1 > sizeof(bname)) {
+- errno = ENAMETOOLONG;
+- return(NULL);
++ len = endp - startp + 1;
++
++ if (len + 1 > allocated) {
++ size_t new_allocated = 2*(len+1);
++ void *new_bname = malloc(new_allocated);
++ if (!new_bname)
++ return NULL;
++ allocated = new_allocated;
++ free(bname);
++ bname = new_bname;
+ }
+- (void)strncpy(bname, startp, endp - startp + 1);
+- bname[endp - startp + 1] = '\0';
++
++ (void)strncpy(bname, startp, len);
++ bname[len] = '\0';
+ return(bname);
+ }
+--- a/compat/dirname.c
++++ b/compat/dirname.c
+@@ -34,13 +34,25 @@ static char rcsid[] = "$OpenBSD: dirname
+ #include <errno.h>
+ #include <string.h>
+ #include <sys/param.h>
++#include <stdlib.h>
+
+ char *
+ openbsd_dirname(path)
+ const char *path;
+ {
+- static char bname[MAXPATHLEN];
++ static char *bname = NULL;
++ static size_t allocated = 0;
+ register const char *endp;
++ int len;
++
++ if (!allocated) {
++ allocated = 64;
++ bname = malloc(allocated);
++ if (!bname) {
++ allocated = 0;
++ return NULL;
++ }
++ }
+
+ /* Empty or NULL string gets treated as "." */
+ if (path == NULL || *path == '\0') {
+@@ -67,11 +79,19 @@ openbsd_dirname(path)
+ } while (endp > path && *endp == '/');
+ }
+
+- if (endp - path + 1 > sizeof(bname)) {
+- errno = ENAMETOOLONG;
+- return(NULL);
++ len = endp - path + 1;
++
++ if (len + 1 > allocated) {
++ size_t new_allocated = 2*(len+1);
++ void *new_bname = malloc(new_allocated);
++ if (!new_bname)
++ return NULL;
++ allocated = new_allocated;
++ free(bname);
++ bname = new_bname;
+ }
+- (void)strncpy(bname, path, endp - path + 1);
+- bname[endp - path + 1] = '\0';
++
++ (void)strncpy(bname, path, len);
++ bname[len] = '\0';
+ return(bname);
+ }
+--- a/lib/append.c
++++ b/lib/append.c
+@@ -38,7 +38,7 @@ typedef struct tar_dev tar_dev_t;
+ struct tar_ino
+ {
+ ino_t ti_ino;
+- char ti_name[MAXPATHLEN];
++ char ti_name[];
+ };
+ typedef struct tar_ino tar_ino_t;
+
+@@ -61,7 +61,7 @@ tar_append_file(TAR *t, const char *real
+ libtar_hashptr_t hp;
+ tar_dev_t *td = NULL;
+ tar_ino_t *ti = NULL;
+- char path[MAXPATHLEN];
++ char *path = NULL;
+
+ #ifdef DEBUG
+ printf("==> tar_append_file(TAR=0x%lx (\"%s\"), realname=\"%s\", "
+@@ -126,34 +126,39 @@ tar_append_file(TAR *t, const char *real
+ }
+ else
+ {
++ const char *name;
+ #ifdef DEBUG
+ printf("+++ adding entry: device (0x%lx,0x%lx), inode %ld "
+ "(\"%s\")...\n", major(s.st_dev), minor(s.st_dev),
+ s.st_ino, realname);
+ #endif
+- ti = (tar_ino_t *)calloc(1, sizeof(tar_ino_t));
++ name = savename ? savename : realname;
++ ti = (tar_ino_t *)calloc(1, sizeof(tar_ino_t) + strlen(name) + 1);
+ if (ti == NULL)
+ return -1;
+ ti->ti_ino = s.st_ino;
+- snprintf(ti->ti_name, sizeof(ti->ti_name), "%s",
+- savename ? savename : realname);
++ snprintf(ti->ti_name, strlen(name) + 1, "%s", name);
+ libtar_hash_add(td->td_h, ti);
+ }
+
+ /* check if it's a symlink */
+ if (TH_ISSYM(t))
+ {
+- i = readlink(realname, path, sizeof(path));
++ if ((path = malloc(s.st_size + 1)) == NULL)
++ return -1;
++ i = readlink(realname, path, s.st_size);
+ if (i == -1)
++ {
++ free(path);
+ return -1;
+- if (i >= MAXPATHLEN)
+- i = MAXPATHLEN - 1;
++ }
+ path[i] = '\0';
+ #ifdef DEBUG
+ printf(" tar_append_file(): encoding symlink \"%s\" -> "
+ "\"%s\"...\n", realname, path);
+ #endif
+ th_set_link(t, path);
++ free(path);
+ }
+
+ /* print file info */
+--- a/lib/decode.c
++++ b/lib/decode.c
+@@ -33,7 +33,8 @@ th_get_pathname(TAR *t)
+ /* allocate the th_pathname buffer if not already */
+ if (t->th_pathname == NULL)
+ {
+- t->th_pathname = malloc(MAXPATHLEN * sizeof(char));
++ /* Allocate the maximum length of prefix + '/' + name + '\0' */
++ t->th_pathname = malloc(155 + 1 + 100 + 1);
+ if (t->th_pathname == NULL)
+ /* out of memory */
+ return NULL;
+@@ -41,11 +42,11 @@ th_get_pathname(TAR *t)
+
+ if (t->th_buf.prefix[0] == '\0')
+ {
+- snprintf(t->th_pathname, MAXPATHLEN, "%.100s", t->th_buf.name);
++ sprintf(t->th_pathname, "%.100s", t->th_buf.name);
+ }
+ else
+ {
+- snprintf(t->th_pathname, MAXPATHLEN, "%.155s/%.100s",
++ sprintf(t->th_pathname, "%.155s/%.100s",
+ t->th_buf.prefix, t->th_buf.name);
+ }
+
+--- a/lib/util.c
++++ b/lib/util.c
+@@ -15,6 +15,7 @@
+ #include <stdio.h>
+ #include <sys/param.h>
+ #include <errno.h>
++#include <stdlib.h>
+
+ #ifdef STDC_HEADERS
+ # include <string.h>
+@@ -25,13 +26,15 @@
+ int
+ path_hashfunc(char *key, int numbuckets)
+ {
+- char buf[MAXPATHLEN];
++ char *buf;
+ char *p;
++ int i;
+
+- strcpy(buf, key);
++ buf = strdup(key);
+ p = basename(buf);
+-
+- return (((unsigned int)p[0]) % numbuckets);
++ i = ((unsigned int)p[0]) % numbuckets;
++ free(buf);
++ return (i);
+ }
+
+
+@@ -77,15 +80,26 @@ ino_hash(ino_t *inode)
+ int
+ mkdirhier(char *path)
+ {
+- char src[MAXPATHLEN], dst[MAXPATHLEN] = "";
+- char *dirp, *nextp = src;
+- int retval = 1;
++ char *src, *dst = NULL;
++ char *dirp, *nextp = NULL;
++ int retval = 1, len;
++
++ len = strlen(path);
++ if ((src = strdup(path)) == NULL)
++ {
++ errno = ENOMEM;
++ return -1;
++ }
++ nextp = src;
+
+- if (strlcpy(src, path, sizeof(src)) > sizeof(src))
++ /* Make room for // with absolute paths */
++ if ((dst = malloc(len + 2)) == NULL)
+ {
+- errno = ENAMETOOLONG;
++ free(src);
++ errno = ENOMEM;
+ return -1;
+ }
++ dst[0] = '\0';
+
+ if (path[0] == '/')
+ strcpy(dst, "/");
+@@ -102,12 +116,18 @@ mkdirhier(char *path)
+ if (mkdir(dst, 0777) == -1)
+ {
+ if (errno != EEXIST)
++ {
++ free(src);
++ free(dst);
+ return -1;
++ }
+ }
+ else
+ retval = 0;
+ }
+
++ free(src);
++ free(dst);
+ return retval;
+ }
+
+--- a/lib/wrapper.c
++++ b/lib/wrapper.c
+@@ -16,6 +16,7 @@
+ #include <sys/param.h>
+ #include <dirent.h>
+ #include <errno.h>
++#include <stdlib.h>
+
+ #ifdef STDC_HEADERS
+ # include <string.h>
+@@ -26,8 +27,8 @@ int
+ tar_extract_glob(TAR *t, char *globname, char *prefix)
+ {
+ char *filename;
+- char buf[MAXPATHLEN];
+- int i;
++ char *buf = NULL;
++ int i, len;
+
+ while ((i = th_read(t)) == 0)
+ {
+@@ -41,11 +42,25 @@ tar_extract_glob(TAR *t, char *globname,
+ if (t->options & TAR_VERBOSE)
+ th_print_long_ls(t);
+ if (prefix != NULL)
+- snprintf(buf, sizeof(buf), "%s/%s", prefix, filename);
++ {
++ len = strlen(prefix) + 1 + strlen(filename);
++ if ((buf = malloc(len + 1)) == NULL)
++ return -1;
++ sprintf(buf, "%s/%s", prefix, filename);
++ }
+ else
+- strlcpy(buf, filename, sizeof(buf));
++ {
++ len = strlen(filename);
++ if ((buf = malloc(len + 1)) == NULL)
++ return -1;
++ strcpy(buf, filename);
++ }
+ if (tar_extract_file(t, buf) != 0)
++ {
++ free(buf);
+ return -1;
++ }
++ free(buf);
+ }
+
+ return (i == 1 ? 0 : -1);
+@@ -56,8 +71,9 @@ int
+ tar_extract_all(TAR *t, char *prefix)
+ {
+ char *filename;
+- char buf[MAXPATHLEN];
+- int i;
++ char *buf = NULL;
++ size_t bufsize = 0;
++ int i, len;
+
+ #ifdef DEBUG
+ printf("==> tar_extract_all(TAR *t, \"%s\")\n",
+@@ -73,15 +89,29 @@ tar_extract_all(TAR *t, char *prefix)
+ if (t->options & TAR_VERBOSE)
+ th_print_long_ls(t);
+ if (prefix != NULL)
+- snprintf(buf, sizeof(buf), "%s/%s", prefix, filename);
++ {
++ len = strlen(prefix) + 1 + strlen(filename);
++ if ((buf = malloc(len + 1)) == NULL)
++ return -1;
++ sprintf(buf, "%s/%s", prefix, filename);
++ }
+ else
+- strlcpy(buf, filename, sizeof(buf));
++ {
++ len = strlen(filename);
++ if ((buf = malloc(len + 1)) == NULL)
++ return -1;
++ strcpy(buf, filename);
++ }
+ #ifdef DEBUG
+ printf(" tar_extract_all(): calling tar_extract_file(t, "
+ "\"%s\")\n", buf);
+ #endif
+ if (tar_extract_file(t, buf) != 0)
++ {
++ free(buf);
+ return -1;
++ }
++ free(buf);
+ }
+
+ return (i == 1 ? 0 : -1);
+@@ -91,11 +121,14 @@ tar_extract_all(TAR *t, char *prefix)
+ int
+ tar_append_tree(TAR *t, char *realdir, char *savedir)
+ {
+- char realpath[MAXPATHLEN];
+- char savepath[MAXPATHLEN];
++ char *realpath = NULL;
++ size_t realpathsize = 0;
++ char *savepath = NULL;
++ size_t savepathsize = 0;
+ struct dirent *dent;
+ DIR *dp;
+ struct stat s;
++ int len;
+
+ #ifdef DEBUG
+ printf("==> tar_append_tree(0x%lx, \"%s\", \"%s\")\n",
+@@ -122,11 +155,21 @@ tar_append_tree(TAR *t, char *realdir, c
+ strcmp(dent->d_name, "..") == 0)
+ continue;
+
+- snprintf(realpath, MAXPATHLEN, "%s/%s", realdir,
++ len = strlen(realdir) + 1 + strlen(dent->d_name);
++ if ((realpath = malloc(len + 1)) == NULL)
++ return -1;
++ snprintf(realpath, len + 1, "%s/%s", realdir,
+ dent->d_name);
+ if (savedir)
+- snprintf(savepath, MAXPATHLEN, "%s/%s", savedir,
++ {
++ len = strlen(savedir) + 1 + strlen(dent->d_name);
++ if ((savepath = malloc(len + 1)) == NULL) {
++ free(realpath);
++ return -1;
++ }
++ snprintf(savepath, len + 1, "%s/%s", savedir,
+ dent->d_name);
++ }
+
+ if (lstat(realpath, &s) != 0)
+ return -1;
+@@ -135,13 +178,23 @@ tar_append_tree(TAR *t, char *realdir, c
+ {
+ if (tar_append_tree(t, realpath,
+ (savedir ? savepath : NULL)) != 0)
++ {
++ free(realpath);
++ free(savepath);
+ return -1;
++ }
+ continue;
+ }
+
+ if (tar_append_file(t, realpath,
+ (savedir ? savepath : NULL)) != 0)
++ {
++ free(realpath);
++ free(savepath);
+ return -1;
++ }
++ free(realpath);
++ free(savepath);
+ }
+
+ closedir(dp);
+--- a/libtar/libtar.c
++++ b/libtar/libtar.c
+@@ -111,8 +111,9 @@ create(char *tarfile, char *rootdir, lib
+ {
+ TAR *t;
+ char *pathname;
+- char buf[MAXPATHLEN];
++ char *buf = NULL;
+ libtar_listptr_t lp;
++ int len;
+
+ if (tar_open(&t, tarfile,
+ #ifdef HAVE_LIBZ
+@@ -133,17 +134,29 @@ create(char *tarfile, char *rootdir, lib
+ {
+ pathname = (char *)libtar_listptr_data(&lp);
+ if (pathname[0] != '/' && rootdir != NULL)
+- snprintf(buf, sizeof(buf), "%s/%s", rootdir, pathname);
++ {
++ len = strlen(rootdir) + 1 + strlen(pathname);
++ if ((buf = malloc(len + 1)) == NULL)
++ return -1;
++ snprintf(buf, len + 1, "%s/%s", rootdir, pathname);
++ }
+ else
+- strlcpy(buf, pathname, sizeof(buf));
++ {
++ len = strlen(pathname);
++ if ((buf = malloc(len + 1)) == NULL)
++ return -1;
++ strlcpy(buf, pathname, len + 1);
++ }
+ if (tar_append_tree(t, buf, pathname) != 0)
+ {
+ fprintf(stderr,
+ "tar_append_tree(\"%s\", \"%s\"): %s\n", buf,
+ pathname, strerror(errno));
+ tar_close(t);
++ free(buf);
+ return -1;
+ }
++ free(buf);
+ }
+
+ if (tar_append_eof(t) != 0)
diff --git a/meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/files/no_static_buffers.patch b/meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/files/no_static_buffers.patch
new file mode 100644
index 00000000..548d7518
--- /dev/null
+++ b/meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/files/no_static_buffers.patch
@@ -0,0 +1,82 @@
+From: Kamil Dudka <kdudka@redhat.com>
+Date: Wed, 23 Oct 2013 13:04:22 +0000 (+0200)
+Origin: http://repo.or.cz/w/libtar.git/commitdiff/ec613af2e9371d7a3e1f7c7a6822164a4255b4d1
+Subject: decode: avoid using a static buffer in th_get_pathname()
+
+decode: avoid using a static buffer in th_get_pathname()
+
+A solution suggested by Chris Frey:
+https://lists.feep.net:8080/pipermail/libtar/2013-October/000377.html
+
+Note this can break programs that expect sizeof(TAR) to be fixed.
+
+--- a/lib/decode.c
++++ b/lib/decode.c
+@@ -13,6 +13,7 @@
+ #include <internal.h>
+
+ #include <stdio.h>
++#include <stdlib.h>
+ #include <sys/param.h>
+ #include <pwd.h>
+ #include <grp.h>
+@@ -26,20 +27,30 @@
+ char *
+ th_get_pathname(TAR *t)
+ {
+- static TLS_THREAD char filename[MAXPATHLEN];
+-
+ if (t->th_buf.gnu_longname)
+ return t->th_buf.gnu_longname;
+
+- if (t->th_buf.prefix[0] != '\0')
++ /* allocate the th_pathname buffer if not already */
++ if (t->th_pathname == NULL)
++ {
++ t->th_pathname = malloc(MAXPATHLEN * sizeof(char));
++ if (t->th_pathname == NULL)
++ /* out of memory */
++ return NULL;
++ }
++
++ if (t->th_buf.prefix[0] == '\0')
++ {
++ snprintf(t->th_pathname, MAXPATHLEN, "%.100s", t->th_buf.name);
++ }
++ else
+ {
+- snprintf(filename, sizeof(filename), "%.155s/%.100s",
++ snprintf(t->th_pathname, MAXPATHLEN, "%.155s/%.100s",
+ t->th_buf.prefix, t->th_buf.name);
+- return filename;
+ }
+
+- snprintf(filename, sizeof(filename), "%.100s", t->th_buf.name);
+- return filename;
++ /* will be deallocated in tar_close() */
++ return t->th_pathname;
+ }
+
+
+--- a/lib/handle.c
++++ b/lib/handle.c
+@@ -121,6 +121,7 @@ tar_close(TAR *t)
+ libtar_hash_free(t->h, ((t->oflags & O_ACCMODE) == O_RDONLY
+ ? free
+ : (libtar_freefunc_t)tar_dev_free));
++ free(t->th_pathname);
+ free(t);
+
+ return i;
+--- a/lib/libtar.h
++++ b/lib/libtar.h
+@@ -85,6 +85,9 @@ typedef struct
+ int options;
+ struct tar_header th_buf;
+ libtar_hash_t *h;
++
++ /* introduced in libtar 1.2.21 */
++ char *th_pathname;
+ }
+ TAR;
+
diff --git a/meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/files/no_strip.patch b/meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/files/no_strip.patch
new file mode 100644
index 00000000..a3187285
--- /dev/null
+++ b/meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/files/no_strip.patch
@@ -0,0 +1,24 @@
+Description: make install must not strip binaries
+
+--- a/lib/Makefile.in
++++ b/lib/Makefile.in
+@@ -20,7 +20,7 @@ SHELL = @SHELL@
+
+ ### Installation programs and flags
+ INSTALL = @INSTALL@
+-INSTALL_PROGRAM = @INSTALL_PROGRAM@ -s
++INSTALL_PROGRAM = @INSTALL_PROGRAM@
+ INSTALL_DATA = @INSTALL_DATA@
+ LN_S = @LN_S@
+ MKDIR = @MKDIR@
+--- a/libtar/Makefile.in
++++ b/libtar/Makefile.in
+@@ -20,7 +20,7 @@ SHELL = @SHELL@
+
+ ### Installation programs and flags
+ INSTALL = @INSTALL@
+-INSTALL_PROGRAM = @INSTALL_PROGRAM@ -s
++INSTALL_PROGRAM = @INSTALL_PROGRAM@
+ INSTALL_DATA = @INSTALL_DATA@
+ LN_S = @LN_S@
+ MKDIR = @MKDIR@
diff --git a/meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/files/oldgnu_prefix.patch b/meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/files/oldgnu_prefix.patch
new file mode 100644
index 00000000..99ab509e
--- /dev/null
+++ b/meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/files/oldgnu_prefix.patch
@@ -0,0 +1,21 @@
+Description: Detect old-style GNU headers correctly
+Author: Steinar H. Gunderson <sesse@debian.org>
+
+--- libtar-1.2.20.orig/lib/decode.c
++++ libtar-1.2.20/lib/decode.c
+@@ -69,7 +69,14 @@ th_get_pathname(TAR *t)
+ return NULL;
+ }
+
+- if (t->th_buf.prefix[0] == '\0')
++ /*
++ * Old GNU headers (also used by newer GNU tar when doing incremental
++ * dumps) use the POSIX prefix field for many other things, such as
++ * mtime and ctime. New-style GNU headers don't, but also don't use the
++ * POSIX prefix field. Thus, only honor the prefix field if the archive
++ * is actually a POSIX archive. This is the same logic as GNU tar uses.
++ */
++ if (strncmp(t->th_buf.magic, TMAGIC, TMAGLEN - 1) != 0 || t->th_buf.prefix[0] == '\0')
+ {
+ sprintf(t->th_pathname, "%.100s", t->th_buf.name);
+ }
diff --git a/meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/files/series b/meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/files/series
new file mode 100644
index 00000000..617ca258
--- /dev/null
+++ b/meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/files/series
@@ -0,0 +1,7 @@
+no_static_buffers.patch
+no_maxpathlen.patch
+CVE-2013-4420.patch
+th_get_size-unsigned-int.patch
+oldgnu_prefix.patch
+testsuite.patch
+no_strip.patch
diff --git a/meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/files/testsuite.patch b/meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/files/testsuite.patch
new file mode 100644
index 00000000..e8be9321
--- /dev/null
+++ b/meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/files/testsuite.patch
@@ -0,0 +1,50 @@
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -10,5 +10,5 @@ ACLOCAL_AMFLAGS = -I autoconf
+
+ #@SET_MAKE@
+
+-SUBDIRS = lib libtar doc
++SUBDIRS = lib libtar doc testsuite
+
+--- a/doc/Makefile.in
++++ b/doc/Makefile.in
+@@ -151,3 +151,4 @@ install: all
+ echo ".so man3/@LISTHASH_PREFIX@_list_new.3" > ${DESTDIR}${mandir}/man3/$${i}.3; \
+ done
+
++check:
+--- a/lib/Makefile.in
++++ b/lib/Makefile.in
+@@ -104,3 +104,4 @@ install: ${ALL}
+ ${INSTALL_DATA} ${srcdir}/libtar.h ${DESTDIR}${includedir}
+ ${INSTALL_DATA} ../listhash/libtar_listhash.h ${DESTDIR}${includedir}
+
++check:
+--- a/libtar/Makefile.in
++++ b/libtar/Makefile.in
+@@ -76,3 +76,4 @@ install: ${ALL}
+ ${MKDIR} ${DESTDIR}${bindir}
+ $(LIBTOOL) --mode=install ${INSTALL_PROGRAM} libtar ${DESTDIR}${bindir}
+
++check:
+--- /dev/null
++++ b/testsuite/Makefile.in
+@@ -0,0 +1,7 @@
++all:
++
++check: ../libtar/libtar
++ ../libtar/libtar -C ../doc -c test.tar .
++ ../libtar/libtar -t test.tar
++ $(RM) test.tar
++install:
+--- a/configure.ac
++++ b/configure.ac
+@@ -120,6 +120,6 @@ fi
+
+
+ dnl ### Create output files. #######################################
+-AC_CONFIG_FILES([Makefile lib/Makefile libtar/Makefile doc/Makefile])
++AC_CONFIG_FILES([Makefile lib/Makefile libtar/Makefile doc/Makefile testsuite/Makefile])
+ AC_OUTPUT
+
diff --git a/meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/files/th_get_size-unsigned-int.patch b/meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/files/th_get_size-unsigned-int.patch
new file mode 100644
index 00000000..e12ca914
--- /dev/null
+++ b/meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/files/th_get_size-unsigned-int.patch
@@ -0,0 +1,52 @@
+Origin: http://repo.or.cz/w/libtar.git/commitdiff/e4c1f2974258d6a325622cfd712873d49b5e7a73
+From: Chris Frey <cdfrey@foursquare.net>
+Date: Thu, 24 Oct 2013 18:52:44 -0400
+Subject: [PATCH] Change th_get_size() macro to return unsigned int
+
+On systems where size_t is larger than an int (and larger than
+unsigned int), then in various places in the library, where
+stuff like this happens:
+
+ size_t sz = th_get_size(t);
+
+then the int value returned from th_get_size() is sign extended to
+some unwieldy amount.
+
+On 64bit systems, this can yield extremely large values.
+
+By fixing this problem in the header, and only for th_get_size(),
+we avoid breaking the API of the function call oct_to_int()
+(which arguably should return an unsigned int, since the sscanf()
+it uses expects to yield an unsigned int). We also fix the library,
+which uses th_get_size() internally to assign sizes to size_t.
+
+The drawback is that not all client code that uses th_get_size()
+will be fixed, until they recompile, but they will automatically
+take advantage of the bugs fixed *inside* the library.
+
+The remaining th_get_*() functions operate on modes and CRC values
+and the like, and should be fine, remaining as ints.
+
+Thanks very much to Magnus Holmgren for catching this behaviour.
+https://lists.feep.net:8080/pipermail/libtar/2013-October/000365.html
+---
+ lib/libtar.h | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/lib/libtar.h b/lib/libtar.h
+index 2fefee0..13bb82d 100644
+--- a/lib/libtar.h
++++ b/lib/libtar.h
+@@ -185,7 +185,11 @@ int th_write(TAR *t);
+
+ /* decode tar header info */
+ #define th_get_crc(t) oct_to_int((t)->th_buf.chksum)
+-#define th_get_size(t) oct_to_int((t)->th_buf.size)
++/* We cast from int (what oct_to_int() returns) to
++ unsigned int, to avoid unwieldy sign extensions
++ from occurring on systems where size_t is bigger than int,
++ since th_get_size() is often stored into a size_t. */
++#define th_get_size(t) ((unsigned int)oct_to_int((t)->th_buf.size))
+ #define th_get_mtime(t) oct_to_int((t)->th_buf.mtime)
+ #define th_get_devmajor(t) oct_to_int((t)->th_buf.devmajor)
+ #define th_get_devminor(t) oct_to_int((t)->th_buf.devminor)
diff --git a/meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/libtar_1.2.20.bb b/meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/libtar_1.2.20.bb
new file mode 100644
index 00000000..904f5c60
--- /dev/null
+++ b/meta-agl-devel/meta-oem-extra-libs/recipes-core/libtar/libtar_1.2.20.bb
@@ -0,0 +1,31 @@
+SUMMARY = "libtar, tar manipulating library"
+DESCRIPTION = "libtar is a library for manipulating POSIX tar files"
+HOMEPAGE = "http://www.feep.net/libtar"
+SECTION = "libs"
+LICENSE = "NCSA"
+LIC_FILES_CHKSUM = "file://COPYRIGHT;md5=61cbac6719ae682ce6cd45b5c11e21af"
+
+# Source and patches taken from debian check there for changes.
+# Check http://repo.or.cz/w/libtar.git/ as upstream.
+# More patches found here: https://github.com/tklauser/libtar
+#
+SRC_URI = "http://httpredir.debian.org/debian/pool/main/libt/libtar/libtar_${PV}.orig.tar.gz"
+SRC_URI += "file://no_static_buffers.patch"
+SRC_URI += "file://no_maxpathlen.patch"
+SRC_URI += "file://CVE-2013-4420.patch"
+SRC_URI += "file://th_get_size-unsigned-int.patch"
+SRC_URI += "file://oldgnu_prefix.patch"
+SRC_URI += "file://testsuite.patch"
+SRC_URI += "file://no_strip.patch"
+
+SRC_URI[md5sum] = "6ced95ab3a4b33fbfe2dfb231d156cdb"
+SRC_URI[sha256sum] = "50f24c857a7ef1cb092e6508758b86d06f1188508f897f3e6b40c573e8879109"
+
+# tarball does not contain PV
+S = "${WORKDIR}/${PN}"
+
+CFLAGS_append = " -DHAVE_STDARG_H"
+
+RDEPENDS_${PN} += "zlib"
+
+inherit autotools
diff --git a/meta-agl-devel/meta-oem-extra-libs/recipes-core/packagegroups/nativesdk-packagegroup-sdk-host.bbappend b/meta-agl-devel/meta-oem-extra-libs/recipes-core/packagegroups/nativesdk-packagegroup-sdk-host.bbappend
new file mode 100644
index 00000000..33ca38ae
--- /dev/null
+++ b/meta-agl-devel/meta-oem-extra-libs/recipes-core/packagegroups/nativesdk-packagegroup-sdk-host.bbappend
@@ -0,0 +1 @@
+RDEPENDS_${PN} =+ "nativesdk-protobuf-dev"
diff --git a/meta-agl-devel/meta-oem-extra-libs/recipes-core/packagegroups/packagegroup-ivi-common-core-os-commonlibs.bbappend b/meta-agl-devel/meta-oem-extra-libs/recipes-core/packagegroups/packagegroup-ivi-common-core-os-commonlibs.bbappend
new file mode 100644
index 00000000..c2de93c1
--- /dev/null
+++ b/meta-agl-devel/meta-oem-extra-libs/recipes-core/packagegroups/packagegroup-ivi-common-core-os-commonlibs.bbappend
@@ -0,0 +1,53 @@
+RDEPENDS_${PN} += "\
+ boost \
+ boost-atomic \
+ boost-chrono \
+ boost-date-time \
+ boost-dev \
+ boost-filesystem \
+ boost-graph \
+ boost-iostreams \
+ boost-log \
+ boost-program-options \
+ boost-random \
+ boost-regex \
+ boost-serialization \
+ boost-signals \
+ boost-staticdev \
+ boost-system \
+ boost-test \
+ boost-thread \
+ boost-timer \
+ fixesproto-dev \
+ imagemagick \
+ iptables \
+ libtar \
+ libtar-dev \
+ util-macros \
+ zlib \
+ glibc \
+ curl \
+ giflib \
+ neon \
+ mongoose \
+ fuse \
+ protobuf \
+ bsdiff \
+ kmod \
+ libcroco \
+ tiff \
+ librsvg \
+ libpcap \
+ iputils \
+ net-tools \
+ pixman \
+ bluez5 \
+ speex \
+ glib-2.0 \
+ libogg \
+ thrift \
+ ppp \
+ libdatrie \
+ libthai \
+ libwebsockets \
+"
diff --git a/meta-agl-devel/meta-oem-extra-libs/recipes-devtools/bsdiff/bsdiff_git.bb b/meta-agl-devel/meta-oem-extra-libs/recipes-devtools/bsdiff/bsdiff_git.bb
new file mode 100644
index 00000000..8eb72719
--- /dev/null
+++ b/meta-agl-devel/meta-oem-extra-libs/recipes-devtools/bsdiff/bsdiff_git.bb
@@ -0,0 +1,19 @@
+SUMMARY = "Binary delta tools and library"
+HOMEPAGE = "https://github.com/clearlinux/bsdiff"
+LICENSE = "BSD"
+LIC_FILES_CHKSUM = "file://COPYING;md5=0dbe7a50f028269750631fcbded3846a"
+
+SRC_URI = "git://github.com/clearlinux/bsdiff.git;protocol=https"
+
+PV = "1.0.1+git${SRCPV}"
+SRCREV = "8c0a87b7c9eb5b22ed4e03a4eb42b32bd390df14"
+
+S = "${WORKDIR}/git"
+
+DEPENDS = "xz bzip2 zlib libcheck"
+
+inherit pkgconfig autotools
+
+EXTRA_OECONF = "--disable-tests"
+
+BBCLASSEXTEND = "native"
diff --git a/meta-agl-devel/meta-oem-extra-libs/recipes-support/imagemagick/imagemagick_%.bbappend b/meta-agl-devel/meta-oem-extra-libs/recipes-support/imagemagick/imagemagick_%.bbappend
new file mode 100644
index 00000000..2fa9538e
--- /dev/null
+++ b/meta-agl-devel/meta-oem-extra-libs/recipes-support/imagemagick/imagemagick_%.bbappend
@@ -0,0 +1,2 @@
+DEPENDS_append = " libxml2 libxml2-native"
+EXTRA_OECONF_append = " --with-xml"
diff --git a/meta-agl-devel/meta-oem-extra-libs/recipes-support/libdatrie/libdatrie_0.2.9.bb b/meta-agl-devel/meta-oem-extra-libs/recipes-support/libdatrie/libdatrie_0.2.9.bb
new file mode 100755
index 00000000..44fd0b47
--- /dev/null
+++ b/meta-agl-devel/meta-oem-extra-libs/recipes-support/libdatrie/libdatrie_0.2.9.bb
@@ -0,0 +1,28 @@
+#
+# No base recipe
+#
+
+DESCRIPTION = "datrie is an implementation of double-array structure \
+for representing trie, as proposed by Junichi Aoe."
+HOMEPAGE = "http://linux.thai.net/projects/libthai"
+
+PR = "r0"
+
+inherit autotools pkgconfig
+
+LICENSE = "LGPL-2.1"
+LIC_FILES_CHKSUM = "file://COPYING;md5=2d5025d4aa3495befef8f17206a5b0a1"
+
+SRC_URI = "http://linux.thai.net/pub/thailinux/software/libthai/${BPN}-${PV}.tar.xz"
+
+SRC_URI[md5sum] = "687624f374e748de81b01399736bb735"
+SRC_URI[sha256sum] = "d980713e7ad8e19cf3b54ee0173782b94332af8e7e4e936dde01d2cd72e1da1d"
+
+
+# Add more packages
+PACKAGES =+ "${PN}1-bin"
+
+FILES_${PN}1-bin += "${bindir}/*"
+
+BBCLASSEXTEND += "native"
+
diff --git a/meta-agl-devel/meta-oem-extra-libs/recipes-support/libthai/libthai_0.1.20.bb b/meta-agl-devel/meta-oem-extra-libs/recipes-support/libthai/libthai_0.1.20.bb
new file mode 100755
index 00000000..0271da08
--- /dev/null
+++ b/meta-agl-devel/meta-oem-extra-libs/recipes-support/libthai/libthai_0.1.20.bb
@@ -0,0 +1,13 @@
+DESCRIPTION = "Thai language support routines"
+LICENSE = "LGPL"
+DEPENDS = "libdatrie libdatrie-native"
+
+SRC_URI = "http://linux.thai.net/pub/thailinux/software/libthai/${PN}-${PV}.tar.xz"
+
+inherit autotools pkgconfig
+
+LICENSE = "LGPL-2.1"
+LIC_FILES_CHKSUM = "file://COPYING;md5=2d5025d4aa3495befef8f17206a5b0a1"
+
+SRC_URI[md5sum] = "2b58148d73361316121d5384efeda9e6"
+SRC_URI[sha256sum] = "5a107f5a4dc5433ec6deb744435a4d8dc89daec0a189b9c76a90648fda0ef7ed"
diff --git a/meta-agl-devel/meta-oem-extra-libs/recipes-support/mongoose/README.md b/meta-agl-devel/meta-oem-extra-libs/recipes-support/mongoose/README.md
new file mode 100644
index 00000000..85bcfd0a
--- /dev/null
+++ b/meta-agl-devel/meta-oem-extra-libs/recipes-support/mongoose/README.md
@@ -0,0 +1,10 @@
+Add Mongoose Embedded Web Server Library for AGL OEM NEDDS
+================================================================
+Default Mongoose has build in 3 sub libs libmongoose.so
+libmongoose_ssl.so and libmongoose_mqtt.so define with
+MONGOOSE_EXLIBS in bb files.
+If necessary you can modify MONGOOSE_EXLIBS and CFLAGS_XXX in
+bb file to customize the library function.
+
+access https://github.com/cesanta/mongoose for more infomation
+
diff --git a/meta-agl-devel/meta-oem-extra-libs/recipes-support/mongoose/mongoose_6.6.bb b/meta-agl-devel/meta-oem-extra-libs/recipes-support/mongoose/mongoose_6.6.bb
new file mode 100644
index 00000000..2833c19d
--- /dev/null
+++ b/meta-agl-devel/meta-oem-extra-libs/recipes-support/mongoose/mongoose_6.6.bb
@@ -0,0 +1,76 @@
+SUMMARY = "Mongoose - Embedded Web Server / Embedded Networking Library"
+DESCRIPTION = "Mongoose is ideal for embedded environments. It has been designed for connecting devices and bringing them online. \
+ Mongoose makes embedded network programming fast, robust, and easy."
+
+HOMEPAGE = "https://www.cesanta.com/"
+
+LICENSE = "GPLv2"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=3548d4c6b2c754880739734d5e100aa9"
+
+SECTION = "libs"
+
+PV = "6.6+git${SRCPV}"
+SRCREV = "a23daa1547937b17bc30894d4bf19ddca80c7d35"
+SRC_URI = "git://github.com/cesanta/mongoose.git;branch=master"
+
+S = "${WORKDIR}/git"
+
+DEPENDS = "openssl"
+
+MONGOOSE_EXLIBS ?= "libmongoose.so libmongoose_ssl.so libmongoose_mqtt.so"
+
+python () {
+ d.setVar("CFLAGS_DEF", "-DMG_ENABLE_THREADS -DMG_ENABLE_COAP -DMG_ENABLE_HTTP_STREAMING_MULTIPART")
+ d.setVar("CFLAGS_SSL", "-DMG_ENABLE_THREADS -DMG_ENABLE_SSL -lssl -lcrypto")
+ d.setVar("CFLAGS_MQTT", "-DMG_ENABLE_THREADS -DMG_ENABLE_SSL -lssl -lcrypto -DMG_ENABLE_MQTT_BROKER -DMG_ENABLE_HTTP=0")
+}
+
+FILES_${PN} += "${exec_prefix}/lib/libmongoose.so \
+ ${exec_prefix}/lib/libmongoose_mqtt.so \
+ ${exec_prefix}/lib/libmongoose_ssl.so \
+ "
+
+FILES_${PN}-dbg = "${exec_prefix}/src/*"
+
+FILES_${PN}-dev = "${exec_prefix}/include/mongoose.h"
+
+FILES_${PN}-doc = "${exec_prefix}/share/doc/*"
+
+TARGET_CC_ARCH += "${LDFLAGS}"
+
+do_compile() {
+
+ if [ "${@bb.utils.contains('MONGOOSE_EXLIBS', 'libmongoose.so', 'def', '', d)}" = "def" ]; then
+ ${CC} mongoose.c -fPIC -shared -o libmongoose.so ${CFLAGS_DEF}
+ fi
+
+ if [ "${@bb.utils.contains('MONGOOSE_EXLIBS', 'libmongoose_ssl.so', 'ssl', '', d)}" = "ssl" ]; then
+ ${CC} mongoose.c -fPIC -shared -o libmongoose_ssl.so ${CFLAGS_SSL}
+ fi
+
+ if [ "${@bb.utils.contains('MONGOOSE_EXLIBS', 'libmongoose_mqtt.so', 'mqtt', '', d)}" = "mqtt" ]; then
+ ${CC} mongoose.c -fPIC -shared -o libmongoose_mqtt.so ${CFLAGS_MQTT}
+ fi
+}
+
+do_install() {
+
+ install -d ${D}${exec_prefix}/lib/
+ install -d ${D}${exec_prefix}/include/
+ install -d ${D}${exec_prefix}/src/debug/mongoose/6.6/
+ install -d ${D}${exec_prefix}/share/doc/
+
+ for libs in ${MONGOOSE_EXLIBS}
+ do
+ install -m 0644 ${S}/${libs} ${D}${exec_prefix}/lib/${libs}
+ done
+
+ install -m 0644 ${S}/mongoose.h ${D}${exec_prefix}/include/mongoose.h
+ install -m 0644 ${S}/mongoose.c ${D}${exec_prefix}/src/debug/mongoose/6.6/mongoose.c
+ install -m 0644 ${S}/mongoose.h ${D}${exec_prefix}/src/debug/mongoose/6.6/mongoose.h
+
+ tar -czf docs.tar.gz ${S}/docs/
+ install -m 0644 ${S}/docs.tar.gz ${D}${exec_prefix}/share/doc/docs.tar.gz
+ install -m 0644 ${S}/LICENSE ${D}${exec_prefix}/share/doc/LICENSE
+ install -m 0644 ${S}/CONTRIBUTING.md ${D}${exec_prefix}/share/doc/CONTRIBUTING.md
+}
diff --git a/meta-agl-devel/meta-pipewire/conf/include/agl-pipewire.inc b/meta-agl-devel/meta-pipewire/conf/include/agl-pipewire.inc
new file mode 100644
index 00000000..edd89311
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/conf/include/agl-pipewire.inc
@@ -0,0 +1,3 @@
+DISTRO_FEATURES_append = " pipewire"
+PREFERRED_RPROVIDER_virtual/pipewire-config = "pipewire-conf-agl"
+PREFERRED_RPROVIDER_virtual/wireplumber-config = "wireplumber-board-config-agl"
diff --git a/meta-agl-devel/meta-pipewire/conf/layer.conf b/meta-agl-devel/meta-pipewire/conf/layer.conf
new file mode 100644
index 00000000..8ad06e3e
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/conf/layer.conf
@@ -0,0 +1,12 @@
+# 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 += "meta-pipewire"
+BBFILE_PATTERN_meta-pipewire = "^${LAYERDIR}/"
+BBFILE_PRIORITY_meta-pipewire = "71"
+
+LAYERSERIES_COMPAT_meta-pipewire = "thud"
diff --git a/meta-agl-devel/meta-pipewire/recipes-connectivity/bluez-alsa/bluez-alsa/0001-utils-add-a-gstreamer-helper-application-for-interco.patch b/meta-agl-devel/meta-pipewire/recipes-connectivity/bluez-alsa/bluez-alsa/0001-utils-add-a-gstreamer-helper-application-for-interco.patch
new file mode 100644
index 00000000..37c03218
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-connectivity/bluez-alsa/bluez-alsa/0001-utils-add-a-gstreamer-helper-application-for-interco.patch
@@ -0,0 +1,464 @@
+From 33555a493af67f3acc2129764a1b093aec6254d8 Mon Sep 17 00:00:00 2001
+From: George Kiagiadakis <george.kiagiadakis@collabora.com>
+Date: Fri, 4 Oct 2019 20:51:24 +0300
+Subject: [PATCH] utils: add a gstreamer helper application for interconnection
+ with pipewire
+
+Unfortunately, the bluez-alsa PCM plugin does not work correctly
+when it is used through pipewire (or gstreamer, or anywhere really...).
+
+Thanfully, the bluez-alsa PCM plugin is only a simple client that
+reads/writes on a file descriptor that was opened by bluealsa.
+This allows us to use bluealsa without the PCM plugin, just like it
+is done in the aplay.c util.
+
+This one uses GStreamer to implement the plumbing between pipewire
+and the file descriptor. On the reading side we are also doing some
+tricks to ensure a smooth stream, which is not the case for the
+stream that is coming out of bluealsa.
+
+This helper is implemented as a patch to bluez-alsa so that it can
+use its internal private API. In the future this needs some re-thinking.
+
+Upstream-Status: Inappropriate
+---
+ configure.ac | 7 +
+ utils/Makefile.am | 20 +++
+ utils/gst-helper.c | 379 +++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 406 insertions(+)
+ create mode 100644 utils/gst-helper.c
+
+diff --git a/configure.ac b/configure.ac
+index 4825afa..9125871 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -141,6 +141,13 @@ AM_COND_IF([ENABLE_HCITOP], [
+ PKG_CHECK_MODULES([NCURSES], [ncurses])
+ ])
+
++AC_ARG_ENABLE([gsthelper],
++ [AS_HELP_STRING([--enable-gsthelper], [enable building of gsthelper tool])])
++AM_CONDITIONAL([ENABLE_GSTHELPER], [test "x$enable_gsthelper" = "xyes"])
++AM_COND_IF([ENABLE_GSTHELPER], [
++ PKG_CHECK_MODULES([GST], [gstreamer-1.0 glib-2.0])
++])
++
+ AC_ARG_ENABLE([test],
+ [AS_HELP_STRING([--enable-test], [enable unit test])])
+ AM_CONDITIONAL([ENABLE_TEST], [test "x$enable_test" = "xyes"])
+diff --git a/utils/Makefile.am b/utils/Makefile.am
+index 9057f2c..9790474 100644
+--- a/utils/Makefile.am
++++ b/utils/Makefile.am
+@@ -47,3 +47,23 @@ hcitop_LDADD = \
+ @LIBBSD_LIBS@ \
+ @NCURSES_LIBS@
+ endif
++
++if ENABLE_GSTHELPER
++bin_PROGRAMS += bluealsa-gst-helper
++bluealsa_gst_helper_SOURCES = \
++ ../src/shared/dbus-client.c \
++ ../src/shared/ffb.c \
++ ../src/shared/log.c \
++ gst-helper.c
++bluealsa_gst_helper_CFLAGS = \
++ -I$(top_srcdir)/src \
++ @ALSA_CFLAGS@ \
++ @BLUEZ_CFLAGS@ \
++ @DBUS1_CFLAGS@ \
++ @GST_CFLAGS@
++bluealsa_gst_helper_LDADD = \
++ @ALSA_LIBS@ \
++ @BLUEZ_LIBS@ \
++ @DBUS1_LIBS@ \
++ @GST_LIBS@
++endif
+diff --git a/utils/gst-helper.c b/utils/gst-helper.c
+new file mode 100644
+index 0000000..1b021ee
+--- /dev/null
++++ b/utils/gst-helper.c
+@@ -0,0 +1,379 @@
++/* Bluez-Alsa PipeWire integration GStreamer helper
++ *
++ * Copyright © 2016-2019 Arkadiusz Bokowy
++ * Copyright © 2019 Collabora Ltd.
++ * @author George Kiagiadakis <george.kiagiadakis@collabora.com>
++ *
++ * SPDX-License-Identifier: MIT
++ */
++
++#if HAVE_CONFIG_H
++# include <config.h>
++#endif
++
++#include <errno.h>
++#include <getopt.h>
++#include <poll.h>
++#include <pthread.h>
++#include <signal.h>
++#include <stdbool.h>
++#include <stdint.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++
++#include <bluetooth/bluetooth.h>
++#include <dbus/dbus.h>
++#include <gst/gst.h>
++
++#include "shared/dbus-client.h"
++#include "shared/defs.h"
++#include "shared/ffb.h"
++#include "shared/log.h"
++
++struct worker {
++ /* used BlueALSA PCM device */
++ struct ba_pcm ba_pcm;
++ /* file descriptor of PCM FIFO */
++ int ba_pcm_fd;
++ /* file descriptor of PCM control */
++ int ba_pcm_ctrl_fd;
++ /* the gstreamer pipelines (sink & source) */
++ GstElement *pipeline[2];
++};
++
++static struct ba_dbus_ctx dbus_ctx;
++static GHashTable *workers;
++static bool main_loop_on = true;
++
++static void
++main_loop_stop(int sig)
++{
++ /* Call to this handler restores the default action, so on the
++ * second call the program will be forcefully terminated. */
++
++ struct sigaction sigact = { .sa_handler = SIG_DFL };
++ sigaction(sig, &sigact, NULL);
++
++ main_loop_on = false;
++}
++
++static int
++worker_start_pipeline(struct worker *w, int id, int mode, int profile)
++{
++ GError *gerr = NULL;
++ DBusError err = DBUS_ERROR_INIT;
++
++ if (w->pipeline[id])
++ return 0;
++
++ if (!bluealsa_dbus_pcm_open(&dbus_ctx, w->ba_pcm.pcm_path, mode,
++ &w->ba_pcm_fd, &w->ba_pcm_ctrl_fd, &err)) {
++ error("Couldn't open PCM: %s", err.message);
++ dbus_error_free(&err);
++ goto fail;
++ }
++
++ if (mode == BA_PCM_FLAG_SINK) {
++ debug("sink start");
++ w->pipeline[id] = gst_parse_launch(
++ /* add a silent live source to ensure a perfect live stream on the
++ output, even when the bt device is not sending or has gaps;
++ this also effectively changes the clock to be the system clock,
++ which is the same clock used by bluez-alsa on the sending side */
++ "audiotestsrc is-live=true wave=silence ! capsfilter name=capsf "
++ "! audiomixer name=m "
++ /* mix the input from bluez-alsa using fdsrc; rawaudioparse
++ is necessary to convert bytes to time and align the buffers */
++ "fdsrc name=fdelem do-timestamp=true ! capsfilter name=capsf2 "
++ "! rawaudioparse use-sink-caps=true ! m. "
++ /* take the mixer output, convert and push to pipewire */
++ "m.src ! capsfilter name=capsf3 ! audioconvert ! audioresample "
++ "! audio/x-raw,format=F32LE,rate=48000 ! pwaudiosink name=pwelem",
++ &gerr);
++ } else if (mode == BA_PCM_FLAG_SOURCE && profile == BA_PCM_FLAG_PROFILE_SCO) {
++ debug("source start");
++ w->pipeline[id] = gst_parse_launch(
++ /* read from pipewire and put the buffers on a leaky queue, which
++ will essentially allow pwaudiosrc to continue working while
++ the fdsink is blocked (when there is no phone call in progress).
++ 9600 bytes = 50ms @ F32LE/1ch/48000
++ */
++ "pwaudiosrc name=pwelem ! audio/x-raw,format=F32LE,rate=48000 "
++ "! queue leaky=downstream max-size-time=0 max-size-buffers=0 max-size-bytes=9600 "
++ "! audioconvert ! audioresample ! capsfilter name=capsf "
++ "! fdsink name=fdelem", &gerr);
++ }
++
++ if (gerr) {
++ error("Failed to start pipeline: %s", gerr->message);
++ g_error_free(gerr);
++ goto fail;
++ }
++
++ if (w->pipeline[id]) {
++ g_autofree gchar *capsstr = NULL;
++ g_autoptr (GstElement) fdelem = gst_bin_get_by_name(GST_BIN(w->pipeline[id]), "fdelem");
++ g_autoptr (GstElement) pwelem = gst_bin_get_by_name(GST_BIN(w->pipeline[id]), "pwelem");
++ g_autoptr (GstElement) capsf = gst_bin_get_by_name(GST_BIN(w->pipeline[id]), "capsf");
++ g_autoptr (GstElement) capsf2 = gst_bin_get_by_name(GST_BIN(w->pipeline[id]), "capsf2");
++ g_autoptr (GstElement) capsf3 = gst_bin_get_by_name(GST_BIN(w->pipeline[id]), "capsf3");
++ g_autoptr (GstCaps) caps = gst_caps_new_simple("audio/x-raw",
++ "format", G_TYPE_STRING, "S16LE",
++ "layout", G_TYPE_STRING, "interleaved",
++ "channels", G_TYPE_INT, w->ba_pcm.channels,
++ "rate", G_TYPE_INT, w->ba_pcm.sampling,
++ NULL);
++ g_autoptr (GstStructure) stream_props = gst_structure_new("props",
++ "media.role", G_TYPE_STRING, "Communication",
++ "wireplumber.keep-linked", G_TYPE_STRING, "1",
++ NULL);
++
++ g_object_set(capsf, "caps", caps, NULL);
++ if (capsf2)
++ g_object_set(capsf2, "caps", caps, NULL);
++ if (capsf3)
++ g_object_set(capsf3, "caps", caps, NULL);
++
++ capsstr = gst_caps_to_string (caps);
++ debug(" caps: %s", capsstr);
++
++ g_object_set(fdelem, "fd", w->ba_pcm_fd, NULL);
++ g_object_set(pwelem, "stream-properties", stream_props, NULL);
++
++ gst_element_set_state(w->pipeline[id], GST_STATE_PLAYING);
++ }
++
++ return 0;
++fail:
++ g_clear_object(&w->pipeline[id]);
++ return -1;
++}
++
++static int
++worker_start(struct worker *w)
++{
++ int mode = w->ba_pcm.flags & (BA_PCM_FLAG_SOURCE | BA_PCM_FLAG_SINK);
++ int profile = w->ba_pcm.flags & (BA_PCM_FLAG_PROFILE_A2DP | BA_PCM_FLAG_PROFILE_SCO);
++ /* human-readable BT address */
++ char addr[18];
++
++ g_return_val_if_fail (profile != 0 && profile != (BA_PCM_FLAG_PROFILE_A2DP | BA_PCM_FLAG_PROFILE_SCO), -1);
++
++ ba2str(&w->ba_pcm.addr, addr);
++ debug("%p: worker start addr:%s, mode:0x%x, profile:0x%x", w, addr, mode, profile);
++
++ if (mode & BA_PCM_FLAG_SINK)
++ worker_start_pipeline(w, 0, BA_PCM_FLAG_SINK, profile);
++ if (mode & BA_PCM_FLAG_SOURCE)
++ worker_start_pipeline(w, 1, BA_PCM_FLAG_SOURCE, profile);
++}
++
++static int
++worker_stop(struct worker *w)
++{
++ debug("stop worker %p", w);
++ if (w->pipeline[0]) {
++ gst_element_set_state(w->pipeline[0], GST_STATE_NULL);
++ g_clear_object(&w->pipeline[0]);
++ }
++ if (w->pipeline[1]) {
++ gst_element_set_state(w->pipeline[1], GST_STATE_NULL);
++ g_clear_object(&w->pipeline[1]);
++ }
++ if (w->ba_pcm_fd != -1) {
++ close(w->ba_pcm_fd);
++ w->ba_pcm_fd = -1;
++ }
++ if (w->ba_pcm_ctrl_fd != -1) {
++ close(w->ba_pcm_ctrl_fd);
++ w->ba_pcm_ctrl_fd = -1;
++ }
++ return 0;
++}
++
++static int
++supervise_pcm_worker(struct worker *worker)
++{
++ if (worker == NULL)
++ return -1;
++
++ /* no mode? */
++ if (worker->ba_pcm.flags & (BA_PCM_FLAG_SOURCE | BA_PCM_FLAG_SINK) == 0)
++ goto stop;
++
++ /* no profile? */
++ if (worker->ba_pcm.flags & (BA_PCM_FLAG_PROFILE_A2DP | BA_PCM_FLAG_PROFILE_SCO) == 0)
++ goto stop;
++
++ /* check whether SCO has selected codec */
++ if (worker->ba_pcm.flags & BA_PCM_FLAG_PROFILE_SCO &&
++ worker->ba_pcm.codec == 0) {
++ debug("Skipping SCO with codec not selected");
++ goto stop;
++ }
++
++start:
++ return worker_start(worker);
++stop:
++ return worker_stop(worker);
++}
++
++static void
++worker_new(struct ba_pcm *pcm)
++{
++ struct worker *w = g_slice_new0 (struct worker);
++ memcpy(&w->ba_pcm, pcm, sizeof(struct ba_pcm));
++ w->ba_pcm_fd = -1;
++ w->ba_pcm_ctrl_fd = -1;
++ g_hash_table_insert(workers, w->ba_pcm.pcm_path, w);
++ supervise_pcm_worker(w);
++}
++
++static DBusHandlerResult
++dbus_signal_handler(DBusConnection *conn, DBusMessage *message, void *data)
++{
++ (void)conn;
++ (void)data;
++
++ const char *path = dbus_message_get_path(message);
++ const char *interface = dbus_message_get_interface(message);
++ const char *signal = dbus_message_get_member(message);
++
++ DBusMessageIter iter;
++ struct worker *worker;
++
++ if (strcmp(interface, BLUEALSA_INTERFACE_MANAGER) == 0) {
++
++ if (strcmp(signal, "PCMAdded") == 0) {
++ struct ba_pcm pcm;
++ if (!dbus_message_iter_init(message, &iter) ||
++ !bluealsa_dbus_message_iter_get_pcm(&iter, NULL, &pcm)) {
++ error("Couldn't add new PCM: %s", "Invalid signal signature");
++ goto fail;
++ }
++ worker_new(&pcm);
++ return DBUS_HANDLER_RESULT_HANDLED;
++ }
++
++ if (strcmp(signal, "PCMRemoved") == 0) {
++ if (!dbus_message_iter_init(message, &iter) ||
++ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_OBJECT_PATH) {
++ error("Couldn't remove PCM: %s", "Invalid signal signature");
++ goto fail;
++ }
++ dbus_message_iter_get_basic(&iter, &path);
++ g_hash_table_remove(workers, path);
++ return DBUS_HANDLER_RESULT_HANDLED;
++ }
++
++ }
++
++ if (strcmp(interface, DBUS_INTERFACE_PROPERTIES) == 0) {
++ worker = g_hash_table_lookup(workers, path);
++ if (!worker)
++ goto fail;
++ if (!dbus_message_iter_init(message, &iter) ||
++ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) {
++ error("Couldn't update PCM: %s", "Invalid signal signature");
++ goto fail;
++ }
++ dbus_message_iter_get_basic(&iter, &interface);
++ dbus_message_iter_next(&iter);
++ if (!bluealsa_dbus_message_iter_get_pcm_props(&iter, NULL, &worker->ba_pcm))
++ goto fail;
++ supervise_pcm_worker(worker);
++ return DBUS_HANDLER_RESULT_HANDLED;
++ }
++
++fail:
++ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
++}
++
++static void
++destroy_worker(void *worker)
++{
++ struct worker *w = worker;
++ worker_stop(w);
++ g_slice_free(struct worker, w);
++}
++
++int
++main(int argc, char *argv[])
++{
++ int ret = EXIT_SUCCESS;
++
++ log_open(argv[0], false, false);
++ gst_init(&argc, &argv);
++ dbus_threads_init_default();
++
++ DBusError err = DBUS_ERROR_INIT;
++ if (!bluealsa_dbus_connection_ctx_init(&dbus_ctx, BLUEALSA_SERVICE, &err)) {
++ error("Couldn't initialize D-Bus context: %s", err.message);
++ return EXIT_FAILURE;
++ }
++
++ bluealsa_dbus_connection_signal_match_add(&dbus_ctx,
++ BLUEALSA_SERVICE, NULL, BLUEALSA_INTERFACE_MANAGER, "PCMAdded", NULL);
++ bluealsa_dbus_connection_signal_match_add(&dbus_ctx,
++ BLUEALSA_SERVICE, NULL, BLUEALSA_INTERFACE_MANAGER, "PCMRemoved", NULL);
++ bluealsa_dbus_connection_signal_match_add(&dbus_ctx,
++ BLUEALSA_SERVICE, NULL, DBUS_INTERFACE_PROPERTIES, "PropertiesChanged",
++ "arg0='"BLUEALSA_INTERFACE_PCM"'");
++
++ if (!dbus_connection_add_filter(dbus_ctx.conn, dbus_signal_handler, NULL, NULL)) {
++ error("Couldn't add D-Bus filter: %s", err.message);
++ return EXIT_FAILURE;
++ }
++
++ workers = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, destroy_worker);
++
++ {
++ struct ba_pcm *pcms = NULL;
++ size_t pcms_count = 0, i;
++
++ if (!bluealsa_dbus_get_pcms(&dbus_ctx, &pcms, &pcms_count, &err))
++ warn("Couldn't get BlueALSA PCM list: %s", err.message);
++
++ for (i = 0; i < pcms_count; i++) {
++ worker_new(&pcms[i]);
++ }
++
++ free(pcms);
++ }
++
++ struct sigaction sigact = { .sa_handler = main_loop_stop };
++ sigaction(SIGTERM, &sigact, NULL);
++ sigaction(SIGINT, &sigact, NULL);
++
++ /* Ignore SIGPIPE, which may be received when writing to the bluealsa
++ socket when it is closed on the remote end */
++ signal(SIGPIPE, SIG_IGN);
++
++ debug("Starting main loop");
++ while (main_loop_on) {
++
++ struct pollfd pfds[10];
++ nfds_t pfds_len = ARRAYSIZE(pfds);
++
++ if (!bluealsa_dbus_connection_poll_fds(&dbus_ctx, pfds, &pfds_len)) {
++ error("Couldn't get D-Bus connection file descriptors");
++ ret = EXIT_FAILURE;
++ goto out;
++ }
++
++ if (poll(pfds, pfds_len, -1) == -1 &&
++ errno == EINTR)
++ continue;
++
++ if (bluealsa_dbus_connection_poll_dispatch(&dbus_ctx, pfds, pfds_len))
++ while (dbus_connection_dispatch(dbus_ctx.conn) == DBUS_DISPATCH_DATA_REMAINS)
++ continue;
++
++ }
++
++out:
++ g_hash_table_unref(workers);
++ return ret;
++}
+--
+2.23.0
+
diff --git a/meta-agl-devel/meta-pipewire/recipes-connectivity/bluez-alsa/bluez-alsa/bluealsa-gst-helper@.service b/meta-agl-devel/meta-pipewire/recipes-connectivity/bluez-alsa/bluez-alsa/bluealsa-gst-helper@.service
new file mode 100644
index 00000000..495ab622
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-connectivity/bluez-alsa/bluez-alsa/bluealsa-gst-helper@.service
@@ -0,0 +1,18 @@
+[Unit]
+Description=Bluetooth audio helper for user %i
+Requires=pipewire@%i.socket bluez-alsa.service
+After=pipewire@%i.socket bluez-alsa.service
+
+[Service]
+Type=simple
+Restart=on-failure
+ExecStart=/usr/bin/bluealsa-gst-helper
+
+Environment=XDG_RUNTIME_DIR=/run/user/%i
+Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/%i/bus
+
+User=%i
+Slice=user-%i.slice
+SupplementaryGroups=audio
+UMask=0077
+CapabilityBoundingSet=
diff --git a/meta-agl-devel/meta-pipewire/recipes-connectivity/bluez-alsa/bluez-alsa_git.bbappend b/meta-agl-devel/meta-pipewire/recipes-connectivity/bluez-alsa/bluez-alsa_git.bbappend
new file mode 100644
index 00000000..2f9699a8
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-connectivity/bluez-alsa/bluez-alsa_git.bbappend
@@ -0,0 +1,35 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += "\
+ file://0001-utils-add-a-gstreamer-helper-application-for-interco.patch \
+ file://bluealsa-gst-helper@.service \
+ "
+
+PACKAGECONFIG += "gsthelper"
+PACKAGECONFIG[gsthelper] = "--enable-gsthelper, --disable-gsthelper, gstreamer1.0"
+
+do_install_append() {
+ if ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'true', 'false', d)}; then
+ # install the service file
+ mkdir -p ${D}${systemd_system_unitdir}/
+ install -m 0644 ${WORKDIR}/bluealsa-gst-helper@.service ${D}${systemd_system_unitdir}/bluealsa-gst-helper@.service
+
+ # enable the helper to start together with afm-user-session
+ mkdir -p ${D}${systemd_system_unitdir}/afm-user-session@.target.wants
+ ln -sf ../bluealsa-gst-helper@.service ${D}${systemd_system_unitdir}/afm-user-session@.target.wants/bluealsa-gst-helper@.service
+ fi
+}
+
+PACKAGES =+ "${PN}-pipewire"
+
+FILES_${PN}-pipewire = "\
+ ${bindir}/bluealsa-gst-helper \
+ ${systemd_system_unitdir}/bluealsa-gst-helper@.service \
+ ${systemd_system_unitdir}/afm-user-session@.target.wants/bluealsa-gst-helper@.service \
+ "
+RDEPENDS_${PN}-pipewire += "\
+ bluez-alsa \
+ pipewire \
+ gstreamer1.0-plugins-base \
+ gstreamer1.0-pipewire \
+ "
diff --git a/meta-agl-devel/meta-pipewire/recipes-core/packagegroups/packagegroup-pipewire.bb b/meta-agl-devel/meta-pipewire/recipes-core/packagegroups/packagegroup-pipewire.bb
new file mode 100644
index 00000000..4020f1e2
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-core/packagegroups/packagegroup-pipewire.bb
@@ -0,0 +1,17 @@
+SUMMARY = "PipeWire Media Server"
+DESCRIPTION = "The set of packages required to use PipeWire in AGL"
+LICENSE = "MIT & LGPL-2.1"
+
+inherit packagegroup
+
+PACKAGES = "\
+ packagegroup-pipewire \
+ "
+
+RDEPENDS_${PN} += "\
+ agl-service-audiomixer \
+ pipewire \
+ pipewire-alsa \
+ gstreamer1.0-pipewire \
+ bluez-alsa-pipewire \
+"
diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/agl-service-audiomixer/agl-service-audiomixer_git.bb b/meta-agl-devel/meta-pipewire/recipes-multimedia/agl-service-audiomixer/agl-service-audiomixer_git.bb
new file mode 100644
index 00000000..c4de73e7
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/agl-service-audiomixer/agl-service-audiomixer_git.bb
@@ -0,0 +1,16 @@
+SUMMARY = "Audio Mixer Service Binding"
+DESCRIPTION = "AGL Audio Mixer Service Binding"
+SECTION = "apps"
+LICENSE = "MIT"
+LIC_FILES_CHKSUM = "file://LICENSE;beginline=3;md5=e8ad01a5182f2c1b3a2640e9ea268264"
+
+PV = "0.1+git${SRCPV}"
+
+SRC_URI = "git://gerrit.automotivelinux.org/gerrit/apps/agl-service-audiomixer.git;protocol=https;branch=${AGL_BRANCH}"
+SRCREV = "${AGL_APP_REVISION}"
+
+S = "${WORKDIR}/git"
+
+inherit cmake aglwgt pkgconfig
+
+DEPENDS += "pipewire"
diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire-conf-agl/client.env b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire-conf-agl/client.env
new file mode 100644
index 00000000..9b44cee0
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire-conf-agl/client.env
@@ -0,0 +1,10 @@
+# This file contains environment variables that will apply
+# to pipewire clients started by the application framework
+
+# libpipewire by default tries to obtain real-time scheduling
+# for the streaming thread. This is only useful on the desktop, disable here.
+DISABLE_RTKIT=1
+
+# Uncomment to enable libpipewire debug for clients
+# 1=error, 2=warning, 3=info, 4=debug, 5=trace
+#PIPEWIRE_DEBUG=4
diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire-conf-agl/pipewire.conf b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire-conf-agl/pipewire.conf
new file mode 100644
index 00000000..d09ee8ed
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire-conf-agl/pipewire.conf
@@ -0,0 +1,10 @@
+# daemon config file for PipeWire version "0.2.9"
+# distributed by Automotive Grade Linux
+load-module libpipewire-module-protocol-native
+load-module libpipewire-module-spa-monitor alsa/libspa-alsa alsa-monitor alsa
+load-module libpipewire-module-client-node
+load-module libpipewire-module-access
+load-module libpipewire-module-audio-dsp
+load-module libpipewire-module-link-factory
+load-module libpipewire-module-endpoint
+exec /usr/bin/wireplumber
diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire-conf-agl/server.env b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire-conf-agl/server.env
new file mode 100644
index 00000000..c74b941d
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire-conf-agl/server.env
@@ -0,0 +1,12 @@
+# This file contains environment variables that will apply
+# to the pipewire daemon as well as its session manager
+
+# Disable rtkit for wireplumber, which is also a client
+DISABLE_RTKIT=1
+
+# Uncomment to enable wireplumber debug
+#G_MESSAGES_DEBUG=all
+
+# Uncomment to enable pipewire debug
+# 1=error, 2=warning, 3=info, 4=debug, 5=trace
+#PIPEWIRE_DEBUG=4
diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire-conf-agl_git.bb b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire-conf-agl_git.bb
new file mode 100644
index 00000000..2bb76f9d
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire-conf-agl_git.bb
@@ -0,0 +1,40 @@
+SUMMARY = "AGL configuration file for pipewire"
+HOMEPAGE = "https://pipewire.org"
+BUGTRACKER = "https://jira.automotivelinux.org"
+AUTHOR = "George Kiagiadakis <george.kiagiadakis@collabora.com>"
+SECTION = "multimedia"
+
+LICENSE = "MIT"
+LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
+
+SRC_URI = " \
+ file://pipewire.conf \
+ file://client.env \
+ file://server.env \
+ "
+
+do_configure[noexec] = "1"
+do_compile[noexec] = "1"
+
+do_install_append() {
+ # if we are distributing our own configuration file,
+ # replace the one installed by pipewire
+ install -d ${D}/${sysconfdir}/pipewire/
+ install -m 0644 ${WORKDIR}/pipewire.conf ${D}${sysconfdir}/pipewire/pipewire.conf
+
+ # install environment variable files
+ install -d ${D}/${sysconfdir}/afm/unit.env.d/
+ install -m 0644 ${WORKDIR}/client.env ${D}/${sysconfdir}/afm/unit.env.d/pipewire
+ install -m 0644 ${WORKDIR}/server.env ${D}${sysconfdir}/pipewire/environment
+}
+
+FILES_${PN} = "\
+ ${sysconfdir}/pipewire/* \
+ ${sysconfdir}/afm/unit.env.d/* \
+"
+CONFFILES_${PN} += "\
+ ${sysconfdir}/pipewire/* \
+ ${sysconfdir}/afm/unit.env.d/* \
+"
+
+RPROVIDES_${PN} += "virtual/pipewire-config"
diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire.inc b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire.inc
new file mode 100644
index 00000000..e9046e8e
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire.inc
@@ -0,0 +1,117 @@
+SUMMARY = "Multimedia processing server for Linux"
+HOMEPAGE = "https://pipewire.org"
+BUGTRACKER = "https://github.com/PipeWire/pipewire/issues"
+AUTHOR = "Wim Taymans <wtaymans@redhat.com>"
+SECTION = "multimedia"
+
+LICENSE = "MIT & LGPL-2.1"
+LIC_FILES_CHKSUM = "\
+ file://COPYING;beginline=3;md5=b3adc775ca6ee80056383a5ae814cc75 \
+ file://pipewire-alsa/LICENSE;md5=fc178bcd425090939a8b634d1d6a9594 \
+ file://pipewire-jack/LICENSE;md5=fc178bcd425090939a8b634d1d6a9594 \
+ file://pipewire-pulseaudio/LICENSE;md5=fc178bcd425090939a8b634d1d6a9594 \
+"
+
+inherit meson pkgconfig systemd manpages
+
+DEPENDS = "dbus"
+
+PACKAGECONFIG ??= "\
+ ${@bb.utils.filter('DISTRO_FEATURES', 'systemd', d)} \
+ ${@bb.utils.filter('DISTRO_FEATURES', 'bluez5', d)} \
+ alsa audioconvert \
+ pipewire-alsa \
+ gstreamer \
+"
+
+GST_VER = "1.0"
+
+# systemd integration
+PACKAGECONFIG[systemd] = "-Dsystemd=true,-Dsystemd=false,systemd"
+
+# SPA plugins
+PACKAGECONFIG[alsa] = "-Dalsa=true,-Dalsa=false,udev alsa-lib"
+PACKAGECONFIG[audioconvert] = "-Daudioconvert=true,-Daudioconvert=false,speexdsp"
+PACKAGECONFIG[audiotestsrc] = "-Daudiotestsrc=true,-Daudiotestsrc=false, "
+PACKAGECONFIG[bluez5] = "-Dbluez5=true,-Dbluez5=false,bluez5 sbc"
+PACKAGECONFIG[v4l2] = "-Dv4l2=true,-Dv4l2=false,udev v4l-utils"
+PACKAGECONFIG[videotestsrc] = "-Dvideotestsrc=true,-Dvideotestsrc=false, "
+
+# alsa plugin to redirect audio to pipewire
+PACKAGECONFIG[pipewire-alsa] = "-Dpipewire-alsa=true,-Dpipewire-alsa=false,alsa-lib"
+# pulseaudio drop-in replacement library
+PACKAGECONFIG[pipewire-pulseaudio] = "-Dpipewire-pulseaudio=true,-Dpipewire-pulseaudio=false,pulseaudio glib-2.0"
+# jack drop-in replacement library
+PACKAGECONFIG[pipewire-jack] = "-Dpipewire-jack=true,-Dpipewire-jack=false,jack"
+
+# GStreamer plugins
+PACKAGECONFIG[gstreamer] = "-Dgstreamer=true,-Dgstreamer=false,glib-2.0 gstreamer${GST_VER} gstreamer${GST_VER}-plugins-base"
+
+# man pages
+PACKAGECONFIG[manpages] = "-Dman=true,-Dman=false,libxml-parser-perl-native"
+
+do_install_append() {
+ # only install the alsa config file if the alsa-lib plugin has been built
+ # this avoids creating the pipewire-alsa package when the pipewire-alsa
+ # feature is not enabled
+ if [ -d ${D}${libdir}/alsa-lib ]
+ then
+ mkdir -p ${D}${datadir}/alsa/alsa.conf.d
+ install -m 0644 ${S}/pipewire-alsa/conf/50-pipewire.conf ${D}${datadir}/alsa/alsa.conf.d/50-pipewire.conf
+ fi
+}
+
+PACKAGES =+ "\
+ ${PN}-spa-plugins \
+ ${PN}-alsa \
+ ${PN}-pulseaudio \
+ ${PN}-jack \
+ ${PN}-config \
+ gstreamer${GST_VER}-${PN} \
+ lib${PN} \
+ lib${PN}-modules \
+"
+
+FILES_${PN} = "\
+ ${bindir}/pipewire* \
+ ${systemd_user_unitdir}/* \
+"
+
+FILES_lib${PN} = "\
+ ${libdir}/libpipewire-*.so.* \
+"
+
+FILES_lib${PN}-modules = "\
+ ${libdir}/pipewire-*/* \
+"
+
+FILES_${PN}-spa-plugins = "\
+ ${bindir}/spa-* \
+ ${libdir}/spa/* \
+"
+
+FILES_${PN}-alsa = "\
+ ${libdir}/alsa-lib/* \
+ ${datadir}/alsa/alsa.conf.d/50-pipewire.conf \
+"
+
+FILES_${PN}-pulseaudio = "\
+ ${libdir}/libpulse*.so.* \
+"
+
+FILES_gstreamer${GST_VER}-${PN} = "\
+ ${libdir}/gstreamer-${GST_VER}/* \
+"
+
+RDEPENDS_lib${PN} += "lib${PN}-modules ${PN}-spa-plugins"
+
+# The default pipewire config.
+# Replace in your own package using
+# "virtual/pipewire-config"
+FILES_${PN}-config = "\
+ ${sysconfdir}/pipewire/pipewire.conf \
+"
+CONFFILES_${PN}-config += "\
+ ${sysconfdir}/pipewire/pipewire.conf \
+"
+RPROVIDES_${PN}-config += "virtual/pipewire-config"
diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0001-spa-include-install-missing-headers.patch b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0001-spa-include-install-missing-headers.patch
new file mode 100644
index 00000000..5b928117
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0001-spa-include-install-missing-headers.patch
@@ -0,0 +1,41 @@
+From dbb6e10df8c2ba9b874eb9350d4cb93c62dba5a9 Mon Sep 17 00:00:00 2001
+From: George Kiagiadakis <george.kiagiadakis@collabora.com>
+Date: Wed, 29 May 2019 12:09:13 +0300
+Subject: [PATCH] spa/include: install missing headers
+
+Upstream-Status: Accepted
+---
+ spa/include/spa/meson.build | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/spa/include/spa/meson.build b/spa/include/spa/meson.build
+index c9d07659..c079a1a2 100644
+--- a/spa/include/spa/meson.build
++++ b/spa/include/spa/meson.build
+@@ -39,6 +39,7 @@ spa_monitor_headers = [
+ 'monitor/device.h',
+ 'monitor/monitor.h',
+ 'monitor/type-info.h',
++ 'monitor/utils.h',
+ ]
+
+ install_headers(spa_monitor_headers,
+@@ -50,6 +51,7 @@ spa_node_headers = [
+ 'node/io.h',
+ 'node/node.h',
+ 'node/type-info.h',
++ 'node/utils.h',
+ ]
+
+ install_headers(spa_node_headers,
+@@ -97,6 +99,7 @@ spa_utils_headers = [
+ 'utils/dict.h',
+ 'utils/hook.h',
+ 'utils/list.h',
++ 'utils/result.h',
+ 'utils/ringbuffer.h',
+ 'utils/type.h',
+ 'utils/type-info.h',
+--
+2.20.1
+
diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0002-extensions-implement-Endpoint-ClientEndpoint-interfa.patch b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0002-extensions-implement-Endpoint-ClientEndpoint-interfa.patch
new file mode 100644
index 00000000..e49edf49
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0002-extensions-implement-Endpoint-ClientEndpoint-interfa.patch
@@ -0,0 +1,1563 @@
+From 5afe82a430642c2f7e116941709a624b8fd73011 Mon Sep 17 00:00:00 2001
+From: George Kiagiadakis <george.kiagiadakis@collabora.com>
+Date: Thu, 23 May 2019 18:59:05 +0300
+Subject: [PATCH] extensions: implement Endpoint & ClientEndpoint interfaces
+
+The ClientEndpoint interface allows session managers to register
+endpoint objects on pipewire.
+The Endpoint interface allows other clients to interact with
+endpoints provided by the session manager.
+
+Upstream-Status: Pending
+---
+ src/extensions/client-endpoint.h | 106 ++++
+ src/extensions/endpoint.h | 237 +++++++++
+ src/extensions/meson.build | 2 +
+ src/modules/meson.build | 12 +
+ src/modules/module-endpoint.c | 137 +++++
+ src/modules/module-endpoint/endpoint-impl.c | 428 ++++++++++++++++
+ src/modules/module-endpoint/endpoint-impl.h | 52 ++
+ src/modules/module-endpoint/protocol-native.c | 472 ++++++++++++++++++
+ src/pipewire/pipewire.c | 2 +
+ src/pipewire/type.h | 3 +-
+ 10 files changed, 1450 insertions(+), 1 deletion(-)
+ create mode 100644 src/extensions/client-endpoint.h
+ create mode 100644 src/extensions/endpoint.h
+ create mode 100644 src/modules/module-endpoint.c
+ create mode 100644 src/modules/module-endpoint/endpoint-impl.c
+ create mode 100644 src/modules/module-endpoint/endpoint-impl.h
+ create mode 100644 src/modules/module-endpoint/protocol-native.c
+
+diff --git a/src/extensions/client-endpoint.h b/src/extensions/client-endpoint.h
+new file mode 100644
+index 00000000..0389893c
+--- /dev/null
++++ b/src/extensions/client-endpoint.h
+@@ -0,0 +1,106 @@
++/* PipeWire
++ *
++ * Copyright © 2019 Collabora Ltd.
++ * @author George Kiagiadakis <george.kiagiadakis@collabora.com>
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the next
++ * paragraph) shall be included in all copies or substantial portions of the
++ * Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
++#ifndef PIPEWIRE_EXT_CLIENT_ENDPOINT_H
++#define PIPEWIRE_EXT_CLIENT_ENDPOINT_H
++
++#include "endpoint.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++struct pw_client_endpoint_proxy;
++
++#define PW_VERSION_CLIENT_ENDPOINT 0
++#define PW_EXTENSION_MODULE_CLIENT_ENDPOINT PIPEWIRE_MODULE_PREFIX "module-endpoint"
++
++#define PW_CLIENT_ENDPOINT_PROXY_METHOD_UPDATE 0
++#define PW_CLIENT_ENDPOINT_PROXY_METHOD_NUM 1
++
++struct pw_client_endpoint_proxy_methods {
++#define PW_VERSION_CLIENT_ENDPOINT_PROXY_METHODS 0
++ uint32_t version;
++
++ /**
++ * Update endpoint info
++ */
++ int (*update) (void *object,
++#define PW_CLIENT_ENDPOINT_UPDATE_PARAMS (1 << 0)
++#define PW_CLIENT_ENDPOINT_UPDATE_PARAMS_INCREMENTAL (1 << 1)
++#define PW_CLIENT_ENDPOINT_UPDATE_INFO (1 << 2)
++ uint32_t change_mask,
++ uint32_t n_params,
++ const struct spa_pod **params,
++ const struct pw_endpoint_info *info);
++};
++
++static inline int
++pw_client_endpoint_proxy_update(struct pw_client_endpoint_proxy *p,
++ uint32_t change_mask,
++ uint32_t n_params,
++ const struct spa_pod **params,
++ struct pw_endpoint_info *info)
++{
++ return pw_proxy_do((struct pw_proxy*)p,
++ struct pw_client_endpoint_proxy_methods, update,
++ change_mask, n_params, params, info);
++}
++
++#define PW_CLIENT_ENDPOINT_PROXY_EVENT_SET_PARAM 0
++#define PW_CLIENT_ENDPOINT_PROXY_EVENT_NUM 1
++
++struct pw_client_endpoint_proxy_events {
++#define PW_VERSION_CLIENT_ENDPOINT_PROXY_EVENTS 0
++ uint32_t version;
++
++ /**
++ * Set a parameter on the endpoint
++ *
++ * \param id the parameter id to set
++ * \param flags extra parameter flags
++ * \param param the parameter to set
++ */
++ void (*set_param) (void *object, uint32_t id, uint32_t flags,
++ const struct spa_pod *param);
++};
++
++static inline void
++pw_client_endpoint_proxy_add_listener(struct pw_client_endpoint_proxy *p,
++ struct spa_hook *listener,
++ const struct pw_client_endpoint_proxy_events *events,
++ void *data)
++{
++ pw_proxy_add_proxy_listener((struct pw_proxy*)p, listener, events, data);
++}
++
++#define pw_client_endpoint_resource_set_param(r,...) \
++ pw_resource_notify(r,struct pw_client_endpoint_proxy_events,set_param,__VA_ARGS__)
++
++#ifdef __cplusplus
++} /* extern "C" */
++#endif
++
++#endif /* PIPEWIRE_EXT_CLIENT_ENDPOINT_H */
+diff --git a/src/extensions/endpoint.h b/src/extensions/endpoint.h
+new file mode 100644
+index 00000000..211c0895
+--- /dev/null
++++ b/src/extensions/endpoint.h
+@@ -0,0 +1,237 @@
++/* PipeWire
++ *
++ * Copyright © 2019 Collabora Ltd.
++ * @author George Kiagiadakis <george.kiagiadakis@collabora.com>
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the next
++ * paragraph) shall be included in all copies or substantial portions of the
++ * Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
++#ifndef PIPEWIRE_EXT_ENDPOINT_H
++#define PIPEWIRE_EXT_ENDPOINT_H
++
++#include <spa/utils/defs.h>
++#include <spa/utils/type-info.h>
++#include <pipewire/proxy.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++struct pw_endpoint_proxy;
++
++#define PW_VERSION_ENDPOINT 0
++#define PW_EXTENSION_MODULE_ENDPOINT PIPEWIRE_MODULE_PREFIX "module-endpoint"
++
++/* extending enum spa_param_type */
++enum endpoint_param_type {
++ PW_ENDPOINT_PARAM_EnumControl = 0x1000,
++ PW_ENDPOINT_PARAM_Control,
++ PW_ENDPOINT_PARAM_EnumStream,
++};
++
++enum endpoint_param_object_type {
++ PW_ENDPOINT_OBJECT_ParamControl = PW_TYPE_FIRST + SPA_TYPE_OBJECT_START + 0x1001,
++ PW_ENDPOINT_OBJECT_ParamStream,
++};
++
++/** properties for PW_ENDPOINT_OBJECT_ParamControl */
++enum endpoint_param_control {
++ PW_ENDPOINT_PARAM_CONTROL_START, /**< object id, one of enum endpoint_param_type */
++ PW_ENDPOINT_PARAM_CONTROL_id, /**< control id (Int) */
++ PW_ENDPOINT_PARAM_CONTROL_stream_id, /**< stream id (Int) */
++ PW_ENDPOINT_PARAM_CONTROL_name, /**< control name (String) */
++ PW_ENDPOINT_PARAM_CONTROL_type, /**< control type (Range) */
++ PW_ENDPOINT_PARAM_CONTROL_value, /**< control value */
++};
++
++/** properties for PW_ENDPOINT_OBJECT_ParamStream */
++enum endpoint_param_stream {
++ PW_ENDPOINT_PARAM_STREAM_START, /**< object id, one of enum endpoint_param_type */
++ PW_ENDPOINT_PARAM_STREAM_id, /**< stream id (Int) */
++ PW_ENDPOINT_PARAM_STREAM_name, /**< stream name (String) */
++};
++
++static const struct spa_type_info endpoint_param_type_info[] = {
++ { PW_ENDPOINT_PARAM_EnumControl, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_ID_BASE "EnumControl", NULL },
++ { PW_ENDPOINT_PARAM_Control, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_ID_BASE "Control", NULL },
++ { PW_ENDPOINT_PARAM_EnumStream, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_ID_BASE "EnumStream", NULL },
++ { 0, 0, NULL, NULL },
++};
++
++#define PW_ENDPOINT_TYPE_INFO_ParamControl SPA_TYPE_INFO_PARAM_BASE "ParamControl"
++#define PW_ENDPOINT_TYPE_INFO_PARAM_CONTROL_BASE PW_ENDPOINT_TYPE_INFO_ParamControl ":"
++
++static const struct spa_type_info endpoint_param_control_info[] = {
++ { PW_ENDPOINT_PARAM_CONTROL_START, SPA_TYPE_Id, PW_ENDPOINT_TYPE_INFO_PARAM_CONTROL_BASE, spa_type_param, },
++ { PW_ENDPOINT_PARAM_CONTROL_id, SPA_TYPE_Int, PW_ENDPOINT_TYPE_INFO_PARAM_CONTROL_BASE "id", NULL },
++ { PW_ENDPOINT_PARAM_CONTROL_stream_id, SPA_TYPE_Int, PW_ENDPOINT_TYPE_INFO_PARAM_CONTROL_BASE "streamId", NULL },
++ { PW_ENDPOINT_PARAM_CONTROL_name, SPA_TYPE_String, PW_ENDPOINT_TYPE_INFO_PARAM_CONTROL_BASE "name", NULL },
++ { PW_ENDPOINT_PARAM_CONTROL_type, SPA_TYPE_Pod, PW_ENDPOINT_TYPE_INFO_PARAM_CONTROL_BASE "type", NULL },
++ { PW_ENDPOINT_PARAM_CONTROL_value, SPA_TYPE_Struct, PW_ENDPOINT_TYPE_INFO_PARAM_CONTROL_BASE "value", NULL },
++ { 0, 0, NULL, NULL },
++};
++
++#define PW_ENDPOINT_TYPE_INFO_ParamStream SPA_TYPE_INFO_PARAM_BASE "ParamStream"
++#define PW_ENDPOINT_TYPE_INFO_PARAM_STREAM_BASE PW_ENDPOINT_TYPE_INFO_ParamStream ":"
++
++static const struct spa_type_info endpoint_param_stream_info[] = {
++ { PW_ENDPOINT_PARAM_STREAM_START, SPA_TYPE_Id, PW_ENDPOINT_TYPE_INFO_PARAM_STREAM_BASE, spa_type_param, },
++ { PW_ENDPOINT_PARAM_STREAM_id, SPA_TYPE_Int, PW_ENDPOINT_TYPE_INFO_PARAM_STREAM_BASE "id", NULL },
++ { PW_ENDPOINT_PARAM_STREAM_name, SPA_TYPE_String, PW_ENDPOINT_TYPE_INFO_PARAM_STREAM_BASE "name", NULL },
++ { 0, 0, NULL, NULL },
++};
++
++static const struct spa_type_info endpoint_param_object_type_info[] = {
++ { PW_ENDPOINT_OBJECT_ParamControl, SPA_TYPE_Object, SPA_TYPE_INFO_OBJECT_BASE "ParamControl", endpoint_param_control_info, },
++ { PW_ENDPOINT_OBJECT_ParamStream, SPA_TYPE_Object, SPA_TYPE_INFO_OBJECT_BASE "ParamStream", endpoint_param_stream_info },
++ { 0, 0, NULL, NULL },
++};
++
++struct pw_endpoint_info {
++ uint32_t id; /**< id of the global */
++#define PW_ENDPOINT_CHANGE_MASK_PARAMS (1 << 0)
++#define PW_ENDPOINT_CHANGE_MASK_PROPS (1 << 1)
++ uint32_t change_mask; /**< bitfield of changed fields since last call */
++ uint32_t n_params; /**< number of items in \a params */
++ struct spa_param_info *params; /**< parameters */
++ struct spa_dict *props; /**< extra properties */
++};
++
++#define PW_ENDPOINT_PROXY_METHOD_SUBSCRIBE_PARAMS 0
++#define PW_ENDPOINT_PROXY_METHOD_ENUM_PARAMS 1
++#define PW_ENDPOINT_PROXY_METHOD_SET_PARAM 2
++#define PW_ENDPOINT_PROXY_METHOD_NUM 3
++
++struct pw_endpoint_proxy_methods {
++#define PW_VERSION_ENDPOINT_PROXY_METHODS 0
++ uint32_t version;
++
++ /**
++ * Subscribe to parameter changes
++ *
++ * Automatically emit param events for the given ids when
++ * they are changed.
++ *
++ * \param ids an array of param ids
++ * \param n_ids the number of ids in \a ids
++ */
++ int (*subscribe_params) (void *object, uint32_t *ids, uint32_t n_ids);
++
++ /**
++ * Enumerate endpoint parameters
++ *
++ * Start enumeration of endpoint parameters. For each param, a
++ * param event will be emited.
++ *
++ * \param seq a sequence number to place in the reply
++ * \param id the parameter id to enum or SPA_ID_INVALID for all
++ * \param start the start index or 0 for the first param
++ * \param num the maximum number of params to retrieve
++ * \param filter a param filter or NULL
++ */
++ int (*enum_params) (void *object, int seq,
++ uint32_t id, uint32_t start, uint32_t num,
++ const struct spa_pod *filter);
++
++ /**
++ * Set a parameter on the endpoint
++ *
++ * \param id the parameter id to set
++ * \param flags extra parameter flags
++ * \param param the parameter to set
++ */
++ int (*set_param) (void *object, uint32_t id, uint32_t flags,
++ const struct spa_pod *param);
++};
++
++static inline int
++pw_endpoint_proxy_subscribe_params(struct pw_endpoint_proxy *p, uint32_t *ids, uint32_t n_ids)
++{
++ return pw_proxy_do((struct pw_proxy*)p, struct pw_endpoint_proxy_methods,
++ subscribe_params, ids, n_ids);
++}
++
++static inline int
++pw_endpoint_proxy_enum_params(struct pw_endpoint_proxy *p, int seq,
++ uint32_t id, uint32_t start, uint32_t num,
++ const struct spa_pod *filter)
++{
++ return pw_proxy_do((struct pw_proxy*)p, struct pw_endpoint_proxy_methods,
++ enum_params, seq, id, start, num, filter);
++}
++
++static inline int
++pw_endpoint_proxy_set_param(struct pw_endpoint_proxy *p, uint32_t id,
++ uint32_t flags, const struct spa_pod *param)
++{
++ return pw_proxy_do((struct pw_proxy*)p, struct pw_endpoint_proxy_methods,
++ set_param, id, flags, param);
++}
++
++#define PW_ENDPOINT_PROXY_EVENT_INFO 0
++#define PW_ENDPOINT_PROXY_EVENT_PARAM 1
++#define PW_ENDPOINT_PROXY_EVENT_NUM 2
++
++struct pw_endpoint_proxy_events {
++#define PW_VERSION_ENDPOINT_PROXY_EVENTS 0
++ uint32_t version;
++
++ /**
++ * Notify endpoint info
++ *
++ * \param info info about the endpoint
++ */
++ void (*info) (void *object, const struct pw_endpoint_info * info);
++
++ /**
++ * Notify an endpoint param
++ *
++ * Event emited as a result of the enum_params method.
++ *
++ * \param seq the sequence number of the request
++ * \param id the param id
++ * \param index the param index
++ * \param next the param index of the next param
++ * \param param the parameter
++ */
++ void (*param) (void *object, int seq, uint32_t id,
++ uint32_t index, uint32_t next,
++ const struct spa_pod *param);
++};
++
++static inline void
++pw_endpoint_proxy_add_listener(struct pw_endpoint_proxy *p,
++ struct spa_hook *listener,
++ const struct pw_endpoint_proxy_events *events,
++ void *data)
++{
++ pw_proxy_add_proxy_listener((struct pw_proxy*)p, listener, events, data);
++}
++
++#define pw_endpoint_resource_info(r,...) \
++ pw_resource_notify(r,struct pw_endpoint_proxy_events,info,__VA_ARGS__)
++#define pw_endpoint_resource_param(r,...) \
++ pw_resource_notify(r,struct pw_endpoint_proxy_events,param,__VA_ARGS__)
++
++#ifdef __cplusplus
++} /* extern "C" */
++#endif
++
++#endif /* PIPEWIRE_EXT_ENDPOINT_H */
+diff --git a/src/extensions/meson.build b/src/extensions/meson.build
+index a7f5d3cb..9f690caf 100644
+--- a/src/extensions/meson.build
++++ b/src/extensions/meson.build
+@@ -1,5 +1,7 @@
+ pipewire_ext_headers = [
++ 'client-endpoint.h',
+ 'client-node.h',
++ 'endpoint.h',
+ 'protocol-native.h',
+ ]
+
+diff --git a/src/modules/meson.build b/src/modules/meson.build
+index 98bc3864..572f1b6b 100644
+--- a/src/modules/meson.build
++++ b/src/modules/meson.build
+@@ -37,6 +37,18 @@ pipewire_module_client_node = shared_library('pipewire-module-client-node',
+ dependencies : [mathlib, dl_lib, pipewire_dep],
+ )
+
++pipewire_module_endpoint = shared_library('pipewire-module-endpoint',
++ [ 'module-endpoint.c',
++ 'module-endpoint/endpoint-impl.c',
++ 'module-endpoint/protocol-native.c',
++ ],
++ c_args : pipewire_module_c_args,
++ include_directories : [configinc, spa_inc],
++ install : true,
++ install_dir : modules_install_dir,
++ dependencies : [mathlib, dl_lib, pipewire_dep],
++)
++
+ pipewire_module_link_factory = shared_library('pipewire-module-link-factory',
+ [ 'module-link-factory.c' ],
+ c_args : pipewire_module_c_args,
+diff --git a/src/modules/module-endpoint.c b/src/modules/module-endpoint.c
+new file mode 100644
+index 00000000..d830de1b
+--- /dev/null
++++ b/src/modules/module-endpoint.c
+@@ -0,0 +1,137 @@
++/* PipeWire
++ *
++ * Copyright © 2019 Collabora Ltd.
++ * @author George Kiagiadakis <george.kiagiadakis@collabora.com>
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the next
++ * paragraph) shall be included in all copies or substantial portions of the
++ * Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
++#include "config.h"
++
++#include "module-endpoint/endpoint-impl.h"
++
++struct pw_protocol *pw_protocol_native_ext_endpoint_init(struct pw_core *core);
++
++static const struct spa_dict_item module_props[] = {
++ { PW_MODULE_PROP_AUTHOR, "George Kiagiadakis <george.kiagiadakis@collabora.com>" },
++ { PW_MODULE_PROP_DESCRIPTION, "Allows clients to interract with session manager endpoints" },
++ { PW_MODULE_PROP_VERSION, PACKAGE_VERSION },
++};
++
++struct factory_data {
++ struct pw_factory *this;
++ struct pw_properties *properties;
++
++ struct pw_module *module;
++ struct spa_hook module_listener;
++};
++
++static void *create_object(void *_data,
++ struct pw_resource *resource,
++ uint32_t type,
++ uint32_t version,
++ struct pw_properties *properties,
++ uint32_t new_id)
++{
++ void *result;
++ struct pw_resource *endpoint_resource;
++ struct pw_global *parent;
++ struct pw_client *client = pw_resource_get_client(resource);
++
++ endpoint_resource = pw_resource_new(client, new_id, PW_PERM_RWX, type, version, 0);
++ if (endpoint_resource == NULL)
++ goto no_mem;
++
++ parent = pw_client_get_global(client);
++
++ result = pw_client_endpoint_new(endpoint_resource, parent, properties);
++ if (result == NULL)
++ goto no_mem;
++
++ return result;
++
++ no_mem:
++ pw_log_error("can't create endpoint");
++ pw_resource_error(resource, -ENOMEM, "can't create endpoint: no memory");
++ if (properties)
++ pw_properties_free(properties);
++ return NULL;
++}
++
++static const struct pw_factory_implementation impl_factory = {
++ PW_VERSION_FACTORY_IMPLEMENTATION,
++ .create_object = create_object,
++};
++
++static void module_destroy(void *data)
++{
++ struct factory_data *d = data;
++
++ spa_hook_remove(&d->module_listener);
++
++ if (d->properties)
++ pw_properties_free(d->properties);
++
++ pw_factory_destroy(d->this);
++}
++
++static const struct pw_module_events module_events = {
++ PW_VERSION_MODULE_EVENTS,
++ .destroy = module_destroy,
++};
++
++static int module_init(struct pw_module *module, struct pw_properties *properties)
++{
++ struct pw_core *core = pw_module_get_core(module);
++ struct pw_factory *factory;
++ struct factory_data *data;
++
++ factory = pw_factory_new(core,
++ "client-endpoint",
++ PW_TYPE_INTERFACE_ClientEndpoint,
++ PW_VERSION_CLIENT_ENDPOINT,
++ NULL,
++ sizeof(*data));
++ if (factory == NULL)
++ return -ENOMEM;
++
++ data = pw_factory_get_user_data(factory);
++ data->this = factory;
++ data->module = module;
++ data->properties = properties;
++
++ pw_log_debug("module-endpoint %p: new", module);
++
++ pw_factory_set_implementation(factory, &impl_factory, data);
++ pw_factory_register(factory, NULL, pw_module_get_global(module), NULL);
++
++ pw_protocol_native_ext_endpoint_init(core);
++
++ pw_module_add_listener(module, &data->module_listener, &module_events, data);
++ pw_module_update_properties(module, &SPA_DICT_INIT_ARRAY(module_props));
++
++ return 0;
++}
++
++SPA_EXPORT
++int pipewire__module_init(struct pw_module *module, const char *args)
++{
++ return module_init(module, NULL);
++}
+diff --git a/src/modules/module-endpoint/endpoint-impl.c b/src/modules/module-endpoint/endpoint-impl.c
+new file mode 100644
+index 00000000..252eeca1
+--- /dev/null
++++ b/src/modules/module-endpoint/endpoint-impl.c
+@@ -0,0 +1,428 @@
++/* PipeWire
++ *
++ * Copyright © 2019 Collabora Ltd.
++ * @author George Kiagiadakis <george.kiagiadakis@collabora.com>
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the next
++ * paragraph) shall be included in all copies or substantial portions of the
++ * Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
++#include "endpoint-impl.h"
++#include <pipewire/private.h>
++#include <spa/pod/filter.h>
++#include <spa/pod/compare.h>
++
++struct pw_endpoint {
++ struct pw_core *core;
++ struct pw_global *global;
++ struct pw_global *parent;
++
++ struct pw_client_endpoint *client_ep;
++
++ uint32_t n_params;
++ struct spa_pod **params;
++
++ struct pw_endpoint_info info;
++ struct pw_properties *props;
++};
++
++struct pw_client_endpoint {
++ struct pw_resource *owner_resource;
++ struct spa_hook owner_resource_listener;
++
++ struct pw_endpoint endpoint;
++};
++
++struct resource_data {
++ struct pw_endpoint *endpoint;
++ struct pw_client_endpoint *client_ep;
++
++ struct spa_hook resource_listener;
++
++ uint32_t n_subscribe_ids;
++ uint32_t subscribe_ids[32];
++};
++
++static int
++endpoint_enum_params (void *object, int seq,
++ uint32_t id, uint32_t start, uint32_t num,
++ const struct spa_pod *filter)
++{
++ struct pw_resource *resource = object;
++ struct resource_data *data = pw_resource_get_user_data(resource);
++ struct pw_endpoint *this = data->endpoint;
++ struct spa_pod *result;
++ struct spa_pod *param;
++ uint8_t buffer[1024];
++ struct spa_pod_builder b = { 0 };
++ uint32_t index;
++ uint32_t next = start;
++ uint32_t count = 0;
++
++ while (true) {
++ index = next++;
++ if (index >= this->n_params)
++ break;
++
++ param = this->params[index];
++
++ if (param == NULL || !spa_pod_is_object_id(param, id))
++ continue;
++
++ spa_pod_builder_init(&b, buffer, sizeof(buffer));
++ if (spa_pod_filter(&b, &result, param, filter) != 0)
++ continue;
++
++ pw_log_debug("endpoint %p: %d param %u", this, seq, index);
++
++ pw_endpoint_resource_param(resource, seq, id, index, next, result);
++
++ if (++count == num)
++ break;
++ }
++ return 0;
++}
++
++static int
++endpoint_subscribe_params (void *object, uint32_t *ids, uint32_t n_ids)
++{
++ struct pw_resource *resource = object;
++ struct resource_data *data = pw_resource_get_user_data(resource);
++ uint32_t i;
++
++ n_ids = SPA_MIN(n_ids, SPA_N_ELEMENTS(data->subscribe_ids));
++ data->n_subscribe_ids = n_ids;
++
++ for (i = 0; i < n_ids; i++) {
++ data->subscribe_ids[i] = ids[i];
++ pw_log_debug("endpoint %p: resource %d subscribe param %u",
++ data->endpoint, resource->id, ids[i]);
++ endpoint_enum_params(resource, 1, ids[i], 0, UINT32_MAX, NULL);
++ }
++ return 0;
++}
++
++static int
++endpoint_set_param (void *object, uint32_t id, uint32_t flags,
++ const struct spa_pod *param)
++{
++ struct pw_resource *resource = object;
++ struct resource_data *data = pw_resource_get_user_data(resource);
++ struct pw_client_endpoint *client_ep = data->client_ep;
++
++ pw_client_endpoint_resource_set_param(client_ep->owner_resource,
++ id, flags, param);
++
++ return 0;
++}
++
++static const struct pw_endpoint_proxy_methods endpoint_methods = {
++ PW_VERSION_ENDPOINT_PROXY_METHODS,
++ .subscribe_params = endpoint_subscribe_params,
++ .enum_params = endpoint_enum_params,
++ .set_param = endpoint_set_param,
++};
++
++static void
++endpoint_unbind(void *data)
++{
++ struct pw_resource *resource = data;
++ spa_list_remove(&resource->link);
++}
++
++static const struct pw_resource_events resource_events = {
++ PW_VERSION_RESOURCE_EVENTS,
++ .destroy = endpoint_unbind,
++};
++
++static int
++endpoint_bind(void *_data, struct pw_client *client, uint32_t permissions,
++ uint32_t version, uint32_t id)
++{
++ struct pw_endpoint *this = _data;
++ struct pw_global *global = this->global;
++ struct pw_resource *resource;
++ struct resource_data *data;
++
++ resource = pw_resource_new(client, id, permissions, global->type, version, sizeof(*data));
++ if (resource == NULL)
++ goto no_mem;
++
++ data = pw_resource_get_user_data(resource);
++ data->endpoint = this;
++ data->client_ep = this->client_ep;
++ pw_resource_add_listener(resource, &data->resource_listener, &resource_events, resource);
++
++ pw_resource_set_implementation(resource, &endpoint_methods, resource);
++
++ pw_log_debug("endpoint %p: bound to %d", this, resource->id);
++
++ spa_list_append(&global->resource_list, &resource->link);
++
++ this->info.change_mask = PW_ENDPOINT_CHANGE_MASK_PARAMS |
++ PW_ENDPOINT_CHANGE_MASK_PROPS;
++ pw_endpoint_resource_info(resource, &this->info);
++ this->info.change_mask = 0;
++
++ return 0;
++
++ no_mem:
++ pw_log_error("can't create node resource");
++ return -ENOMEM;
++}
++
++static int
++pw_endpoint_init(struct pw_endpoint *this,
++ struct pw_core *core,
++ struct pw_client *owner,
++ struct pw_global *parent,
++ struct pw_properties *properties)
++{
++ struct pw_properties *props = NULL;
++
++ pw_log_debug("endpoint %p: new", this);
++
++ this->core = core;
++ this->parent = parent;
++
++ props = properties ? properties : pw_properties_new(NULL, NULL);
++ if (!props)
++ goto no_mem;
++
++ this->props = pw_properties_copy (props);
++ if (!this->props)
++ goto no_mem;
++
++ this->global = pw_global_new (core,
++ PW_TYPE_INTERFACE_Endpoint,
++ PW_VERSION_ENDPOINT,
++ props, endpoint_bind, this);
++ if (!this->global)
++ goto no_mem;
++
++ this->info.id = this->global->id;
++ this->info.props = &this->props->dict;
++
++ return pw_global_register(this->global, owner, parent);
++
++ no_mem:
++ pw_log_error("can't create endpoint - out of memory");
++ if (props && !properties)
++ pw_properties_free(props);
++ if (this->props)
++ pw_properties_free(this->props);
++ return -ENOMEM;
++}
++
++static void
++pw_endpoint_clear(struct pw_endpoint *this)
++{
++ uint32_t i;
++
++ pw_log_debug("endpoint %p: destroy", this);
++
++ pw_global_destroy(this->global);
++
++ for (i = 0; i < this->n_params; i++)
++ free(this->params[i]);
++ free(this->params);
++
++ free(this->info.params);
++
++ if (this->props)
++ pw_properties_free(this->props);
++}
++
++static void
++endpoint_notify_subscribed(struct pw_endpoint *this,
++ uint32_t index, uint32_t next)
++{
++ struct pw_global *global = this->global;
++ struct pw_resource *resource;
++ struct resource_data *data;
++ struct spa_pod *param = this->params[index];
++ uint32_t id;
++ uint32_t i;
++
++ if (!param || !spa_pod_is_object (param))
++ return;
++
++ id = SPA_POD_OBJECT_ID (param);
++
++ spa_list_for_each(resource, &global->resource_list, link) {
++ data = pw_resource_get_user_data(resource);
++ for (i = 0; i < data->n_subscribe_ids; i++) {
++ if (data->subscribe_ids[i] == id) {
++ pw_endpoint_resource_param(resource, 1, id,
++ index, next, param);
++ }
++ }
++ }
++}
++
++static int
++client_endpoint_update(void *object,
++ uint32_t change_mask,
++ uint32_t n_params,
++ const struct spa_pod **params,
++ const struct pw_endpoint_info *info)
++{
++ struct pw_client_endpoint *cliep = object;
++ struct pw_endpoint *this = &cliep->endpoint;
++
++ if (change_mask & PW_CLIENT_ENDPOINT_UPDATE_PARAMS) {
++ uint32_t i;
++
++ pw_log_debug("endpoint %p: update %d params", this, n_params);
++
++ for (i = 0; i < this->n_params; i++)
++ free(this->params[i]);
++ this->n_params = n_params;
++ this->params = realloc(this->params, this->n_params * sizeof(struct spa_pod *));
++
++ for (i = 0; i < this->n_params; i++) {
++ this->params[i] = params[i] ? spa_pod_copy(params[i]) : NULL;
++ endpoint_notify_subscribed(this, i, i+1);
++ }
++ }
++ else if (change_mask & PW_CLIENT_ENDPOINT_UPDATE_PARAMS_INCREMENTAL) {
++ uint32_t i, j;
++ const struct spa_pod_prop *pold, *pnew;
++
++ pw_log_debug("endpoint %p: update %d params incremental", this, n_params);
++
++ for (i = 0; i < this->n_params; i++) {
++ /* we only support incremental updates for controls */
++ if (!spa_pod_is_object_id (this->params[i], PW_ENDPOINT_PARAM_Control))
++ continue;
++
++ for (j = 0; j < n_params; j++) {
++ if (!spa_pod_is_object_id (params[j], PW_ENDPOINT_PARAM_Control)) {
++ pw_log_warn ("endpoint %p: ignoring incremental update "
++ "on non-control param", this);
++ continue;
++ }
++
++ pold = spa_pod_object_find_prop (
++ (const struct spa_pod_object *) this->params[i],
++ NULL, PW_ENDPOINT_PARAM_CONTROL_id);
++ pnew = spa_pod_object_find_prop (
++ (const struct spa_pod_object *) params[j],
++ NULL, PW_ENDPOINT_PARAM_CONTROL_id);
++
++ if (pold && pnew && spa_pod_compare (&pold->value, &pnew->value) == 0) {
++ free (this->params[i]);
++ this->params[i] = spa_pod_copy (params[j]);
++ endpoint_notify_subscribed(this, i, UINT32_MAX);
++ }
++ }
++ }
++ }
++
++ if (change_mask & PW_CLIENT_ENDPOINT_UPDATE_INFO) {
++ struct pw_global *global = this->global;
++ struct pw_resource *resource;
++
++ if (info->change_mask & PW_ENDPOINT_CHANGE_MASK_PARAMS) {
++ size_t size = info->n_params * sizeof(struct spa_param_info);
++ free(this->info.params);
++ this->info.params = malloc(size);
++ this->info.n_params = info->n_params;
++ memcpy(this->info.params, info->params, size);
++ }
++
++ if (info->change_mask & PW_ENDPOINT_CHANGE_MASK_PROPS) {
++ pw_properties_update(this->props, info->props);
++ }
++
++ this->info.change_mask = info->change_mask;
++ spa_list_for_each(resource, &global->resource_list, link) {
++ pw_endpoint_resource_info(resource, &this->info);
++ }
++ this->info.change_mask = 0;
++ }
++
++ return 0;
++}
++
++static struct pw_client_endpoint_proxy_methods client_endpoint_methods = {
++ PW_VERSION_CLIENT_ENDPOINT_PROXY_METHODS,
++ .update = client_endpoint_update,
++};
++
++static void
++client_endpoint_resource_destroy(void *data)
++{
++ struct pw_client_endpoint *this = data;
++
++ pw_log_debug("client-endpoint %p: destroy", this);
++
++ pw_endpoint_clear(&this->endpoint);
++
++ this->owner_resource = NULL;
++ spa_hook_remove(&this->owner_resource_listener);
++ free(this);
++}
++
++static const struct pw_resource_events owner_resource_events = {
++ PW_VERSION_RESOURCE_EVENTS,
++ .destroy = client_endpoint_resource_destroy,
++};
++
++struct pw_client_endpoint *
++pw_client_endpoint_new(struct pw_resource *owner_resource,
++ struct pw_global *parent,
++ struct pw_properties *properties)
++{
++ struct pw_client_endpoint *this;
++ struct pw_client *owner = pw_resource_get_client(owner_resource);
++ struct pw_core *core = pw_client_get_core(owner);
++
++ this = calloc(1, sizeof(struct pw_client_endpoint));
++ if (this == NULL)
++ return NULL;
++
++ pw_log_debug("client-endpoint %p: new", this);
++
++ if (pw_endpoint_init(&this->endpoint, core, owner, parent, properties) < 0)
++ goto error_no_endpoint;
++ this->endpoint.client_ep = this;
++
++ this->owner_resource = owner_resource;
++ pw_resource_add_listener(this->owner_resource,
++ &this->owner_resource_listener,
++ &owner_resource_events,
++ this);
++ pw_resource_set_implementation(this->owner_resource,
++ &client_endpoint_methods,
++ this);
++
++ return this;
++
++ error_no_endpoint:
++ pw_resource_destroy(owner_resource);
++ free(this);
++ return NULL;
++}
++
++void
++pw_client_endpoint_destroy(struct pw_client_endpoint *this)
++{
++ pw_resource_destroy(this->owner_resource);
++}
+diff --git a/src/modules/module-endpoint/endpoint-impl.h b/src/modules/module-endpoint/endpoint-impl.h
+new file mode 100644
+index 00000000..059aa904
+--- /dev/null
++++ b/src/modules/module-endpoint/endpoint-impl.h
+@@ -0,0 +1,52 @@
++/* PipeWire
++ *
++ * Copyright © 2019 Collabora Ltd.
++ * @author George Kiagiadakis <george.kiagiadakis@collabora.com>
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the next
++ * paragraph) shall be included in all copies or substantial portions of the
++ * Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
++#ifndef PIPEWIRE_ENDPOINT_IMPL_H
++#define PIPEWIRE_ENDPOINT_IMPL_H
++
++#include <pipewire/pipewire.h>
++#include <extensions/endpoint.h>
++#include <extensions/client-endpoint.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++struct pw_endpoint;
++struct pw_client_endpoint;
++
++struct pw_client_endpoint *
++pw_client_endpoint_new(struct pw_resource *resource,
++ struct pw_global *parent,
++ struct pw_properties *properties);
++
++void
++pw_client_endpoint_destroy(struct pw_client_endpoint *endpoint);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* PIPEWIRE_ENDPOINT_IMPL_H */
+diff --git a/src/modules/module-endpoint/protocol-native.c b/src/modules/module-endpoint/protocol-native.c
+new file mode 100644
+index 00000000..a41d3119
+--- /dev/null
++++ b/src/modules/module-endpoint/protocol-native.c
+@@ -0,0 +1,472 @@
++/* PipeWire
++ *
++ * Copyright © 2019 Collabora Ltd.
++ * @author George Kiagiadakis <george.kiagiadakis@collabora.com>
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the next
++ * paragraph) shall be included in all copies or substantial portions of the
++ * Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
++#include <pipewire/pipewire.h>
++#include <spa/pod/parser.h>
++
++#include <extensions/client-endpoint.h>
++#include <extensions/endpoint.h>
++#include <extensions/protocol-native.h>
++
++static void
++serialize_pw_endpoint_info(struct spa_pod_builder *b,
++ const struct pw_endpoint_info *info)
++{
++ struct spa_pod_frame f;
++ uint32_t i, n_props;
++
++ n_props = info->props ? info->props->n_items : 0;
++
++ spa_pod_builder_push_struct(b, &f);
++ spa_pod_builder_add(b,
++ SPA_POD_Id(info->id),
++ SPA_POD_Int(info->change_mask),
++ SPA_POD_Int(info->n_params),
++ SPA_POD_Int(n_props),
++ NULL);
++
++ for (i = 0; i < info->n_params; i++) {
++ spa_pod_builder_add(b,
++ SPA_POD_Id(info->params[i].id),
++ SPA_POD_Int(info->params[i].flags), NULL);
++ }
++
++ for (i = 0; i < n_props; i++) {
++ spa_pod_builder_add(b,
++ SPA_POD_String(info->props->items[i].key),
++ SPA_POD_String(info->props->items[i].value),
++ NULL);
++ }
++
++ spa_pod_builder_pop(b, &f);
++}
++
++/* macro because of alloca() */
++#define deserialize_pw_endpoint_info(p, f, info) \
++do { \
++ if (spa_pod_parser_push_struct(p, f) < 0 || \
++ spa_pod_parser_get(p, \
++ SPA_POD_Id(&(info)->id), \
++ SPA_POD_Int(&(info)->change_mask), \
++ SPA_POD_Int(&(info)->n_params), \
++ SPA_POD_Int(&(info)->props->n_items), \
++ NULL) < 0) \
++ return -EINVAL; \
++ \
++ if ((info)->n_params > 0) \
++ (info)->params = alloca((info)->n_params * sizeof(struct spa_param_info)); \
++ if ((info)->props->n_items > 0) \
++ (info)->props->items = alloca((info)->props->n_items * sizeof(struct spa_dict_item)); \
++ \
++ for (i = 0; i < (info)->n_params; i++) { \
++ if (spa_pod_parser_get(p, \
++ SPA_POD_Id(&(info)->params[i].id), \
++ SPA_POD_Int(&(info)->params[i].flags), \
++ NULL) < 0) \
++ return -EINVAL; \
++ } \
++ \
++ for (i = 0; i < (info)->props->n_items; i++) { \
++ if (spa_pod_parser_get(p, \
++ SPA_POD_String(&(info)->props->items[i].key), \
++ SPA_POD_String(&(info)->props->items[i].value), \
++ NULL) < 0) \
++ return -EINVAL; \
++ } \
++ \
++ spa_pod_parser_pop(p, f); \
++} while(0)
++
++static int
++endpoint_marshal_subscribe_params(void *object, uint32_t *ids, uint32_t n_ids)
++{
++ struct pw_proxy *proxy = object;
++ struct spa_pod_builder *b;
++
++ b = pw_protocol_native_begin_proxy(proxy,
++ PW_ENDPOINT_PROXY_METHOD_SUBSCRIBE_PARAMS, NULL);
++
++ spa_pod_builder_add_struct(b,
++ SPA_POD_Array(sizeof(uint32_t), SPA_TYPE_Id, n_ids, ids));
++
++ return pw_protocol_native_end_proxy(proxy, b);
++}
++
++static int
++endpoint_demarshal_subscribe_params(void *object, const struct pw_protocol_native_message *msg)
++{
++ struct pw_resource *resource = object;
++ struct spa_pod_parser prs;
++ uint32_t csize, ctype, n_ids;
++ uint32_t *ids;
++
++ spa_pod_parser_init(&prs, msg->data, msg->size);
++ if (spa_pod_parser_get_struct(&prs,
++ SPA_POD_Array(&csize, &ctype, &n_ids, &ids)) < 0)
++ return -EINVAL;
++
++ if (ctype != SPA_TYPE_Id)
++ return -EINVAL;
++
++ return pw_resource_do(resource, struct pw_endpoint_proxy_methods,
++ subscribe_params, 0, ids, n_ids);
++}
++
++static int
++endpoint_marshal_enum_params(void *object, int seq, uint32_t id,
++ uint32_t index, uint32_t num, const struct spa_pod *filter)
++{
++ struct pw_proxy *proxy = object;
++ struct spa_pod_builder *b;
++
++ b = pw_protocol_native_begin_proxy(proxy,
++ PW_ENDPOINT_PROXY_METHOD_ENUM_PARAMS, NULL);
++
++ spa_pod_builder_add_struct(b,
++ SPA_POD_Int(seq),
++ SPA_POD_Id(id),
++ SPA_POD_Int(index),
++ SPA_POD_Int(num),
++ SPA_POD_Pod(filter));
++
++ return pw_protocol_native_end_proxy(proxy, b);
++}
++
++static int
++endpoint_demarshal_enum_params(void *object, const struct pw_protocol_native_message *msg)
++{
++ struct pw_resource *resource = object;
++ struct spa_pod_parser prs;
++ uint32_t id, index, num;
++ int seq;
++ struct spa_pod *filter;
++
++ spa_pod_parser_init(&prs, msg->data, msg->size);
++ if (spa_pod_parser_get_struct(&prs,
++ SPA_POD_Int(&seq),
++ SPA_POD_Id(&id),
++ SPA_POD_Int(&index),
++ SPA_POD_Int(&num),
++ SPA_POD_Pod(&filter)) < 0)
++ return -EINVAL;
++
++ return pw_resource_do(resource, struct pw_endpoint_proxy_methods,
++ enum_params, 0, seq, id, index, num, filter);
++}
++
++static int
++endpoint_marshal_set_param(void *object, uint32_t id, uint32_t flags,
++ const struct spa_pod *param)
++{
++ struct pw_proxy *proxy = object;
++ struct spa_pod_builder *b;
++
++ b = pw_protocol_native_begin_proxy(proxy,
++ PW_ENDPOINT_PROXY_METHOD_SET_PARAM, NULL);
++
++ spa_pod_builder_add_struct(b,
++ SPA_POD_Id(id),
++ SPA_POD_Int(flags),
++ SPA_POD_Pod(param));
++ return pw_protocol_native_end_proxy(proxy, b);
++}
++
++static int
++endpoint_demarshal_set_param(void *object, const struct pw_protocol_native_message *msg)
++{
++ struct pw_resource *resource = object;
++ struct spa_pod_parser prs;
++ uint32_t id, flags;
++ struct spa_pod *param;
++
++ spa_pod_parser_init(&prs, msg->data, msg->size);
++ if (spa_pod_parser_get_struct(&prs,
++ SPA_POD_Id(&id),
++ SPA_POD_Int(&flags),
++ SPA_POD_Pod(&param)) < 0)
++ return -EINVAL;
++
++ return pw_resource_do(resource, struct pw_endpoint_proxy_methods,
++ set_param, 0, id, flags, param);
++}
++
++static void
++endpoint_marshal_info(void *object, const struct pw_endpoint_info *info)
++{
++ struct pw_resource *resource = object;
++ struct spa_pod_builder *b;
++
++ b = pw_protocol_native_begin_resource(resource,
++ PW_ENDPOINT_PROXY_EVENT_INFO, NULL);
++ serialize_pw_endpoint_info (b, info);
++ pw_protocol_native_end_resource(resource, b);
++}
++
++static int
++endpoint_demarshal_info(void *object, const struct pw_protocol_native_message *msg)
++{
++ struct pw_proxy *proxy = object;
++ struct spa_pod_parser prs;
++ struct spa_pod_frame f;
++ struct spa_dict props = SPA_DICT_INIT(NULL, 0);
++ struct pw_endpoint_info info = { .props = &props };
++ uint32_t i;
++
++ spa_pod_parser_init(&prs, msg->data, msg->size);
++
++ deserialize_pw_endpoint_info(&prs, &f, &info);
++
++ return pw_proxy_notify(proxy, struct pw_endpoint_proxy_events,
++ info, 0, &info);
++}
++
++static void
++endpoint_marshal_param(void *object, int seq, uint32_t id,
++ uint32_t index, uint32_t next, const struct spa_pod *param)
++{
++ struct pw_resource *resource = object;
++ struct spa_pod_builder *b;
++
++ b = pw_protocol_native_begin_resource(resource,
++ PW_ENDPOINT_PROXY_EVENT_PARAM, NULL);
++
++ spa_pod_builder_add_struct(b,
++ SPA_POD_Int(seq),
++ SPA_POD_Id(id),
++ SPA_POD_Int(index),
++ SPA_POD_Int(next),
++ SPA_POD_Pod(param));
++
++ pw_protocol_native_end_resource(resource, b);
++}
++
++static int
++endpoint_demarshal_param(void *object, const struct pw_protocol_native_message *msg)
++{
++ struct pw_proxy *proxy = object;
++ struct spa_pod_parser prs;
++ uint32_t id, index, next;
++ int seq;
++ struct spa_pod *param;
++
++ spa_pod_parser_init(&prs, msg->data, msg->size);
++ if (spa_pod_parser_get_struct(&prs,
++ SPA_POD_Int(&seq),
++ SPA_POD_Id(&id),
++ SPA_POD_Int(&index),
++ SPA_POD_Int(&next),
++ SPA_POD_Pod(&param)) < 0)
++ return -EINVAL;
++
++ return pw_proxy_notify(proxy, struct pw_endpoint_proxy_events, param, 0,
++ seq, id, index, next, param);
++}
++
++static const struct pw_endpoint_proxy_methods pw_protocol_native_endpoint_method_marshal = {
++ PW_VERSION_ENDPOINT_PROXY_METHODS,
++ &endpoint_marshal_subscribe_params,
++ &endpoint_marshal_enum_params,
++ &endpoint_marshal_set_param,
++};
++
++static const struct pw_protocol_native_demarshal pw_protocol_native_endpoint_method_demarshal[] = {
++ { &endpoint_demarshal_subscribe_params, 0 },
++ { &endpoint_demarshal_enum_params, 0 },
++ { &endpoint_demarshal_set_param, 0 }
++};
++
++static const struct pw_endpoint_proxy_events pw_protocol_native_endpoint_event_marshal = {
++ PW_VERSION_ENDPOINT_PROXY_EVENTS,
++ &endpoint_marshal_info,
++ &endpoint_marshal_param,
++};
++
++static const struct pw_protocol_native_demarshal pw_protocol_native_endpoint_event_demarshal[] = {
++ { &endpoint_demarshal_info, 0 },
++ { &endpoint_demarshal_param, 0 }
++};
++
++static const struct pw_protocol_marshal pw_protocol_native_endpoint_marshal = {
++ PW_TYPE_INTERFACE_Endpoint,
++ PW_VERSION_ENDPOINT,
++ PW_ENDPOINT_PROXY_METHOD_NUM,
++ PW_ENDPOINT_PROXY_EVENT_NUM,
++ &pw_protocol_native_endpoint_method_marshal,
++ &pw_protocol_native_endpoint_method_demarshal,
++ &pw_protocol_native_endpoint_event_marshal,
++ &pw_protocol_native_endpoint_event_demarshal,
++};
++
++
++static int
++client_endpoint_marshal_update(
++ void *object,
++ uint32_t change_mask,
++ uint32_t n_params,
++ const struct spa_pod **params,
++ const struct pw_endpoint_info *info)
++{
++ struct pw_proxy *proxy = object;
++ struct spa_pod_builder *b;
++ struct spa_pod_frame f;
++ uint32_t i;
++
++ b = pw_protocol_native_begin_proxy(proxy,
++ PW_CLIENT_ENDPOINT_PROXY_METHOD_UPDATE, NULL);
++
++ spa_pod_builder_push_struct(b, &f);
++ spa_pod_builder_add(b,
++ SPA_POD_Int(change_mask),
++ SPA_POD_Int(n_params), NULL);
++
++ for (i = 0; i < n_params; i++)
++ spa_pod_builder_add(b, SPA_POD_Pod(params[i]), NULL);
++
++ if (change_mask & PW_CLIENT_ENDPOINT_UPDATE_INFO)
++ serialize_pw_endpoint_info(b, info);
++
++ spa_pod_builder_pop(b, &f);
++
++ return pw_protocol_native_end_proxy(proxy, b);
++}
++
++static int
++client_endpoint_demarshal_update(void *object,
++ const struct pw_protocol_native_message *msg)
++{
++ struct pw_resource *resource = object;
++ struct spa_pod_parser prs;
++ struct spa_pod_frame f[2];
++ uint32_t change_mask, n_params;
++ const struct spa_pod **params = NULL;
++ struct spa_dict props = SPA_DICT_INIT(NULL, 0);
++ struct pw_endpoint_info info = { .props = &props };
++ uint32_t i;
++
++ spa_pod_parser_init(&prs, msg->data, msg->size);
++ if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
++ spa_pod_parser_get(&prs,
++ SPA_POD_Int(&change_mask),
++ SPA_POD_Int(&n_params), NULL) < 0)
++ return -EINVAL;
++
++ if (n_params > 0)
++ params = alloca(n_params * sizeof(struct spa_pod *));
++ for (i = 0; i < n_params; i++)
++ if (spa_pod_parser_get(&prs,
++ SPA_POD_PodObject(&params[i]), NULL) < 0)
++ return -EINVAL;
++
++ if (change_mask & PW_CLIENT_ENDPOINT_UPDATE_INFO)
++ deserialize_pw_endpoint_info(&prs, &f[1], &info);
++
++ pw_resource_do(resource, struct pw_client_endpoint_proxy_methods,
++ update, 0, change_mask, n_params, params, &info);
++ return 0;
++}
++
++static void
++client_endpoint_marshal_set_param (void *object,
++ uint32_t id, uint32_t flags,
++ const struct spa_pod *param)
++{
++ struct pw_resource *resource = object;
++ struct spa_pod_builder *b;
++
++ b = pw_protocol_native_begin_resource(resource,
++ PW_CLIENT_ENDPOINT_PROXY_EVENT_SET_PARAM, NULL);
++
++ spa_pod_builder_add_struct(b,
++ SPA_POD_Id(id),
++ SPA_POD_Int(flags),
++ SPA_POD_Pod(param));
++
++ pw_protocol_native_end_resource(resource, b);
++}
++
++static int
++client_endpoint_demarshal_set_param(void *object,
++ const struct pw_protocol_native_message *msg)
++{
++ struct pw_proxy *proxy = object;
++ struct spa_pod_parser prs;
++ uint32_t id, flags;
++ const struct spa_pod *param = NULL;
++
++ spa_pod_parser_init(&prs, msg->data, msg->size);
++ if (spa_pod_parser_get_struct(&prs,
++ SPA_POD_Id(&id),
++ SPA_POD_Int(&flags),
++ SPA_POD_PodObject(&param)) < 0)
++ return -EINVAL;
++
++ pw_proxy_notify(proxy, struct pw_client_endpoint_proxy_events,
++ set_param, 0, id, flags, param);
++ return 0;
++}
++
++static const struct pw_client_endpoint_proxy_methods pw_protocol_native_client_endpoint_method_marshal = {
++ PW_VERSION_CLIENT_ENDPOINT_PROXY_METHODS,
++ &client_endpoint_marshal_update,
++};
++
++static const struct pw_protocol_native_demarshal pw_protocol_native_client_endpoint_method_demarshal[] = {
++ { &client_endpoint_demarshal_update, 0 }
++};
++
++static const struct pw_client_endpoint_proxy_events pw_protocol_native_client_endpoint_event_marshal = {
++ PW_VERSION_CLIENT_ENDPOINT_PROXY_EVENTS,
++ &client_endpoint_marshal_set_param,
++};
++
++static const struct pw_protocol_native_demarshal pw_protocol_native_client_endpoint_event_demarshal[] = {
++ { &client_endpoint_demarshal_set_param, 0 }
++};
++
++static const struct pw_protocol_marshal pw_protocol_native_client_endpoint_marshal = {
++ PW_TYPE_INTERFACE_ClientEndpoint,
++ PW_VERSION_CLIENT_ENDPOINT,
++ PW_CLIENT_ENDPOINT_PROXY_METHOD_NUM,
++ PW_CLIENT_ENDPOINT_PROXY_EVENT_NUM,
++ &pw_protocol_native_client_endpoint_method_marshal,
++ &pw_protocol_native_client_endpoint_method_demarshal,
++ &pw_protocol_native_client_endpoint_event_marshal,
++ &pw_protocol_native_client_endpoint_event_demarshal,
++};
++
++struct pw_protocol *pw_protocol_native_ext_endpoint_init(struct pw_core *core)
++{
++ struct pw_protocol *protocol;
++
++ protocol = pw_core_find_protocol(core, PW_TYPE_INFO_PROTOCOL_Native);
++
++ if (protocol == NULL)
++ return NULL;
++
++ pw_protocol_add_marshal(protocol, &pw_protocol_native_client_endpoint_marshal);
++ pw_protocol_add_marshal(protocol, &pw_protocol_native_endpoint_marshal);
++
++ return protocol;
++}
+diff --git a/src/pipewire/pipewire.c b/src/pipewire/pipewire.c
+index a8752438..bbbf9420 100644
+--- a/src/pipewire/pipewire.c
++++ b/src/pipewire/pipewire.c
+@@ -647,6 +647,8 @@ static const struct spa_type_info type_info[] = {
+ { PW_TYPE_INTERFACE_Module, SPA_TYPE_Pointer, PW_TYPE_INFO_INTERFACE_BASE "Module", NULL },
+ { PW_TYPE_INTERFACE_ClientNode, SPA_TYPE_Pointer, PW_TYPE_INFO_INTERFACE_BASE "ClientNode", NULL },
+ { PW_TYPE_INTERFACE_Device, SPA_TYPE_Pointer, PW_TYPE_INFO_INTERFACE_BASE "Device", NULL },
++ { PW_TYPE_INTERFACE_Endpoint, SPA_TYPE_Pointer, PW_TYPE_INFO_INTERFACE_BASE "Endpoint", NULL},
++ { PW_TYPE_INTERFACE_ClientEndpoint, SPA_TYPE_Pointer, PW_TYPE_INFO_INTERFACE_BASE "ClientEndpoint", NULL},
+ { SPA_ID_INVALID, SPA_ID_INVALID, "spa_types", spa_types },
+ { 0, 0, NULL, NULL },
+ };
+diff --git a/src/pipewire/type.h b/src/pipewire/type.h
+index a1b205f7..39544913 100644
+--- a/src/pipewire/type.h
++++ b/src/pipewire/type.h
+@@ -48,7 +48,8 @@ enum {
+ /* extensions */
+ PW_TYPE_INTERFACE_EXTENSIONS = PW_TYPE_INTERFACE_START + 0x1000,
+ PW_TYPE_INTERFACE_ClientNode,
+-
++ PW_TYPE_INTERFACE_Endpoint,
++ PW_TYPE_INTERFACE_ClientEndpoint,
+ };
+
+ #define PW_TYPE_INFO_BASE "PipeWire:"
+--
+2.20.1
+
diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0003-pipewire-cli-add-support-for-printing-endpoint-info-.patch b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0003-pipewire-cli-add-support-for-printing-endpoint-info-.patch
new file mode 100644
index 00000000..a709abdf
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0003-pipewire-cli-add-support-for-printing-endpoint-info-.patch
@@ -0,0 +1,149 @@
+From 0e9fe3cfb19c751655f16ce4b8c6100269f23ff2 Mon Sep 17 00:00:00 2001
+From: George Kiagiadakis <george.kiagiadakis@collabora.com>
+Date: Tue, 28 May 2019 11:46:36 +0300
+Subject: [PATCH] pipewire-cli: add support for printing endpoint info & params
+
+Note that you have to run:
+ load-module libpipewire-module-endpoint
+before trying to query any endpoints
+
+Upstream-Status: Pending
+---
+ src/tools/pipewire-cli.c | 78 +++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 77 insertions(+), 1 deletion(-)
+
+diff --git a/src/tools/pipewire-cli.c b/src/tools/pipewire-cli.c
+index 521739f6..9511db82 100644
+--- a/src/tools/pipewire-cli.c
++++ b/src/tools/pipewire-cli.c
+@@ -38,6 +38,8 @@
+ #include <pipewire/type.h>
+ #include <pipewire/permission.h>
+
++#include <extensions/endpoint.h>
++
+ static const char WHITESPACE[] = " \t";
+
+ struct remote_data;
+@@ -176,8 +178,12 @@ static void print_params(struct spa_param_info *params, uint32_t n_params, char
+ return;
+ }
+ for (i = 0; i < n_params; i++) {
++ const struct spa_type_info *type_info = spa_type_param;
++ if (params[i].id >= PW_ENDPOINT_PARAM_EnumControl)
++ type_info = endpoint_param_type_info;
++
+ fprintf(stdout, "%c\t %d (%s) %c%c\n", mark, params[i].id,
+- spa_debug_type_find_name(spa_type_param, params[i].id),
++ spa_debug_type_find_name(type_info, params[i].id),
+ params[i].flags & SPA_PARAM_INFO_READ ? 'r' : '-',
+ params[i].flags & SPA_PARAM_INFO_WRITE ? 'w' : '-');
+ }
+@@ -641,6 +647,16 @@ static void info_device(struct proxy_data *pd)
+ info->change_mask = 0;
+ }
+
++static void info_endpoint(struct proxy_data *pd)
++{
++ struct pw_endpoint_info *info = pd->info;
++
++ info_global(pd);
++ print_properties(info->props, MARK_CHANGE(1), true);
++ print_params(info->params, info->n_params, MARK_CHANGE(0), true);
++ info->change_mask = 0;
++}
++
+ static void core_event_info(void *object, const struct pw_core_info *info)
+ {
+ struct proxy_data *pd = object;
+@@ -708,6 +724,9 @@ static void event_param(void *object, int seq, uint32_t id,
+
+ if (spa_pod_is_object_type(param, SPA_TYPE_OBJECT_Format))
+ spa_debug_format(2, NULL, param);
++ else if (spa_pod_is_object_type(param, PW_ENDPOINT_OBJECT_ParamControl) ||
++ spa_pod_is_object_type(param, PW_ENDPOINT_OBJECT_ParamStream))
++ spa_debug_pod(2, endpoint_param_object_type_info, param);
+ else
+ spa_debug_pod(2, NULL, param);
+ }
+@@ -842,6 +861,53 @@ static const struct pw_device_proxy_events device_events = {
+ .param = event_param
+ };
+
++static void endpoint_info_free(struct pw_endpoint_info *info)
++{
++ free(info->params);
++ if (info->props)
++ pw_properties_free ((struct pw_properties *)info->props);
++ free(info);
++}
++
++static void endpoint_event_info(void *object,
++ const struct pw_endpoint_info *update)
++{
++ struct proxy_data *pd = object;
++ struct remote_data *rd = pd->rd;
++ struct pw_endpoint_info *info = pd->info;
++
++ if (!info) {
++ info = pd->info = calloc(1, sizeof(*info));
++ info->id = update->id;
++ }
++ if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_PARAMS) {
++ info->n_params = update->n_params;
++ free(info->params);
++ info->params = malloc(info->n_params * sizeof(struct spa_param_info));
++ memcpy(info->params, update->params,
++ info->n_params * sizeof(struct spa_param_info));
++ }
++ if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_PROPS) {
++ if (info->props)
++ pw_properties_free ((struct pw_properties *)info->props);
++ info->props =
++ (struct spa_dict *) pw_properties_new_dict (update->props);
++ }
++
++ if (pd->global == NULL)
++ pd->global = pw_map_lookup(&rd->globals, info->id);
++ if (pd->global && pd->global->info_pending) {
++ info_endpoint(pd);
++ pd->global->info_pending = false;
++ }
++}
++
++static const struct pw_endpoint_proxy_events endpoint_events = {
++ PW_VERSION_ENDPOINT_PROXY_EVENTS,
++ .info = endpoint_event_info,
++ .param = event_param
++};
++
+ static void
+ destroy_proxy (void *data)
+ {
+@@ -928,6 +994,12 @@ static bool bind_global(struct remote_data *rd, struct global *global, char **er
+ destroy = (pw_destroy_t) pw_link_info_free;
+ info_func = info_link;
+ break;
++ case PW_TYPE_INTERFACE_Endpoint:
++ events = &endpoint_events;
++ client_version = PW_VERSION_ENDPOINT;
++ destroy = (pw_destroy_t) endpoint_info_free;
++ info_func = info_endpoint;
++ break;
+ default:
+ asprintf(error, "unsupported type %s", spa_debug_type_find_name(pw_type_info(), global->type));
+ return false;
+@@ -1201,6 +1273,10 @@ static bool do_enum_params(struct data *data, const char *cmd, char *args, char
+ pw_device_proxy_enum_params((struct pw_device_proxy*)global->proxy, 0,
+ param_id, 0, 0, NULL);
+ break;
++ case PW_TYPE_INTERFACE_Endpoint:
++ pw_endpoint_proxy_enum_params((struct pw_endpoint_proxy*)global->proxy, 0,
++ param_id, 0, 0, NULL);
++ break;
+ default:
+ asprintf(error, "enum-params not implemented on object %d", atoi(a[0]));
+ return false;
+--
+2.20.1
+
diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0004-pipewire-cli-add-command-to-modify-endpoint-control-.patch b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0004-pipewire-cli-add-command-to-modify-endpoint-control-.patch
new file mode 100644
index 00000000..4394d60d
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0004-pipewire-cli-add-command-to-modify-endpoint-control-.patch
@@ -0,0 +1,124 @@
+From 824c8abf88e9ee82567c177145798b619298ab91 Mon Sep 17 00:00:00 2001
+From: George Kiagiadakis <george.kiagiadakis@collabora.com>
+Date: Wed, 5 Jun 2019 14:57:37 +0300
+Subject: [PATCH] pipewire-cli: add command to modify endpoint control values
+
+Upstream-Status: Pending
+---
+ src/tools/pipewire-cli.c | 86 ++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 86 insertions(+)
+
+diff --git a/src/tools/pipewire-cli.c b/src/tools/pipewire-cli.c
+index 9511db82..b52ab100 100644
+--- a/src/tools/pipewire-cli.c
++++ b/src/tools/pipewire-cli.c
+@@ -210,6 +210,7 @@ static bool do_export_node(struct data *data, const char *cmd, char *args, char
+ static bool do_enum_params(struct data *data, const char *cmd, char *args, char **error);
+ static bool do_permissions(struct data *data, const char *cmd, char *args, char **error);
+ static bool do_get_permissions(struct data *data, const char *cmd, char *args, char **error);
++static bool do_endpoint_control(struct data *data, const char *cmd, char *args, char **error);
+
+ static struct command command_list[] = {
+ { "help", "Show this help", do_help },
+@@ -228,6 +229,7 @@ static struct command command_list[] = {
+ { "enum-params", "Enumerate params of an object <object-id> [<param-id-name>]", do_enum_params },
+ { "permissions", "Set permissions for a client <client-id> <permissions>", do_permissions },
+ { "get-permissions", "Get permissions of a client <client-id>", do_get_permissions },
++ { "endpoint-control", "Set control value on an endpoint <object-id> <control-id> <type: b|i|l|d> <value>", do_endpoint_control },
+ };
+
+ static bool do_help(struct data *data, const char *cmd, char *args, char **error)
+@@ -1357,6 +1359,90 @@ static bool do_get_permissions(struct data *data, const char *cmd, char *args, c
+ return true;
+ }
+
++static bool do_endpoint_control(struct data *data, const char *cmd, char *args, char **error)
++{
++ struct remote_data *rd = data->current;
++ int n;
++ char *a[4];
++ uint32_t id, control_id;
++ struct global *global;
++ char buffer[1024];
++ struct spa_pod_builder b;
++ struct spa_pod_frame f;
++ struct spa_pod *param;
++
++ n = pw_split_ip(args, WHITESPACE, 4, a);
++ if (n < 4) {
++ asprintf(error, "%s <object-id> <control-id> <type: b|i|l|d> <value>", cmd);
++ return false;
++ }
++
++ id = atoi(a[0]);
++ global = pw_map_lookup(&rd->globals, id);
++ if (global == NULL) {
++ asprintf(error, "%s: unknown global %d", cmd, id);
++ return false;
++ }
++ if (global->type != PW_TYPE_INTERFACE_Endpoint) {
++ asprintf(error, "object %d is not an endpoint", atoi(a[0]));
++ return false;
++ }
++ if (global->proxy == NULL) {
++ if (!bind_global(rd, global, error))
++ return false;
++ }
++
++ control_id = atoi(a[1]);
++
++ spa_pod_builder_init(&b, buffer, 1024);
++ spa_pod_builder_push_object (&b, &f,
++ PW_ENDPOINT_OBJECT_ParamControl, PW_ENDPOINT_PARAM_Control);
++ spa_pod_builder_add(&b,
++ PW_ENDPOINT_PARAM_CONTROL_id, SPA_POD_Int(control_id),
++ NULL);
++
++ switch (*a[2]) {
++ case 'b': {
++ bool val = atoi(a[3]);
++ spa_pod_builder_add(&b,
++ PW_ENDPOINT_PARAM_CONTROL_value, SPA_POD_Bool(val),
++ NULL);
++ break;
++ }
++ case 'i': {
++ int val = atoi(a[3]);
++ spa_pod_builder_add(&b,
++ PW_ENDPOINT_PARAM_CONTROL_value, SPA_POD_Int(val),
++ NULL);
++ break;
++ }
++ case 'l': {
++ int64_t val = strtoll(a[3], NULL, 10);
++ spa_pod_builder_add(&b,
++ PW_ENDPOINT_PARAM_CONTROL_value, SPA_POD_Long(val),
++ NULL);
++ break;
++ }
++ case 'd': {
++ double val = strtod(a[3], NULL);
++ spa_pod_builder_add(&b,
++ PW_ENDPOINT_PARAM_CONTROL_value, SPA_POD_Double(val),
++ NULL);
++ break;
++ }
++ default:
++ asprintf(error, "%s: unknown value type %s", cmd, a[2]);
++ return false;
++ }
++
++ param = spa_pod_builder_pop(&b, &f);
++
++ pw_endpoint_proxy_set_param((struct pw_endpoint_proxy *) global->proxy,
++ PW_ENDPOINT_PARAM_Control, 0, param);
++
++ return true;
++}
++
+ static bool parse(struct data *data, char *buf, size_t size, char **error)
+ {
+ char *a[2];
+--
+2.20.1
+
diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0005-arm-build-with-mno-unaligned-access.patch b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0005-arm-build-with-mno-unaligned-access.patch
new file mode 100644
index 00000000..a670e7ff
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0005-arm-build-with-mno-unaligned-access.patch
@@ -0,0 +1,30 @@
+From 2016605938f02835c75928648e99b25f7248aa5b Mon Sep 17 00:00:00 2001
+From: George Kiagiadakis <george.kiagiadakis@collabora.com>
+Date: Mon, 24 Jun 2019 12:19:20 +0300
+Subject: [PATCH] arm: build with -mno-unaligned-access
+
+Upstream-Status: Inappropriate [workaround]
+See also https://github.com/PipeWire/pipewire/issues/161
+---
+ meson.build | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/meson.build b/meson.build
+index 81303d27..f3cc6030 100644
+--- a/meson.build
++++ b/meson.build
+@@ -50,6 +50,11 @@ if cc.get_id() == 'gcc'
+ language : 'c')
+ endif
+
++if host_machine.cpu_family() == 'arm'
++ add_global_arguments('-mno-unaligned-access',
++ language: 'c')
++endif
++
+ sse_args = '-msse'
+ sse2_args = '-msse2'
+ ssse3_args = '-mssse3'
+--
+2.20.1
+
diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0006-logger-print-timestamps-on-logged-messages.patch b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0006-logger-print-timestamps-on-logged-messages.patch
new file mode 100644
index 00000000..4d9117f0
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0006-logger-print-timestamps-on-logged-messages.patch
@@ -0,0 +1,52 @@
+From 352c58357e5922b21d664c1f5a0b89a74f864f41 Mon Sep 17 00:00:00 2001
+From: George Kiagiadakis <george.kiagiadakis@collabora.com>
+Date: Wed, 3 Jul 2019 17:47:46 +0300
+Subject: [PATCH] logger: print timestamps on logged messages
+
+Timestamps have usec precision and the seconds are limited
+to 9 digits. Usually what matters in these messages is to spot
+delays between printouts and not really what is the absolute
+time of the system.
+
+Upstream-Status: Submitted [https://github.com/PipeWire/pipewire/pull/164]
+---
+ spa/plugins/support/logger.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/spa/plugins/support/logger.c b/spa/plugins/support/logger.c
+index 87ba3c21..2976601c 100644
+--- a/spa/plugins/support/logger.c
++++ b/spa/plugins/support/logger.c
+@@ -27,6 +27,7 @@
+ #include <string.h>
+ #include <errno.h>
+ #include <stdio.h>
++#include <time.h>
+ #include <sys/eventfd.h>
+
+ #include <spa/support/log.h>
+@@ -70,6 +71,9 @@ impl_log_logv(struct spa_log *log,
+ const char *prefix = "", *suffix = "";
+ int size;
+ bool do_trace;
++ struct timespec now;
++
++ clock_gettime(CLOCK_MONOTONIC_RAW, &now);
+
+ if ((do_trace = (level == SPA_LOG_LEVEL_TRACE && impl->have_source)))
+ level++;
+@@ -86,8 +90,9 @@ impl_log_logv(struct spa_log *log,
+ }
+
+ vsnprintf(text, sizeof(text), fmt, args);
+- size = snprintf(location, sizeof(location), "%s[%s][%s:%i %s()] %s%s\n",
+- prefix, levels[level], strrchr(file, '/') + 1, line, func, text, suffix);
++ size = snprintf(location, sizeof(location), "%s[%s][%09lu.%06lu][%s:%i %s()] %s%s\n",
++ prefix, levels[level], now.tv_sec & 0x1FFFFFFF, now.tv_nsec / 1000,
++ strrchr(file, '/') + 1, line, func, text, suffix);
+
+ if (SPA_UNLIKELY(do_trace)) {
+ uint32_t index;
+--
+2.20.1
+
diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0007-alsa-make-corrections-on-the-timeout-based-on-how-fa.patch b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0007-alsa-make-corrections-on-the-timeout-based-on-how-fa.patch
new file mode 100644
index 00000000..86495014
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0007-alsa-make-corrections-on-the-timeout-based-on-how-fa.patch
@@ -0,0 +1,130 @@
+From 05a3a926df4906cdf60f7978843c637bbf37714a Mon Sep 17 00:00:00 2001
+From: George Kiagiadakis <george.kiagiadakis@collabora.com>
+Date: Tue, 9 Jul 2019 18:06:18 +0300
+Subject: [PATCH] alsa: make corrections on the timeout based on how fast ALSA
+ consumes samples
+
+This feels a bit hacky, but it actually makes huge difference when pipewire is
+running in qemu.
+
+The idea is that it keeps track of how much samples are in the device
+(fill level) and calculates how many are consumed when a timeout occurs.
+Then it converts that into a time based on the sample rate and compares it to
+the system clock time that elapsed since the last write to the device.
+The division between the two gives a rate (drift) that can be used to shorten
+the timeout window.
+
+So for instance, if the timeout window was 21.3 ms, but the device actually
+consumed an equivalent of 28 ms in samples, the drift will be 21.3/28 = 0.76
+and the next timeout window will be approximately 21.3 * 0.76 = 16.1 ms
+
+To avoid making things worse, the drift is clamped between 0.6 and 1.0.
+Min 0.6 was arbitrarily chosen, but sometimes alsa does report strange numbers,
+causing the drift to be very low, which in turn causes an early wakeup.
+Max 1.0 basically means that we don't care if the device is consuming samples
+slower. In that case, the early wakeup mechanism will throttle pipewire.
+
+Fixes #163
+
+Upstream-Status: Submitted [https://github.com/PipeWire/pipewire/pull/166]
+---
+ spa/plugins/alsa/alsa-utils.c | 31 ++++++++++++++++++++++++++-----
+ spa/plugins/alsa/alsa-utils.h | 2 ++
+ 2 files changed, 28 insertions(+), 5 deletions(-)
+
+diff --git a/spa/plugins/alsa/alsa-utils.c b/spa/plugins/alsa/alsa-utils.c
+index 87582c1c..872969bf 100644
+--- a/spa/plugins/alsa/alsa-utils.c
++++ b/spa/plugins/alsa/alsa-utils.c
+@@ -593,7 +593,21 @@ static int get_status(struct state *state, snd_pcm_sframes_t *delay)
+
+ static int update_time(struct state *state, uint64_t nsec, snd_pcm_sframes_t delay, bool slave)
+ {
+- double err, corr;
++ double err, corr, drift;
++ snd_pcm_sframes_t consumed;
++
++ consumed = state->fill_level - delay;
++ if (state->alsa_started && consumed > 0) {
++ double sysclk_diff = nsec - state->last_time;
++ double devclk_diff = ((double) consumed) * 1e9 / state->rate;
++ drift = sysclk_diff / devclk_diff;
++ drift = SPA_CLAMP(drift, 0.6, 1.0);
++
++ spa_log_trace_fp(state->log, "cons:%ld sclk:%f dclk:%f drift:%f",
++ consumed, sysclk_diff, devclk_diff, drift);
++ } else {
++ drift = 1.0;
++ }
+
+ if (state->stream == SND_PCM_STREAM_PLAYBACK)
+ err = delay - state->last_threshold;
+@@ -650,11 +664,11 @@ static int update_time(struct state *state, uint64_t nsec, snd_pcm_sframes_t del
+ state->clock->rate_diff = corr;
+ }
+
+- spa_log_trace_fp(state->log, "slave:%d %"PRIu64" %f %ld %f %f %d", slave, nsec,
+- corr, delay, err, state->threshold * corr,
++ spa_log_trace_fp(state->log, "slave:%d %"PRIu64" %f %ld %f %f %f %d", slave, nsec,
++ corr, delay, err, state->threshold * corr, drift,
+ state->threshold);
+
+- state->next_time += state->threshold / corr * 1e9 / state->rate;
++ state->next_time += state->threshold / corr * drift * 1e9 / state->rate;
+ state->last_threshold = state->threshold;
+
+ return 0;
+@@ -783,6 +797,10 @@ again:
+ goto again;
+
+ state->sample_count += total_written;
++ state->fill_level += total_written;
++
++ clock_gettime(CLOCK_MONOTONIC, &state->now);
++ state->last_time = SPA_TIMESPEC_TO_NSEC (&state->now);
+
+ if (!state->alsa_started && total_written > 0) {
+ spa_log_trace(state->log, "snd_pcm_start %lu", written);
+@@ -935,7 +953,7 @@ static int handle_play(struct state *state, uint64_t nsec, snd_pcm_sframes_t del
+ {
+ int res;
+
+- if (delay >= state->last_threshold * 2) {
++ if (delay > state->last_threshold * 2) {
+ spa_log_trace(state->log, "early wakeup %ld %d", delay, state->threshold);
+ state->next_time = nsec + (delay - state->last_threshold) * SPA_NSEC_PER_SEC / state->rate;
+ return -EAGAIN;
+@@ -944,6 +962,8 @@ static int handle_play(struct state *state, uint64_t nsec, snd_pcm_sframes_t del
+ if ((res = update_time(state, nsec, delay, false)) < 0)
+ return res;
+
++ state->fill_level = delay;
++
+ if (spa_list_is_empty(&state->ready)) {
+ struct spa_io_buffers *io = state->io;
+
+@@ -1072,6 +1092,7 @@ int spa_alsa_start(struct state *state)
+
+ state->slaved = is_slaved(state);
+ state->last_threshold = state->threshold;
++ state->fill_level = 0;
+
+ init_loop(state);
+ state->safety = 0.0;
+diff --git a/spa/plugins/alsa/alsa-utils.h b/spa/plugins/alsa/alsa-utils.h
+index a862873f..b53890b5 100644
+--- a/spa/plugins/alsa/alsa-utils.h
++++ b/spa/plugins/alsa/alsa-utils.h
+@@ -134,7 +134,9 @@ struct state {
+ int64_t sample_time;
+ uint64_t next_time;
+ uint64_t base_time;
++ uint64_t last_time;
+
++ snd_pcm_uframes_t fill_level;
+ uint64_t underrun;
+ double safety;
+
+--
+2.20.1
+
diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0008-audio-dsp-allow-mode-to-be-set-with-a-property.patch b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0008-audio-dsp-allow-mode-to-be-set-with-a-property.patch
new file mode 100644
index 00000000..681bae69
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0008-audio-dsp-allow-mode-to-be-set-with-a-property.patch
@@ -0,0 +1,45 @@
+From 0c85e1110e32720785f861c7a85cf0636394eee4 Mon Sep 17 00:00:00 2001
+From: Julian Bouzas <julian.bouzas@collabora.com>
+Date: Thu, 27 Jun 2019 12:44:39 -0400
+Subject: [PATCH] audio-dsp: allow mode to be set with a property
+
+Upstream-Status: Submitted [https://github.com/PipeWire/pipewire/pull/167]
+---
+ src/modules/module-audio-dsp/audio-dsp.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/src/modules/module-audio-dsp/audio-dsp.c b/src/modules/module-audio-dsp/audio-dsp.c
+index be8a7592..68249307 100644
+--- a/src/modules/module-audio-dsp/audio-dsp.c
++++ b/src/modules/module-audio-dsp/audio-dsp.c
+@@ -264,7 +264,7 @@ struct pw_node *pw_audio_dsp_new(struct pw_core *core,
+ {
+ struct pw_node *node;
+ struct node *n;
+- const char *api, *alias, *str, *factory;
++ const char *api, *alias, *str, *factory, *mode;
+ char node_name[128];
+ struct pw_properties *pr;
+ int i;
+@@ -279,6 +279,7 @@ struct pw_node *pw_audio_dsp_new(struct pw_core *core,
+ pw_log_error("missing audio-dsp.name property");
+ goto error;
+ }
++ mode = pw_properties_get(pr, "audio-dsp.mode");
+
+ snprintf(node_name, sizeof(node_name), "system_%s", alias);
+ for (i = 0; node_name[i]; i++) {
+@@ -296,7 +297,9 @@ struct pw_node *pw_audio_dsp_new(struct pw_core *core,
+ if ((str = pw_properties_get(pr, "node.id")) != NULL)
+ pw_properties_set(pr, "node.session", str);
+
+- if (direction == PW_DIRECTION_OUTPUT) {
++ if (mode) {
++ factory = mode;
++ } else if (direction == PW_DIRECTION_OUTPUT) {
+ pw_properties_set(pr, "merger.monitor", "1");
+ factory = "merge";
+ } else {
+--
+2.20.1
+
diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0009-audioconvert-do-setup-internal-links-and-buffers-als.patch b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0009-audioconvert-do-setup-internal-links-and-buffers-als.patch
new file mode 100644
index 00000000..87141e91
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0009-audioconvert-do-setup-internal-links-and-buffers-als.patch
@@ -0,0 +1,55 @@
+From ddcda9fa6ec49168c5ddd9fbeda748c5fad18fce Mon Sep 17 00:00:00 2001
+From: George Kiagiadakis <george.kiagiadakis@collabora.com>
+Date: Wed, 10 Jul 2019 14:53:15 +0300
+Subject: [PATCH] audioconvert: do setup internal links and buffers also in
+ convert mode
+
+Upstream-Status: Submitted [https://github.com/PipeWire/pipewire/pull/167]
+---
+ spa/plugins/audioconvert/audioconvert.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/spa/plugins/audioconvert/audioconvert.c b/spa/plugins/audioconvert/audioconvert.c
+index fa8dec97..0af0732d 100644
+--- a/spa/plugins/audioconvert/audioconvert.c
++++ b/spa/plugins/audioconvert/audioconvert.c
+@@ -79,6 +79,8 @@ struct impl {
+ #define MODE_MERGE 1
+ #define MODE_CONVERT 2
+ int mode;
++ bool fmt_is_set[2];
++ bool buffers_set[2];
+ bool started;
+
+ struct spa_handle *hnd_fmt[2];
+@@ -791,11 +793,11 @@ impl_node_port_set_param(struct spa_node *node,
+ if (id == SPA_PARAM_Format) {
+ if (param == NULL)
+ clean_convert(this);
+- else if ((direction == SPA_DIRECTION_OUTPUT && this->mode == MODE_MERGE) ||
+- (direction == SPA_DIRECTION_INPUT && this->mode == MODE_SPLIT)) {
++ else if (this->fmt_is_set[SPA_DIRECTION_REVERSE(direction)]) {
+ if ((res = setup_convert(this)) < 0)
+ return res;
+ }
++ this->fmt_is_set[direction] = (param != NULL);
+ }
+ return res;
+ }
+@@ -824,11 +826,11 @@ impl_node_port_use_buffers(struct spa_node *node,
+ direction, port_id, buffers, n_buffers)) < 0)
+ return res;
+
+- if ((direction == SPA_DIRECTION_OUTPUT && this->mode == MODE_MERGE) ||
+- (direction == SPA_DIRECTION_INPUT && this->mode == MODE_SPLIT)) {
++ if (buffers && this->buffers_set[SPA_DIRECTION_REVERSE(direction)]) {
+ if ((res = setup_buffers(this, SPA_DIRECTION_INPUT)) < 0)
+ return res;
+ }
++ this->buffers_set[direction] = (buffers != NULL);
+ return res;
+ }
+
+--
+2.20.1
+
diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0010-gst-Implement-new-pwaudio-src-sink-elements-based-on.patch b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0010-gst-Implement-new-pwaudio-src-sink-elements-based-on.patch
new file mode 100644
index 00000000..6b1a6441
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0010-gst-Implement-new-pwaudio-src-sink-elements-based-on.patch
@@ -0,0 +1,1249 @@
+From bbc875ec4268a88bf2465244e089b119011e7479 Mon Sep 17 00:00:00 2001
+From: George Kiagiadakis <george.kiagiadakis@collabora.com>
+Date: Tue, 19 Feb 2019 18:23:19 +0200
+Subject: [PATCH] gst: Implement new pwaudio{src,sink} elements, based on
+ GstAudioBase{Src,Sink}
+
+These are much more reliable elements to use for audio data.
+* GstAudioBaseSink provides a reliable clock implementation based
+ on the number of samples read/written
+* on the pipewire side we make sure to dequeue, fill and enqueue
+ a single buffer inside the process() function, which avoids
+ underruns
+
+Both elements share a common ringbuffer that actually implements
+the pipewire integration.
+
+Upstream-Status: Submitted [https://github.com/PipeWire/pipewire/pull/140]
+---
+ src/gst/gstpipewire.c | 8 +-
+ src/gst/gstpwaudioringbuffer.c | 542 +++++++++++++++++++++++++++++++++
+ src/gst/gstpwaudioringbuffer.h | 83 +++++
+ src/gst/gstpwaudiosink.c | 200 ++++++++++++
+ src/gst/gstpwaudiosink.h | 48 +++
+ src/gst/gstpwaudiosrc.c | 200 ++++++++++++
+ src/gst/gstpwaudiosrc.h | 48 +++
+ src/gst/meson.build | 6 +
+ 8 files changed, 1134 insertions(+), 1 deletion(-)
+ create mode 100644 src/gst/gstpwaudioringbuffer.c
+ create mode 100644 src/gst/gstpwaudioringbuffer.h
+ create mode 100644 src/gst/gstpwaudiosink.c
+ create mode 100644 src/gst/gstpwaudiosink.h
+ create mode 100644 src/gst/gstpwaudiosrc.c
+ create mode 100644 src/gst/gstpwaudiosrc.h
+
+diff --git a/src/gst/gstpipewire.c b/src/gst/gstpipewire.c
+index 4040264b..68fd446f 100644
+--- a/src/gst/gstpipewire.c
++++ b/src/gst/gstpipewire.c
+@@ -40,6 +40,8 @@
+ #include "gstpipewiresrc.h"
+ #include "gstpipewiresink.h"
+ #include "gstpipewiredeviceprovider.h"
++#include "gstpwaudiosrc.h"
++#include "gstpwaudiosink.h"
+
+ GST_DEBUG_CATEGORY (pipewire_debug);
+
+@@ -52,12 +54,16 @@ plugin_init (GstPlugin *plugin)
+ GST_TYPE_PIPEWIRE_SRC);
+ gst_element_register (plugin, "pipewiresink", GST_RANK_NONE,
+ GST_TYPE_PIPEWIRE_SINK);
++ gst_element_register (plugin, "pwaudiosrc", GST_RANK_NONE,
++ GST_TYPE_PW_AUDIO_SRC);
++ gst_element_register (plugin, "pwaudiosink", GST_RANK_NONE,
++ GST_TYPE_PW_AUDIO_SINK);
+
+ if (!gst_device_provider_register (plugin, "pipewiredeviceprovider",
+ GST_RANK_PRIMARY + 1, GST_TYPE_PIPEWIRE_DEVICE_PROVIDER))
+ return FALSE;
+
+- GST_DEBUG_CATEGORY_INIT (pipewire_debug, "pipewire", 0, "PipeWirie elements");
++ GST_DEBUG_CATEGORY_INIT (pipewire_debug, "pipewire", 0, "PipeWire elements");
+
+ return TRUE;
+ }
+diff --git a/src/gst/gstpwaudioringbuffer.c b/src/gst/gstpwaudioringbuffer.c
+new file mode 100644
+index 00000000..989b2cd7
+--- /dev/null
++++ b/src/gst/gstpwaudioringbuffer.c
+@@ -0,0 +1,542 @@
++/* PipeWire
++ *
++ * Copyright © 2018 Wim Taymans
++ * Copyright © 2019 Collabora Ltd.
++ * @author George Kiagiadakis <george.kiagiadakis@collabora.com>
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the next
++ * paragraph) shall be included in all copies or substantial portions of the
++ * Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
++
++#include "gstpwaudioringbuffer.h"
++
++#include <spa/param/audio/format-utils.h>
++#include <spa/pod/builder.h>
++
++GST_DEBUG_CATEGORY_STATIC (pw_audio_ring_buffer_debug);
++#define GST_CAT_DEFAULT pw_audio_ring_buffer_debug
++
++#define gst_pw_audio_ring_buffer_parent_class parent_class
++G_DEFINE_TYPE (GstPwAudioRingBuffer, gst_pw_audio_ring_buffer, GST_TYPE_AUDIO_RING_BUFFER);
++
++enum
++{
++ PROP_0,
++ PROP_ELEMENT,
++ PROP_DIRECTION,
++ PROP_PROPS
++};
++
++static void
++gst_pw_audio_ring_buffer_init (GstPwAudioRingBuffer * self)
++{
++ self->loop = pw_loop_new (NULL);
++ self->main_loop = pw_thread_loop_new (self->loop, "pw-audioringbuffer-loop");
++ self->core = pw_core_new (self->loop, NULL, 0);
++}
++
++static void
++gst_pw_audio_ring_buffer_finalize (GObject * object)
++{
++ GstPwAudioRingBuffer *self = GST_PW_AUDIO_RING_BUFFER (object);
++
++ pw_core_destroy (self->core);
++ pw_thread_loop_destroy (self->main_loop);
++ pw_loop_destroy (self->loop);
++}
++
++static void
++gst_pw_audio_ring_buffer_set_property (GObject * object, guint prop_id,
++ const GValue * value, GParamSpec * pspec)
++{
++ GstPwAudioRingBuffer *self = GST_PW_AUDIO_RING_BUFFER (object);
++
++ switch (prop_id) {
++ case PROP_ELEMENT:
++ self->elem = g_value_get_object (value);
++ break;
++
++ case PROP_DIRECTION:
++ self->direction = g_value_get_int (value);
++ break;
++
++ case PROP_PROPS:
++ self->props = g_value_get_pointer (value);
++ break;
++
++ default:
++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
++ break;
++ }
++}
++
++static void
++on_remote_state_changed (void *data, enum pw_remote_state old,
++ enum pw_remote_state state, const char *error)
++{
++ GstPwAudioRingBuffer *self = GST_PW_AUDIO_RING_BUFFER (data);
++
++ GST_DEBUG_OBJECT (self->elem, "got remote state %d", state);
++
++ switch (state) {
++ case PW_REMOTE_STATE_UNCONNECTED:
++ case PW_REMOTE_STATE_CONNECTING:
++ case PW_REMOTE_STATE_CONNECTED:
++ break;
++ case PW_REMOTE_STATE_ERROR:
++ GST_ELEMENT_ERROR (self->elem, RESOURCE, FAILED,
++ ("remote error: %s", error), (NULL));
++ break;
++ }
++ pw_thread_loop_signal (self->main_loop, FALSE);
++}
++
++static const struct pw_remote_events remote_events = {
++ PW_VERSION_REMOTE_EVENTS,
++ .state_changed = on_remote_state_changed,
++};
++
++static gboolean
++wait_for_remote_state (GstPwAudioRingBuffer *self,
++ enum pw_remote_state target)
++{
++ while (TRUE) {
++ enum pw_remote_state state = pw_remote_get_state (self->remote, NULL);
++ if (state == target)
++ return TRUE;
++ if (state == PW_REMOTE_STATE_ERROR)
++ return FALSE;
++ pw_thread_loop_wait (self->main_loop);
++ }
++}
++
++static gboolean
++gst_pw_audio_ring_buffer_open_device (GstAudioRingBuffer *buf)
++{
++ GstPwAudioRingBuffer *self = GST_PW_AUDIO_RING_BUFFER (buf);
++
++ GST_DEBUG_OBJECT (self->elem, "open device");
++
++ if (pw_thread_loop_start (self->main_loop) < 0)
++ goto mainloop_error;
++
++ pw_thread_loop_lock (self->main_loop);
++
++ self->remote = pw_remote_new (self->core, NULL, 0);
++ pw_remote_add_listener (self->remote, &self->remote_listener, &remote_events,
++ self);
++
++ if (self->props->fd == -1)
++ pw_remote_connect (self->remote);
++ else
++ pw_remote_connect_fd (self->remote, self->props->fd);
++
++ GST_DEBUG_OBJECT (self->elem, "waiting for connection");
++
++ if (!wait_for_remote_state (self, PW_REMOTE_STATE_CONNECTED))
++ goto connect_error;
++
++ pw_thread_loop_unlock (self->main_loop);
++
++ return TRUE;
++
++ /* ERRORS */
++mainloop_error:
++ {
++ GST_ELEMENT_ERROR (self->elem, RESOURCE, FAILED,
++ ("Failed to start mainloop"), (NULL));
++ return FALSE;
++ }
++connect_error:
++ {
++ pw_thread_loop_unlock (self->main_loop);
++ return FALSE;
++ }
++}
++
++static gboolean
++gst_pw_audio_ring_buffer_close_device (GstAudioRingBuffer *buf)
++{
++ GstPwAudioRingBuffer *self = GST_PW_AUDIO_RING_BUFFER (buf);
++
++ GST_DEBUG_OBJECT (self->elem, "closing device");
++
++ pw_thread_loop_lock (self->main_loop);
++ if (self->remote) {
++ pw_remote_disconnect (self->remote);
++ wait_for_remote_state (self, PW_REMOTE_STATE_UNCONNECTED);
++ }
++ pw_thread_loop_unlock (self->main_loop);
++
++ pw_thread_loop_stop (self->main_loop);
++
++ if (self->remote) {
++ pw_remote_destroy (self->remote);
++ self->remote = NULL;
++ }
++ return TRUE;
++}
++
++static void
++on_stream_state_changed (void *data, enum pw_stream_state old,
++ enum pw_stream_state state, const char *error)
++{
++ GstPwAudioRingBuffer *self = GST_PW_AUDIO_RING_BUFFER (data);
++
++ GST_DEBUG_OBJECT (self->elem, "got stream state: %s",
++ pw_stream_state_as_string (state));
++
++ switch (state) {
++ case PW_STREAM_STATE_UNCONNECTED:
++ GST_ELEMENT_ERROR (self->elem, RESOURCE, FAILED,
++ ("stream disconnected unexpectedly"), (NULL));
++ break;
++ case PW_STREAM_STATE_CONNECTING:
++ case PW_STREAM_STATE_CONFIGURE:
++ case PW_STREAM_STATE_READY:
++ case PW_STREAM_STATE_PAUSED:
++ case PW_STREAM_STATE_STREAMING:
++ break;
++ case PW_STREAM_STATE_ERROR:
++ GST_ELEMENT_ERROR (self->elem, RESOURCE, FAILED,
++ ("stream error: %s", error), (NULL));
++ break;
++ }
++ pw_thread_loop_signal (self->main_loop, FALSE);
++}
++
++static gboolean
++wait_for_stream_state (GstPwAudioRingBuffer *self,
++ enum pw_stream_state target)
++{
++ while (TRUE) {
++ enum pw_stream_state state = pw_stream_get_state (self->stream, NULL);
++ if (state >= target)
++ return TRUE;
++ if (state == PW_STREAM_STATE_ERROR || state == PW_STREAM_STATE_UNCONNECTED)
++ return FALSE;
++ pw_thread_loop_wait (self->main_loop);
++ }
++}
++
++static void
++on_stream_format_changed (void *data, const struct spa_pod *format)
++{
++ GstPwAudioRingBuffer *self = GST_PW_AUDIO_RING_BUFFER (data);
++ const struct spa_pod *params[1];
++ struct spa_pod_builder b = { NULL };
++ uint8_t buffer[512];
++
++ spa_pod_builder_init (&b, buffer, sizeof (buffer));
++ params[0] = spa_pod_builder_add_object (&b,
++ SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers,
++ SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(16, 1, INT32_MAX),
++ SPA_PARAM_BUFFERS_blocks, SPA_POD_Int(1),
++ SPA_PARAM_BUFFERS_size, SPA_POD_Int(self->segsize),
++ SPA_PARAM_BUFFERS_stride, SPA_POD_Int(self->bpf),
++ SPA_PARAM_BUFFERS_align, SPA_POD_Int(16));
++
++ GST_DEBUG_OBJECT (self->elem, "doing finish format, buffer size:%d", self->segsize);
++ pw_stream_finish_format (self->stream, 0, params, 1);
++}
++
++static void
++on_stream_process (void *data)
++{
++ GstPwAudioRingBuffer *self = GST_PW_AUDIO_RING_BUFFER (data);
++ GstAudioRingBuffer *buf = GST_AUDIO_RING_BUFFER (data);
++ struct pw_buffer *b;
++ struct spa_data *d;
++ gint size; /*< size to read/write from/to the spa buffer */
++ gint offset; /*< offset to read/write from/to in the spa buffer */
++ gint segment; /*< the current segment number in the ringbuffer */
++ guint8 *ringptr; /*< pointer to the beginning of the current segment */
++ gint segsize; /*< the size of one segment in the ringbuffer */
++ gint copy_size; /*< the bytes to copy in one memcpy() invocation */
++ gint remain; /*< remainder of bytes available in the spa buffer */
++
++ if (g_atomic_int_get (&buf->state) != GST_AUDIO_RING_BUFFER_STATE_STARTED) {
++ GST_LOG_OBJECT (self->elem, "ring buffer is not started");
++ return;
++ }
++
++ b = pw_stream_dequeue_buffer (self->stream);
++ if (!b) {
++ GST_WARNING_OBJECT (self->elem, "no pipewire buffer available");
++ return;
++ }
++
++ d = &b->buffer->datas[0];
++
++ if (self->direction == PW_DIRECTION_OUTPUT) {
++ /* in output mode, always fill the entire spa buffer */
++ offset = d->chunk->offset = 0;
++ size = d->chunk->size = d->maxsize;
++ b->size = size / self->bpf;
++ } else {
++ offset = SPA_MIN (d->chunk->offset, d->maxsize);
++ size = SPA_MIN (d->chunk->size, d->maxsize - offset);
++ }
++
++ do {
++ gst_audio_ring_buffer_prepare_read (buf, &segment, &ringptr, &segsize);
++
++ /* in INPUT (src) mode, it is possible that the skew algorithm
++ * advances the ringbuffer behind our back */
++ if (self->segoffset > 0 && self->cur_segment != segment)
++ self->segoffset = 0;
++
++ copy_size = SPA_MIN (size, segsize - self->segoffset);
++
++ if (self->direction == PW_DIRECTION_OUTPUT) {
++ memcpy (((guint8*) d->data) + offset, ringptr + self->segoffset,
++ copy_size);
++ } else {
++ memcpy (ringptr + self->segoffset, ((guint8*) d->data) + offset,
++ copy_size);
++ }
++
++ remain = size - (segsize - self->segoffset);
++
++ GST_TRACE_OBJECT (self->elem,
++ "seg %d: %s %d bytes remained:%d offset:%d segoffset:%d", segment,
++ self->direction == PW_DIRECTION_INPUT ? "INPUT" : "OUTPUT",
++ copy_size, remain, offset, self->segoffset);
++
++ if (remain >= 0) {
++ offset += (segsize - self->segoffset);
++ size = remain;
++
++ /* write silence on the segment we just read */
++ if (self->direction == PW_DIRECTION_OUTPUT)
++ gst_audio_ring_buffer_clear (buf, segment);
++
++ /* notify that we have read a complete segment */
++ gst_audio_ring_buffer_advance (buf, 1);
++ self->segoffset = 0;
++ } else {
++ self->segoffset += size;
++ self->cur_segment = segment;
++ }
++ } while (remain > 0);
++
++ pw_stream_queue_buffer (self->stream, b);
++}
++
++static const struct pw_stream_events stream_events = {
++ PW_VERSION_STREAM_EVENTS,
++ .state_changed = on_stream_state_changed,
++ .format_changed = on_stream_format_changed,
++ .process = on_stream_process,
++};
++
++static gboolean
++copy_properties (GQuark field_id, const GValue *value, gpointer user_data)
++{
++ struct pw_properties *properties = user_data;
++
++ if (G_VALUE_HOLDS_STRING (value))
++ pw_properties_set (properties,
++ g_quark_to_string (field_id),
++ g_value_get_string (value));
++ return TRUE;
++}
++
++static gboolean
++gst_pw_audio_ring_buffer_acquire (GstAudioRingBuffer *buf,
++ GstAudioRingBufferSpec *spec)
++{
++ GstPwAudioRingBuffer *self = GST_PW_AUDIO_RING_BUFFER (buf);
++ struct pw_properties *props;
++ struct spa_pod_builder b = { NULL };
++ uint8_t buffer[512];
++ const struct spa_pod *params[1];
++
++ g_return_val_if_fail (spec, FALSE);
++ g_return_val_if_fail (GST_AUDIO_INFO_IS_VALID (&spec->info), FALSE);
++ g_return_val_if_fail (!self->stream, TRUE); /* already acquired */
++
++ g_return_val_if_fail (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW, FALSE);
++ g_return_val_if_fail (GST_AUDIO_INFO_IS_FLOAT (&spec->info), FALSE);
++
++ GST_DEBUG_OBJECT (self->elem, "acquire");
++
++ /* construct param & props objects */
++
++ if (self->props->properties) {
++ props = pw_properties_new (NULL, NULL);
++ gst_structure_foreach (self->props->properties, copy_properties, props);
++ } else {
++ props = NULL;
++ }
++
++ spa_pod_builder_init (&b, buffer, sizeof (buffer));
++ params[0] = spa_pod_builder_add_object (&b,
++ SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
++ SPA_FORMAT_mediaType, SPA_POD_Id (SPA_MEDIA_TYPE_audio),
++ SPA_FORMAT_mediaSubtype, SPA_POD_Id (SPA_MEDIA_SUBTYPE_raw),
++ SPA_FORMAT_AUDIO_format, SPA_POD_Id (SPA_AUDIO_FORMAT_F32),
++ SPA_FORMAT_AUDIO_rate, SPA_POD_Int (GST_AUDIO_INFO_RATE (&spec->info)),
++ SPA_FORMAT_AUDIO_channels, SPA_POD_Int (GST_AUDIO_INFO_CHANNELS (&spec->info)));
++
++ self->segsize = spec->segsize;
++ self->bpf = GST_AUDIO_INFO_BPF (&spec->info);
++ self->rate = GST_AUDIO_INFO_RATE (&spec->info);
++ self->segoffset = 0;
++
++ /* connect stream */
++
++ pw_thread_loop_lock (self->main_loop);
++
++ GST_DEBUG_OBJECT (self->elem, "creating stream");
++
++ self->stream = pw_stream_new (self->remote, self->props->client_name, props);
++ pw_stream_add_listener(self->stream, &self->stream_listener, &stream_events,
++ self);
++
++ if (pw_stream_connect (self->stream,
++ self->direction,
++ self->props->path ? (uint32_t)atoi(self->props->path) : SPA_ID_INVALID,
++ PW_STREAM_FLAG_AUTOCONNECT |
++ PW_STREAM_FLAG_MAP_BUFFERS |
++ PW_STREAM_FLAG_RT_PROCESS,
++ params, 1) < 0)
++ goto start_error;
++
++ GST_DEBUG_OBJECT (self->elem, "waiting for stream READY");
++
++ if (!wait_for_stream_state (self, PW_STREAM_STATE_READY))
++ goto start_error;
++
++ pw_thread_loop_unlock (self->main_loop);
++
++ /* allocate the internal ringbuffer */
++
++ spec->seglatency = spec->segtotal + 1;
++ buf->size = spec->segtotal * spec->segsize;
++ buf->memory = g_malloc (buf->size);
++
++ gst_audio_format_fill_silence (buf->spec.info.finfo, buf->memory,
++ buf->size);
++
++ GST_DEBUG_OBJECT (self->elem, "acquire done");
++
++ return TRUE;
++
++start_error:
++ {
++ GST_ERROR_OBJECT (self->elem, "could not start stream");
++ pw_stream_destroy (self->stream);
++ self->stream = NULL;
++ pw_thread_loop_unlock (self->main_loop);
++ return FALSE;
++ }
++}
++
++static gboolean
++gst_pw_audio_ring_buffer_release (GstAudioRingBuffer *buf)
++{
++ GstPwAudioRingBuffer *self = GST_PW_AUDIO_RING_BUFFER (buf);
++
++ GST_DEBUG_OBJECT (self->elem, "release");
++
++ pw_thread_loop_lock (self->main_loop);
++ if (self->stream) {
++ spa_hook_remove (&self->stream_listener);
++ pw_stream_disconnect (self->stream);
++ pw_stream_destroy (self->stream);
++ self->stream = NULL;
++ }
++ pw_thread_loop_unlock (self->main_loop);
++
++ /* free the buffer */
++ g_free (buf->memory);
++ buf->memory = NULL;
++
++ return TRUE;
++}
++
++static guint
++gst_pw_audio_ring_buffer_delay (GstAudioRingBuffer *buf)
++{
++ GstPwAudioRingBuffer *self = GST_PW_AUDIO_RING_BUFFER (buf);
++ struct pw_time t;
++
++ if (!self->stream || pw_stream_get_time (self->stream, &t) < 0)
++ return 0;
++
++ if (self->direction == PW_DIRECTION_OUTPUT) {
++ /* on output streams, we set the pw_buffer.size in frames,
++ so no conversion is necessary */
++ return t.queued;
++ } else {
++ /* on input streams, pw_buffer.size is set by pw_stream in ticks,
++ so we need to convert it to frames and also add segoffset, which
++ is the number of bytes we have read but not advertised yet, as
++ the segment is incomplete */
++ if (t.rate.denom > 0)
++ return
++ gst_util_uint64_scale (t.queued, self->rate * t.rate.num, t.rate.denom)
++ + self->segoffset / self->bpf;
++ else
++ return self->segoffset / self->bpf;
++ }
++
++ return 0;
++}
++
++static void
++gst_pw_audio_ring_buffer_class_init (GstPwAudioRingBufferClass * klass)
++{
++ GObjectClass *gobject_class;
++ GstAudioRingBufferClass *gstaudiorbuf_class;
++
++ gobject_class = (GObjectClass *) klass;
++ gstaudiorbuf_class = (GstAudioRingBufferClass *) klass;
++
++ gobject_class->finalize = gst_pw_audio_ring_buffer_finalize;
++ gobject_class->set_property = gst_pw_audio_ring_buffer_set_property;
++
++ gstaudiorbuf_class->open_device = gst_pw_audio_ring_buffer_open_device;
++ gstaudiorbuf_class->acquire = gst_pw_audio_ring_buffer_acquire;
++ gstaudiorbuf_class->release = gst_pw_audio_ring_buffer_release;
++ gstaudiorbuf_class->close_device = gst_pw_audio_ring_buffer_close_device;
++ gstaudiorbuf_class->delay = gst_pw_audio_ring_buffer_delay;
++
++ g_object_class_install_property (gobject_class, PROP_ELEMENT,
++ g_param_spec_object ("element", "Element", "The audio source or sink",
++ GST_TYPE_ELEMENT,
++ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
++
++ g_object_class_install_property (gobject_class, PROP_DIRECTION,
++ g_param_spec_int ("direction", "Direction", "The stream direction",
++ PW_DIRECTION_INPUT, PW_DIRECTION_OUTPUT, PW_DIRECTION_INPUT,
++ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
++
++ g_object_class_install_property (gobject_class, PROP_PROPS,
++ g_param_spec_pointer ("props", "Properties", "The properties struct",
++ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
++
++ GST_DEBUG_CATEGORY_INIT (pw_audio_ring_buffer_debug, "pwaudioringbuffer", 0,
++ "PipeWire Audio Ring Buffer");
++}
+diff --git a/src/gst/gstpwaudioringbuffer.h b/src/gst/gstpwaudioringbuffer.h
+new file mode 100644
+index 00000000..f47f668a
+--- /dev/null
++++ b/src/gst/gstpwaudioringbuffer.h
+@@ -0,0 +1,83 @@
++/* PipeWire
++ *
++ * Copyright © 2018 Wim Taymans
++ * Copyright © 2019 Collabora Ltd.
++ * @author George Kiagiadakis <george.kiagiadakis@collabora.com>
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the next
++ * paragraph) shall be included in all copies or substantial portions of the
++ * Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
++#ifndef __GST_PW_AUDIO_RING_BUFFER_H__
++#define __GST_PW_AUDIO_RING_BUFFER_H__
++
++#include <gst/gst.h>
++#include <gst/audio/audio.h>
++#include <pipewire/pipewire.h>
++
++G_BEGIN_DECLS
++
++#define GST_TYPE_PW_AUDIO_RING_BUFFER \
++ (gst_pw_audio_ring_buffer_get_type ())
++
++G_DECLARE_FINAL_TYPE(GstPwAudioRingBuffer, gst_pw_audio_ring_buffer,
++ GST, PW_AUDIO_RING_BUFFER, GstAudioRingBuffer);
++
++typedef struct _GstPwAudioRingBufferProps GstPwAudioRingBufferProps;
++
++struct _GstPwAudioRingBuffer
++{
++ GstAudioRingBuffer parent;
++
++ /* properties */
++ GstElement *elem;
++ enum pw_direction direction;
++ GstPwAudioRingBufferProps *props;
++
++ /* internal */
++ struct pw_loop *loop;
++ struct pw_thread_loop *main_loop;
++
++ struct pw_core *core;
++ struct pw_remote *remote;
++ struct spa_hook remote_listener;
++
++ struct pw_stream *stream;
++ struct spa_hook stream_listener;
++
++ gint segsize;
++ gint bpf;
++ gint rate;
++
++ /* on_stream_process() state */
++ gint segoffset;
++ gint cur_segment;
++};
++
++struct _GstPwAudioRingBufferProps
++{
++ gchar *path;
++ gchar *client_name;
++ GstStructure *properties;
++ int fd;
++};
++
++G_END_DECLS
++
++#endif
+diff --git a/src/gst/gstpwaudiosink.c b/src/gst/gstpwaudiosink.c
+new file mode 100644
+index 00000000..6cb71385
+--- /dev/null
++++ b/src/gst/gstpwaudiosink.c
+@@ -0,0 +1,200 @@
++/* PipeWire
++ *
++ * Copyright © 2018 Wim Taymans
++ * Copyright © 2019 Collabora Ltd.
++ * @author George Kiagiadakis <george.kiagiadakis@collabora.com>
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the next
++ * paragraph) shall be included in all copies or substantial portions of the
++ * Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
++
++#include "gstpwaudiosink.h"
++
++GST_DEBUG_CATEGORY_STATIC (pw_audio_sink_debug);
++#define GST_CAT_DEFAULT pw_audio_sink_debug
++
++G_DEFINE_TYPE (GstPwAudioSink, gst_pw_audio_sink, GST_TYPE_AUDIO_BASE_SINK);
++
++enum
++{
++ PROP_0,
++ PROP_PATH,
++ PROP_CLIENT_NAME,
++ PROP_STREAM_PROPERTIES,
++ PROP_FD
++};
++
++static GstStaticPadTemplate gst_pw_audio_sink_template =
++GST_STATIC_PAD_TEMPLATE ("sink",
++ GST_PAD_SINK,
++ GST_PAD_ALWAYS,
++ GST_STATIC_CAPS (GST_AUDIO_CAPS_MAKE (GST_AUDIO_NE (F32))
++ ", layout = (string)\"interleaved\"")
++);
++
++
++static void
++gst_pw_audio_sink_init (GstPwAudioSink * self)
++{
++ self->props.fd = -1;
++}
++
++static void
++gst_pw_audio_sink_finalize (GObject * object)
++{
++ GstPwAudioSink *pwsink = GST_PW_AUDIO_SINK (object);
++
++ g_free (pwsink->props.path);
++ g_free (pwsink->props.client_name);
++ if (pwsink->props.properties)
++ gst_structure_free (pwsink->props.properties);
++}
++
++static void
++gst_pw_audio_sink_set_property (GObject * object, guint prop_id,
++ const GValue * value, GParamSpec * pspec)
++{
++ GstPwAudioSink *pwsink = GST_PW_AUDIO_SINK (object);
++
++ switch (prop_id) {
++ case PROP_PATH:
++ g_free (pwsink->props.path);
++ pwsink->props.path = g_value_dup_string (value);
++ break;
++
++ case PROP_CLIENT_NAME:
++ g_free (pwsink->props.client_name);
++ pwsink->props.client_name = g_value_dup_string (value);
++ break;
++
++ case PROP_STREAM_PROPERTIES:
++ if (pwsink->props.properties)
++ gst_structure_free (pwsink->props.properties);
++ pwsink->props.properties =
++ gst_structure_copy (gst_value_get_structure (value));
++ break;
++
++ case PROP_FD:
++ pwsink->props.fd = g_value_get_int (value);
++ break;
++
++ default:
++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
++ break;
++ }
++}
++
++static void
++gst_pw_audio_sink_get_property (GObject * object, guint prop_id,
++ GValue * value, GParamSpec * pspec)
++{
++ GstPwAudioSink *pwsink = GST_PW_AUDIO_SINK (object);
++
++ switch (prop_id) {
++ case PROP_PATH:
++ g_value_set_string (value, pwsink->props.path);
++ break;
++
++ case PROP_CLIENT_NAME:
++ g_value_set_string (value, pwsink->props.client_name);
++ break;
++
++ case PROP_STREAM_PROPERTIES:
++ gst_value_set_structure (value, pwsink->props.properties);
++ break;
++
++ case PROP_FD:
++ g_value_set_int (value, pwsink->props.fd);
++ break;
++
++ default:
++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
++ break;
++ }
++}
++
++static GstAudioRingBuffer *
++gst_pw_audio_sink_create_ringbuffer (GstAudioBaseSink * sink)
++{
++ GstPwAudioSink *self = GST_PW_AUDIO_SINK (sink);
++ GstAudioRingBuffer *buffer;
++
++ GST_DEBUG_OBJECT (sink, "creating ringbuffer");
++ buffer = g_object_new (GST_TYPE_PW_AUDIO_RING_BUFFER,
++ "element", sink,
++ "direction", PW_DIRECTION_OUTPUT,
++ "props", &self->props,
++ NULL);
++ GST_DEBUG_OBJECT (sink, "created ringbuffer @%p", buffer);
++
++ return buffer;
++}
++
++static void
++gst_pw_audio_sink_class_init (GstPwAudioSinkClass * klass)
++{
++ GObjectClass *gobject_class;
++ GstElementClass *gstelement_class;
++ GstAudioBaseSinkClass *gstaudiobsink_class;
++
++ gobject_class = (GObjectClass *) klass;
++ gstelement_class = (GstElementClass *) klass;
++ gstaudiobsink_class = (GstAudioBaseSinkClass *) klass;
++
++ gobject_class->finalize = gst_pw_audio_sink_finalize;
++ gobject_class->set_property = gst_pw_audio_sink_set_property;
++ gobject_class->get_property = gst_pw_audio_sink_get_property;
++
++ gstaudiobsink_class->create_ringbuffer = gst_pw_audio_sink_create_ringbuffer;
++
++ g_object_class_install_property (gobject_class, PROP_PATH,
++ g_param_spec_string ("path", "Path",
++ "The sink path to connect to (NULL = default)", NULL,
++ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
++
++ g_object_class_install_property (gobject_class, PROP_CLIENT_NAME,
++ g_param_spec_string ("client-name", "Client Name",
++ "The client name to use (NULL = default)", NULL,
++ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
++
++ g_object_class_install_property (gobject_class, PROP_STREAM_PROPERTIES,
++ g_param_spec_boxed ("stream-properties", "Stream properties",
++ "List of PipeWire stream properties", GST_TYPE_STRUCTURE,
++ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
++
++ g_object_class_install_property (gobject_class, PROP_FD,
++ g_param_spec_int ("fd", "Fd", "The fd to connect with", -1, G_MAXINT, -1,
++ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
++
++ gst_element_class_set_static_metadata (gstelement_class,
++ "PipeWire Audio sink", "Sink/Audio",
++ "Send audio to PipeWire",
++ "George Kiagiadakis <george.kiagiadakis@collabora.com>");
++
++ gst_element_class_add_pad_template (gstelement_class,
++ gst_static_pad_template_get (&gst_pw_audio_sink_template));
++
++ GST_DEBUG_CATEGORY_INIT (pw_audio_sink_debug, "pwaudiosink", 0,
++ "PipeWire Audio Sink");
++}
++
+diff --git a/src/gst/gstpwaudiosink.h b/src/gst/gstpwaudiosink.h
+new file mode 100644
+index 00000000..7ed0de7b
+--- /dev/null
++++ b/src/gst/gstpwaudiosink.h
+@@ -0,0 +1,48 @@
++/* PipeWire
++ *
++ * Copyright © 2018 Wim Taymans
++ * Copyright © 2019 Collabora Ltd.
++ * @author George Kiagiadakis <george.kiagiadakis@collabora.com>
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the next
++ * paragraph) shall be included in all copies or substantial portions of the
++ * Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
++#ifndef __GST_PW_AUDIO_SINK_H__
++#define __GST_PW_AUDIO_SINK_H__
++
++#include "gstpwaudioringbuffer.h"
++
++G_BEGIN_DECLS
++
++#define GST_TYPE_PW_AUDIO_SINK \
++ (gst_pw_audio_sink_get_type ())
++
++G_DECLARE_FINAL_TYPE(GstPwAudioSink, gst_pw_audio_sink,
++ GST, PW_AUDIO_SINK, GstAudioBaseSink);
++
++struct _GstPwAudioSink
++{
++ GstAudioBaseSink parent;
++ GstPwAudioRingBufferProps props;
++};
++
++G_END_DECLS
++
++#endif
+diff --git a/src/gst/gstpwaudiosrc.c b/src/gst/gstpwaudiosrc.c
+new file mode 100644
+index 00000000..6c522982
+--- /dev/null
++++ b/src/gst/gstpwaudiosrc.c
+@@ -0,0 +1,200 @@
++/* PipeWire
++ *
++ * Copyright © 2018 Wim Taymans
++ * Copyright © 2019 Collabora Ltd.
++ * @author George Kiagiadakis <george.kiagiadakis@collabora.com>
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the next
++ * paragraph) shall be included in all copies or substantial portions of the
++ * Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
++
++#include "gstpwaudiosrc.h"
++
++GST_DEBUG_CATEGORY_STATIC (pw_audio_src_debug);
++#define GST_CAT_DEFAULT pw_audio_src_debug
++
++G_DEFINE_TYPE (GstPwAudioSrc, gst_pw_audio_src, GST_TYPE_AUDIO_BASE_SRC);
++
++enum
++{
++ PROP_0,
++ PROP_PATH,
++ PROP_CLIENT_NAME,
++ PROP_STREAM_PROPERTIES,
++ PROP_FD
++};
++
++static GstStaticPadTemplate gst_pw_audio_src_template =
++GST_STATIC_PAD_TEMPLATE ("src",
++ GST_PAD_SRC,
++ GST_PAD_ALWAYS,
++ GST_STATIC_CAPS (GST_AUDIO_CAPS_MAKE (GST_AUDIO_NE (F32))
++ ", layout = (string)\"interleaved\"")
++);
++
++
++static void
++gst_pw_audio_src_init (GstPwAudioSrc * self)
++{
++ self->props.fd = -1;
++}
++
++static void
++gst_pw_audio_src_finalize (GObject * object)
++{
++ GstPwAudioSrc *self = GST_PW_AUDIO_SRC (object);
++
++ g_free (self->props.path);
++ g_free (self->props.client_name);
++ if (self->props.properties)
++ gst_structure_free (self->props.properties);
++}
++
++static void
++gst_pw_audio_src_set_property (GObject * object, guint prop_id,
++ const GValue * value, GParamSpec * pspec)
++{
++ GstPwAudioSrc *self = GST_PW_AUDIO_SRC (object);
++
++ switch (prop_id) {
++ case PROP_PATH:
++ g_free (self->props.path);
++ self->props.path = g_value_dup_string (value);
++ break;
++
++ case PROP_CLIENT_NAME:
++ g_free (self->props.client_name);
++ self->props.client_name = g_value_dup_string (value);
++ break;
++
++ case PROP_STREAM_PROPERTIES:
++ if (self->props.properties)
++ gst_structure_free (self->props.properties);
++ self->props.properties =
++ gst_structure_copy (gst_value_get_structure (value));
++ break;
++
++ case PROP_FD:
++ self->props.fd = g_value_get_int (value);
++ break;
++
++ default:
++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
++ break;
++ }
++}
++
++static void
++gst_pw_audio_src_get_property (GObject * object, guint prop_id,
++ GValue * value, GParamSpec * pspec)
++{
++ GstPwAudioSrc *self = GST_PW_AUDIO_SRC (object);
++
++ switch (prop_id) {
++ case PROP_PATH:
++ g_value_set_string (value, self->props.path);
++ break;
++
++ case PROP_CLIENT_NAME:
++ g_value_set_string (value, self->props.client_name);
++ break;
++
++ case PROP_STREAM_PROPERTIES:
++ gst_value_set_structure (value, self->props.properties);
++ break;
++
++ case PROP_FD:
++ g_value_set_int (value, self->props.fd);
++ break;
++
++ default:
++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
++ break;
++ }
++}
++
++static GstAudioRingBuffer *
++gst_pw_audio_src_create_ringbuffer (GstAudioBaseSrc * sink)
++{
++ GstPwAudioSrc *self = GST_PW_AUDIO_SRC (sink);
++ GstAudioRingBuffer *buffer;
++
++ GST_DEBUG_OBJECT (sink, "creating ringbuffer");
++ buffer = g_object_new (GST_TYPE_PW_AUDIO_RING_BUFFER,
++ "element", sink,
++ "direction", PW_DIRECTION_INPUT,
++ "props", &self->props,
++ NULL);
++ GST_DEBUG_OBJECT (sink, "created ringbuffer @%p", buffer);
++
++ return buffer;
++}
++
++static void
++gst_pw_audio_src_class_init (GstPwAudioSrcClass * klass)
++{
++ GObjectClass *gobject_class;
++ GstElementClass *gstelement_class;
++ GstAudioBaseSrcClass *gstaudiobsrc_class;
++
++ gobject_class = (GObjectClass *) klass;
++ gstelement_class = (GstElementClass *) klass;
++ gstaudiobsrc_class = (GstAudioBaseSrcClass *) klass;
++
++ gobject_class->finalize = gst_pw_audio_src_finalize;
++ gobject_class->set_property = gst_pw_audio_src_set_property;
++ gobject_class->get_property = gst_pw_audio_src_get_property;
++
++ gstaudiobsrc_class->create_ringbuffer = gst_pw_audio_src_create_ringbuffer;
++
++ g_object_class_install_property (gobject_class, PROP_PATH,
++ g_param_spec_string ("path", "Path",
++ "The sink path to connect to (NULL = default)", NULL,
++ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
++
++ g_object_class_install_property (gobject_class, PROP_CLIENT_NAME,
++ g_param_spec_string ("client-name", "Client Name",
++ "The client name to use (NULL = default)", NULL,
++ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
++
++ g_object_class_install_property (gobject_class, PROP_STREAM_PROPERTIES,
++ g_param_spec_boxed ("stream-properties", "Stream properties",
++ "List of PipeWire stream properties", GST_TYPE_STRUCTURE,
++ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
++
++ g_object_class_install_property (gobject_class, PROP_FD,
++ g_param_spec_int ("fd", "Fd", "The fd to connect with", -1, G_MAXINT, -1,
++ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
++
++ gst_element_class_set_static_metadata (gstelement_class,
++ "PipeWire Audio source", "Source/Audio",
++ "Receive audio from PipeWire",
++ "George Kiagiadakis <george.kiagiadakis@collabora.com>");
++
++ gst_element_class_add_pad_template (gstelement_class,
++ gst_static_pad_template_get (&gst_pw_audio_src_template));
++
++ GST_DEBUG_CATEGORY_INIT (pw_audio_src_debug, "pwaudiosrc", 0,
++ "PipeWire Audio Src");
++}
++
+diff --git a/src/gst/gstpwaudiosrc.h b/src/gst/gstpwaudiosrc.h
+new file mode 100644
+index 00000000..c46e644c
+--- /dev/null
++++ b/src/gst/gstpwaudiosrc.h
+@@ -0,0 +1,48 @@
++/* PipeWire
++ *
++ * Copyright © 2018 Wim Taymans
++ * Copyright © 2019 Collabora Ltd.
++ * @author George Kiagiadakis <george.kiagiadakis@collabora.com>
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the next
++ * paragraph) shall be included in all copies or substantial portions of the
++ * Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
++#ifndef __GST_PW_AUDIO_SRC_H__
++#define __GST_PW_AUDIO_SRC_H__
++
++#include "gstpwaudioringbuffer.h"
++
++G_BEGIN_DECLS
++
++#define GST_TYPE_PW_AUDIO_SRC \
++ (gst_pw_audio_src_get_type ())
++
++G_DECLARE_FINAL_TYPE(GstPwAudioSrc, gst_pw_audio_src,
++ GST, PW_AUDIO_SRC, GstAudioBaseSrc);
++
++struct _GstPwAudioSrc
++{
++ GstAudioBaseSrc parent;
++ GstPwAudioRingBufferProps props;
++};
++
++G_END_DECLS
++
++#endif
+diff --git a/src/gst/meson.build b/src/gst/meson.build
+index ad0e0801..0e922347 100644
+--- a/src/gst/meson.build
++++ b/src/gst/meson.build
+@@ -6,6 +6,9 @@ pipewire_gst_sources = [
+ 'gstpipewirepool.c',
+ 'gstpipewiresink.c',
+ 'gstpipewiresrc.c',
++ 'gstpwaudioringbuffer.c',
++ 'gstpwaudiosink.c',
++ 'gstpwaudiosrc.c',
+ ]
+
+ pipewire_gst_headers = [
+@@ -15,6 +18,9 @@ pipewire_gst_headers = [
+ 'gstpipewirepool.h',
+ 'gstpipewiresink.h',
+ 'gstpipewiresrc.h',
++ 'gstpwaudioringbuffer.h',
++ 'gstpwaudiosink.h',
++ 'gstpwaudiosrc.h',
+ ]
+
+ pipewire_gst_c_args = [
+--
+2.20.1
+
diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0011-gst-pwaudioringbuffer-make-the-buffer-size-sensitive.patch b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0011-gst-pwaudioringbuffer-make-the-buffer-size-sensitive.patch
new file mode 100644
index 00000000..5ffabb6d
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0011-gst-pwaudioringbuffer-make-the-buffer-size-sensitive.patch
@@ -0,0 +1,60 @@
+From 6e289d0058d71bc433d1918a8bbf3305f3e4f517 Mon Sep 17 00:00:00 2001
+From: Julian Bouzas <julian.bouzas@collabora.com>
+Date: Tue, 7 May 2019 10:36:35 -0400
+Subject: [PATCH] gst/pwaudioringbuffer: make the buffer size sensitive to the
+ number of channels
+
+Upstream-Status: Submitted [https://github.com/PipeWire/pipewire/pull/140]
+---
+ src/gst/gstpwaudioringbuffer.c | 6 ++++--
+ src/gst/gstpwaudioringbuffer.h | 1 +
+ 2 files changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/src/gst/gstpwaudioringbuffer.c b/src/gst/gstpwaudioringbuffer.c
+index 989b2cd7..181304e8 100644
+--- a/src/gst/gstpwaudioringbuffer.c
++++ b/src/gst/gstpwaudioringbuffer.c
+@@ -246,17 +246,18 @@ on_stream_format_changed (void *data, const struct spa_pod *format)
+ const struct spa_pod *params[1];
+ struct spa_pod_builder b = { NULL };
+ uint8_t buffer[512];
++ const gint b_size = self->segsize * self->channels;
+
+ spa_pod_builder_init (&b, buffer, sizeof (buffer));
+ params[0] = spa_pod_builder_add_object (&b,
+ SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers,
+ SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(16, 1, INT32_MAX),
+ SPA_PARAM_BUFFERS_blocks, SPA_POD_Int(1),
+- SPA_PARAM_BUFFERS_size, SPA_POD_Int(self->segsize),
++ SPA_PARAM_BUFFERS_size, SPA_POD_Int(b_size),
+ SPA_PARAM_BUFFERS_stride, SPA_POD_Int(self->bpf),
+ SPA_PARAM_BUFFERS_align, SPA_POD_Int(16));
+
+- GST_DEBUG_OBJECT (self->elem, "doing finish format, buffer size:%d", self->segsize);
++ GST_DEBUG_OBJECT (self->elem, "doing finish format, buffer size:%d", b_size);
+ pw_stream_finish_format (self->stream, 0, params, 1);
+ }
+
+@@ -402,6 +403,7 @@ gst_pw_audio_ring_buffer_acquire (GstAudioRingBuffer *buf,
+ self->segsize = spec->segsize;
+ self->bpf = GST_AUDIO_INFO_BPF (&spec->info);
+ self->rate = GST_AUDIO_INFO_RATE (&spec->info);
++ self->channels = GST_AUDIO_INFO_CHANNELS (&spec->info);
+ self->segoffset = 0;
+
+ /* connect stream */
+diff --git a/src/gst/gstpwaudioringbuffer.h b/src/gst/gstpwaudioringbuffer.h
+index f47f668a..f600f012 100644
+--- a/src/gst/gstpwaudioringbuffer.h
++++ b/src/gst/gstpwaudioringbuffer.h
+@@ -64,6 +64,7 @@ struct _GstPwAudioRingBuffer
+ gint segsize;
+ gint bpf;
+ gint rate;
++ gint channels;
+
+ /* on_stream_process() state */
+ gint segoffset;
+--
+2.20.1
+
diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0012-gst-pwaudioringbuffer-request-pause-play-on-the-appr.patch b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0012-gst-pwaudioringbuffer-request-pause-play-on-the-appr.patch
new file mode 100644
index 00000000..3680cc35
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0012-gst-pwaudioringbuffer-request-pause-play-on-the-appr.patch
@@ -0,0 +1,76 @@
+From 1eb1e3a839f97ad4aa43c289f702c587a068a333 Mon Sep 17 00:00:00 2001
+From: George Kiagiadakis <george.kiagiadakis@collabora.com>
+Date: Thu, 11 Jul 2019 16:21:17 +0300
+Subject: [PATCH] gst/pwaudioringbuffer: request pause/play on the appropriate
+ stream state changes
+
+This allows the client to properly go to PAUSED when the session manager
+unlinks the stream and go again to PLAYING when the sm re-links it.
+This allows the session manager to implement policies without letting
+the client pipeline freeze (in the absence of a running audio clock)
+when it is unlinked. Note that in case the client doesn't handle the
+request, there is still no issue. Like in pulseaudio, the clock just
+freezes, so the pipeline stops progressing.
+
+This is similar to the pulseaudio cork/uncork mechanism.
+
+Upstream-Status: Submitted [https://github.com/PipeWire/pipewire/pull/140]
+---
+ src/gst/gstpwaudioringbuffer.c | 27 +++++++++++++++++++++++----
+ 1 file changed, 23 insertions(+), 4 deletions(-)
+
+diff --git a/src/gst/gstpwaudioringbuffer.c b/src/gst/gstpwaudioringbuffer.c
+index 181304e8..04259927 100644
+--- a/src/gst/gstpwaudioringbuffer.c
++++ b/src/gst/gstpwaudioringbuffer.c
+@@ -202,11 +202,16 @@ on_stream_state_changed (void *data, enum pw_stream_state old,
+ enum pw_stream_state state, const char *error)
+ {
+ GstPwAudioRingBuffer *self = GST_PW_AUDIO_RING_BUFFER (data);
++ GstMessage *msg;
+
+ GST_DEBUG_OBJECT (self->elem, "got stream state: %s",
+ pw_stream_state_as_string (state));
+
+ switch (state) {
++ case PW_STREAM_STATE_ERROR:
++ GST_ELEMENT_ERROR (self->elem, RESOURCE, FAILED,
++ ("stream error: %s", error), (NULL));
++ break;
+ case PW_STREAM_STATE_UNCONNECTED:
+ GST_ELEMENT_ERROR (self->elem, RESOURCE, FAILED,
+ ("stream disconnected unexpectedly"), (NULL));
+@@ -214,12 +219,26 @@ on_stream_state_changed (void *data, enum pw_stream_state old,
+ case PW_STREAM_STATE_CONNECTING:
+ case PW_STREAM_STATE_CONFIGURE:
+ case PW_STREAM_STATE_READY:
++ break;
+ case PW_STREAM_STATE_PAUSED:
+- case PW_STREAM_STATE_STREAMING:
++ if (old == PW_STREAM_STATE_STREAMING) {
++ if (GST_STATE (self->elem) != GST_STATE_PAUSED &&
++ GST_STATE_TARGET (self->elem) != GST_STATE_PAUSED) {
++ GST_DEBUG_OBJECT (self->elem, "requesting GST_STATE_PAUSED");
++ msg = gst_message_new_request_state (GST_OBJECT (self->elem),
++ GST_STATE_PAUSED);
++ gst_element_post_message (self->elem, msg);
++ }
++ }
+ break;
+- case PW_STREAM_STATE_ERROR:
+- GST_ELEMENT_ERROR (self->elem, RESOURCE, FAILED,
+- ("stream error: %s", error), (NULL));
++ case PW_STREAM_STATE_STREAMING:
++ if (GST_STATE (self->elem) != GST_STATE_PLAYING &&
++ GST_STATE_TARGET (self->elem) != GST_STATE_PLAYING) {
++ GST_DEBUG_OBJECT (self->elem, "requesting GST_STATE_PLAYING");
++ msg = gst_message_new_request_state (GST_OBJECT (self->elem),
++ GST_STATE_PLAYING);
++ gst_element_post_message (self->elem, msg);
++ }
+ break;
+ }
+ pw_thread_loop_signal (self->main_loop, FALSE);
+--
+2.20.1
+
diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0013-gst-pwaudioringbuffer-wait-only-for-STREAM_STATE_CON.patch b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0013-gst-pwaudioringbuffer-wait-only-for-STREAM_STATE_CON.patch
new file mode 100644
index 00000000..539e3a5e
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0013-gst-pwaudioringbuffer-wait-only-for-STREAM_STATE_CON.patch
@@ -0,0 +1,35 @@
+From 1b2bf0f435f2912c32fbd7a6118ed9bfb41f031c Mon Sep 17 00:00:00 2001
+From: George Kiagiadakis <george.kiagiadakis@collabora.com>
+Date: Thu, 11 Jul 2019 16:34:35 +0300
+Subject: [PATCH] gst/pwaudioringbuffer: wait only for STREAM_STATE_CONFIGURE
+ when starting
+
+The CONFIGURE state is reached when the pw_client_node is exported,
+while the READY state requires the session manager to try and link
+the stream. If the SM does not want to link the stream due to policy,
+the client should not hang there forever.
+
+Upstream-Status: Submitted [https://github.com/PipeWire/pipewire/pull/140]
+---
+ src/gst/gstpwaudioringbuffer.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/gst/gstpwaudioringbuffer.c b/src/gst/gstpwaudioringbuffer.c
+index 04259927..b92b5feb 100644
+--- a/src/gst/gstpwaudioringbuffer.c
++++ b/src/gst/gstpwaudioringbuffer.c
+@@ -444,9 +444,9 @@ gst_pw_audio_ring_buffer_acquire (GstAudioRingBuffer *buf,
+ params, 1) < 0)
+ goto start_error;
+
+- GST_DEBUG_OBJECT (self->elem, "waiting for stream READY");
++ GST_DEBUG_OBJECT (self->elem, "waiting for stream CONFIGURE");
+
+- if (!wait_for_stream_state (self, PW_STREAM_STATE_READY))
++ if (!wait_for_stream_state (self, PW_STREAM_STATE_CONFIGURE))
+ goto start_error;
+
+ pw_thread_loop_unlock (self->main_loop);
+--
+2.20.1
+
diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0014-gst-pwaudiosink-set-the-default-latency-time-buffer-.patch b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0014-gst-pwaudiosink-set-the-default-latency-time-buffer-.patch
new file mode 100644
index 00000000..6f15b7f7
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0014-gst-pwaudiosink-set-the-default-latency-time-buffer-.patch
@@ -0,0 +1,37 @@
+From 460ce06c9cc6fd7b0106e0ce8a265bbeff4ae406 Mon Sep 17 00:00:00 2001
+From: George Kiagiadakis <george.kiagiadakis@collabora.com>
+Date: Thu, 11 Jul 2019 17:07:15 +0300
+Subject: [PATCH] gst/pwaudiosink: set the default latency time (buffer size)
+ to be 21.3ms
+
+This is to solve underrun issues that seem to appear with the default
+10ms latency that GstBaseAudioSink has.
+Hopefully in the future we will have a better mechanism to pick
+the appropriate latency instead of hardcoding it here.
+
+Upstream-Status: Submitted [https://github.com/PipeWire/pipewire/pull/140]
+---
+ src/gst/gstpwaudiosink.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/src/gst/gstpwaudiosink.c b/src/gst/gstpwaudiosink.c
+index 6cb71385..069996c3 100644
+--- a/src/gst/gstpwaudiosink.c
++++ b/src/gst/gstpwaudiosink.c
+@@ -57,6 +57,13 @@ static void
+ gst_pw_audio_sink_init (GstPwAudioSink * self)
+ {
+ self->props.fd = -1;
++
++ /* Bump the default buffer size up to 21.3 ms, which is the default on most
++ * sound cards, in hope to match the alsa buffer size on the pipewire server.
++ * This may not always happen, but it still sounds better than the 10ms
++ * default latency. This is temporary until we have a better mechanism to
++ * select the appropriate latency */
++ GST_AUDIO_BASE_SINK (self)->latency_time = 21333;
+ }
+
+ static void
+--
+2.20.1
+
diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0015-audioconvert-fmtconvert-assume-F32-on-the-other-port.patch b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0015-audioconvert-fmtconvert-assume-F32-on-the-other-port.patch
new file mode 100644
index 00000000..ed3c1b06
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0015-audioconvert-fmtconvert-assume-F32-on-the-other-port.patch
@@ -0,0 +1,44 @@
+From aa5de0cfc31df9cd8fb6d24367d2852dbbc8dcb9 Mon Sep 17 00:00:00 2001
+From: George Kiagiadakis <george.kiagiadakis@collabora.com>
+Date: Mon, 29 Jul 2019 16:12:45 +0300
+Subject: [PATCH] audioconvert/fmtconvert: assume F32 on the other port when
+ listing formats
+
+This allows picking F32LE as the default format on links that have
+no restriction and it avoids failing negotiation when the restricted
+end cannot handle S16/F32/F32P
+
+For instance this pipeline would previously fail:
+
+ audio-dsp mode=merge ! audio-dsp mode=convert ! alsa-sink
+old negotiation: S16LE S24_32LE
+new negotiation: F32LE S24_32LE
+
+The link between the audio-dsp nodes has no restriction, so previously
+it would negotiate S16LE, which would then fail to negotiate with alsa-sink
+because fmtconvert does not know how to convert S16LE to S24_32LE directly.
+
+With this change, the middle link negotiates to F32LE, which can be
+converted to anything.
+
+Upstream-Status: Submitted [https://github.com/PipeWire/pipewire/pull/169]
+---
+ spa/plugins/audioconvert/fmtconvert.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/spa/plugins/audioconvert/fmtconvert.c b/spa/plugins/audioconvert/fmtconvert.c
+index df4ffb6b..a330f68f 100644
+--- a/spa/plugins/audioconvert/fmtconvert.c
++++ b/spa/plugins/audioconvert/fmtconvert.c
+@@ -338,7 +338,7 @@ static int port_enum_formats(struct spa_node *node,
+ if (other->have_format)
+ info = other->format;
+ else
+- info.info.raw.format = SPA_AUDIO_FORMAT_S16;
++ info.info.raw.format = SPA_AUDIO_FORMAT_F32;
+
+ if (info.info.raw.format == SPA_AUDIO_FORMAT_F32P ||
+ info.info.raw.format == SPA_AUDIO_FORMAT_F32) {
+--
+2.20.1
+
diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0016-gst-pwaudioringbuffer-set-node.latency-to-get-schedu.patch b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0016-gst-pwaudioringbuffer-set-node.latency-to-get-schedu.patch
new file mode 100644
index 00000000..b97e21ff
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0016-gst-pwaudioringbuffer-set-node.latency-to-get-schedu.patch
@@ -0,0 +1,41 @@
+From 3af64cf4e1d33c33a9757c0f30c7de1068202540 Mon Sep 17 00:00:00 2001
+From: George Kiagiadakis <george.kiagiadakis@collabora.com>
+Date: Tue, 20 Aug 2019 18:33:35 +0300
+Subject: [PATCH] gst: pwaudioringbuffer: set node.latency to get scheduled
+ correctly in capture mode
+
+Upstream-Status: Pending
+---
+ src/gst/gstpwaudioringbuffer.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/src/gst/gstpwaudioringbuffer.c b/src/gst/gstpwaudioringbuffer.c
+index b92b5feb..2314dd77 100644
+--- a/src/gst/gstpwaudioringbuffer.c
++++ b/src/gst/gstpwaudioringbuffer.c
+@@ -403,11 +403,9 @@ gst_pw_audio_ring_buffer_acquire (GstAudioRingBuffer *buf,
+
+ /* construct param & props objects */
+
++ props = pw_properties_new (NULL, NULL);
+ if (self->props->properties) {
+- props = pw_properties_new (NULL, NULL);
+ gst_structure_foreach (self->props->properties, copy_properties, props);
+- } else {
+- props = NULL;
+ }
+
+ spa_pod_builder_init (&b, buffer, sizeof (buffer));
+@@ -425,6 +423,9 @@ gst_pw_audio_ring_buffer_acquire (GstAudioRingBuffer *buf,
+ self->channels = GST_AUDIO_INFO_CHANNELS (&spec->info);
+ self->segoffset = 0;
+
++ pw_properties_setf(props, "node.latency", "%u/%u",
++ self->segsize / self->bpf, self->rate);
++
+ /* connect stream */
+
+ pw_thread_loop_lock (self->main_loop);
+--
+2.23.0
+
diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0017-connection-move-remaining-data-and-fds.patch b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0017-connection-move-remaining-data-and-fds.patch
new file mode 100644
index 00000000..be5ac5ea
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0017-connection-move-remaining-data-and-fds.patch
@@ -0,0 +1,61 @@
+From 75247f77eae2c473b18cf8d7e117216f73d2e127 Mon Sep 17 00:00:00 2001
+From: Wim Taymans <wtaymans@redhat.com>
+Date: Tue, 1 Oct 2019 10:43:48 +0200
+Subject: [PATCH] connection: move remaining data and fds
+
+If we can't send all of the data, move the remaining data to the
+start of the buffer so that we can send it again later.
+
+See #111
+
+Upstream-Status: Backport [3d48ba8394396fc8d8cadb1bff3514217ddd70e6]
+---
+ .../module-protocol-native/connection.c | 23 +++++++++++--------
+ 1 file changed, 14 insertions(+), 9 deletions(-)
+
+diff --git a/src/modules/module-protocol-native/connection.c b/src/modules/module-protocol-native/connection.c
+index dbb6a3cf..cb592e41 100644
+--- a/src/modules/module-protocol-native/connection.c
++++ b/src/modules/module-protocol-native/connection.c
+@@ -491,8 +491,12 @@ int pw_protocol_native_connection_flush(struct pw_protocol_native_connection *co
+ if (sent < 0) {
+ if (errno == EINTR)
+ continue;
+- else
+- goto send_error;
++ else {
++ res = -errno;
++ pw_log_error("could not sendmsg on fd:%d n_fds:%d: %s",
++ conn->fd, n_fds, spa_strerror(res));
++ goto exit;
++ }
+ }
+ break;
+ }
+@@ -504,15 +508,16 @@ int pw_protocol_native_connection_flush(struct pw_protocol_native_connection *co
+ n_fds -= outfds;
+ fds += outfds;
+ }
+- buf->buffer_size = size;
+- buf->n_fds = n_fds;
+
+- return 0;
++ res = 0;
+
+- /* ERRORS */
+- send_error:
+- res = -errno;
+- pw_log_error("could not sendmsg: %s", strerror(errno));
++exit:
++ if (size > 0)
++ memmove(buf->buffer_data, data, size);
++ buf->buffer_size = size;
++ if (n_fds > 0)
++ memmove(buf->fds, fds, n_fds * sizeof(int));
++ buf->n_fds = n_fds;
+ return res;
+ }
+
+--
+2.23.0
+
diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0018-protocol-improve-flushing.patch b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0018-protocol-improve-flushing.patch
new file mode 100644
index 00000000..e027765e
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0018-protocol-improve-flushing.patch
@@ -0,0 +1,222 @@
+From 7e885c029a6cc66ce1881f6f2c50d5f76a7d3372 Mon Sep 17 00:00:00 2001
+From: Wim Taymans <wtaymans@redhat.com>
+Date: Tue, 1 Oct 2019 12:53:56 +0200
+Subject: [PATCH] protocol: improve flushing
+
+Use the IO_OUT flag to schedule flushing instead of a flush_event.
+
+Handle EGAIN and wait for IO_OUT to try again.
+
+Fixes #111
+
+Upstream-Status: Backport [cc8e992cd155b4f19312a5036c7b744fc547410f]
+---
+ src/modules/module-protocol-native.c | 89 +++++++++++++------
+ .../module-protocol-native/connection.c | 2 -
+ 2 files changed, 62 insertions(+), 29 deletions(-)
+
+diff --git a/src/modules/module-protocol-native.c b/src/modules/module-protocol-native.c
+index 411bad6c..b7cd3140 100644
+--- a/src/modules/module-protocol-native.c
++++ b/src/modules/module-protocol-native.c
+@@ -83,8 +83,7 @@ struct client {
+ struct spa_hook conn_listener;
+
+ bool disconnecting;
+- bool flush_signaled;
+- struct spa_source *flush_event;
++ bool flushing;
+ };
+
+ struct server {
+@@ -106,6 +105,7 @@ struct client_data {
+ struct spa_source *source;
+ struct pw_protocol_native_connection *connection;
+ bool busy;
++ bool need_flush;
+ };
+
+ static void
+@@ -194,12 +194,14 @@ client_busy_changed(void *data, bool busy)
+ {
+ struct client_data *c = data;
+ struct pw_client *client = c->client;
+- enum spa_io mask = SPA_IO_ERR | SPA_IO_HUP;
++ uint32_t mask = c->source->mask;
+
+ c->busy = busy;
+
+- if (!busy)
+- mask |= SPA_IO_IN;
++ if (busy)
++ SPA_FLAG_UNSET(mask, SPA_IO_IN);
++ else
++ SPA_FLAG_SET(mask, SPA_IO_IN);
+
+ pw_log_debug("protocol-native %p: busy changed %d", client->protocol, busy);
+ pw_loop_update_io(client->core->main_loop, c->source, mask);
+@@ -214,13 +216,32 @@ connection_data(void *data, int fd, enum spa_io mask)
+ {
+ struct client_data *this = data;
+ struct pw_client *client = this->client;
++ int res;
+
+- if (mask & (SPA_IO_ERR | SPA_IO_HUP)) {
++ if (mask & SPA_IO_HUP) {
+ pw_log_info("protocol-native %p: client %p disconnected", client->protocol, client);
+ pw_client_destroy(client);
+ return;
+ }
+-
++ if (mask & SPA_IO_ERR) {
++ pw_log_error("protocol-native %p: client %p error", client->protocol, client);
++ pw_client_destroy(client);
++ return;
++ }
++ if (mask & SPA_IO_OUT) {
++ res = pw_protocol_native_connection_flush(this->connection);
++ if (res >= 0) {
++ int mask = this->source->mask;
++ SPA_FLAG_UNSET(mask, SPA_IO_OUT);
++ pw_loop_update_io(client->protocol->core->main_loop,
++ this->source, mask);
++ } else if (res != EAGAIN) {
++ pw_log_error("client %p: could not flush: %s",
++ client, spa_strerror(res));
++ pw_client_destroy(client);
++ return;
++ }
++ }
+ if (mask & SPA_IO_IN)
+ process_messages(this);
+ }
+@@ -288,7 +309,8 @@ static struct pw_client *client_new(struct server *s, int fd)
+
+ this->client = client;
+ this->source = pw_loop_add_io(pw_core_get_main_loop(core),
+- fd, SPA_IO_ERR | SPA_IO_HUP, true, connection_data, this);
++ fd, SPA_IO_ERR | SPA_IO_HUP, true,
++ connection_data, this);
+ if (this->source == NULL)
+ goto cleanup_client;
+
+@@ -396,7 +418,7 @@ socket_data(void *data, int fd, enum spa_io mask)
+
+ if (!client->busy)
+ pw_loop_update_io(client->protocol->core->main_loop,
+- c->source, SPA_IO_IN | SPA_IO_ERR | SPA_IO_HUP);
++ c->source, c->source->mask | SPA_IO_IN);
+ }
+
+ static bool add_socket(struct pw_protocol *protocol, struct server *s)
+@@ -479,6 +501,17 @@ on_remote_data(void *data, int fd, enum spa_io mask)
+ res = -EPIPE;
+ goto error;
+ }
++ if (mask & SPA_IO_OUT) {
++ res = pw_protocol_native_connection_flush(conn);
++ if (res >= 0) {
++ int mask = impl->source->mask;
++ SPA_FLAG_UNSET(mask, SPA_IO_OUT);
++ pw_loop_update_io(core->main_loop,
++ impl->source, mask);
++ impl->flushing = false;
++ } else if (res != EAGAIN)
++ goto error;
++ }
+
+ if (mask & SPA_IO_IN) {
+ const struct pw_protocol_native_message *msg;
+@@ -545,23 +578,17 @@ error:
+ }
+
+
+-static void do_flush_event(void *data, uint64_t count)
+-{
+- struct client *impl = data;
+- impl->flush_signaled = false;
+- if (impl->connection)
+- if (pw_protocol_native_connection_flush(impl->connection) < 0)
+- impl->this.disconnect(&impl->this);
+-}
+-
+ static void on_need_flush(void *data)
+ {
+ struct client *impl = data;
+ struct pw_remote *remote = impl->this.remote;
+
+- if (!impl->flush_signaled) {
+- impl->flush_signaled = true;
+- pw_loop_signal_event(remote->core->main_loop, impl->flush_event);
++ if (!impl->flushing) {
++ int mask = impl->source->mask;
++ impl->flushing = true;
++ SPA_FLAG_SET(mask, SPA_IO_OUT);
++ pw_loop_update_io(remote->core->main_loop,
++ impl->source, mask);
+ }
+ }
+
+@@ -619,12 +646,9 @@ static void impl_disconnect(struct pw_protocol_client *client)
+ static void impl_destroy(struct pw_protocol_client *client)
+ {
+ struct client *impl = SPA_CONTAINER_OF(client, struct client, this);
+- struct pw_remote *remote = client->remote;
+
+ impl_disconnect(client);
+
+- pw_loop_destroy_source(remote->core->main_loop, impl->flush_event);
+-
+ if (impl->properties)
+ pw_properties_free(impl->properties);
+
+@@ -665,8 +689,6 @@ impl_new_client(struct pw_protocol *protocol,
+ this->disconnect = impl_disconnect;
+ this->destroy = impl_destroy;
+
+- impl->flush_event = pw_loop_add_event(remote->core->main_loop, do_flush_event, impl);
+-
+ spa_list_append(&protocol->client_list, &this->link);
+
+ return this;
+@@ -701,10 +723,23 @@ static void on_before_hook(void *_data)
+ struct pw_protocol_server *this = &server->this;
+ struct pw_client *client, *tmp;
+ struct client_data *data;
++ int res;
+
+ spa_list_for_each_safe(client, tmp, &this->client_list, protocol_link) {
+ data = client->user_data;
+- pw_protocol_native_connection_flush(data->connection);
++
++ res = pw_protocol_native_connection_flush(data->connection);
++ if (res == -EAGAIN) {
++ int mask = data->source->mask;
++ SPA_FLAG_SET(mask, SPA_IO_OUT);
++ pw_loop_update_io(client->protocol->core->main_loop,
++ data->source, mask);
++ } else if (res < 0) {
++ pw_log_warn("client %p: could not flush: %s",
++ data->client, spa_strerror(res));
++ pw_client_destroy(client);
++ }
++
+ }
+ }
+
+diff --git a/src/modules/module-protocol-native/connection.c b/src/modules/module-protocol-native/connection.c
+index cb592e41..8b9e919d 100644
+--- a/src/modules/module-protocol-native/connection.c
++++ b/src/modules/module-protocol-native/connection.c
+@@ -493,8 +493,6 @@ int pw_protocol_native_connection_flush(struct pw_protocol_native_connection *co
+ continue;
+ else {
+ res = -errno;
+- pw_log_error("could not sendmsg on fd:%d n_fds:%d: %s",
+- conn->fd, n_fds, spa_strerror(res));
+ goto exit;
+ }
+ }
+--
+2.23.0
+
diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/pipewire@.service b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/pipewire@.service
new file mode 100644
index 00000000..e116dc1f
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/pipewire@.service
@@ -0,0 +1,24 @@
+[Unit]
+Description=Multimedia Service for user %i
+Requires=pipewire@%i.socket
+
+[Install]
+Also=pipewire@%i.socket
+
+[Service]
+Type=simple
+Restart=on-failure
+ExecStart=/usr/bin/pipewire
+
+Environment=XDG_RUNTIME_DIR=/run/user/%i
+Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/%i/bus
+EnvironmentFile=-/etc/pipewire/environment
+
+User=%i
+Slice=user-%i.slice
+SmackProcessLabel=System::Pipewire
+SupplementaryGroups=audio
+UMask=0077
+CapabilityBoundingSet=
+SystemCallFilter=@basic-io @file-system @io-event @ipc \
+ @memlock @network-io @process @resources @signal
diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/pipewire@.socket b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/pipewire@.socket
new file mode 100644
index 00000000..10cb3227
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/pipewire@.socket
@@ -0,0 +1,19 @@
+[Unit]
+Description=Multimedia Service socket for user %i
+Requires=afm-user-setup@%i.service
+After=afm-user-setup@%i.service
+
+[Socket]
+Priority=6
+Backlog=5
+ListenStream=/run/user/%i/pipewire-0
+Service=pipewire@%i.service
+SmackLabel=*
+SmackLabelIPIn=System
+SmackLabelIPOut=System
+SocketUser=%i
+SocketGroup=%i
+SocketMode=0660
+
+[Install]
+WantedBy=afm-user-session@%i.target
diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/smack-pipewire b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/smack-pipewire
new file mode 100644
index 00000000..8d5b541f
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/smack-pipewire
@@ -0,0 +1,8 @@
+System System::Pipewire rwxa--
+System::Pipewire System -wx---
+System::Pipewire System::Shared r-x---
+System::Pipewire System::Run rwxat-
+System::Pipewire System::Log rwxa--
+System::Pipewire _ r-x--l
+System::Pipewire User::Home r-x--l
+System::Pipewire User::App-Shared rwxat-
diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire_git.bb b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire_git.bb
new file mode 100644
index 00000000..823da421
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire_git.bb
@@ -0,0 +1,29 @@
+require pipewire.inc
+
+SRC_URI = "gitsm://github.com/PipeWire/pipewire;protocol=https;branch=work \
+ file://0001-spa-include-install-missing-headers.patch \
+ file://0002-extensions-implement-Endpoint-ClientEndpoint-interfa.patch \
+ file://0003-pipewire-cli-add-support-for-printing-endpoint-info-.patch \
+ file://0004-pipewire-cli-add-command-to-modify-endpoint-control-.patch \
+ file://0005-arm-build-with-mno-unaligned-access.patch \
+ file://0006-logger-print-timestamps-on-logged-messages.patch \
+ file://0007-alsa-make-corrections-on-the-timeout-based-on-how-fa.patch \
+ file://0008-audio-dsp-allow-mode-to-be-set-with-a-property.patch \
+ file://0009-audioconvert-do-setup-internal-links-and-buffers-als.patch \
+ file://0010-gst-Implement-new-pwaudio-src-sink-elements-based-on.patch \
+ file://0011-gst-pwaudioringbuffer-make-the-buffer-size-sensitive.patch \
+ file://0012-gst-pwaudioringbuffer-request-pause-play-on-the-appr.patch \
+ file://0013-gst-pwaudioringbuffer-wait-only-for-STREAM_STATE_CON.patch \
+ file://0014-gst-pwaudiosink-set-the-default-latency-time-buffer-.patch \
+ file://0015-audioconvert-fmtconvert-assume-F32-on-the-other-port.patch \
+ file://0016-gst-pwaudioringbuffer-set-node.latency-to-get-schedu.patch \
+ file://0017-connection-move-remaining-data-and-fds.patch \
+ file://0018-protocol-improve-flushing.patch \
+ "
+
+SRCREV = "4be788962e60891237f1f018627bf709ae3981e6"
+
+PV = "0.2.90+git${SRCPV}+3"
+S = "${WORKDIR}/git"
+
+RDEPENDS_${PN} += "virtual/pipewire-sessionmanager virtual/pipewire-config"
diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire_git.bbappend b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire_git.bbappend
new file mode 100644
index 00000000..8a0b0741
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire_git.bbappend
@@ -0,0 +1,30 @@
+SRC_URI += "\
+ file://pipewire@.service \
+ file://pipewire@.socket \
+ file://smack-pipewire \
+ "
+
+do_install_append() {
+ if ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'true', 'false', d)}; then
+ # remove the original user unit files shipped by pipewire
+ rm -rf ${D}${systemd_unitdir}
+
+ # install our own system-level templates
+ mkdir -p ${D}${systemd_system_unitdir}/
+ install -m 0644 ${WORKDIR}/pipewire@.service ${D}${systemd_system_unitdir}/pipewire@.service
+ install -m 0644 ${WORKDIR}/pipewire@.socket ${D}${systemd_system_unitdir}/pipewire@.socket
+
+ # enable the socket to start together with afm-user-session
+ mkdir -p ${D}${systemd_system_unitdir}/afm-user-session@.target.wants
+ ln -sf ../pipewire@.socket ${D}${systemd_system_unitdir}/afm-user-session@.target.wants/pipewire@.socket
+
+ # install smack rules
+ mkdir -p ${D}${sysconfdir}/smack/accesses.d
+ install -m 0644 ${WORKDIR}/smack-pipewire ${D}${sysconfdir}/smack/accesses.d/pipewire
+ fi
+}
+
+FILES_${PN} += "\
+ ${systemd_system_unitdir}/* \
+ ${sysconfdir}/smack/accesses.d/* \
+"
diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/wireplumber.conf.in b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/wireplumber.conf.in
new file mode 100644
index 00000000..76a57419
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/wireplumber.conf.in
@@ -0,0 +1,55 @@
+# Basic pipewire integration - do not remove
+load-module C libwireplumber-module-pipewire
+
+# Grants access to security confined clients
+load-module C libwireplumber-module-client-permissions
+
+# Endpoint implementation for standard audio devices
+# using software conversions, mixing and volume controls
+load-module C libwireplumber-module-pw-audio-softdsp-endpoint
+
+# Endpoint that provides high-level volume controls for the AGL mixer
+# The streams specified here are the ones that will appear in the mixer.
+# They must match the stream names in the alsa-udev module,
+# except for "Master", which is treated specially.
+load-module C libwireplumber-module-mixer {
+ "streams": <["Master", "Multimedia", "Speech-Low", "Custom-Low",
+ "Navigation", "Speech-High", "Custom-High",
+ "Communication", "Emergency"]>
+}
+
+# Monitors the ALSA devices that are discovered via udev
+# and creates softdsp-endopints for each one of them
+# The streams specified here are the ones that will be available for linking
+# clients. Currently, they are matched against the client's role string.
+load-module C libwireplumber-module-pw-alsa-udev {
+ "streams": <["Multimedia", "Speech-Low", "Custom-Low",
+ "Navigation", "Speech-High", "Custom-High",
+ "Communication", "Emergency"]>
+}
+
+# Monitors the Audio clients that are discovered via pipewire
+# and creates simple-endpoints for each one of them
+load-module C libwireplumber-module-pw-audio-client
+
+# Implements linking clients to devices and maintains
+# information about the devices to be used.
+# Notes:
+# - Devices must be specified in hw:X,Y format, where X and Y are integers.
+# Things like hw:Intel,0 or paths are not understood.
+# - Roles and priorities can be arbitrary strings and arbitrary numbers
+# - Roles are matched against the stream names specified in the modules above.
+load-module C libwireplumber-module-simple-policy {
+ "default-playback-device": <"PLAYBACK">,
+ "default-capture-device": <"CAPTURE">,
+ "role-priorities": <{
+ "Multimedia": 1,
+ "Speech-Low": 2,
+ "Custom-Low": 3,
+ "Navigation": 5,
+ "Speech-High:": 7,
+ "Custom-High": 8,
+ "Communication": 9,
+ "Emergency": 10
+ }>
+}
diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl_git.bb b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl_git.bb
new file mode 100644
index 00000000..7ed9ea1a
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl_git.bb
@@ -0,0 +1,69 @@
+SUMMARY = "AGL configuration file for wireplumber"
+HOMEPAGE = "https://gitlab.freedesktop.org/gkiagia/wireplumber"
+BUGTRACKER = "https://jira.automotivelinux.org"
+AUTHOR = "George Kiagiadakis <george.kiagiadakis@collabora.com>"
+SECTION = "multimedia"
+
+LICENSE = "MIT"
+LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
+
+SRC_URI = "file://wireplumber.conf.in"
+
+PACKAGE_ARCH = "${MACHINE_ARCH}"
+
+do_configure[noexec] = "1"
+do_compile[noexec] = "1"
+
+#
+# For device names, any unique substring of the "endpoint" name is valid.
+# To list all endpoints:
+# export XDG_RUNTIME_DIR=/run/user/1001
+# pipewire-cli
+# > connect pipewire-0
+# > list-objects
+# ... and look for objects of type "PipeWire:Interface:Endpoint/0"
+#
+# For instance:
+# id 269, parent 40, type PipeWire:Interface:Endpoint/0
+# media.name = "USB Audio on WD15 Dock (hw:1,0 / node 5)"
+# media.class = "Audio/Sink"
+# id 270, parent 40, type PipeWire:Interface:Endpoint/0
+# media.name = "USB Audio on WD15 Dock (hw:1,0 / node 7)"
+# media.class = "Audio/Source"
+#
+# Audio/Sink endpoints are valid for playback
+# Audio/Source endpoints are valid for capture
+#
+# Wireplumber will first filter endpoints based on the media.class, depending
+# on whether the client is doing playback or capture and then it will look
+# for a sub-string match in the media.name
+#
+DEV_PLAYBACK = "hw:0,0"
+DEV_CAPTURE = "hw:0,0"
+
+DEV_PLAYBACK_dra7xx-evm = "DRA7xx-EVM"
+DEV_CAPTURE_dra7xx-evm = "DRA7xx-EVM"
+
+DEV_PLAYBACK_m3ulcb = "ak4613"
+DEV_CAPTURE_m3ulcb = "ak4613"
+
+DEV_PLAYBACK_h3ulcb = "ak4613"
+DEV_CAPTURE_h3ulcb = "ak4613"
+
+DEV_PLAYBACK_raspberrypi3 = "bcm2835 ALSA on bcm2835 ALSA"
+DEV_CAPTURE_raspberrypi3 = "hw:0,0"
+
+do_install_append() {
+ sed -e "s/PLAYBACK/${DEV_PLAYBACK}/" -e "s/CAPTURE/${DEV_CAPTURE}/" ${WORKDIR}/wireplumber.conf.in > ${WORKDIR}/wireplumber.conf
+ install -d ${D}/${sysconfdir}/wireplumber/
+ install -m 644 ${WORKDIR}/wireplumber.conf ${D}/${sysconfdir}/wireplumber/wireplumber.conf
+}
+
+FILES_${PN} += "\
+ ${sysconfdir}/wireplumber/* \
+"
+CONFFILES_${PN} += "\
+ ${sysconfdir}/wireplumber/* \
+"
+
+RPROVIDES_${PN} += "virtual/wireplumber-config"
diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber_git.bb b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber_git.bb
new file mode 100644
index 00000000..2979d7e5
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber_git.bb
@@ -0,0 +1,36 @@
+SUMMARY = "Session / Policy Manager for PipeWire"
+HOMEPAGE = "https://gitlab.freedesktop.org/gkiagia/wireplumber"
+BUGTRACKER = "https://gitlab.freedesktop.org/gkiagia/wireplumber/issues"
+AUTHOR = "George Kiagiadakis <george.kiagiadakis@collabora.com>"
+SECTION = "multimedia"
+
+LICENSE = "MIT"
+LIC_FILES_CHKSUM = "file://LICENSE;beginline=3;md5=e8ad01a5182f2c1b3a2640e9ea268264"
+
+inherit meson pkgconfig gobject-introspection
+
+DEPENDS = "glib-2.0 glib-2.0-native pipewire"
+
+SRC_URI = "git://gitlab.freedesktop.org/gkiagia/wireplumber;protocol=https;branch=0.1"
+SRCREV = "50db6a5930d01e9f34dda6952654ee4cb7926405"
+
+PV = "0.1.1+git${SRCPV}"
+S = "${WORKDIR}/git"
+
+PACKAGES =+ "${PN}-config"
+
+FILES_${PN} += "\
+ ${libdir}/wireplumber-*/* \
+"
+RPROVIDES_${PN} += "virtual/pipewire-sessionmanager"
+RDEPENDS_${PN} += "virtual/wireplumber-config"
+
+
+FILES_${PN}-config += "\
+ ${sysconfdir}/wireplumber/* \
+"
+CONFFILES_${PN}-config += "\
+ ${sysconfdir}/wireplumber/* \
+"
+
+RPROVIDES_${PN}-config += "virtual/wireplumber-config"
diff --git a/meta-agl-devel/meta-pipewire/recipes-security/security-manager/security-manager/0001-Adapt-smack-rules-to-allow-connections-to-pipewire.patch b/meta-agl-devel/meta-pipewire/recipes-security/security-manager/security-manager/0001-Adapt-smack-rules-to-allow-connections-to-pipewire.patch
new file mode 100644
index 00000000..821c1e1d
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-security/security-manager/security-manager/0001-Adapt-smack-rules-to-allow-connections-to-pipewire.patch
@@ -0,0 +1,25 @@
+From cc5cbaddad6fe559e9e482467266fb18fb00c6a7 Mon Sep 17 00:00:00 2001
+From: George Kiagiadakis <george.kiagiadakis@collabora.com>
+Date: Wed, 26 Jun 2019 16:02:13 +0300
+Subject: [PATCH] Adapt smack rules to allow connections to pipewire
+
+Signed-off-by: George Kiagiadakis <george.kiagiadakis@collabora.com>
+---
+ policy/app-rules-template.smack | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/policy/app-rules-template.smack b/policy/app-rules-template.smack
+index 910f40c..78b75de 100644
+--- a/policy/app-rules-template.smack
++++ b/policy/app-rules-template.smack
+@@ -4,6 +4,7 @@ System ~PKG~ rwxat
+ ~APP~ System::Shared rx
+ ~APP~ System::Run rwxat
+ ~APP~ System::Log rwxa
++~APP~ System::Pipewire rw
+ ~APP~ _ l
+ ~APP~ User::Home rxl
+ ~APP~ User::App-Shared rwxat
+--
+2.20.1
+
diff --git a/meta-agl-devel/meta-pipewire/recipes-security/security-manager/security-manager_%.bbappend b/meta-agl-devel/meta-pipewire/recipes-security/security-manager/security-manager_%.bbappend
new file mode 100644
index 00000000..319a27d6
--- /dev/null
+++ b/meta-agl-devel/meta-pipewire/recipes-security/security-manager/security-manager_%.bbappend
@@ -0,0 +1,2 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/security-manager:"
+SRC_URI += "file://0001-Adapt-smack-rules-to-allow-connections-to-pipewire.patch"
diff --git a/meta-agl-devel/meta-speech-framework/conf/include/agl-speech-framework.inc b/meta-agl-devel/meta-speech-framework/conf/include/agl-speech-framework.inc
new file mode 100644
index 00000000..9b7a0f07
--- /dev/null
+++ b/meta-agl-devel/meta-speech-framework/conf/include/agl-speech-framework.inc
@@ -0,0 +1,2 @@
+# Currently no default voiceagent
+PREFERRED_RPROVIDER_virtual/voiceagent ?= ""
diff --git a/meta-agl-devel/meta-speech-framework/conf/include/agl-voiceagent-alexa.inc b/meta-agl-devel/meta-speech-framework/conf/include/agl-voiceagent-alexa.inc
new file mode 100644
index 00000000..ad509d14
--- /dev/null
+++ b/meta-agl-devel/meta-speech-framework/conf/include/agl-voiceagent-alexa.inc
@@ -0,0 +1,6 @@
+# A bbappend has been added to meta-agl to enable nghttp2, mask out the one
+# from meta-aac to avoid triggering rebuilds of all curl dependencies when
+# agl-voiceagent-alexa is configured.
+BBMASK += "meta-aac/recipes-support/curl/curl_%.bbappend"
+
+PREFERRED_RPROVIDER_virtual/voiceagent = "alexa-voiceagent-service"
diff --git a/meta-agl-devel/meta-speech-framework/conf/layer.conf b/meta-agl-devel/meta-speech-framework/conf/layer.conf
new file mode 100644
index 00000000..ce97b9e0
--- /dev/null
+++ b/meta-agl-devel/meta-speech-framework/conf/layer.conf
@@ -0,0 +1,27 @@
+# We have a conf and classes directory, add to BBPATH
+BBPATH .= ":${LAYERDIR}"
+
+# Let us add layer-specific bbappends which are only applied when that
+# layer is included in our configuration -
+# e.g. only add layers if a bsp is present.
+# This is based on the BBFILE_COLLECTIONS name of the layer.
+# We use either the BBFILE_COLLECTIONS name of the layer directly (meta-ti)
+BBFILES += "${@' '.join('${LAYERDIR}/%s/recipes*/*/*.bbappend' % layer \
+ for layer in BBFILE_COLLECTIONS.split())}"
+BBFILES += "${@' '.join('${LAYERDIR}/%s/recipes*/*/*.bb' % layer \
+ for layer in BBFILE_COLLECTIONS.split())}"
+# or we prepend it with meta- (e.g. rpi, fsl*)
+BBFILES += "${@' '.join('${LAYERDIR}/meta-%s/recipes*/*/*.bbappend' % layer \
+ for layer in BBFILE_COLLECTIONS.split())}"
+BBFILES += "${@' '.join('${LAYERDIR}/meta-%s/recipes*/*/*.bb' % layer \
+ for layer in BBFILE_COLLECTIONS.split())}"
+
+# We have recipes-* directories, add to BBFILES
+BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
+ ${LAYERDIR}/recipes-*/*/*.bbappend"
+
+BBFILE_COLLECTIONS += "speech-framework"
+BBFILE_PATTERN_speech-framework = "^${LAYERDIR}/"
+BBFILE_PRIORITY_speech-framework = "8"
+
+LAYERSERIES_COMPAT_speech-framework = "thud"
diff --git a/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-service/0001-remove-library-dependency-copying.patch b/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-service/0001-remove-library-dependency-copying.patch
new file mode 100644
index 00000000..7b0141c4
--- /dev/null
+++ b/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-service/0001-remove-library-dependency-copying.patch
@@ -0,0 +1,30 @@
+Remove copying of library dependencies
+
+Since we are targeting building into an image, the widget build does
+not have to copy host library dependencies into the widget as it would
+when being built standalone with the SDK. Remove the copying, as
+runtime dependencies will be used to pull the libraries in.
+
+Upstream-Status: Inappropriate [embedded specific]
+
+Signed-off-by: Scott Murray <scott.murray@konsulko.com>
+
+diff --git a/platforms/agl/alexa-voiceagent-service/libs/CMakeLists.txt b/platforms/agl/alexa-voiceagent-service/libs/CMakeLists.txt
+index 4732e7b..ffc149d 100644
+--- a/libs/CMakeLists.txt
++++ b/libs/CMakeLists.txt
+@@ -70,14 +70,6 @@ add_avs_library(SpeechEncoder ${AAC_HOME}/lib/libSpeechEncoder.so)
+ add_avs_library(OpusEncoderContext ${AAC_HOME}/lib/libOpusEncoderContext.so)
+ add_avs_library(SpeechSynthesizer ${AAC_HOME}/lib/libSpeechSynthesizer.so)
+ add_avs_library(TemplateRuntime ${AAC_HOME}/lib/libTemplateRuntime.so)
+-#add_avs_library(curl ${AAC_HOME}/lib/libcurl.so.4.5.0)
+-add_avs_library(curl ${AAC_HOME}/lib/libcurl.so.4)
+-#add_avs_library(nghttp2 ${AAC_HOME}/lib/libnghttp2.so.14.16)
+-add_avs_library(nghttp2 ${AAC_HOME}/lib/libnghttp2.so.14)
+-#add_avs_library(opus ${AAC_HOME}/lib/libopus.so.0.6.1)
+-add_avs_library(opus ${AAC_HOME}/lib/libopus.so.0)
+-#add_avs_library(sqlite3 ${AAC_HOME}/lib/libsqlite3.so.0.8.6)
+-add_avs_library(sqlite3 ${AAC_HOME}/lib/libsqlite3.so.0)
+ add_avs_library(equalizer ${AAC_HOME}/lib/libEqualizer.so)
+ add_avs_library(EqualizerImplementations ${AAC_HOME}/lib/libEqualizerImplementations.so)
+
diff --git a/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-service/0002-update-config.xml.in.patch b/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-service/0002-update-config.xml.in.patch
new file mode 100644
index 00000000..fd5aaf75
--- /dev/null
+++ b/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-service/0002-update-config.xml.in.patch
@@ -0,0 +1,31 @@
+Update config.xml.in
+
+Remove now unneeded 4A binding dependency, and add new required audio
+permission.
+
+Upstream-Status: Pending
+
+Signed-off-by: Scott Murray <scott.murray@konsulko.com>
+
+diff --git a/platforms/agl/alexa-voiceagent-service/conf.d/wgt/config.xml.in b/platforms/agl/alexa-voiceagent-service/conf.d/wgt/config.xml.in
+index 3486518..14fd6a2 100644
+--- a/conf.d/wgt/config.xml.in
++++ b/conf.d/wgt/config.xml.in
+@@ -9,6 +9,7 @@
+
+ <feature name="urn:AGL:widget:required-permission">
+ <param name="urn:AGL:permission::public:no-htdocs" value="required" />
++ <param name="urn:AGL:permission::public:audio" value="required" />
+ <param name="urn:AGL:permission:audio:public:audiostream" value="required" />
+ <param name="urn:AGL:permission::public:hidden" value="required" />
+ <param name="urn:AGL:permission::system:run-by-default" value="required" />
+@@ -23,7 +24,6 @@
+ </feature>
+
+ <feature name="urn:AGL:widget:required-api">
+- <param name="ahl-4a" value="ws" />
+ <param name="vshl-capabilities" value="ws" />
+ </feature>
+-</widget>
+\ No newline at end of file
++</widget>
diff --git a/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-service/0003-update-audio-device-configuration.patch b/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-service/0003-update-audio-device-configuration.patch
new file mode 100644
index 00000000..ede3d533
--- /dev/null
+++ b/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-service/0003-update-audio-device-configuration.patch
@@ -0,0 +1,197 @@
+Update audio device configuration
+
+Rework the audio output device configuration to match the expectations
+of the PipeWire output sink configuration in the gstreamer output code.
+Currently, this means that the role is being stored as the device name
+so the gstreamer code can use it when setting up the output sink
+properties.
+
+Upstream-Status: Pending
+
+Signed-off-by: Scott Murray <scott.murray@konsulko.com>
+
+diff --git a/platforms/agl/alexa-voiceagent-service/src/plugins/aasb-client/config/AASBConfigProviderImpl.cpp b/platforms/agl/alexa-voiceagent-service/src/plugins/aasb-client/config/AASBConfigProviderImpl.cpp
+index 83d0341..b51185c 100644
+--- a/src/plugins/aasb-client/config/AASBConfigProviderImpl.cpp
++++ b/src/plugins/aasb-client/config/AASBConfigProviderImpl.cpp
+@@ -97,25 +97,25 @@ AASBConfigProviderImpl::AudioIOConfiguration AASBConfigProviderImpl::getAudioIOC
+
+ // Output devices
+ if(!m_ttsOutputDevice.empty())
+- audioConfig.ttsOutputDevice = m_audio->openAHLChannel(m_ttsOutputDevice);
++ audioConfig.ttsOutputDevice = m_audio->openChannel(m_ttsOutputDevice);
+
+ if(!m_musicOutputDevice.empty())
+- audioConfig.musicOutputDevice = m_audio->openAHLChannel(m_musicOutputDevice);
++ audioConfig.musicOutputDevice = m_audio->openChannel(m_musicOutputDevice);
+
+ if(!m_notificationOutputDevice.empty())
+- audioConfig.notificationOutputDevice = m_audio->openAHLChannel(m_notificationOutputDevice);
++ audioConfig.notificationOutputDevice = m_audio->openChannel(m_notificationOutputDevice);
+
+ if(!m_alarmOutputDevice.empty())
+- audioConfig.alarmOutputDevice = m_audio->openAHLChannel(m_alarmOutputDevice);
++ audioConfig.alarmOutputDevice = m_audio->openChannel(m_alarmOutputDevice);
+
+ if(!m_earconOutputDevice.empty())
+- audioConfig.earconOutputDevice = m_audio->openAHLChannel(m_earconOutputDevice);
++ audioConfig.earconOutputDevice = m_audio->openChannel(m_earconOutputDevice);
+
+ if(!m_communicationOutputDevice.empty())
+- audioConfig.communicationOutputDevice = m_audio->openAHLChannel(m_communicationOutputDevice);
++ audioConfig.communicationOutputDevice = m_audio->openChannel(m_communicationOutputDevice);
+
+ if(!m_ringtoneOutputDevice.empty())
+- audioConfig.ringtoneOutputDevice = m_audio->openAHLChannel(m_ringtoneOutputDevice);
++ audioConfig.ringtoneOutputDevice = m_audio->openChannel(m_ringtoneOutputDevice);
+
+ return audioConfig;
+ }
+@@ -585,4 +585,4 @@ void AASBConfigProviderImpl::logCurrentConfiguration() {
+ }
+
+ } // namespace alexa
+-} // namespace agl
+\ No newline at end of file
++} // namespace agl
+diff --git a/src/plugins/audio/Audio.cpp b/src/plugins/audio/Audio.cpp
+index d662a06..1b2fa9d 100644
+--- a/src/plugins/audio/Audio.cpp
++++ b/src/plugins/audio/Audio.cpp
+@@ -13,8 +13,6 @@
+ * permissions and limitations under the License.
+ */
+
+-#include <json.h>
+-
+ #include <AACE/Engine/Core/EngineMacros.h>
+
+ #include "Audio.h"
+@@ -22,7 +20,7 @@
+ namespace agl {
+ namespace audio {
+
+-/// Shortcut to reach logging level.
++// Shortcut to reach logging level.
+ using Level = agl::common::interfaces::ILogger::Level;
+
+ using namespace agl::common::interfaces;
+@@ -31,68 +29,30 @@ static std::string TAG = "agl::audio::Audio";
+
+ std::shared_ptr<Audio> Audio::create(
+ std::shared_ptr<agl::common::interfaces::ILogger> logger,
+- shared_ptr<agl::common::interfaces::IAFBApi> api) {
++ shared_ptr<agl::common::interfaces::IAFBApi> api)
++{
+ return std::shared_ptr<Audio>(new Audio(logger, api));
+ }
+
+ Audio::Audio(std::shared_ptr<ILogger> logger,
+ std::shared_ptr<IAFBApi> api) :
+ m_logger(logger),
+- m_api(api) {
+-
+-}
+-
+-std::string Audio::openAHLChannel(const std::string &role)
++ m_api(api)
+ {
+- json_object *request = json_object_new_object();
+- json_object *response = NULL;
+- json_object_object_add(request, "action", json_object_new_string("open"));
+- if (callAHL(role, request, &response)) {
+- json_object *val = NULL;
+- std::string result;
+- if (json_object_object_get_ex(response, "device_uri", &val)) {
+- const char* device = json_object_get_string(val);
+- m_logger->log(Level::DEBUG, TAG, "openAHLChannel: device=" + std::string(device));
+- result = device;
+- }
+- json_object_put(response);
+- return result;
+- }
+- return "";
+ }
+
+-bool Audio::setAHLChannelVolume(const std::string &role, int volume)
++std::string Audio::openChannel(const std::string &role)
+ {
+- json_object *request = json_object_new_object();
+- json_object_object_add(request, "action", json_object_new_string("volume"));
+- json_object_object_add(request, "value", json_object_new_int(volume));
+- return callAHL(role, request, NULL);
++ // For now, return the given role as the device string, to match
++ // the expectation of the PipeWire sink configuration in the
++ // gstreamer output code.
++ return role;
+ }
+
+-bool Audio::callAHL(const std::string &role, json_object *request, json_object **response)
++bool Audio::setChannelVolume(const std::string &role, int volume)
+ {
+- json_object *object = NULL;
+- std::string error, info;
+- bool result = false;
+-
+- if (m_api->callSync("ahl-4a", role, request, &object, error, info) < 0) {
+- m_logger->log(Level::ERROR, TAG, "VA service call=" + role + " failed, error=" + error + ", info=" + info);
+- goto exit;
+- }
+-
+- m_logger->log(Level::DEBUG, TAG, "callAHL, response=" + std::string(json_object_get_string(object)));
+- result = true;
+- if (response) {
+- *response = object;
+- }
+-
+-exit:
+- if (!result && object) {
+- json_object_put(object);
+- }
+-
+- return result;
++ return true;
+ }
+
+-}
+-}
+\ No newline at end of file
++} // namespace audio
++} // namespace agl
+diff --git a/src/plugins/audio/Audio.h b/src/plugins/audio/Audio.h
+index 14bef4d..8998242 100644
+--- a/src/plugins/audio/Audio.h
++++ b/src/plugins/audio/Audio.h
+@@ -35,23 +35,21 @@ public:
+ std::shared_ptr<agl::common::interfaces::ILogger> logger,
+ shared_ptr<agl::common::interfaces::IAFBApi> api);
+
+- std::string openAHLChannel(const std::string &role);
+- bool setAHLChannelVolume(const std::string &role, int volume);
++ std::string openChannel(const std::string &role);
++ bool setChannelVolume(const std::string &role, int volume);
+
+ private:
+ Audio(std::shared_ptr<agl::common::interfaces::ILogger> logger,
+ shared_ptr<agl::common::interfaces::IAFBApi> api);
+
+- bool callAHL(const std::string &role, json_object *request, json_object **response);
+-
+- // Logger.
+- std::shared_ptr<agl::common::interfaces::ILogger> m_logger;
++ // Logger.
++ std::shared_ptr<agl::common::interfaces::ILogger> m_logger;
+
+ // AFB API object for events pub/sub, and for calling other AGL services.
+- std::shared_ptr<agl::common::interfaces::IAFBApi> m_api;
++ std::shared_ptr<agl::common::interfaces::IAFBApi> m_api;
+ };
+
+-}
+-}
++} // namespace audio
++} // namespace agl
+
+-#endif // AGL_AUDIO_AUDIO_H_
+\ No newline at end of file
++#endif // AGL_AUDIO_AUDIO_H_
diff --git a/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-service/0004-update-config-and-database-paths.patch b/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-service/0004-update-config-and-database-paths.patch
new file mode 100644
index 00000000..0bf4267f
--- /dev/null
+++ b/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-service/0004-update-config-and-database-paths.patch
@@ -0,0 +1,124 @@
+alexa-voiceagent-service: update config and database file paths
+
+Tweak getDataRootPath in the AASBConfigProviderImpl class to use the
+AFM_WORKDIR environment variable as the basis for the path, which
+moves things from the binding installation hierarchy into the app
+framework's provided application data directory. This avoids the
+permissions problems stemming from the new security model of running
+as non-root. Also reworked the main configuration JSON file location
+logic to use a new helper member function that checks for the file
+in /etc/xdg/AGL and then in AFM_WORKDIR (app-data directory), before
+falling back to the original location in var/config under the binding
+installation directory. The local copy of GetBindingDirPath has been
+removed, as it seems to be working fine now that the binding is being
+built with AFB_BINDING_VERSION = 3.
+
+Upstream-Status: Pending
+
+Signed-off-by: Scott Murray <scott.murray@konsulko.com>
+
+diff --git a/src/plugins/aasb-client/config/AASBConfigProviderImpl.cpp b/src/plugins/aasb-client/config/AASBConfigProviderImpl.cpp
+index b51185c..5d5c3ba 100644
+--- a/src/plugins/aasb-client/config/AASBConfigProviderImpl.cpp
++++ b/src/plugins/aasb-client/config/AASBConfigProviderImpl.cpp
+@@ -19,6 +19,7 @@
+ #include <iostream>
+ #include <sstream>
+ #include <unistd.h>
++#include <sys/stat.h>
+
+ #include <rapidjson/document.h>
+ #include <rapidjson/istreamwrapper.h>
+@@ -36,6 +37,9 @@ using Level = agl::common::interfaces::ILogger::Level;
+ /// Logging tag for this file.
+ static std::string TAG = "agl::alexa::AASBConfigProviderImpl";
+
++/// Directory where user over-ride alexa json configuration may be.
++static std::string ALEXA_CONFIG_FILE_OVERRIDE_DIR = "/etc/xdg/AGL/";
++
+ /// File name where alexa json configuration is stored.
+ static std::string ALEXA_CONFIG_FILE_NAME = "AlexaAutoCoreEngineConfig.json";
+
+@@ -64,8 +68,7 @@ AASBConfigProviderImpl::AASBConfigProviderImpl(std::shared_ptr<agl::common::inte
+ m_enableLocalVoiceControl(false) {
+ m_LocalVoiceControlConfiguration = std::unique_ptr<LVCConfiguration>(new LVCConfiguration());
+ m_carControlConfiguration = std::unique_ptr<CarControlConfiguration>(new CarControlConfiguration());
+- std::string alexaConfigFile = getDataRootPath() + ALEXA_CONFIG_FILE_NAME;
+- initConfigFromFile(alexaConfigFile);
++ initConfigFromFile(getAlexaConfigPath());
+ logCurrentConfiguration();
+ }
+
+@@ -520,32 +523,25 @@ void AASBConfigProviderImpl::initConfigFromFile(const std::string& fileName) {
+ }
+ }
+
+-// GetBindingDirPath() method provided by AGL SDK crashes every single time.
+-// It turns out that on latest AGL platforms, GetBindingDirPath(afb_api_t) version
+-// is supposed to be the correct version. However when we include filescan-utils.h
+-// it compiles a version without "afb_api_t" parameter. For now, I have made a
+-// copy of this method here which accepts "afb_api_t" parameter.
+-// TODO: Fix it
+-std::string GetBindingDirectoryPath(afb_api_t api) {
+- // A file description should not be greater than 999.999.999
+- char fd_link[CONTROL_MAXPATH_LEN];
+- char retdir[CONTROL_MAXPATH_LEN];
+- ssize_t len;
+- sprintf(fd_link, "/proc/self/fd/%d", afb_dynapi_rootdir_get_fd(api));
+-
+- if ((len = readlink(fd_link, retdir, sizeof(retdir) - 1)) == -1) {
+- perror("lstat");
+- strncpy(retdir, "/tmp", CONTROL_MAXPATH_LEN - 1);
+- } else {
+- retdir[len] = '\0';
+- }
+-
+- return std::string(retdir);
++std::string AASBConfigProviderImpl::getDataRootPath() {
++ std::string workDir(getenv("AFM_WORKDIR"));
++ return workDir + "/";
+ }
+
+-std::string AASBConfigProviderImpl::getDataRootPath() {
+- std::string bindingDir(GetBindingDirectoryPath(m_api));
+- return bindingDir + "/var/config/";
++std::string AASBConfigProviderImpl::getAlexaConfigPath() {
++ struct stat statbuf;
++
++ // Look in over-ride directory first
++ std::string configPath = ALEXA_CONFIG_FILE_OVERRIDE_DIR + ALEXA_CONFIG_FILE_NAME;
++ if(stat(configPath.c_str(), &statbuf) != 0) {
++ // Look in work directory (app-data) next
++ configPath = getDataRootPath() + ALEXA_CONFIG_FILE_NAME;
++ if(stat(configPath.c_str(), &statbuf) != 0) {
++ // Fall back to default version in widget
++ configPath = std::string(GetBindingDirPath(m_api)) + "/var/config/" + ALEXA_CONFIG_FILE_NAME;
++ }
++ }
++ return configPath;
+ }
+
+ void AASBConfigProviderImpl::logCurrentConfiguration() {
+diff --git a/src/plugins/aasb-client/config/AASBConfigProviderImpl.h b/src/plugins/aasb-client/config/AASBConfigProviderImpl.h
+index 6b79994..e32f7b7 100644
+--- a/src/plugins/aasb-client/config/AASBConfigProviderImpl.h
++++ b/src/plugins/aasb-client/config/AASBConfigProviderImpl.h
+@@ -87,6 +87,11 @@ private:
+ */
+ std::string getDataRootPath();
+
++ /**
++ * Provides the path where alexa json config resides.
++ */
++ std::string getAlexaConfigPath();
++
+ /**
+ * Logs the current configuration loaded by this object.
+ */
+@@ -139,4 +144,4 @@ private:
+ } // namespace alexa
+ } // namespace agl
+
+-#endif // AGL_ALEXA_SVC_AASB_CONFIG_PROVIDER_IMPL_H_
+\ No newline at end of file
++#endif // AGL_ALEXA_SVC_AASB_CONFIG_PROVIDER_IMPL_H_
diff --git a/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-service_git.bb b/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-service_git.bb
new file mode 100644
index 00000000..296cf2d2
--- /dev/null
+++ b/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-service_git.bb
@@ -0,0 +1,41 @@
+SUMMARY = "Alexa voice agent binding"
+DESCRIPTION = "alexa-voiceagent-service is an Alexa Auto SDK based voiceagent binding"
+HOMEPAGE = "https://gerrit.automotivelinux.org/gerrit/apps/agl-service-voice-high"
+SECTION = "apps"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://License.txt;md5=3b83ef96387f14655fc854ddc3c6bd57"
+
+DEPENDS = " \
+ libafb-helpers \
+ libappcontroller \
+ avs-device-sdk \
+ aac-module-core \
+ aac-module-alexa \
+ aac-module-cbl \
+ aac-module-contact-uploader \
+ aac-module-navigation \
+ aac-module-phone-control \
+ aac-module-gstreamer \
+"
+
+SRC_URI = "git://github.com/alexa/alexa-auto-sdk.git;protocol=https;branch=2.0 \
+ file://0001-remove-library-dependency-copying.patch \
+ file://0002-update-config.xml.in.patch \
+ file://0003-update-audio-device-configuration.patch \
+ file://0004-update-config-and-database-paths.patch \
+"
+SRCREV = "86916d2d8c1702a8be3c88a9012ca56583bcc0c8"
+
+PV = "2.0+git${SRCPV}"
+S = "${WORKDIR}/git/platforms/agl/alexa-voiceagent-service"
+
+inherit cmake aglwgt
+
+EXTRA_OECMAKE += "-DAAC_HOME=${RECIPE_SYSROOT}/${AAC_PREFIX}"
+
+# NOTE: curl and opus are from the base SDK libraries, sqlite3 from the
+# core module
+RDEPENDS_${PN} += "libcurl libopus libsqlite3"
+
+RPROVIDES_${PN} += "virtual/voiceagent"
diff --git a/meta-agl-devel/meta-speech-framework/meta-aac/recipes-modules/aac-module-gstreamer/aac-module-gstreamer.bbappend b/meta-agl-devel/meta-speech-framework/meta-aac/recipes-modules/aac-module-gstreamer/aac-module-gstreamer.bbappend
new file mode 100644
index 00000000..1b2618e8
--- /dev/null
+++ b/meta-agl-devel/meta-speech-framework/meta-aac/recipes-modules/aac-module-gstreamer/aac-module-gstreamer.bbappend
@@ -0,0 +1,9 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${BPN}:"
+
+# Needed for the required gstreamer-app-1.0 pkgconfig bits
+DEPENDS += "gstreamer1.0-plugins-base"
+
+AAC_PATCHES += "file://0001-gstreamer-implement-pipewire-integration.patch"
+
+# Pull static library into appropriate package to avoid a QA error
+FILES_${PN}-staticdev += "${AAC_PREFIX}/lib/libaal.a"
diff --git a/meta-agl-devel/meta-speech-framework/meta-aac/recipes-modules/aac-module-gstreamer/aac-module-gstreamer/0001-gstreamer-implement-pipewire-integration.patch b/meta-agl-devel/meta-speech-framework/meta-aac/recipes-modules/aac-module-gstreamer/aac-module-gstreamer/0001-gstreamer-implement-pipewire-integration.patch
new file mode 100644
index 00000000..b0a5c104
--- /dev/null
+++ b/meta-agl-devel/meta-speech-framework/meta-aac/recipes-modules/aac-module-gstreamer/aac-module-gstreamer/0001-gstreamer-implement-pipewire-integration.patch
@@ -0,0 +1,94 @@
+gstreamer: implement pipewire integration using pwaudiosrc/pwaudiosink
+
+The code path is wrapped in #ifdef USE_PIPEWIRE so that it can be toggled
+easily at compile time.
+
+The device string is abused to hold the role name, just like it was
+with 4A. In the future this may need to be reconsidered. In theory,
+we could detect the backend or make it configurable from the upper layer
+if we knew exactly what kind of data is in that device string
+(is it an ALSA device name? a pipewire role? a pipewire node id?
+a pulseaudio device name? ...)
+
+Upstream-Status: Pending
+
+Signed-off-by: George Kiagiadakis <george.kiagiadakis@collabora.com>
+[reworked for SDK 2.0]
+Signed-off-by: Scott Murray <scott.murray@konsulko.com>
+
+diff --git a/lib/aal/CMakeLists.txt b/lib/aal/CMakeLists.txt
+index a892465..c92b2cf 100644
+--- a/lib/aal/CMakeLists.txt
++++ b/lib/aal/CMakeLists.txt
+@@ -7,6 +7,7 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON)
+
+ add_definitions(-DUSE_GLOOP)
+ add_definitions(-DUSE_FAKEMUTE)
++add_definitions(-DUSE_PIPEWIRE)
+
+ # GStreamer
+ find_package(PkgConfig)
+diff --git a/lib/aal/src/player.c b/lib/aal/src/player.c
+index 02a2881..8747854 100644
+--- a/lib/aal/src/player.c
++++ b/lib/aal/src/player.c
+@@ -120,6 +120,19 @@ aal_handle_t aal_player_create(const aal_attributes_t *attr)
+ g_object_get(volume, "volume", &ctx->saved_volume, NULL);
+ #endif
+
++#ifdef USE_PIPEWIRE
++ sink = create_and_add_element(bin, "pwaudiosink", "sink");
++ if (sink && attr->device && !IS_EMPTY_STRING(attr->device)) {
++ g_info("Using role: %s\n", attr->device);
++ GstStructure *s = gst_structure_new("properties",
++ "media.role",
++ G_TYPE_STRING,
++ attr->device,
++ NULL);
++ g_object_set(G_OBJECT(sink), "stream-properties", s, NULL);
++ gst_structure_free(s);
++ }
++#else
+ if (!attr->device || IS_EMPTY_STRING(attr->device)) {
+ sink = create_and_add_element(bin, "autoaudiosink", "sink");
+ } else {
+@@ -128,6 +141,7 @@ aal_handle_t aal_player_create(const aal_attributes_t *attr)
+ if (sink)
+ g_object_set(G_OBJECT(sink), "device", attr->device, NULL);
+ }
++#endif
+ if (!sink)
+ goto exit;
+
+diff --git a/lib/aal/src/recorder.c b/lib/aal/src/recorder.c
+index 96c9b2a..66b36e1 100644
+--- a/lib/aal/src/recorder.c
++++ b/lib/aal/src/recorder.c
+@@ -86,6 +86,19 @@ aal_handle_t aal_recorder_create(const aal_attributes_t *attr)
+ if (!ctx)
+ goto exit;
+
++#ifdef USE_PIPEWIRE
++ source = create_and_add_element(ctx->pipeline, "pwaudiosrc", "source");
++ if (source && attr->device && !IS_EMPTY_STRING(attr->device)) {
++ g_info("Using role: %s\n", attr->device);
++ GstStructure *s = gst_structure_new("properties",
++ "media.role",
++ G_TYPE_STRING,
++ attr->device,
++ NULL);
++ g_object_set(G_OBJECT(source), "stream-properties", s, NULL);
++ gst_structure_free(s);
++ }
++#else
+ if (!attr->device || IS_EMPTY_STRING(attr->device)) {
+ source = create_and_add_element(ctx->pipeline, "autoaudiosrc", "source");
+ } else {
+@@ -94,6 +107,7 @@ aal_handle_t aal_recorder_create(const aal_attributes_t *attr)
+ if (source)
+ g_object_set(G_OBJECT(source), "device", attr->device, NULL);
+ }
++#endif
+ if (!source)
+ goto exit;
+
diff --git a/meta-agl-devel/meta-speech-framework/recipes-apis/agl-service-voice-high-capabilities/agl-service-voice-high-capabilities_git.bb b/meta-agl-devel/meta-speech-framework/recipes-apis/agl-service-voice-high-capabilities/agl-service-voice-high-capabilities_git.bb
new file mode 100644
index 00000000..efeba097
--- /dev/null
+++ b/meta-agl-devel/meta-speech-framework/recipes-apis/agl-service-voice-high-capabilities/agl-service-voice-high-capabilities_git.bb
@@ -0,0 +1,19 @@
+SUMMARY = "agl-service-voice-high"
+DESCRIPTION = "AGL High Level Voice service"
+HOMEPAGE = "https://git.automotivelinux.org/apps/agl-service-voice-high-capabilities"
+SECTION = "apps"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
+
+inherit cmake pkgconfig aglwgt
+
+DEPENDS += "lua lua-native"
+RDEPENDS_${PN} += "lua"
+
+SRC_URI = "gitsm://gerrit.automotivelinux.org/gerrit/apps/agl-service-voice-high-capabilities.git;protocol=https;branch=${AGL_BRANCH}"
+SRCREV = "${AGL_APP_REVISION}"
+
+PV = "0.1+git${SRCPV}"
+S = "${WORKDIR}/git"
+
diff --git a/meta-agl-devel/meta-speech-framework/recipes-apis/agl-service-voice-high/agl-service-voice-high_git.bb b/meta-agl-devel/meta-speech-framework/recipes-apis/agl-service-voice-high/agl-service-voice-high_git.bb
new file mode 100644
index 00000000..9b9fa928
--- /dev/null
+++ b/meta-agl-devel/meta-speech-framework/recipes-apis/agl-service-voice-high/agl-service-voice-high_git.bb
@@ -0,0 +1,17 @@
+SUMMARY = "High level voice service binding"
+DESCRIPTION = "agl-service-voice-high is the binding library"
+HOMEPAGE = "https://gerrit.automotivelinux.org/gerrit/apps/agl-service-voice-high"
+SECTION = "apps"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://License.txt;md5=3b83ef96387f14655fc854ddc3c6bd57"
+
+SRC_URI = "gitsm://gerrit.automotivelinux.org/gerrit/apps/agl-service-voice-high;protocol=https;branch=${AGL_BRANCH}"
+SRCREV = "${AGL_APP_REVISION}"
+
+PV = "1.0+git${SRCPV}"
+S = "${WORKDIR}/git"
+
+inherit cmake aglwgt
+
+DEPENDS += "json-c systemd af-binder glib-2.0 lua"
diff --git a/meta-agl-devel/meta-speech-framework/recipes-platform/packagegroups/packagegroup-agl-core-services.bbappend b/meta-agl-devel/meta-speech-framework/recipes-platform/packagegroups/packagegroup-agl-core-services.bbappend
new file mode 100644
index 00000000..42fc5e58
--- /dev/null
+++ b/meta-agl-devel/meta-speech-framework/recipes-platform/packagegroups/packagegroup-agl-core-services.bbappend
@@ -0,0 +1,7 @@
+# Checking PREFERRED_RPROVIDER_virtual/voiceagent below is less than ideal, but
+# seems required until there is a usable default voiceagent.
+RDEPENDS_${PN} += " \
+ agl-service-voice-high \
+ agl-service-voice-high-capabilities \
+ ${@oe.utils.conditional("PREFERRED_RPROVIDER_virtual/voiceagent", "", "", "virtual/voiceagent", d)} \
+"
diff --git a/meta-agl-devel/templates/feature/agl-audio-soundmanager-framework/50_bblayers.conf.inc b/meta-agl-devel/templates/feature/agl-audio-soundmanager-framework/50_bblayers.conf.inc
new file mode 100644
index 00000000..2ab00c61
--- /dev/null
+++ b/meta-agl-devel/templates/feature/agl-audio-soundmanager-framework/50_bblayers.conf.inc
@@ -0,0 +1,5 @@
+
+BBLAYERS =+ " \
+ ${METADIR}/meta-agl-devel/meta-audio-soundmanager-framework \
+ "
+
diff --git a/meta-agl-devel/templates/feature/agl-audio-soundmanager-framework/50_local.conf.inc b/meta-agl-devel/templates/feature/agl-audio-soundmanager-framework/50_local.conf.inc
new file mode 100644
index 00000000..70852b7d
--- /dev/null
+++ b/meta-agl-devel/templates/feature/agl-audio-soundmanager-framework/50_local.conf.inc
@@ -0,0 +1,6 @@
+DISTRO_FEATURES_append = " agl-audio-soundmanager-framework pulseaudio"
+IMAGE_INSTALL_append += "agl-service-audio-soundmanager pulseaudio-config-soundmanager audiomanager-plugins-config-soundmanager"
+
+PREFERRED_PROVIDER_virtual/audio-framework = "agl-service-audio-soundmanager"
+PREFERRED_RPROVIDER_virtual/pulseaudio-config = "pulseaudio-config-soundmanager"
+PREFERRED_RPROVIDER_virtual/audiomanager-plugins-config = "audiomanager-plugins-config-soundmanager"
diff --git a/meta-agl-devel/templates/feature/agl-audio-soundmanager-framework/README_feature_agl-audio-soundmanager-framework.md b/meta-agl-devel/templates/feature/agl-audio-soundmanager-framework/README_feature_agl-audio-soundmanager-framework.md
new file mode 100644
index 00000000..919c2a0a
--- /dev/null
+++ b/meta-agl-devel/templates/feature/agl-audio-soundmanager-framework/README_feature_agl-audio-soundmanager-framework.md
@@ -0,0 +1,9 @@
+---
+description: Feature agl-audio-soundmanager-framework
+authors: Jan-Simon Möller <jsmoeller@linuxfoundation.org>, Kazumasa Mitsunari <knimitz@witz-inc.co.jp>, Ronan Le Martret <ronan.lemartret@iot.bzh>, Stephane Desneux <stephane.desneux@iot.bzh>
+---
+
+### Feature agl-audio-soundmanager-framework
+
+*Description is missing - please complete file meta-agl-devel/templates/feature/agl-audio-soundmanager-framework/README_feature_agl-audio-soundmanager-framework.md*
+
diff --git a/meta-agl-devel/templates/feature/agl-gstrecorder/50_bblayers.conf.inc b/meta-agl-devel/templates/feature/agl-gstrecorder/50_bblayers.conf.inc
new file mode 100644
index 00000000..72160da4
--- /dev/null
+++ b/meta-agl-devel/templates/feature/agl-gstrecorder/50_bblayers.conf.inc
@@ -0,0 +1,5 @@
+
+BBLAYERS =+ " \
+ ${METADIR}/meta-agl-devel/meta-gstrecorder-rcar-gen3 \
+ "
+
diff --git a/meta-agl-devel/templates/feature/agl-gstrecorder/50_local.conf.inc b/meta-agl-devel/templates/feature/agl-gstrecorder/50_local.conf.inc
new file mode 100644
index 00000000..54fedd6c
--- /dev/null
+++ b/meta-agl-devel/templates/feature/agl-gstrecorder/50_local.conf.inc
@@ -0,0 +1,3 @@
+#see meta-agl-devel/meta-gstrecorder-rcar-gen3/conf/include/agl_gstrecorder.inc
+require conf/include/agl_gstrecorder.inc
+
diff --git a/meta-agl-devel/templates/feature/agl-gstrecorder/50_setupwarning.sh b/meta-agl-devel/templates/feature/agl-gstrecorder/50_setupwarning.sh
new file mode 100755
index 00000000..ae6b1312
--- /dev/null
+++ b/meta-agl-devel/templates/feature/agl-gstrecorder/50_setupwarning.sh
@@ -0,0 +1,14 @@
+#Note to the user!
+
+echo "##################################"
+echo "# ATTENTION: the network between #"
+echo "# sender and receiver of the #"
+echo "# gstrecorder feed needs to be #"
+echo "# configured or #"
+echo "# WESTON WILL FAIL TO START ! #"
+echo "# #"
+echo "# (hint: 192.168.20.x) #"
+echo "##################################"
+
+sleep 2
+
diff --git a/meta-agl-devel/templates/feature/agl-gstrecorder/README_feature_agl-gstrecorder.md b/meta-agl-devel/templates/feature/agl-gstrecorder/README_feature_agl-gstrecorder.md
new file mode 100644
index 00000000..39617bb9
--- /dev/null
+++ b/meta-agl-devel/templates/feature/agl-gstrecorder/README_feature_agl-gstrecorder.md
@@ -0,0 +1,9 @@
+---
+description: Feature agl-gstrecorder
+authors: Harunobu Kurokawa <harunobu.kurokawa.dn@renesas.com>, Jan-Simon Möller <jsmoeller@linuxfoundation.org>, Scott Murray <scott.murray@konsulko.com>, Stephane Desneux <stephane.desneux@iot.bzh>
+---
+
+### Feature agl-gstrecorder
+
+*Description is missing - please complete file meta-agl-devel/templates/feature/agl-gstrecorder/README_feature_agl-gstrecorder.md*
+
diff --git a/meta-agl-devel/templates/feature/agl-html5-framework/50_bblayers.conf.inc b/meta-agl-devel/templates/feature/agl-html5-framework/50_bblayers.conf.inc
new file mode 100644
index 00000000..952ef4ea
--- /dev/null
+++ b/meta-agl-devel/templates/feature/agl-html5-framework/50_bblayers.conf.inc
@@ -0,0 +1,5 @@
+
+BBLAYERS =+ " \
+ ${METADIR}/meta-agl-devel/meta-html5-framework \
+ "
+
diff --git a/meta-agl-devel/templates/feature/agl-html5-framework/README_feature_agl-html5-framework.md b/meta-agl-devel/templates/feature/agl-html5-framework/README_feature_agl-html5-framework.md
new file mode 100644
index 00000000..d992009c
--- /dev/null
+++ b/meta-agl-devel/templates/feature/agl-html5-framework/README_feature_agl-html5-framework.md
@@ -0,0 +1,9 @@
+---
+description: Feature agl-html5-framework
+authors: Jacobo Aragunde Pérez <jaragunde@igalia.com>
+---
+
+### Feature agl-html5-framework
+
+*Description is missing - please complete file meta-agl-devel/templates/feature/agl-html5-framework/README_feature_agl-html5-framework.md*
+
diff --git a/meta-agl-devel/templates/feature/agl-oem-extra-libs/50_bblayers.conf.inc b/meta-agl-devel/templates/feature/agl-oem-extra-libs/50_bblayers.conf.inc
new file mode 100644
index 00000000..2443ecd1
--- /dev/null
+++ b/meta-agl-devel/templates/feature/agl-oem-extra-libs/50_bblayers.conf.inc
@@ -0,0 +1,5 @@
+BBLAYERS =+ " \
+ ${METADIR}/meta-agl-devel/meta-oem-extra-libs \
+ ${METADIR}/external/meta-openembedded/meta-filesystems \
+ "
+
diff --git a/meta-agl-devel/templates/feature/agl-oem-extra-libs/README_feature_agl-oem-extra-libs.md b/meta-agl-devel/templates/feature/agl-oem-extra-libs/README_feature_agl-oem-extra-libs.md
new file mode 100644
index 00000000..8ff5850c
--- /dev/null
+++ b/meta-agl-devel/templates/feature/agl-oem-extra-libs/README_feature_agl-oem-extra-libs.md
@@ -0,0 +1,9 @@
+---
+description: Feature agl-oem-extra-libs
+authors: Jan-Simon Möller <jsmoeller@linuxfoundation.org>, Stephane Desneux <stephane.desneux@iot.bzh>, tte_zheng_wenlong <wenlong_zheng_za@mail.toyota.co.jp>
+---
+
+### Feature agl-oem-extra-libs
+
+*Description is missing - please complete file meta-agl-devel/templates/feature/agl-oem-extra-libs/README_feature_agl-oem-extra-libs.md*
+
diff --git a/meta-agl-devel/templates/feature/agl-pipewire/50_bblayers.conf.inc b/meta-agl-devel/templates/feature/agl-pipewire/50_bblayers.conf.inc
new file mode 100644
index 00000000..8a6baaa2
--- /dev/null
+++ b/meta-agl-devel/templates/feature/agl-pipewire/50_bblayers.conf.inc
@@ -0,0 +1,5 @@
+
+BBLAYERS =+ " \
+ ${METADIR}/meta-agl-devel/meta-pipewire \
+ "
+
diff --git a/meta-agl-devel/templates/feature/agl-pipewire/50_local.conf.inc b/meta-agl-devel/templates/feature/agl-pipewire/50_local.conf.inc
new file mode 100644
index 00000000..33838b08
--- /dev/null
+++ b/meta-agl-devel/templates/feature/agl-pipewire/50_local.conf.inc
@@ -0,0 +1,2 @@
+#see meta-agl-devel/meta-pipewire/conf/include/agl-pipewire.inc
+require conf/include/agl-pipewire.inc
diff --git a/meta-agl-devel/templates/feature/agl-pipewire/README_feature_agl-pipewire.md b/meta-agl-devel/templates/feature/agl-pipewire/README_feature_agl-pipewire.md
new file mode 100644
index 00000000..55e1931c
--- /dev/null
+++ b/meta-agl-devel/templates/feature/agl-pipewire/README_feature_agl-pipewire.md
@@ -0,0 +1,9 @@
+---
+description: Feature agl-pipewire
+authors: George Kiagiadakis <george.kiagiadakis@collabora.com>
+---
+
+### Feature agl-pipewire
+
+*Description is missing - please complete file meta-agl-devel/templates/feature/agl-pipewire/README_feature_agl-pipewire.md*
+
diff --git a/meta-agl-devel/templates/feature/agl-speech-framework/50_bblayers.conf.inc b/meta-agl-devel/templates/feature/agl-speech-framework/50_bblayers.conf.inc
new file mode 100644
index 00000000..60f88c97
--- /dev/null
+++ b/meta-agl-devel/templates/feature/agl-speech-framework/50_bblayers.conf.inc
@@ -0,0 +1,5 @@
+
+BBLAYERS =+ " \
+ ${METADIR}/meta-agl-devel/meta-speech-framework \
+ "
+
diff --git a/meta-agl-devel/templates/feature/agl-speech-framework/50_local.conf.inc b/meta-agl-devel/templates/feature/agl-speech-framework/50_local.conf.inc
new file mode 100644
index 00000000..c542f383
--- /dev/null
+++ b/meta-agl-devel/templates/feature/agl-speech-framework/50_local.conf.inc
@@ -0,0 +1,2 @@
+#see meta-agl-devel/meta-speech-framework/conf/include/agl-speech-framework.inc
+require conf/include/agl-speech-framework.inc
diff --git a/meta-agl-devel/templates/feature/agl-speech-framework/README_feature_agl-speech-framework.md b/meta-agl-devel/templates/feature/agl-speech-framework/README_feature_agl-speech-framework.md
new file mode 100644
index 00000000..ca6acdbc
--- /dev/null
+++ b/meta-agl-devel/templates/feature/agl-speech-framework/README_feature_agl-speech-framework.md
@@ -0,0 +1,9 @@
+---
+description: Feature agl-speech-framework
+authors: Shotaro Uchida <shotaru@amazon.com>
+---
+
+### Feature agl-speech-framework
+
+*Description is missing - please complete file meta-agl-devel/templates/feature/agl-speech-framework/README_feature_agl-speech-framework.md*
+
diff --git a/meta-agl-devel/templates/feature/agl-voiceagent-alexa/50_bblayers.conf.inc b/meta-agl-devel/templates/feature/agl-voiceagent-alexa/50_bblayers.conf.inc
new file mode 100644
index 00000000..2397a1d7
--- /dev/null
+++ b/meta-agl-devel/templates/feature/agl-voiceagent-alexa/50_bblayers.conf.inc
@@ -0,0 +1,10 @@
+BBLAYERS =+ " \
+ ${METADIR}/external/alexa-auto-sdk/builder/meta-aac \
+"
+
+# Per the SDK documentation, the module recipes need to be manually
+# added, as they sit outside of the layer.
+BBFILES += "${METADIR}/external/alexa-auto-sdk/modules/*/*.bb"
+
+# Include the recipe for the required gstreamer module as well
+BBFILES += "${METADIR}/external/alexa-auto-sdk/extensions/experimental/gstreamer/modules/*/*.bb"
diff --git a/meta-agl-devel/templates/feature/agl-voiceagent-alexa/50_local.conf.inc b/meta-agl-devel/templates/feature/agl-voiceagent-alexa/50_local.conf.inc
new file mode 100644
index 00000000..828b88d6
--- /dev/null
+++ b/meta-agl-devel/templates/feature/agl-voiceagent-alexa/50_local.conf.inc
@@ -0,0 +1,2 @@
+#see meta-agl-devel/meta-speech-framework/conf/include/agl-voiceagent-alexa.inc
+require conf/include/agl-voiceagent-alexa.inc
diff --git a/meta-agl-devel/templates/feature/agl-voiceagent-alexa/README_feature_agl-voiceagent-alexa.md b/meta-agl-devel/templates/feature/agl-voiceagent-alexa/README_feature_agl-voiceagent-alexa.md
new file mode 100644
index 00000000..584042fe
--- /dev/null
+++ b/meta-agl-devel/templates/feature/agl-voiceagent-alexa/README_feature_agl-voiceagent-alexa.md
@@ -0,0 +1,8 @@
+---
+description: Feature agl-voiceagent-alexa
+authors: Scott Murray <scott.murray@konsulko.com>
+---
+
+### Feature agl-voiceagent-alexa
+
+Enables building Amazon Alexa voice agent binding for the speech framework using the Alexa Automotive SDK.
diff --git a/meta-agl-devel/templates/feature/agl-voiceagent-alexa/included.dep b/meta-agl-devel/templates/feature/agl-voiceagent-alexa/included.dep
new file mode 100644
index 00000000..fde3c2de
--- /dev/null
+++ b/meta-agl-devel/templates/feature/agl-voiceagent-alexa/included.dep
@@ -0,0 +1 @@
+agl-speech-framework