From 4204309872da5cb401cbb2729d9e2d4869a87f42 Mon Sep 17 00:00:00 2001 From: takeshi_hoshina Date: Thu, 22 Oct 2020 14:58:56 +0900 Subject: agl-basesystem 0.1 --- meta-agl-devel/.gitreview | 2 +- .../conf/layer.conf | 12 + .../agl-service-windowmanager_git.bbappend | 9 + .../files/areas.horizontal.json | 94 ++ .../wayland/weston-ini-conf.bbappend | 12 + .../wayland/weston-ini-conf/hdmi-a-1-180.cfg | 4 + .../wayland/weston-ini-conf/virtual-landscape.cfg | 3 + .../images/agl-image-graphical-html5.bb | 10 + .../images/agl-image-graphical-html5.inc | 9 + .../packagegroups/packagegroup-agl-appfw-html5.bb | 18 + .../packagegroup-agl-profile-graphical-html5.bb | 23 + .../chromium/chromium-browser-service.bb | 19 + .../chromium/chromium68/v8-qemu-wrapper.patch | 40 + .../recipes-wam/chromium/chromium68_git.bb | 404 +++++ .../recipes-wam/chromium/gn-utils.inc | 157 ++ .../recipes-wam/wam/files/WebAppMgr.env | 202 +++ .../recipes-wam/wam/files/WebAppMgr@.service | 36 + .../recipes-wam/wam/files/trunc-webapp-roles.patch | 53 + .../recipes-wam/wam/wam_git.bb | 51 + .../meta-html5-framework/conf/layer.conf | 12 - .../images/agl-demo-platform-crosssdk.bbappend | 3 - .../images/agl-demo-platform.bbappend | 3 - .../packagegroup-agl-demo-platform-html5.bb | 26 - .../chromium/chromium-browser-service.bb | 19 - .../chromium/chromium68/v8-qemu-wrapper.patch | 40 - .../recipes-wam/chromium/chromium68_git.bb | 404 ----- .../recipes-wam/chromium/gn-utils.inc | 157 -- .../recipes-wam/wam/files/WebAppMgr.env | 202 --- .../recipes-wam/wam/files/WebAppMgr@.service | 36 - .../recipes-wam/wam/wam-tinyproxy_git.bb | 20 - .../recipes-wam/wam/wam_git.bb | 51 - ...-gstreamer-helper-application-for-interco.patch | 75 +- .../agl-service-audiomixer_git.bb | 3 +- .../pipewire/pipewire-conf-agl/pipewire.conf | 10 - .../pipewire/pipewire-conf-agl/pipewire.conf.in | 17 + .../pipewire/pipewire-conf-agl_git.bb | 9 +- .../recipes-multimedia/pipewire/pipewire.inc | 7 +- ...t-version-check-to-require-meson-0.47-not.patch | 30 + .../0001-spa-include-install-missing-headers.patch | 41 - .../0002-arm-build-with-mno-unaligned-access.patch | 30 + ...implement-Endpoint-ClientEndpoint-interfa.patch | 1563 -------------------- ...nt-new-pwaudio-src-sink-elements-based-on.patch | 1280 ++++++++++++++++ ...i-add-support-for-printing-endpoint-info-.patch | 149 -- ...t-always-assume-that-output-ports-are-NOT.patch | 35 + ...i-add-command-to-modify-endpoint-control-.patch | 124 -- .../0005-arm-build-with-mno-unaligned-access.patch | 30 - ...005-module-access-add-same-sec-label-mode.patch | 94 ++ ...ll-reuse_buffers-when-resetting-the-state.patch | 30 + ...ogger-print-timestamps-on-logged-messages.patch | 52 - ...orrections-on-the-timeout-based-on-how-fa.patch | 130 -- ...-dsp-allow-mode-to-be-set-with-a-property.patch | 45 - ...t-do-setup-internal-links-and-buffers-als.patch | 55 - ...nt-new-pwaudio-src-sink-elements-based-on.patch | 1249 ---------------- ...ringbuffer-make-the-buffer-size-sensitive.patch | 60 - ...ringbuffer-request-pause-play-on-the-appr.patch | 76 - ...ringbuffer-wait-only-for-STREAM_STATE_CON.patch | 35 - ...sink-set-the-default-latency-time-buffer-.patch | 37 - ...t-fmtconvert-assume-F32-on-the-other-port.patch | 44 - ...ringbuffer-set-node.latency-to-get-schedu.patch | 41 - ...17-connection-move-remaining-data-and-fds.patch | 61 - .../pipewire/0018-protocol-improve-flushing.patch | 222 --- .../recipes-multimedia/pipewire/pipewire_git.bb | 30 +- .../00-audio-sink.endpoint | 10 + .../00-audio-source.endpoint | 10 + .../00-default-input-audio.endpoint-link | 7 + .../00-default-output-audio.endpoint-link | 7 + .../00-stream-input-audio.endpoint | 9 + .../00-stream-output-audio.endpoint | 9 + .../01-hw00-audio-sink.endpoint | 12 + .../01-hw00-audio-source.endpoint | 12 + .../30-ak4613-audio-sink.endpoint | 12 + .../30-ak4613-audio-source.endpoint | 12 + .../30-dra7xx-audio-sink.endpoint | 12 + .../30-dra7xx-audio-source.endpoint | 12 + .../30-rpi3-audio-sink.endpoint | 13 + .../40-fiberdyne-amp.endpoint | 12 + .../40-microchip-mic.endpoint | 12 + .../70-usb-audio-sink.endpoint | 12 + .../70-usb-audio-source.endpoint | 12 + .../bluealsa-input-audio.endpoint-link | 11 + .../bluealsa-output-audio.endpoint-link | 11 + .../wireplumber-board-config-agl/capture.streams | 3 + .../wireplumber-board-config-agl/playback.streams | 31 + .../wireplumber-board-config-agl/wireplumber.conf | 30 + .../wireplumber.conf.in | 55 - .../wireplumber-board-config-agl_git.bb | 68 +- ...-Build-cpptoml-without-a-cmake-subproject.patch | 28 + .../wireplumber/wireplumber_git.bb | 20 +- .../recipes-security/cynagora/cynagora_%.bbappend | 5 + ...ck-rules-to-allow-connections-to-pipewire.patch | 25 - .../security-manager/security-manager_%.bbappend | 6 +- .../conf/include/agl-speech-framework.inc | 3 +- .../conf/include/agl-voiceagent-alexa.inc | 6 +- .../pryon-lite/pryon-lite.bbappend | 2 + .../alexa-voice-high-config/voice-high.json | 1 + .../alexa-voice-high-config_1.0.bb | 20 + .../AlexaAutoCoreEngineConfig.json.in | 184 +++ .../alexa-voiceagent-config_1.0.bb | 40 + .../0001-remove-library-dependency-copying.patch | 15 +- ...segmentation-fault-for-release-build-mode.patch | 33 + .../0006-fix-event-argument-json.patch | 183 +++ .../alexa-voiceagent-service/alexa.json | 14 + .../alexa-voiceagent-service_git.bb | 25 +- .../packagegroup-agl-ivi-services.bbappend | 4 + .../packagegroup-agl-voiceagent-alexa.bb | 15 + .../agl-service-voice-high-capabilities_git.bb | 8 +- .../agl-service-voice-high_git.bb | 5 +- .../default-voice-high-config/voice-high.json | 1 + .../default-voice-high-config_1.0.bb | 20 + .../packagegroup-agl-core-services.bbappend | 7 - .../packagegroup-agl-ivi-services.bbappend | 5 + .../agl-html5-framework/50_bblayers.conf.inc | 5 - .../README_feature_agl-html5-framework.md | 9 - .../50_bblayers.conf.inc | 5 + .../agl-profile-graphical-html5/50_local.conf.inc | 3 + .../README_feature_agl-profile-graphical-html5.md | 8 + .../agl-profile-graphical-html5/included.dep | 1 + .../50_bblayers.conf.inc | 6 + .../50_local.conf.inc | 1 + ...README_feature_agl-voiceagent-alexa-wakeword.md | 10 + .../agl-voiceagent-alexa-wakeword/included.dep | 1 + 121 files changed, 3712 insertions(+), 5201 deletions(-) create mode 100644 meta-agl-devel/meta-agl-profile-graphical-html5/conf/layer.conf create mode 100644 meta-agl-devel/meta-agl-profile-graphical-html5/recipes-apis/agl-service-windowmanager/agl-service-windowmanager_git.bbappend create mode 100644 meta-agl-devel/meta-agl-profile-graphical-html5/recipes-apis/agl-service-windowmanager/files/areas.horizontal.json create mode 100644 meta-agl-devel/meta-agl-profile-graphical-html5/recipes-graphics/wayland/weston-ini-conf.bbappend create mode 100644 meta-agl-devel/meta-agl-profile-graphical-html5/recipes-graphics/wayland/weston-ini-conf/hdmi-a-1-180.cfg create mode 100644 meta-agl-devel/meta-agl-profile-graphical-html5/recipes-graphics/wayland/weston-ini-conf/virtual-landscape.cfg create mode 100644 meta-agl-devel/meta-agl-profile-graphical-html5/recipes-platform/images/agl-image-graphical-html5.bb create mode 100644 meta-agl-devel/meta-agl-profile-graphical-html5/recipes-platform/images/agl-image-graphical-html5.inc create mode 100644 meta-agl-devel/meta-agl-profile-graphical-html5/recipes-platform/packagegroups/packagegroup-agl-appfw-html5.bb create mode 100644 meta-agl-devel/meta-agl-profile-graphical-html5/recipes-platform/packagegroups/packagegroup-agl-profile-graphical-html5.bb create mode 100644 meta-agl-devel/meta-agl-profile-graphical-html5/recipes-wam/chromium/chromium-browser-service.bb create mode 100644 meta-agl-devel/meta-agl-profile-graphical-html5/recipes-wam/chromium/chromium68/v8-qemu-wrapper.patch create mode 100644 meta-agl-devel/meta-agl-profile-graphical-html5/recipes-wam/chromium/chromium68_git.bb create mode 100644 meta-agl-devel/meta-agl-profile-graphical-html5/recipes-wam/chromium/gn-utils.inc create mode 100644 meta-agl-devel/meta-agl-profile-graphical-html5/recipes-wam/wam/files/WebAppMgr.env create mode 100644 meta-agl-devel/meta-agl-profile-graphical-html5/recipes-wam/wam/files/WebAppMgr@.service create mode 100644 meta-agl-devel/meta-agl-profile-graphical-html5/recipes-wam/wam/files/trunc-webapp-roles.patch create mode 100644 meta-agl-devel/meta-agl-profile-graphical-html5/recipes-wam/wam/wam_git.bb delete mode 100644 meta-agl-devel/meta-html5-framework/conf/layer.conf delete mode 100644 meta-agl-devel/meta-html5-framework/recipes-platform/images/agl-demo-platform-crosssdk.bbappend delete mode 100644 meta-agl-devel/meta-html5-framework/recipes-platform/images/agl-demo-platform.bbappend delete mode 100644 meta-agl-devel/meta-html5-framework/recipes-platform/packagegroups/packagegroup-agl-demo-platform-html5.bb delete mode 100644 meta-agl-devel/meta-html5-framework/recipes-wam/chromium/chromium-browser-service.bb delete mode 100644 meta-agl-devel/meta-html5-framework/recipes-wam/chromium/chromium68/v8-qemu-wrapper.patch delete mode 100644 meta-agl-devel/meta-html5-framework/recipes-wam/chromium/chromium68_git.bb delete mode 100644 meta-agl-devel/meta-html5-framework/recipes-wam/chromium/gn-utils.inc delete mode 100644 meta-agl-devel/meta-html5-framework/recipes-wam/wam/files/WebAppMgr.env delete mode 100644 meta-agl-devel/meta-html5-framework/recipes-wam/wam/files/WebAppMgr@.service delete mode 100644 meta-agl-devel/meta-html5-framework/recipes-wam/wam/wam-tinyproxy_git.bb delete mode 100644 meta-agl-devel/meta-html5-framework/recipes-wam/wam/wam_git.bb delete mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire-conf-agl/pipewire.conf create mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire-conf-agl/pipewire.conf.in create mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0001-meson-revert-version-check-to-require-meson-0.47-not.patch delete mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0001-spa-include-install-missing-headers.patch create mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0002-arm-build-with-mno-unaligned-access.patch delete mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0002-extensions-implement-Endpoint-ClientEndpoint-interfa.patch create mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0003-gst-Implement-new-pwaudio-src-sink-elements-based-on.patch delete mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0003-pipewire-cli-add-support-for-printing-endpoint-info-.patch create mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0004-audioconvert-always-assume-that-output-ports-are-NOT.patch delete mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0004-pipewire-cli-add-command-to-modify-endpoint-control-.patch delete mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0005-arm-build-with-mno-unaligned-access.patch create mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0005-module-access-add-same-sec-label-mode.patch create mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0006-alsa-pcm-call-reuse_buffers-when-resetting-the-state.patch delete mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0006-logger-print-timestamps-on-logged-messages.patch delete mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0007-alsa-make-corrections-on-the-timeout-based-on-how-fa.patch delete mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0008-audio-dsp-allow-mode-to-be-set-with-a-property.patch delete mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0009-audioconvert-do-setup-internal-links-and-buffers-als.patch delete mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0010-gst-Implement-new-pwaudio-src-sink-elements-based-on.patch delete mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0011-gst-pwaudioringbuffer-make-the-buffer-size-sensitive.patch delete mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0012-gst-pwaudioringbuffer-request-pause-play-on-the-appr.patch delete mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0013-gst-pwaudioringbuffer-wait-only-for-STREAM_STATE_CON.patch delete mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0014-gst-pwaudiosink-set-the-default-latency-time-buffer-.patch delete mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0015-audioconvert-fmtconvert-assume-F32-on-the-other-port.patch delete mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0016-gst-pwaudioringbuffer-set-node.latency-to-get-schedu.patch delete mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0017-connection-move-remaining-data-and-fds.patch delete mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0018-protocol-improve-flushing.patch create mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/00-audio-sink.endpoint create mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/00-audio-source.endpoint create mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/00-default-input-audio.endpoint-link create mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/00-default-output-audio.endpoint-link create mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/00-stream-input-audio.endpoint create mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/00-stream-output-audio.endpoint create mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/01-hw00-audio-sink.endpoint create mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/01-hw00-audio-source.endpoint create mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/30-ak4613-audio-sink.endpoint create mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/30-ak4613-audio-source.endpoint create mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/30-dra7xx-audio-sink.endpoint create mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/30-dra7xx-audio-source.endpoint create mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/30-rpi3-audio-sink.endpoint create mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/40-fiberdyne-amp.endpoint create mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/40-microchip-mic.endpoint create mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/70-usb-audio-sink.endpoint create mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/70-usb-audio-source.endpoint create mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/bluealsa-input-audio.endpoint-link create mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/bluealsa-output-audio.endpoint-link create mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/capture.streams create mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/playback.streams create mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/wireplumber.conf delete mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/wireplumber.conf.in create mode 100644 meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber/0001-Build-cpptoml-without-a-cmake-subproject.patch create mode 100644 meta-agl-devel/meta-pipewire/recipes-security/cynagora/cynagora_%.bbappend delete mode 100644 meta-agl-devel/meta-pipewire/recipes-security/security-manager/security-manager/0001-Adapt-smack-rules-to-allow-connections-to-pipewire.patch create mode 100644 meta-agl-devel/meta-speech-framework/meta-aac-amazonlite/recipes-wakeword/pryon-lite/pryon-lite.bbappend create mode 100644 meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voice-high-config/voice-high.json create mode 100644 meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voice-high-config_1.0.bb create mode 100644 meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-config/AlexaAutoCoreEngineConfig.json.in create mode 100644 meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-config_1.0.bb create mode 100644 meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-service/0005-fix-segmentation-fault-for-release-build-mode.patch create mode 100644 meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-service/0006-fix-event-argument-json.patch create mode 100644 meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-service/alexa.json create mode 100644 meta-agl-devel/meta-speech-framework/meta-aac/recipes-platform/packagegroups/packagegroup-agl-ivi-services.bbappend create mode 100644 meta-agl-devel/meta-speech-framework/meta-aac/recipes-platform/packagegroups/packagegroup-agl-voiceagent-alexa.bb create mode 100644 meta-agl-devel/meta-speech-framework/recipes-apis/agl-service-voice-high/default-voice-high-config/voice-high.json create mode 100644 meta-agl-devel/meta-speech-framework/recipes-apis/agl-service-voice-high/default-voice-high-config_1.0.bb delete mode 100644 meta-agl-devel/meta-speech-framework/recipes-platform/packagegroups/packagegroup-agl-core-services.bbappend create mode 100644 meta-agl-devel/meta-speech-framework/recipes-platform/packagegroups/packagegroup-agl-ivi-services.bbappend delete mode 100644 meta-agl-devel/templates/feature/agl-html5-framework/50_bblayers.conf.inc delete mode 100644 meta-agl-devel/templates/feature/agl-html5-framework/README_feature_agl-html5-framework.md create mode 100644 meta-agl-devel/templates/feature/agl-profile-graphical-html5/50_bblayers.conf.inc create mode 100644 meta-agl-devel/templates/feature/agl-profile-graphical-html5/50_local.conf.inc create mode 100644 meta-agl-devel/templates/feature/agl-profile-graphical-html5/README_feature_agl-profile-graphical-html5.md create mode 100644 meta-agl-devel/templates/feature/agl-profile-graphical-html5/included.dep create mode 100644 meta-agl-devel/templates/feature/agl-voiceagent-alexa-wakeword/50_bblayers.conf.inc create mode 100644 meta-agl-devel/templates/feature/agl-voiceagent-alexa-wakeword/50_local.conf.inc create mode 100644 meta-agl-devel/templates/feature/agl-voiceagent-alexa-wakeword/README_feature_agl-voiceagent-alexa-wakeword.md create mode 100644 meta-agl-devel/templates/feature/agl-voiceagent-alexa-wakeword/included.dep (limited to 'meta-agl-devel') diff --git a/meta-agl-devel/.gitreview b/meta-agl-devel/.gitreview index e2b97232..d4a1744e 100644 --- a/meta-agl-devel/.gitreview +++ b/meta-agl-devel/.gitreview @@ -2,4 +2,4 @@ host=gerrit.automotivelinux.org port=29418 project=AGL/meta-agl-devel -defaultbranch=halibut +defaultbranch=icefish diff --git a/meta-agl-devel/meta-agl-profile-graphical-html5/conf/layer.conf b/meta-agl-devel/meta-agl-profile-graphical-html5/conf/layer.conf new file mode 100644 index 00000000..6673b564 --- /dev/null +++ b/meta-agl-devel/meta-agl-profile-graphical-html5/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-agl-profile-graphical-html5/recipes-apis/agl-service-windowmanager/agl-service-windowmanager_git.bbappend b/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-apis/agl-service-windowmanager/agl-service-windowmanager_git.bbappend new file mode 100644 index 00000000..06f89f69 --- /dev/null +++ b/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-apis/agl-service-windowmanager/agl-service-windowmanager_git.bbappend @@ -0,0 +1,9 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +SRC_URI += " \ + file://areas.horizontal.json \ +" + +do_compile_prepend() { + cp ${WORKDIR}/areas.horizontal.json ${S}/conf/areas.json +} diff --git a/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-apis/agl-service-windowmanager/files/areas.horizontal.json b/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-apis/agl-service-windowmanager/files/areas.horizontal.json new file mode 100644 index 00000000..4b6f0c39 --- /dev/null +++ b/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-apis/agl-service-windowmanager/files/areas.horizontal.json @@ -0,0 +1,94 @@ +{ + "areas": [ + { + "name": "fullscreen", + "rect": { + "x": 0, + "y": 0, + "w": 1920, + "h": 1080 + } + }, + { + "name": "normal.full", + "rect": { + "x": 218, + "y": 0, + "w": 1702, + "h": 1080 + } + }, + { + "name": "split.main", + "rect": { + "x": 218, + "y": 0, + "w": 744, + "h": 1080 + } + }, + { + "name": "split.sub", + "rect": { + "x": 962, + "y": 0, + "w": 744, + "h": 1080 + } + }, + { + "name": "software_keyboard", + "rect": { + "x": 962, + "y": 0, + "w": 744, + "h": 1080 + } + }, + { + "name": "restriction.normal", + "rect": { + "x": 218, + "y": 0, + "w": 1488, + "h": 1080 + } + }, + { + "name": "restriction.split.main", + "rect": { + "x": 218, + "y": 0, + "w": 744, + "h": 1080 + } + }, + { + "name": "restriction.split.sub", + "rect": { + "x": 962, + "y": 0, + "w": 744, + "h": 1080 + } + }, + { + "name": "on_screen", + "rect": { + "x": 218, + "y": 0, + "w": 1488, + "h": 1080 + } + }, + { + "name": "remote.fullscreen", + "rect": { + "x": 0, + "y": 0, + "w": 720, + "h": 640 + } + } + ] +} diff --git a/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-graphics/wayland/weston-ini-conf.bbappend b/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-graphics/wayland/weston-ini-conf.bbappend new file mode 100644 index 00000000..2c5201aa --- /dev/null +++ b/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-graphics/wayland/weston-ini-conf.bbappend @@ -0,0 +1,12 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" + +SRC_URI_remove = " \ + file://hdmi-a-1-270.cfg \ + file://hdmi-a-1-90.cfg \ + file://virtual.cfg \ +" + +SRC_URI += " \ + file://hdmi-a-1-180.cfg \ + file://virtual-landscape.cfg \ +" diff --git a/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-graphics/wayland/weston-ini-conf/hdmi-a-1-180.cfg b/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-graphics/wayland/weston-ini-conf/hdmi-a-1-180.cfg new file mode 100644 index 00000000..59e2c2db --- /dev/null +++ b/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-graphics/wayland/weston-ini-conf/hdmi-a-1-180.cfg @@ -0,0 +1,4 @@ +# A display is connected to HDMI-A-1 +[output] +name=HDMI-A-1 +transform=0 diff --git a/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-graphics/wayland/weston-ini-conf/virtual-landscape.cfg b/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-graphics/wayland/weston-ini-conf/virtual-landscape.cfg new file mode 100644 index 00000000..d6925363 --- /dev/null +++ b/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-graphics/wayland/weston-ini-conf/virtual-landscape.cfg @@ -0,0 +1,3 @@ +[output] +name=Virtual-1 +mode=1920x1080 diff --git a/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-platform/images/agl-image-graphical-html5.bb b/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-platform/images/agl-image-graphical-html5.bb new file mode 100644 index 00000000..0ec6829e --- /dev/null +++ b/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-platform/images/agl-image-graphical-html5.bb @@ -0,0 +1,10 @@ +SUMMARY = "An image containing all packages required to run web applications" + +require agl-image-graphical-html5.inc + +LICENSE = "MIT" + +IMAGE_INSTALL_append = "\ + packagegroup-agl-profile-graphical-html5 \ + " + diff --git a/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-platform/images/agl-image-graphical-html5.inc b/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-platform/images/agl-image-graphical-html5.inc new file mode 100644 index 00000000..21f3b19a --- /dev/null +++ b/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-platform/images/agl-image-graphical-html5.inc @@ -0,0 +1,9 @@ +require recipes-platform/images/agl-image-minimal.inc + +IMAGE_FEATURES += "splash" + +IMAGE_FEATURES += "${@bb.utils.contains('DISTRO_FEATURES', 'agl-devel', 'ssh-server-dropbear' , '', d)}" + +inherit distro_features_check + +REQUIRED_DISTRO_FEATURES = "wayland" diff --git a/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-platform/packagegroups/packagegroup-agl-appfw-html5.bb b/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-platform/packagegroups/packagegroup-agl-appfw-html5.bb new file mode 100644 index 00000000..cc9ed3d6 --- /dev/null +++ b/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-platform/packagegroups/packagegroup-agl-appfw-html5.bb @@ -0,0 +1,18 @@ +SUMMARY = "AGL web runtime packages" +DESCRIPTION = "Specific packages for the AGL web runtime (minus profile-graphical)" + +LICENSE = "MIT" + +inherit packagegroup + +PACKAGES = "\ + packagegroup-agl-appfw-html5 \ + " + +ALLOW_EMPTY_${PN} = "1" + +# add packages for WAM +RDEPENDS_${PN} += " \ + chromium-browser-service \ + wam \ + " diff --git a/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-platform/packagegroups/packagegroup-agl-profile-graphical-html5.bb b/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-platform/packagegroups/packagegroup-agl-profile-graphical-html5.bb new file mode 100644 index 00000000..20275014 --- /dev/null +++ b/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-platform/packagegroups/packagegroup-agl-profile-graphical-html5.bb @@ -0,0 +1,23 @@ +SUMMARY = "AGL web runtime profile" +DESCRIPTION = "The full set of packages required for AGL web runtime" +LICENSE = "MIT" + +inherit packagegroup + +PACKAGES = "\ + packagegroup-agl-profile-graphical-html5 \ + profile-graphical-html5 \ + " + +ALLOW_EMPTY_${PN} = "1" + +RDEPENDS_${PN} += "\ + packagegroup-agl-profile-graphical \ + packagegroup-agl-appfw-html5 \ +" + +RDEPENDS_${PN} += "\ + agl-login-manager \ + " + +RDEPENDS_profile-graphical-html5 = "${PN}" diff --git a/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-wam/chromium/chromium-browser-service.bb b/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-wam/chromium/chromium-browser-service.bb new file mode 100644 index 00000000..2686c7c8 --- /dev/null +++ b/meta-agl-devel/meta-agl-profile-graphical-html5/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-agl-profile-graphical-html5/recipes-wam/chromium/chromium68/v8-qemu-wrapper.patch b/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-wam/chromium/chromium68/v8-qemu-wrapper.patch new file mode 100644 index 00000000..485766b0 --- /dev/null +++ b/meta-agl-devel/meta-agl-profile-graphical-html5/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 +Signed-off-by: Maksim Sisov + +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-agl-profile-graphical-html5/recipes-wam/chromium/chromium68_git.bb b/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-wam/chromium/chromium68_git.bb new file mode 100644 index 00000000..100eb628 --- /dev/null +++ b/meta-agl-devel/meta-agl-profile-graphical-html5/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 " +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};name=chromium68 \ + git://github.com/webosose/v8;destsuffix=git/src/v8;rev=${SRCREV_v8};name=v8 \ + file://v8-qemu-wrapper.patch \ +" +SRCREV_chromium68 = "5ebefe83ead91ce6fd2ac8ff9699b848a83ee0ff" +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-agl-profile-graphical-html5/recipes-wam/chromium/gn-utils.inc b/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-wam/chromium/gn-utils.inc new file mode 100644 index 00000000..0fd55a63 --- /dev/null +++ b/meta-agl-devel/meta-agl-profile-graphical-html5/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-agl-profile-graphical-html5/recipes-wam/wam/files/WebAppMgr.env b/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-wam/wam/files/WebAppMgr.env new file mode 100644 index 00000000..c8ddc517 --- /dev/null +++ b/meta-agl-devel/meta-agl-profile-graphical-html5/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-agl-profile-graphical-html5/recipes-wam/wam/files/WebAppMgr@.service b/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-wam/wam/files/WebAppMgr@.service new file mode 100644 index 00000000..09573a76 --- /dev/null +++ b/meta-agl-devel/meta-agl-profile-graphical-html5/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-agl-profile-graphical-html5/recipes-wam/wam/files/trunc-webapp-roles.patch b/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-wam/wam/files/trunc-webapp-roles.patch new file mode 100644 index 00000000..63ad8208 --- /dev/null +++ b/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-wam/wam/files/trunc-webapp-roles.patch @@ -0,0 +1,53 @@ +From 870dd9c0e80d2f7ce843399f606299629ae7b570 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jacobo=20Aragunde=20P=C3=A9rez?= +Date: Thu, 23 Jan 2020 11:57:23 +0100 +Subject: [PATCH] Set webapp roles that are max 12 characters long. + +This is a workaround for SPEC-3127. To prevent repeated roles as much +as possible, I'm using the appid as a basis instead of "Webapp-" + +host + port, which has many chances to be redundant in the first 12 +chars. + +Bug-AGL: SPEC-3127 +--- + src/agl/WebRuntimeAGL.cpp | 10 +++------- + 1 file changed, 3 insertions(+), 7 deletions(-) + +diff --git a/src/agl/WebRuntimeAGL.cpp b/src/agl/WebRuntimeAGL.cpp +index a919759..baa2708 100644 +--- a/src/agl/WebRuntimeAGL.cpp ++++ b/src/agl/WebRuntimeAGL.cpp +@@ -162,7 +162,6 @@ int WebAppLauncherRuntime::run(int argc, const char** argv) { + bool isWaitHostService = isWaitForHostService(args); + m_id = getAppId(args); + m_url = getAppUrl(args); +- m_role = "WebApp"; + + if(isWaitHostService) { + while(!WebAppManagerServiceAGL::instance()->isHostServiceRunning()) { +@@ -220,15 +219,9 @@ bool WebAppLauncherRuntime::init() { + if (n != std::string::npos) { + std::string sport = authority.substr(n+1); + m_host = authority.substr(0, n); +- m_role.push_back('-'); +- m_role.append(m_host); +- m_role.push_back('-'); +- m_role.append(sport); + m_port = stringTo(sport); + } else { + m_host = authority; +- m_role.push_back('-'); +- m_role.append(m_host); + } + } + +@@ -265,6 +258,9 @@ bool WebAppLauncherRuntime::init() { + m_role = "homescreen"; + else if (m_id.rfind("webapps-homescreen", 0) == 0) + m_role = "homescreen"; ++ else { ++ m_role = m_id.substr(0,12); ++ } + + LOG_DEBUG("id=[%s], name=[%s], role=[%s], url=[%s], host=[%s], port=%d, token=[%s]", + m_id.c_str(), m_name.c_str(), m_role.c_str(), m_url.c_str(), diff --git a/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-wam/wam/wam_git.bb b/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-wam/wam/wam_git.bb new file mode 100644 index 00000000..2ccd6e63 --- /dev/null +++ b/meta-agl-devel/meta-agl-profile-graphical-html5/recipes-wam/wam/wam_git.bb @@ -0,0 +1,51 @@ +SUMMARY = "WAM" +AUTHOR = "Jani Hautakangas " +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.icefish;protocol=https \ + file://WebAppMgr@.service \ + file://WebAppMgr.env \ + file://trunc-webapp-roles.patch \ +" +S = "${WORKDIR}/git" +SRCREV = "060043b40ffc9fafcf94eec832c2158e81c74f32" + +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/ +} + +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 +} diff --git a/meta-agl-devel/meta-html5-framework/conf/layer.conf b/meta-agl-devel/meta-html5-framework/conf/layer.conf deleted file mode 100644 index 6673b564..00000000 --- a/meta-agl-devel/meta-html5-framework/conf/layer.conf +++ /dev/null @@ -1,12 +0,0 @@ -# We have a conf and classes directory, add to BBPATH -BBPATH .= ":${LAYERDIR}" - -# We have recipes-* directories, add to BBFILES -BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \ - ${LAYERDIR}/recipes-*/*/*.bbappend" - -BBFILE_COLLECTIONS += "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 deleted file mode 100644 index d5d978dd..00000000 --- a/meta-agl-devel/meta-html5-framework/recipes-platform/images/agl-demo-platform-crosssdk.bbappend +++ /dev/null @@ -1,3 +0,0 @@ -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 deleted file mode 100644 index d5d978dd..00000000 --- a/meta-agl-devel/meta-html5-framework/recipes-platform/images/agl-demo-platform.bbappend +++ /dev/null @@ -1,3 +0,0 @@ -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 deleted file mode 100644 index c4e3c0d7..00000000 --- a/meta-agl-devel/meta-html5-framework/recipes-platform/packagegroups/packagegroup-agl-demo-platform-html5.bb +++ /dev/null @@ -1,26 +0,0 @@ -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 deleted file mode 100644 index 2686c7c8..00000000 --- a/meta-agl-devel/meta-html5-framework/recipes-wam/chromium/chromium-browser-service.bb +++ /dev/null @@ -1,19 +0,0 @@ -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 deleted file mode 100644 index 485766b0..00000000 --- a/meta-agl-devel/meta-html5-framework/recipes-wam/chromium/chromium68/v8-qemu-wrapper.patch +++ /dev/null @@ -1,40 +0,0 @@ -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 -Signed-off-by: Maksim Sisov - -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 deleted file mode 100644 index e23e53ee..00000000 --- a/meta-agl-devel/meta-html5-framework/recipes-wam/chromium/chromium68_git.bb +++ /dev/null @@ -1,404 +0,0 @@ -# Copyright (c) 2018 LG Electronics, Inc. - -SUMMARY = "Chromium webruntime for webOS" -AUTHOR = "Lokesh Kumar Goel " -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 deleted file mode 100644 index 0fd55a63..00000000 --- a/meta-agl-devel/meta-html5-framework/recipes-wam/chromium/gn-utils.inc +++ /dev/null @@ -1,157 +0,0 @@ -# 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 deleted file mode 100644 index c8ddc517..00000000 --- a/meta-agl-devel/meta-html5-framework/recipes-wam/wam/files/WebAppMgr.env +++ /dev/null @@ -1,202 +0,0 @@ -##### 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 deleted file mode 100644 index 09573a76..00000000 --- a/meta-agl-devel/meta-html5-framework/recipes-wam/wam/files/WebAppMgr@.service +++ /dev/null @@ -1,36 +0,0 @@ -# @@@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 deleted file mode 100644 index 25a6ed2d..00000000 --- a/meta-agl-devel/meta-html5-framework/recipes-wam/wam/wam-tinyproxy_git.bb +++ /dev/null @@ -1,20 +0,0 @@ -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 deleted file mode 100644 index 16737cab..00000000 --- a/meta-agl-devel/meta-html5-framework/recipes-wam/wam/wam_git.bb +++ /dev/null @@ -1,51 +0,0 @@ -SUMMARY = "WAM" -AUTHOR = "Jani Hautakangas " -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-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 index 37c03218..6c9a388c 100644 --- 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 @@ -1,4 +1,4 @@ -From 33555a493af67f3acc2129764a1b093aec6254d8 Mon Sep 17 00:00:00 2001 +From f2e6a0a324106b40195f88953e55a355875d2b1b Mon Sep 17 00:00:00 2001 From: George Kiagiadakis Date: Fri, 4 Oct 2019 20:51:24 +0300 Subject: [PATCH] utils: add a gstreamer helper application for interconnection @@ -24,8 +24,8 @@ Upstream-Status: Inappropriate --- configure.ac | 7 + utils/Makefile.am | 20 +++ - utils/gst-helper.c | 379 +++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 406 insertions(+) + utils/gst-helper.c | 432 +++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 459 insertions(+) create mode 100644 utils/gst-helper.c diff --git a/configure.ac b/configure.ac @@ -76,10 +76,10 @@ index 9057f2c..9790474 100644 +endif diff --git a/utils/gst-helper.c b/utils/gst-helper.c new file mode 100644 -index 0000000..1b021ee +index 0000000..de1d47c --- /dev/null +++ b/utils/gst-helper.c -@@ -0,0 +1,379 @@ +@@ -0,0 +1,432 @@ +/* Bluez-Alsa PipeWire integration GStreamer helper + * + * Copyright © 2016-2019 Arkadiusz Bokowy @@ -123,6 +123,9 @@ index 0000000..1b021ee + int ba_pcm_ctrl_fd; + /* the gstreamer pipelines (sink & source) */ + GstElement *pipeline[2]; ++ /* the queue & pwaudiosink of the sink pipeline */ ++ GstElement *queue; ++ GstElement *pwelem; +}; + +static struct ba_dbus_ctx dbus_ctx; @@ -141,11 +144,44 @@ index 0000000..1b021ee + main_loop_on = false; +} + ++static GstBusSyncReply ++bus_sync_handler(GstBus *bus, GstMessage *message, gpointer user_data) ++{ ++ struct worker *w = user_data; ++ GstState s; ++ ++ switch (GST_MESSAGE_TYPE (message)) { ++ case GST_MESSAGE_REQUEST_STATE: ++ gst_message_parse_request_state (message, &s); ++ ++ debug ("corked: %d", (s == GST_STATE_PAUSED)); ++ ++ /* drop queue data when corked */ ++ g_object_set (w->queue, ++ "leaky", (s == GST_STATE_PAUSED) ? 2 /* downstream */ : 0 /* no */, ++ NULL); ++ gst_element_set_state (w->pwelem, s); ++ ++ /* flush the queue when resuming */ ++ if (s == GST_STATE_PLAYING) { ++ gst_element_send_event (w->queue, gst_event_new_flush_start ()); ++ gst_element_send_event (w->queue, gst_event_new_flush_stop (FALSE)); ++ } ++ break; ++ default: ++ break; ++ } ++ ++ gst_message_unref (message); ++ return GST_BUS_DROP; ++} ++ +static int +worker_start_pipeline(struct worker *w, int id, int mode, int profile) +{ + GError *gerr = NULL; + DBusError err = DBUS_ERROR_INIT; ++ const gchar * role = NULL; + + if (w->pipeline[id]) + return 0; @@ -172,9 +208,15 @@ index 0000000..1b021ee + "! 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", ++ "! audio/x-raw,format=F32LE,rate=48000 ! identity sync=true " ++ "! queue name=queue leaky=no max-size-time=0 max-size-buffers=0 max-size-bytes=192000 " ++ "! pwaudiosink name=pwelem", + &gerr); -+ } else if (mode == BA_PCM_FLAG_SOURCE && profile == BA_PCM_FLAG_PROFILE_SCO) { ++ ++ /* a2dp is for music, sco is for calls */ ++ role = (profile == BA_PCM_FLAG_PROFILE_A2DP) ? "Multimedia" : "Communication"; ++ } ++ 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 @@ -183,9 +225,11 @@ index 0000000..1b021ee + 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 " ++ "! queue name=queue leaky=downstream max-size-time=0 max-size-buffers=0 max-size-bytes=9600 " + "! audioconvert ! audioresample ! capsfilter name=capsf " + "! fdsink name=fdelem", &gerr); ++ ++ role = "Communication"; + } + + if (gerr) { @@ -198,6 +242,7 @@ index 0000000..1b021ee + 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) queue = gst_bin_get_by_name(GST_BIN(w->pipeline[id]), "queue"); + 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"); @@ -208,8 +253,9 @@ index 0000000..1b021ee + "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", ++ "media.role", G_TYPE_STRING, role, ++ "bluealsa.profile", G_TYPE_STRING, ++ (profile == BA_PCM_FLAG_PROFILE_SCO) ? "sco" : "a2dp", + NULL); + + g_object_set(capsf, "caps", caps, NULL); @@ -224,6 +270,13 @@ index 0000000..1b021ee + g_object_set(fdelem, "fd", w->ba_pcm_fd, NULL); + g_object_set(pwelem, "stream-properties", stream_props, NULL); + ++ if (mode == BA_PCM_FLAG_SINK) { ++ g_autoptr (GstBus) bus = gst_pipeline_get_bus(GST_PIPELINE(w->pipeline[id])); ++ gst_bus_set_sync_handler(bus, bus_sync_handler, w, NULL); ++ w->queue = queue; ++ w->pwelem = pwelem; ++ } ++ + gst_element_set_state(w->pipeline[id], GST_STATE_PLAYING); + } + @@ -460,5 +513,5 @@ index 0000000..1b021ee + return ret; +} -- -2.23.0 +2.24.0 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 index c4de73e7..2a826119 100644 --- 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 @@ -13,4 +13,5 @@ S = "${WORKDIR}/git" inherit cmake aglwgt pkgconfig -DEPENDS += "pipewire" +DEPENDS += "pipewire wireplumber json-c" +RDEPENDS_${PN} = "agl-service-signal-composer" 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 deleted file mode 100644 index d09ee8ed..00000000 --- a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire-conf-agl/pipewire.conf +++ /dev/null @@ -1,10 +0,0 @@ -# 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/pipewire.conf.in b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire-conf-agl/pipewire.conf.in new file mode 100644 index 00000000..6c055bcf --- /dev/null +++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire-conf-agl/pipewire.conf.in @@ -0,0 +1,17 @@ +# daemon config file for PipeWire version "0.2.9" +# distributed by Automotive Grade Linux + +add-spa-lib audio.convert* audioconvert/libspa-audioconvert +add-spa-lib api.alsa.* alsa/libspa-alsa +add-spa-lib api.v4l2.* v4l2/libspa-v4l2 +add-spa-lib api.bluez5.* bluez5/libspa-bluez5 + +load-module libpipewire-module-protocol-native +load-module libpipewire-module-spa-node-factory +load-module libpipewire-module-client-node +load-module libpipewire-module-client-device +load-module libpipewire-module-access same-sec-label-mode=1 +load-module libpipewire-module-adapter +load-module libpipewire-module-link-factory +load-module libpipewire-module-session-manager +exec /usr/bin/wireplumber 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 index 2bb76f9d..a28c6534 100644 --- 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 @@ -8,7 +8,7 @@ LICENSE = "MIT" LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" SRC_URI = " \ - file://pipewire.conf \ + file://pipewire.conf.in \ file://client.env \ file://server.env \ " @@ -17,8 +17,11 @@ 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 + # enable optional features in the config + BLUEZ5=${@bb.utils.contains('DISTRO_FEATURES', 'bluez5', '', '#', d)} + sed -e "s/#IF_BLUEZ5 /${BLUEZ5}/" ${WORKDIR}/pipewire.conf.in > ${WORKDIR}/pipewire.conf + + # install our custom config install -d ${D}/${sysconfdir}/pipewire/ install -m 0644 ${WORKDIR}/pipewire.conf ${D}${sysconfdir}/pipewire/pipewire.conf diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire.inc b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire.inc index e9046e8e..b3081ca4 100644 --- a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire.inc +++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire.inc @@ -19,7 +19,7 @@ DEPENDS = "dbus" PACKAGECONFIG ??= "\ ${@bb.utils.filter('DISTRO_FEATURES', 'systemd', d)} \ ${@bb.utils.filter('DISTRO_FEATURES', 'bluez5', d)} \ - alsa audioconvert \ + alsa audioconvert audiomixer \ pipewire-alsa \ gstreamer \ " @@ -31,11 +31,14 @@ 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[audioconvert] = "-Daudioconvert=true,-Daudioconvert=false," +PACKAGECONFIG[audiomixer] = "-Daudiomixer=true,-Daudiomixer=false," PACKAGECONFIG[audiotestsrc] = "-Daudiotestsrc=true,-Daudiotestsrc=false, " PACKAGECONFIG[bluez5] = "-Dbluez5=true,-Dbluez5=false,bluez5 sbc" +PACKAGECONFIG[jack] = "-Djack=true,-Djack=false,jack" PACKAGECONFIG[v4l2] = "-Dv4l2=true,-Dv4l2=false,udev v4l-utils" PACKAGECONFIG[videotestsrc] = "-Dvideotestsrc=true,-Dvideotestsrc=false, " +PACKAGECONFIG[vulkan] = "-Dvulkan=true,-Dvulkan=false,vulkan" # alsa plugin to redirect audio to pipewire PACKAGECONFIG[pipewire-alsa] = "-Dpipewire-alsa=true,-Dpipewire-alsa=false,alsa-lib" diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0001-meson-revert-version-check-to-require-meson-0.47-not.patch b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0001-meson-revert-version-check-to-require-meson-0.47-not.patch new file mode 100644 index 00000000..4e7bb0d4 --- /dev/null +++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0001-meson-revert-version-check-to-require-meson-0.47-not.patch @@ -0,0 +1,30 @@ +From 5a249321aa84cd74e3d83bcd555c85fba3cd682d Mon Sep 17 00:00:00 2001 +From: George Kiagiadakis +Date: Sun, 22 Sep 2019 17:59:19 +0300 +Subject: [PATCH] meson: revert version check to require meson 0.47, not 0.50 + +meson 0.50 is not really needed, but there are some strange warnings +if you require an older version; in any case, AGL does not have 0.50 +yet, so let's not fail compilation because of that... + +Upstream-Status: Inappropriate [workaround] +--- + meson.build | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/meson.build b/meson.build +index 2734b0d2..c9da6b4d 100644 +--- a/meson.build ++++ b/meson.build +@@ -1,7 +1,7 @@ + project('pipewire', ['c' ], + version : '0.2.9', + license : 'MIT', +- meson_version : '>= 0.50.0', ++ meson_version : '>= 0.47.0', + default_options : [ 'warning_level=1', + 'c_std=gnu99', + 'buildtype=debugoptimized' ]) +-- +2.24.0 + 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 deleted file mode 100644 index 5b928117..00000000 --- a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0001-spa-include-install-missing-headers.patch +++ /dev/null @@ -1,41 +0,0 @@ -From dbb6e10df8c2ba9b874eb9350d4cb93c62dba5a9 Mon Sep 17 00:00:00 2001 -From: George Kiagiadakis -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-arm-build-with-mno-unaligned-access.patch b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0002-arm-build-with-mno-unaligned-access.patch new file mode 100644 index 00000000..2077af63 --- /dev/null +++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0002-arm-build-with-mno-unaligned-access.patch @@ -0,0 +1,30 @@ +From e4b81946baf2d8c08de87088c01a1d87ae4f03d9 Mon Sep 17 00:00:00 2001 +From: George Kiagiadakis +Date: Mon, 24 Jun 2019 12:19:20 +0300 +Subject: [PATCH] arm: build with -mno-unaligned-access + +Upstream-Status: Inappropriate [workaround] +See also https://gitlab.freedesktop.org/pipewire/pipewire/issues/161 +--- + meson.build | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/meson.build b/meson.build +index c9da6b4d..5c121339 100644 +--- a/meson.build ++++ b/meson.build +@@ -52,6 +52,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.24.0 + 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 deleted file mode 100644 index e49edf49..00000000 --- a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0002-extensions-implement-Endpoint-ClientEndpoint-interfa.patch +++ /dev/null @@ -1,1563 +0,0 @@ -From 5afe82a430642c2f7e116941709a624b8fd73011 Mon Sep 17 00:00:00 2001 -From: George Kiagiadakis -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 -+ * -+ * 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 -+ * -+ * 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 -+#include -+#include -+ -+#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 -+ * -+ * 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 " }, -+ { 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 -+ * -+ * 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 -+#include -+#include -+ -+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 -+ * -+ * 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 -+#include -+#include -+ -+#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 -+ * -+ * 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 -+#include -+ -+#include -+#include -+#include -+ -+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(¶m)) < 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(¶m)) < 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(¶ms[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(¶m)) < 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-gst-Implement-new-pwaudio-src-sink-elements-based-on.patch b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0003-gst-Implement-new-pwaudio-src-sink-elements-based-on.patch new file mode 100644 index 00000000..b3eba21f --- /dev/null +++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0003-gst-Implement-new-pwaudio-src-sink-elements-based-on.patch @@ -0,0 +1,1280 @@ +From 1b1f884a165ed7b2147affbdddf85a641d4cf180 Mon Sep 17 00:00:00 2001 +From: George Kiagiadakis +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: Denied +See https://gitlab.freedesktop.org/pipewire/pipewire/merge_requests/140 +--- + src/gst/gstpipewire.c | 8 +- + src/gst/gstpwaudioringbuffer.c | 565 +++++++++++++++++++++++++++++++++ + src/gst/gstpwaudioringbuffer.h | 83 +++++ + src/gst/gstpwaudiosink.c | 207 ++++++++++++ + src/gst/gstpwaudiosink.h | 48 +++ + src/gst/gstpwaudiosrc.c | 200 ++++++++++++ + src/gst/gstpwaudiosrc.h | 48 +++ + src/gst/meson.build | 6 + + 8 files changed, 1164 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..babf2d83 +--- /dev/null ++++ b/src/gst/gstpwaudioringbuffer.c +@@ -0,0 +1,565 @@ ++/* PipeWire ++ * ++ * Copyright © 2018 Wim Taymans ++ * Copyright © 2019 Collabora Ltd. ++ * @author George Kiagiadakis ++ * ++ * 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 ++#include ++ ++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); ++ 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)); ++ break; ++ case PW_STREAM_STATE_CONNECTING: ++ break; ++ case PW_STREAM_STATE_PAUSED: ++ 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_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); ++} ++ ++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_param_changed (void *data, uint32_t id, 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]; ++ ++ if (format == NULL || id != SPA_PARAM_Format) ++ return; ++ ++ 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_update_params (self->stream, 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_INFO_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, ++ .param_changed = on_stream_param_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 */ ++ ++ props = pw_properties_new (NULL, NULL); ++ if (self->props->properties) { ++ gst_structure_foreach (self->props->properties, copy_properties, props); ++ } ++ ++ 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; ++ ++ pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%u/%u", ++ self->segsize / self->bpf, self->rate); ++ GST_DEBUG_OBJECT (self->elem, "segsize:%u, bpf:%u, node.latency = %s", ++ self->segsize, self->bpf, pw_properties_get (props, PW_KEY_NODE_LATENCY)); ++ ++ /* 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 CONFIGURE"); ++ ++ if (!wait_for_stream_state (self, PW_STREAM_STATE_PAUSED)) ++ 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 ++ * ++ * 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 ++#include ++#include ++ ++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..069996c3 +--- /dev/null ++++ b/src/gst/gstpwaudiosink.c +@@ -0,0 +1,207 @@ ++/* PipeWire ++ * ++ * Copyright © 2018 Wim Taymans ++ * Copyright © 2019 Collabora Ltd. ++ * @author George Kiagiadakis ++ * ++ * 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; ++ ++ /* 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 ++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 "); ++ ++ 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 ++ * ++ * 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 ++ * ++ * 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 "); ++ ++ 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 ++ * ++ * 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.24.0 + 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 deleted file mode 100644 index a709abdf..00000000 --- a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0003-pipewire-cli-add-support-for-printing-endpoint-info-.patch +++ /dev/null @@ -1,149 +0,0 @@ -From 0e9fe3cfb19c751655f16ce4b8c6100269f23ff2 Mon Sep 17 00:00:00 2001 -From: George Kiagiadakis -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 - #include - -+#include -+ - 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-audioconvert-always-assume-that-output-ports-are-NOT.patch b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0004-audioconvert-always-assume-that-output-ports-are-NOT.patch new file mode 100644 index 00000000..beb87839 --- /dev/null +++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0004-audioconvert-always-assume-that-output-ports-are-NOT.patch @@ -0,0 +1,35 @@ +From ce155eb0073fba84556782633f79bb7d03492c07 Mon Sep 17 00:00:00 2001 +From: George Kiagiadakis +Date: Wed, 2 Oct 2019 21:40:34 +0300 +Subject: [PATCH] audioconvert: always assume that output ports are NOT monitor + ports + +Otherwise, when we setup audioconvert in merge+split mode, +it assumes that the splitter's ports are monitor ports and +belong to the merger. + +Upstream-Status: Inappropriate [workaround] +--- + spa/plugins/audioconvert/audioconvert.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/spa/plugins/audioconvert/audioconvert.c b/spa/plugins/audioconvert/audioconvert.c +index 74a62a35..72da37d1 100644 +--- a/spa/plugins/audioconvert/audioconvert.c ++++ b/spa/plugins/audioconvert/audioconvert.c +@@ -113,8 +113,12 @@ struct impl { + unsigned int add_listener:1; + }; + ++#if 0 + #define IS_MONITOR_PORT(this,dir,port_id) (dir == SPA_DIRECTION_OUTPUT && port_id > 0 && \ + this->mode[SPA_DIRECTION_INPUT] == SPA_PARAM_PORT_CONFIG_MODE_dsp) ++#else ++#define IS_MONITOR_PORT(this,dir,port_id) (false) ++#endif + + static void emit_node_info(struct impl *this, bool full) + { +-- +2.24.0 + 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 deleted file mode 100644 index 4394d60d..00000000 --- a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0004-pipewire-cli-add-command-to-modify-endpoint-control-.patch +++ /dev/null @@ -1,124 +0,0 @@ -From 824c8abf88e9ee82567c177145798b619298ab91 Mon Sep 17 00:00:00 2001 -From: George Kiagiadakis -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 []", do_enum_params }, - { "permissions", "Set permissions for a client ", do_permissions }, - { "get-permissions", "Get permissions of a client ", do_get_permissions }, -+ { "endpoint-control", "Set control value on an endpoint ", 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 ", 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 deleted file mode 100644 index a670e7ff..00000000 --- a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0005-arm-build-with-mno-unaligned-access.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 2016605938f02835c75928648e99b25f7248aa5b Mon Sep 17 00:00:00 2001 -From: George Kiagiadakis -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/0005-module-access-add-same-sec-label-mode.patch b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0005-module-access-add-same-sec-label-mode.patch new file mode 100644 index 00000000..07a1ec11 --- /dev/null +++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0005-module-access-add-same-sec-label-mode.patch @@ -0,0 +1,94 @@ +From 19fad1a4fa8bdc4f02aac4e169e7ff9cab18bdcd Mon Sep 17 00:00:00 2001 +From: George Kiagiadakis +Date: Tue, 19 Nov 2019 17:09:07 +0200 +Subject: [PATCH] module-access: add same-sec-label-mode + +This is a mode where the access module allows all clients that have +the same security label as the pipewire daemon, and every other +client is put on the restricted state. + +In systems that use SMACK security labels, such as AGL, this allows +the session manager (which is spawned by pipewire, inheriting the +same smack label) to have full access to all objects, while every +other client is restricted and the session manager must decide +what to do with it + +Note that while this option is configurable, there is no loss of +security if this option is not set in the configuration. Clients +that don't have the same security context will be considered to +be flatpak clients because pipewire will not be able to open +/proc/pid/cmdline. This however results in some unwanted error +messages that may be confusing. + +Upstream-Status: Inappropriate [agl/smack specific] +--- + src/modules/module-access.c | 45 ++++++++++++++++++++++++++++++++++++- + 1 file changed, 44 insertions(+), 1 deletion(-) + +diff --git a/src/modules/module-access.c b/src/modules/module-access.c +index 09dafa43..f75306d9 100644 +--- a/src/modules/module-access.c ++++ b/src/modules/module-access.c +@@ -50,6 +50,30 @@ struct impl { + struct spa_hook module_listener; + }; + ++static int check_seclabel(const char *str) ++{ ++ char attr[1024]; ++ int fd, len; ++ ++ fd = open("/proc/self/attr/current", O_RDONLY); ++ if (fd < 0) ++ return -errno; ++ ++ if ((len = read(fd, attr, 1024)) <= 0) { ++ close(fd); ++ return -EIO; ++ } ++ attr[len] = '\0'; ++ ++ if (strcmp(attr, str) == 0) { ++ close(fd); ++ return 1; ++ } ++ ++ close(fd); ++ return 0; ++} ++ + static int check_cmdline(struct pw_client *client, int pid, const char *str) + { + char path[2048]; +@@ -121,8 +145,27 @@ core_check_access(void *data, struct pw_client *client) + const char *str; + int pid, res; + ++ props = pw_client_get_properties(client); ++ ++ if (impl->properties && ++ (str = pw_properties_get(impl->properties, "same-sec-label-mode")) != NULL && ++ strcmp(str, "1") == 0) { ++ if (props && (str = pw_properties_get(props, PW_KEY_SEC_LABEL)) != NULL) { ++ res = check_seclabel(str); ++ if (res == 1) ++ goto granted; ++ else if (res < 0) ++ pw_log_warn("module %p: client %p seclabel check failed: %s", ++ impl, client, spa_strerror(res)); ++ } ++ pw_log_debug("module %p: seclabel restricted client %p added", ++ impl, client); ++ items[0] = SPA_DICT_ITEM_INIT(PW_KEY_ACCESS, "restricted"); ++ goto wait_permissions; ++ } ++ + pid = -EINVAL; +- if ((props = pw_client_get_properties(client)) != NULL) { ++ if (props != NULL) { + if ((str = pw_properties_get(props, PW_KEY_SEC_PID)) != NULL) + pid = atoi(str); + } +-- +2.24.0 + diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0006-alsa-pcm-call-reuse_buffers-when-resetting-the-state.patch b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0006-alsa-pcm-call-reuse_buffers-when-resetting-the-state.patch new file mode 100644 index 00000000..cae4d70f --- /dev/null +++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0006-alsa-pcm-call-reuse_buffers-when-resetting-the-state.patch @@ -0,0 +1,30 @@ +From 5946fbd2ca3a7f892b4ebc10090f62df6bb1ec88 Mon Sep 17 00:00:00 2001 +From: George Kiagiadakis +Date: Thu, 9 Jan 2020 19:27:23 +0200 +Subject: [PATCH] alsa-pcm: call reuse_buffers when resetting the state of the + buffers + +This allows the upstream node to put buffers back to its pool in case +they were left around in the ready list locally when the alsa-pcm-sink +was last paused. + +Fixes #203 +--- + spa/plugins/alsa/alsa-pcm.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/spa/plugins/alsa/alsa-pcm.c b/spa/plugins/alsa/alsa-pcm.c +index 63d75549..a6f22cf0 100644 +--- a/spa/plugins/alsa/alsa-pcm.c ++++ b/spa/plugins/alsa/alsa-pcm.c +@@ -1115,6 +1115,7 @@ static void reset_buffers(struct state *this) + struct buffer *b = &this->buffers[i]; + if (this->stream == SND_PCM_STREAM_PLAYBACK) { + SPA_FLAG_SET(b->flags, BUFFER_FLAG_OUT); ++ spa_node_call_reuse_buffer(&this->callbacks, 0, b->id); + } else { + spa_list_append(&this->free, &b->link); + SPA_FLAG_CLEAR(b->flags, BUFFER_FLAG_OUT); +-- +2.24.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 deleted file mode 100644 index 4d9117f0..00000000 --- a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0006-logger-print-timestamps-on-logged-messages.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 352c58357e5922b21d664c1f5a0b89a74f864f41 Mon Sep 17 00:00:00 2001 -From: George Kiagiadakis -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 - #include - #include -+#include - #include - - #include -@@ -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 deleted file mode 100644 index 86495014..00000000 --- a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0007-alsa-make-corrections-on-the-timeout-based-on-how-fa.patch +++ /dev/null @@ -1,130 +0,0 @@ -From 05a3a926df4906cdf60f7978843c637bbf37714a Mon Sep 17 00:00:00 2001 -From: George Kiagiadakis -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 deleted file mode 100644 index 681bae69..00000000 --- a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0008-audio-dsp-allow-mode-to-be-set-with-a-property.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0c85e1110e32720785f861c7a85cf0636394eee4 Mon Sep 17 00:00:00 2001 -From: Julian Bouzas -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 deleted file mode 100644 index 87141e91..00000000 --- a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0009-audioconvert-do-setup-internal-links-and-buffers-als.patch +++ /dev/null @@ -1,55 +0,0 @@ -From ddcda9fa6ec49168c5ddd9fbeda748c5fad18fce Mon Sep 17 00:00:00 2001 -From: George Kiagiadakis -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 deleted file mode 100644 index 6b1a6441..00000000 --- a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0010-gst-Implement-new-pwaudio-src-sink-elements-based-on.patch +++ /dev/null @@ -1,1249 +0,0 @@ -From bbc875ec4268a88bf2465244e089b119011e7479 Mon Sep 17 00:00:00 2001 -From: George Kiagiadakis -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 -+ * -+ * 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 -+#include -+ -+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 -+ * -+ * 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 -+#include -+#include -+ -+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 -+ * -+ * 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 "); -+ -+ 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 -+ * -+ * 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 -+ * -+ * 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 "); -+ -+ 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 -+ * -+ * 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 deleted file mode 100644 index 5ffabb6d..00000000 --- a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0011-gst-pwaudioringbuffer-make-the-buffer-size-sensitive.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 6e289d0058d71bc433d1918a8bbf3305f3e4f517 Mon Sep 17 00:00:00 2001 -From: Julian Bouzas -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 deleted file mode 100644 index 3680cc35..00000000 --- a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0012-gst-pwaudioringbuffer-request-pause-play-on-the-appr.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 1eb1e3a839f97ad4aa43c289f702c587a068a333 Mon Sep 17 00:00:00 2001 -From: George Kiagiadakis -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 deleted file mode 100644 index 539e3a5e..00000000 --- a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0013-gst-pwaudioringbuffer-wait-only-for-STREAM_STATE_CON.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 1b2bf0f435f2912c32fbd7a6118ed9bfb41f031c Mon Sep 17 00:00:00 2001 -From: George Kiagiadakis -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 deleted file mode 100644 index 6f15b7f7..00000000 --- a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0014-gst-pwaudiosink-set-the-default-latency-time-buffer-.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 460ce06c9cc6fd7b0106e0ce8a265bbeff4ae406 Mon Sep 17 00:00:00 2001 -From: George Kiagiadakis -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 deleted file mode 100644 index ed3c1b06..00000000 --- a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0015-audioconvert-fmtconvert-assume-F32-on-the-other-port.patch +++ /dev/null @@ -1,44 +0,0 @@ -From aa5de0cfc31df9cd8fb6d24367d2852dbbc8dcb9 Mon Sep 17 00:00:00 2001 -From: George Kiagiadakis -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 deleted file mode 100644 index b97e21ff..00000000 --- a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0016-gst-pwaudioringbuffer-set-node.latency-to-get-schedu.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 3af64cf4e1d33c33a9757c0f30c7de1068202540 Mon Sep 17 00:00:00 2001 -From: George Kiagiadakis -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 deleted file mode 100644 index be5ac5ea..00000000 --- a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0017-connection-move-remaining-data-and-fds.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 75247f77eae2c473b18cf8d7e117216f73d2e127 Mon Sep 17 00:00:00 2001 -From: Wim Taymans -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 deleted file mode 100644 index e027765e..00000000 --- a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire/0018-protocol-improve-flushing.patch +++ /dev/null @@ -1,222 +0,0 @@ -From 7e885c029a6cc66ce1881f6f2c50d5f76a7d3372 Mon Sep 17 00:00:00 2001 -From: Wim Taymans -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_git.bb b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire_git.bb index 823da421..1a4e4eb9 100644 --- a/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire_git.bb +++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/pipewire/pipewire_git.bb @@ -1,29 +1,17 @@ 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 \ +SRC_URI = "git://gitlab.freedesktop.org/pipewire/pipewire.git;protocol=https;branch=master \ + file://0001-meson-revert-version-check-to-require-meson-0.47-not.patch \ + file://0002-arm-build-with-mno-unaligned-access.patch \ + file://0003-gst-Implement-new-pwaudio-src-sink-elements-based-on.patch \ + file://0004-audioconvert-always-assume-that-output-ports-are-NOT.patch \ + file://0005-module-access-add-same-sec-label-mode.patch \ + file://0006-alsa-pcm-call-reuse_buffers-when-resetting-the-state.patch \ " -SRCREV = "4be788962e60891237f1f018627bf709ae3981e6" +SRCREV = "b0932e687fc47e0872ca291531f2291d99042d70" -PV = "0.2.90+git${SRCPV}+3" +PV = "0.2.91+git${SRCPV}+2" S = "${WORKDIR}/git" RDEPENDS_${PN} += "virtual/pipewire-sessionmanager virtual/pipewire-config" diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/00-audio-sink.endpoint b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/00-audio-sink.endpoint new file mode 100644 index 00000000..4bc43574 --- /dev/null +++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/00-audio-sink.endpoint @@ -0,0 +1,10 @@ +[match-node] +priority = 0 +properties = [ + { name = "media.class", value = "Audio/Sink" }, +] + +[endpoint] +type = "pw-audio-softdsp-endpoint" +direction = "sink" +streams = "playback.streams" diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/00-audio-source.endpoint b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/00-audio-source.endpoint new file mode 100644 index 00000000..7657f6f4 --- /dev/null +++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/00-audio-source.endpoint @@ -0,0 +1,10 @@ +[match-node] +priority = 0 +properties = [ + { name = "media.class", value = "Audio/Source" }, +] + +[endpoint] +type = "pw-audio-softdsp-endpoint" +direction = "source" +streams = "capture.streams" diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/00-default-input-audio.endpoint-link b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/00-default-input-audio.endpoint-link new file mode 100644 index 00000000..4b70dc89 --- /dev/null +++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/00-default-input-audio.endpoint-link @@ -0,0 +1,7 @@ +[match-endpoint] +priority = 0 +direction = "sink" +media_class = "Stream/Input/Audio" + +[endpoint-link] +keep = false diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/00-default-output-audio.endpoint-link b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/00-default-output-audio.endpoint-link new file mode 100644 index 00000000..5d6428f9 --- /dev/null +++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/00-default-output-audio.endpoint-link @@ -0,0 +1,7 @@ +[match-endpoint] +priority = 0 +direction = "source" +media_class = "Stream/Output/Audio" + +[endpoint-link] +keep = false diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/00-stream-input-audio.endpoint b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/00-stream-input-audio.endpoint new file mode 100644 index 00000000..2993f3e4 --- /dev/null +++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/00-stream-input-audio.endpoint @@ -0,0 +1,9 @@ +[match-node] +priority = 0 +properties = [ + { name = "media.class", value = "Stream/Input/Audio" }, +] + +[endpoint] +direction = "sink" +type = "pw-audio-softdsp-endpoint" diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/00-stream-output-audio.endpoint b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/00-stream-output-audio.endpoint new file mode 100644 index 00000000..1cf82ea0 --- /dev/null +++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/00-stream-output-audio.endpoint @@ -0,0 +1,9 @@ +[match-node] +priority = 0 +properties = [ + { name = "media.class", value = "Stream/Output/Audio" }, +] + +[endpoint] +direction = "source" +type = "pw-audio-softdsp-endpoint" diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/01-hw00-audio-sink.endpoint b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/01-hw00-audio-sink.endpoint new file mode 100644 index 00000000..85a9b511 --- /dev/null +++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/01-hw00-audio-sink.endpoint @@ -0,0 +1,12 @@ +[match-node] +priority = 1 +properties = [ + { name = "media.class", value = "Audio/Sink" }, + { name = "api.alsa.path", value = "hw:0,0" }, +] + +[endpoint] +type = "pw-audio-softdsp-endpoint" +direction = "sink" +streams = "playback.streams" +priority = 1 diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/01-hw00-audio-source.endpoint b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/01-hw00-audio-source.endpoint new file mode 100644 index 00000000..c77701c0 --- /dev/null +++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/01-hw00-audio-source.endpoint @@ -0,0 +1,12 @@ +[match-node] +priority = 1 +properties = [ + { name = "media.class", value = "Audio/Source" }, + { name = "api.alsa.path", value = "hw:0,0" }, +] + +[endpoint] +type = "pw-audio-softdsp-endpoint" +direction = "source" +streams = "capture.streams" +priority = 1 diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/30-ak4613-audio-sink.endpoint b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/30-ak4613-audio-sink.endpoint new file mode 100644 index 00000000..afc4303e --- /dev/null +++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/30-ak4613-audio-sink.endpoint @@ -0,0 +1,12 @@ +[match-node] +priority = 30 +properties = [ + { name = "media.class", value = "Audio/Sink" }, + { name = "api.alsa.card.id", value = "ak4613" }, +] + +[endpoint] +type = "pw-audio-softdsp-endpoint" +direction = "sink" +streams = "playback.streams" +priority = 30 diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/30-ak4613-audio-source.endpoint b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/30-ak4613-audio-source.endpoint new file mode 100644 index 00000000..ad568059 --- /dev/null +++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/30-ak4613-audio-source.endpoint @@ -0,0 +1,12 @@ +[match-node] +priority = 30 +properties = [ + { name = "media.class", value = "Audio/Source" }, + { name = "api.alsa.card.id", value = "ak4613" }, +] + +[endpoint] +type = "pw-audio-softdsp-endpoint" +direction = "source" +streams = "capture.streams" +priority = 30 diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/30-dra7xx-audio-sink.endpoint b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/30-dra7xx-audio-sink.endpoint new file mode 100644 index 00000000..becd21e2 --- /dev/null +++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/30-dra7xx-audio-sink.endpoint @@ -0,0 +1,12 @@ +[match-node] +priority = 30 +properties = [ + { name = "media.class", value = "Audio/Sink" }, + { name = "api.alsa.card.id", value = "DRA7xx-EVM" }, +] + +[endpoint] +type = "pw-audio-softdsp-endpoint" +direction = "sink" +streams = "playback.streams" +priority = 30 diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/30-dra7xx-audio-source.endpoint b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/30-dra7xx-audio-source.endpoint new file mode 100644 index 00000000..72ef4677 --- /dev/null +++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/30-dra7xx-audio-source.endpoint @@ -0,0 +1,12 @@ +[match-node] +priority = 30 +properties = [ + { name = "media.class", value = "Audio/Source" }, + { name = "api.alsa.card.id", value = "DRA7xx-EVM" }, +] + +[endpoint] +type = "pw-audio-softdsp-endpoint" +direction = "source" +streams = "capture.streams" +priority = 30 diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/30-rpi3-audio-sink.endpoint b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/30-rpi3-audio-sink.endpoint new file mode 100644 index 00000000..74e4d62e --- /dev/null +++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/30-rpi3-audio-sink.endpoint @@ -0,0 +1,13 @@ +[match-node] +priority = 30 +properties = [ + { name = "media.class", value = "Audio/Sink" }, + { name = "api.alsa.card.name", value = "bcm2835 ALSA" }, + { name = "api.alsa.pcm.name", value = "bcm2835 ALSA" }, +] + +[endpoint] +type = "pw-audio-softdsp-endpoint" +direction = "sink" +streams = "playback.streams" +priority = 30 diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/40-fiberdyne-amp.endpoint b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/40-fiberdyne-amp.endpoint new file mode 100644 index 00000000..807ad468 --- /dev/null +++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/40-fiberdyne-amp.endpoint @@ -0,0 +1,12 @@ +[match-node] +priority = 40 +properties = [ + { name = "media.class", value = "Audio/Sink" }, + { name = "api.alsa.card.id", value = "ep016ch" }, +] + +[endpoint] +type = "pw-audio-softdsp-endpoint" +direction = "sink" +streams = "playback.streams" +priority = 40 diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/40-microchip-mic.endpoint b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/40-microchip-mic.endpoint new file mode 100644 index 00000000..bbfcd43a --- /dev/null +++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/40-microchip-mic.endpoint @@ -0,0 +1,12 @@ +[match-node] +priority = 40 +properties = [ + { name = "media.class", value = "Audio/Source" }, + { name = "api.alsa.card.id", value = "ep811ch" }, +] + +[endpoint] +type = "pw-audio-softdsp-endpoint" +direction = "source" +streams = "capture.streams" +priority = 40 diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/70-usb-audio-sink.endpoint b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/70-usb-audio-sink.endpoint new file mode 100644 index 00000000..62e27909 --- /dev/null +++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/70-usb-audio-sink.endpoint @@ -0,0 +1,12 @@ +[match-node] +priority = 70 +properties = [ + { name = "media.class", value = "Audio/Sink" }, + { name = "api.alsa.card.driver", value = "USB-Audio" }, +] + +[endpoint] +type = "pw-audio-softdsp-endpoint" +direction = "sink" +streams = "playback.streams" +priority = 70 diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/70-usb-audio-source.endpoint b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/70-usb-audio-source.endpoint new file mode 100644 index 00000000..505ae8d8 --- /dev/null +++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/70-usb-audio-source.endpoint @@ -0,0 +1,12 @@ +[match-node] +priority = 70 +properties = [ + { name = "media.class", value = "Audio/Source" }, + { name = "api.alsa.card.driver", value = "USB-Audio" }, +] + +[endpoint] +type = "pw-audio-softdsp-endpoint" +direction = "source" +streams = "capture.streams" +priority = 70 diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/bluealsa-input-audio.endpoint-link b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/bluealsa-input-audio.endpoint-link new file mode 100644 index 00000000..b5753a10 --- /dev/null +++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/bluealsa-input-audio.endpoint-link @@ -0,0 +1,11 @@ +[match-endpoint] +priority = 75 +direction = "sink" +name = "bluealsa*" +media_class = "Stream/Input/Audio" +properties = [ + { name = "bluealsa.profile", value = "sco" }, +] + +[endpoint-link] +keep = true diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/bluealsa-output-audio.endpoint-link b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/bluealsa-output-audio.endpoint-link new file mode 100644 index 00000000..d1b3cec0 --- /dev/null +++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/bluealsa-output-audio.endpoint-link @@ -0,0 +1,11 @@ +[match-endpoint] +priority = 75 +direction = "source" +name = "bluealsa*" +media_class = "Stream/Output/Audio" +properties = [ + { name = "bluealsa.profile", value = "sco" }, +] + +[endpoint-link] +keep = true diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/capture.streams b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/capture.streams new file mode 100644 index 00000000..e7ce36f6 --- /dev/null +++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/capture.streams @@ -0,0 +1,3 @@ +[[streams]] +name = "Default" +priority = 25 diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/playback.streams b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/playback.streams new file mode 100644 index 00000000..c645416a --- /dev/null +++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/playback.streams @@ -0,0 +1,31 @@ +[[streams]] +name = "Multimedia" +priority = 25 + +[[streams]] +name = "Speech-Low" +priority = 30 + +[[streams]] +name = "Custom-Low" +priority = 35 + +[[streams]] +name = "Navigation" +priority = 50 + +[[streams]] +name = "Speech-High" +priority = 60 + +[[streams]] +name = "Custom-High" +priority = 65 + +[[streams]] +name = "Communication" +priority = 75 + +[[streams]] +name = "Emergency" +priority = 99 diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/wireplumber.conf b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/wireplumber.conf new file mode 100644 index 00000000..e0975a81 --- /dev/null +++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/wireplumber.conf @@ -0,0 +1,30 @@ +# Register well-known SPA factories +# These do not need to exist on the system to be registered +add-spa-lib audio.convert* audioconvert/libspa-audioconvert +add-spa-lib api.alsa.* alsa/libspa-alsa +add-spa-lib api.v4l2.* v4l2/libspa-v4l2 +add-spa-lib api.bluez5.* bluez5/libspa-bluez5 + +# the client-device pipewire module is needed for libwireplumber-module-monitor +load-pipewire-module libpipewire-module-client-device + +# Session object implementation +# This keeps track of the default input & output device endpoint +load-module C libwireplumber-module-session + +# 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 + +load-module C libwireplumber-module-monitor { + "factory": <"api.alsa.enum.udev">, + "flags": <["use-adapter", "activate-devices"]> +} + +# Implements endpoint creation based on TOML configuration files +load-module C libwireplumber-module-config-endpoint + +# Implements linking clients to devices based on TOML configuration files +load-module C libwireplumber-module-config-policy 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 deleted file mode 100644 index 76a57419..00000000 --- a/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber-board-config-agl/wireplumber.conf.in +++ /dev/null @@ -1,55 +0,0 @@ -# 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 index 7ed9ea1a..cab61e49 100644 --- 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 @@ -7,56 +7,42 @@ SECTION = "multimedia" LICENSE = "MIT" LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" -SRC_URI = "file://wireplumber.conf.in" +SRC_URI = "\ + file://wireplumber.conf \ + file://00-audio-sink.endpoint \ + file://00-audio-source.endpoint \ + file://00-default-input-audio.endpoint-link \ + file://00-default-output-audio.endpoint-link \ + file://00-stream-input-audio.endpoint \ + file://00-stream-output-audio.endpoint \ + file://01-hw00-audio-sink.endpoint \ + file://01-hw00-audio-source.endpoint \ + file://30-ak4613-audio-sink.endpoint \ + file://30-ak4613-audio-source.endpoint \ + file://30-dra7xx-audio-sink.endpoint \ + file://30-dra7xx-audio-source.endpoint \ + file://30-rpi3-audio-sink.endpoint \ + file://40-fiberdyne-amp.endpoint \ + file://40-microchip-mic.endpoint \ + file://70-usb-audio-sink.endpoint \ + file://70-usb-audio-source.endpoint \ + file://bluealsa-input-audio.endpoint-link \ + file://bluealsa-output-audio.endpoint-link \ + file://capture.streams \ + file://playback.streams \ +" 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 + install -m 644 ${WORKDIR}/*.endpoint ${D}/${sysconfdir}/wireplumber/ + install -m 644 ${WORKDIR}/*.endpoint-link ${D}/${sysconfdir}/wireplumber/ + install -m 644 ${WORKDIR}/*.streams ${D}/${sysconfdir}/wireplumber/ } FILES_${PN} += "\ diff --git a/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber/0001-Build-cpptoml-without-a-cmake-subproject.patch b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber/0001-Build-cpptoml-without-a-cmake-subproject.patch new file mode 100644 index 00000000..726b35e7 --- /dev/null +++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber/0001-Build-cpptoml-without-a-cmake-subproject.patch @@ -0,0 +1,28 @@ +From e5efe3d4f0abc28251dac245ce0cf4124e7e2a12 Mon Sep 17 00:00:00 2001 +From: George Kiagiadakis +Date: Thu, 5 Dec 2019 17:59:44 +0200 +Subject: [PATCH] Build cpptoml without a cmake subproject + +Upstream-Status: Inappropriate +--- + meson.build | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/meson.build b/meson.build +index 5a75d96..0b21377 100644 +--- a/meson.build ++++ b/meson.build +@@ -24,9 +24,7 @@ else + wireplumber_config_dir = join_paths(get_option('prefix'), get_option('sysconfdir'), 'wireplumber') + endif + +-cmake = import('cmake') +-cpptoml = cmake.subproject('cpptoml') +-cpptoml_dep = cpptoml.dependency('cpptoml') ++cpptoml_dep = declare_dependency(include_directories: include_directories('subprojects/cpptoml')) + + gobject_dep = dependency('gobject-2.0') + gmodule_dep = dependency('gmodule-2.0') +-- +2.24.0 + 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 index 2979d7e5..0e810b37 100644 --- a/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber_git.bb +++ b/meta-agl-devel/meta-pipewire/recipes-multimedia/wireplumber/wireplumber_git.bb @@ -1,6 +1,6 @@ SUMMARY = "Session / Policy Manager for PipeWire" -HOMEPAGE = "https://gitlab.freedesktop.org/gkiagia/wireplumber" -BUGTRACKER = "https://gitlab.freedesktop.org/gkiagia/wireplumber/issues" +HOMEPAGE = "https://gitlab.freedesktop.org/pipewire/wireplumber" +BUGTRACKER = "https://gitlab.freedesktop.org/pipewire/wireplumber/issues" AUTHOR = "George Kiagiadakis " SECTION = "multimedia" @@ -11,12 +11,22 @@ 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" +SRC_URI = "\ + git://gitlab.freedesktop.org/pipewire/wireplumber.git;protocol=https;branch=master \ + https://raw.githubusercontent.com/skystrife/cpptoml/fededad7169e538ca47e11a9ee9251bc361a9a65/include/cpptoml.h \ + file://0001-Build-cpptoml-without-a-cmake-subproject.patch \ +" +SRCREV = "0e98e4150b73d0bed9b72bf8d3eba49671962991" +SRC_URI[sha256sum] = "3e4e1d315fa1229921c7a4297ead08775b5bb1220c18a7eac62db9ca7e79df0d" -PV = "0.1.1+git${SRCPV}" +PV = "0.1.90+git${SRCPV}" S = "${WORKDIR}/git" +do_configure_prepend() { + mkdir -p ${WORKDIR}/git/subprojects/cpptoml/include + cp -f ${WORKDIR}/cpptoml.h ${WORKDIR}/git/subprojects/cpptoml/include/ +} + PACKAGES =+ "${PN}-config" FILES_${PN} += "\ diff --git a/meta-agl-devel/meta-pipewire/recipes-security/cynagora/cynagora_%.bbappend b/meta-agl-devel/meta-pipewire/recipes-security/cynagora/cynagora_%.bbappend new file mode 100644 index 00000000..9395c90c --- /dev/null +++ b/meta-agl-devel/meta-pipewire/recipes-security/cynagora/cynagora_%.bbappend @@ -0,0 +1,5 @@ + +do_install_append() { + echo "System::Pipewire * * http://tizen.org/privilege/internal/dbus yes forever" >> ${D}${sysconfdir}/security/cynagora.initial +} + 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 deleted file mode 100644 index 821c1e1d..00000000 --- a/meta-agl-devel/meta-pipewire/recipes-security/security-manager/security-manager/0001-Adapt-smack-rules-to-allow-connections-to-pipewire.patch +++ /dev/null @@ -1,25 +0,0 @@ -From cc5cbaddad6fe559e9e482467266fb18fb00c6a7 Mon Sep 17 00:00:00 2001 -From: George Kiagiadakis -Date: Wed, 26 Jun 2019 16:02:13 +0300 -Subject: [PATCH] Adapt smack rules to allow connections to pipewire - -Signed-off-by: George Kiagiadakis ---- - 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 index 319a27d6..59449446 100644 --- 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 @@ -1,2 +1,4 @@ -FILESEXTRAPATHS_prepend := "${THISDIR}/security-manager:" -SRC_URI += "file://0001-Adapt-smack-rules-to-allow-connections-to-pipewire.patch" + +do_install_append() { + echo "~APP~ System::Pipewire rw" >> ${D}${datadir}/security-manager/policy/app-rules-template.smack +} 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 index 9b7a0f07..ee19d25f 100644 --- 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 @@ -1,2 +1 @@ -# Currently no default voiceagent -PREFERRED_RPROVIDER_virtual/voiceagent ?= "" +PREFERRED_RPROVIDER_virtual/voice-high-config = "default-voice-high-config" 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 index ad509d14..10df0926 100644 --- 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 @@ -3,4 +3,8 @@ # agl-voiceagent-alexa is configured. BBMASK += "meta-aac/recipes-support/curl/curl_%.bbappend" -PREFERRED_RPROVIDER_virtual/voiceagent = "alexa-voiceagent-service" +PREFERRED_RPROVIDER_virtual/voice-high-config = "alexa-voice-high-config" + +FEATURE_PACKAGES_agl-voiceagent-alexa = "packagegroup-agl-voiceagent-alexa" + +IMAGE_FEATURES += "agl-voiceagent-alexa" diff --git a/meta-agl-devel/meta-speech-framework/meta-aac-amazonlite/recipes-wakeword/pryon-lite/pryon-lite.bbappend b/meta-agl-devel/meta-speech-framework/meta-aac-amazonlite/recipes-wakeword/pryon-lite/pryon-lite.bbappend new file mode 100644 index 00000000..ceba2eb2 --- /dev/null +++ b/meta-agl-devel/meta-speech-framework/meta-aac-amazonlite/recipes-wakeword/pryon-lite/pryon-lite.bbappend @@ -0,0 +1,2 @@ +# Required to avoid QA errors from the prebuilt libraries +INSANE_SKIP_${PN} += "ldflags" diff --git a/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voice-high-config/voice-high.json b/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voice-high-config/voice-high.json new file mode 100644 index 00000000..f460ccfc --- /dev/null +++ b/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voice-high-config/voice-high.json @@ -0,0 +1 @@ +{ "default": "VA-001" } diff --git a/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voice-high-config_1.0.bb b/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voice-high-config_1.0.bb new file mode 100644 index 00000000..736a7ce5 --- /dev/null +++ b/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voice-high-config_1.0.bb @@ -0,0 +1,20 @@ +SUMMARY = "High level voice service binding default voiceagent configuration for Alexa" +DESCRIPTION = "Alexa default voiceagent JSON configuration file for agl-service-voice-high binding" +HOMEPAGE = "https://gerrit.automotivelinux.org/gerrit/apps/agl-service-voice-high" +SECTION = "apps" + +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10" + +SRC_URI = "file://voice-high.json" + +inherit allarch + +do_compile[noexec] = "1" + +do_install () { + install -D -m 644 ${WORKDIR}/voice-high.json ${D}${sysconfdir}/xdg/AGL/voice-high.json +} + +RPROVIDES_${PN} += "virtual/voice-high-config" + diff --git a/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-config/AlexaAutoCoreEngineConfig.json.in b/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-config/AlexaAutoCoreEngineConfig.json.in new file mode 100644 index 00000000..9ead4893 --- /dev/null +++ b/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-config/AlexaAutoCoreEngineConfig.json.in @@ -0,0 +1,184 @@ +{ + "deviceInfo": + { + "clientId":"@@ALEXA_CLIENTID@@", + "deviceSerialNumber":"@@ALEXA_SERIALNUMBER@@", + "productId":"@@ALEXA_PRODUCTID@@" + }, + "libcurlUtils": + { + "CURLOPT_CAPATH":"/etc/ssl/certs" + }, + "miscDatabase": + { + "databaseFilePath":"./miscDatabase.db" + }, + "certifiedSender": + { + "databaseFilePath":"./certifiedSender.db" + }, + "alertsCapabilityAgent": + { + "databaseFilePath":"./alertsCapabilityAgent.db" + }, + "notifications": + { + "databaseFilePath":"./notifications.db" + }, + "settings": + { + "databaseFilePath":"./settings.db", + "defaultAVSClientSettings": + { + "locale":"en-US" + } + }, + "aace.storage": { + "localStoragePath": "./sample-aace.db", + "storageType": "sqlite" + }, + "aace.vehicle": { + "info": { + "make": "Amazon", + "model": "AACE", + "year": "2018", + "trim": "aac", + "geography": "US", + "version": "1.2.3", + "os": "sample-aace", + "arch": "sample-aace", + "language": "en_US", + "microphone": "SingleArray", + "countries": "US,GB,IE,CA,DE,AT,IN,JP,AU,NZ,FR" + }, + "operatingCountry": "US", + "currentLocation": "36.1363,-115.1513" + }, + "aace.audio.input": { + "voice": "Default" + }, + "aace.audio.output": { + "tts": "Speech-High", + "music": "Speech-Low" + }, + "aace.wakeword": { + "enabled":@@WAKEWORD@@ + }, + "aace.cbl": { + "enabled": true + }, + "aace.localmediasource": { + "enabled":false, + "sources": { + "bluetooth":false, + "usb":false, + "fmRadio":false, + "amRadio":false, + "satelliteRadio":false, + "lineIn":false, + "compactDisc":false + } + }, + "aace.localvoicecontrol": { + "enabled":false, + "socketRootDirectory":"/var/" + }, + "aace.localskills": { + "aace.carcontrol": { + "enabled": false, + "cannedzones": [ + { + "name" : "zone.all", + "enabled": true, + "climate": { + "syncController": false, + "recirculationController": false + }, + "airconditioner" : { + "modes": { + "AUTO": true, + "ECONOMY": false, + "MANUAL": false, + "MAXIMIUM": false + } + }, + "heater" : { + "minimum": 60.0, + "maximum": 80.0, + "precision": 1.0, + "unit": "FAHRENHEIT" + }, + "fan" : { + "minimum": 0.0, + "maximium": 10.0, + "precision": 1.0 + }, + "vent": { + "positions" : { + "BODY": true, + "MIX": false, + "FLOOR": false, + "WINDSHIELD": false + } + }, + "window" : { + "defrost": true + }, + "light" : { + "type": "LIGHT", + "colors" : { + "WHITE": true, + "RED": true, + "ORANGE": true, + "YELLOW": true, + "GREEN": true, + "BLUE": true, + "INDIGO": true, + "VIOLET": true + } + } + }, + { + "name" : "zone.back.driver", + "enabled": false + }, + { + "name" : "zone.back.passenger", + "enabled": false + }, + { + "name" : "zone.driver", + "enabled": false + }, + { + "name" : "zone.first.row", + "enabled": false + }, + { + "name" : "zone.fourth.row", + "enabled": false + }, + { + "name" : "zone.front", + "enabled": false + }, + { + "name" : "zone.passenger", + "enabled": false + }, + { + "name" : "zone.rear", + "enabled": false + }, + { + "name" : "zone.second.row", + "enabled": false + }, + { + "name" : "zone.third.row", + "enabled": false + } + ] + } + } +} diff --git a/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-config_1.0.bb b/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-config_1.0.bb new file mode 100644 index 00000000..7e5992bb --- /dev/null +++ b/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-config_1.0.bb @@ -0,0 +1,40 @@ +SUMMARY = "Alexa service binding default configuration to connect to Alexa" +DESCRIPTION = "Alexa alexa-voiceagent-service binding configuration files" +HOMEPAGE = "https://github.com/alexa/alexa-auto-sdk/tree/master/platforms/agl/alexa-voiceagent-service" +SECTION = "apps" + +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10" + +SRC_URI = "file://AlexaAutoCoreEngineConfig.json.in" + +inherit allarch + +ALEXA_WAKEWORD ??= "false" + +do_compile () { + + if test x"${ALEXA_CLIENTID}" == x"" ; then + bbfatal "ALEXA CLIENTID not defined in your environment e.g. conf/local.conf" + fi + + if test x"${ALEXA_SERIALNUMBER}" == x"" ; then + bbfatal "ALEXA SERIALNUMBER not defined in your environment e.g. conf/local.conf" + fi + + if test x"${ALEXA_PRODUCTID}" == x"" ; then + bbfatal "ALEXA PRODUCTID not defined in your environment e.g. conf/local.conf" + fi + +} + +do_install () { + #replace + sed -e "s/@@ALEXA_CLIENTID@@/${ALEXA_CLIENTID}/" -e "s/@@ALEXA_SERIALNUMBER@@/${ALEXA_SERIALNUMBER}/" -e "s/@@ALEXA_PRODUCTID@@/${ALEXA_PRODUCTID}/" -e "s/@@WAKEWORD@@/${ALEXA_WAKEWORD}/" ${WORKDIR}/AlexaAutoCoreEngineConfig.json.in > ${WORKDIR}/AlexaAutoCoreEngineConfig.json + + # install + install -D -m 644 ${WORKDIR}/AlexaAutoCoreEngineConfig.json ${D}${sysconfdir}/xdg/AGL/AlexaAutoCoreEngineConfig.json +} + +RPROVIDES_${PN} += "virtual/alexa-voiceagent-config" + 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 index 7b0141c4..3e45c527 100644 --- 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 @@ -9,11 +9,11 @@ Upstream-Status: Inappropriate [embedded specific] Signed-off-by: Scott Murray -diff --git a/platforms/agl/alexa-voiceagent-service/libs/CMakeLists.txt b/platforms/agl/alexa-voiceagent-service/libs/CMakeLists.txt -index 4732e7b..ffc149d 100644 +diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt +index 4732e7b..938e5f3 100644 --- a/libs/CMakeLists.txt +++ b/libs/CMakeLists.txt -@@ -70,14 +70,6 @@ add_avs_library(SpeechEncoder ${AAC_HOME}/lib/libSpeechEncoder.so) +@@ -70,22 +70,13 @@ 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) @@ -28,3 +28,12 @@ index 4732e7b..ffc149d 100644 add_avs_library(equalizer ${AAC_HOME}/lib/libEqualizer.so) add_avs_library(EqualizerImplementations ${AAC_HOME}/lib/libEqualizerImplementations.so) +-if(EXISTS ${AAC_HOME}/lib/libpryon_lite.so.1.13) ++if(EXISTS ${AAC_HOME}/lib/libAACEAmazonLiteEngine.so) + add_aace_library(AACEAmazonLiteEngine) + add_avs_library(AMAZONLITE ${AAC_HOME}/lib/libAMAZONLITE.so) + add_avs_library(KeywordDetectorProvider ${AAC_HOME}/lib/libKeywordDetectorProvider.so) +- add_avs_library(pryon_lite ${AAC_HOME}/lib/libpryon_lite.so.1.13) + endif() + + if(EXISTS ${AAC_HOME}/lib/libAACEGStreamerEngine.so) diff --git a/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-service/0005-fix-segmentation-fault-for-release-build-mode.patch b/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-service/0005-fix-segmentation-fault-for-release-build-mode.patch new file mode 100644 index 00000000..5012dfe8 --- /dev/null +++ b/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-service/0005-fix-segmentation-fault-for-release-build-mode.patch @@ -0,0 +1,33 @@ +Fix segmentation fault for release build mode + +'int IAFBApi::callSync(...)' is missing a return +statement. When the sdk is compiled in release mode +executing this code results in a segmentation fault. + +According to the C++ standard, a return statement is +required on a function that returns a non-void value. +Specifically: <> + +The proposed fix provides the missing return statement +for IAFBApi's callSync method. + +Upstream-Status: Pending + +Signed-off-by: Raquel Medina + +diff --git a/platforms/agl/alexa-voiceagent-service/src/plugins/afb/AFBApiImpl.cpp b/platforms/agl/alexa-voiceagent-service/src/plugins/afb/AFBApiImpl.cpp +index 5ed9bce..e68ef7f 100644 +--- a/src/plugins/afb/AFBApiImpl.cpp ++++ b/src/plugins/afb/AFBApiImpl.cpp +@@ -77,6 +77,8 @@ int AFBApiImpl::callSync( + info = infoStr; + free(infoStr); + } ++ ++ return rc; + } + + /// Shim to transfer C++ function to C callback using void* + diff --git a/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-service/0006-fix-event-argument-json.patch b/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-service/0006-fix-event-argument-json.patch new file mode 100644 index 00000000..8c6f1e4b --- /dev/null +++ b/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-service/0006-fix-event-argument-json.patch @@ -0,0 +1,183 @@ +Fix event argument JSON + +It was discovered while trying to use some of the capabilities events +that the argument JSON was incorrectly formatted, with instances of +all or part of it being double-quoted as strings with escaping. A +couple instances of this had previously been worked around by hacks +involving reparsing all or some parts of the arguments a second time +with a JSON parser, but it seems better to fix it at the source so +that the events match documentation and are usable as is. + +Note that it is ATM not clear if all affected event argument payloads +are correct, e.g. LocalMediaSource may need some more work. + +Upstream-Status: Pending + +Signed-off-by: Scott Murray + +diff --git a/src/plugins/aasb-client/AlexaCapabilityDirectiveRouterImpl.cpp b/src/plugins/aasb-client/AlexaCapabilityDirectiveRouterImpl.cpp +index 6aea920..23ed90c 100644 +--- a/src/plugins/aasb-client/AlexaCapabilityDirectiveRouterImpl.cpp ++++ b/src/plugins/aasb-client/AlexaCapabilityDirectiveRouterImpl.cpp +@@ -17,6 +17,8 @@ + + #include + ++#include ++ + #include + + #include "AlexaConsts.h" +@@ -322,7 +324,16 @@ void AlexaCapabilityDirectiveRouterImpl::processTemplateRuntimeAction( + + json_object* argsJ = json_object_new_object(); + json_object* actionJ = json_object_new_string(vshlCapabilityAction.c_str()); +- json_object* payloadJ = json_object_new_string(payload.c_str()); ++ json_object* payloadJ = NULL; ++ if(payload.length()) { ++ payloadJ = json_tokener_parse(payload.c_str()); ++ } else { ++ payloadJ = json_object_new_string(""); ++ } ++ if(!payloadJ) { ++ m_logger->log(Level::ERROR, TAG, "Unable to parse payload JSON: " + payload); ++ return; ++ } + json_object_object_add(argsJ, agl::alexa::JSON_ATTR_ACTION.c_str(), actionJ); + json_object_object_add(argsJ, agl::alexa::JSON_ATTR_PAYLOAD.c_str(), payloadJ); + +@@ -343,24 +354,40 @@ void AlexaCapabilityDirectiveRouterImpl::processCBLAction( + const std::string& payload) { + m_logger->log(Level::DEBUG, TAG, "Processing CBL action: " + action); + +- json_object* eventDataJ = json_object_new_object(); ++ json_object* payloadJ = NULL; ++ if(payload.length()) { ++ payloadJ = json_tokener_parse(payload.c_str()); ++ } else { ++ payloadJ = json_object_new_string(""); ++ } ++ if(!payloadJ) { ++ m_logger->log(Level::ERROR, TAG, "Unable to parse payload JSON: " + payload); ++ return; ++ } ++ // The payload string may already be of the form of a document like ++ // "{ "payload" : { ... } }", the simplest way to handle that is to use ++ // it as the event json_object if that's the case, that way we avoid ++ // having to worry about copying. ++ json_object* eventDataJ = NULL; ++ if(json_object_object_get_ex(payloadJ, "payload", NULL)) { ++ eventDataJ = payloadJ; ++ } else { ++ eventDataJ = json_object_new_object(); ++ json_object_object_add(eventDataJ, JSON_ATTR_PAYLOAD.c_str(), payloadJ); ++ } + json_object* vaIdJ = json_object_new_string(m_alexaVoiceAgentId.c_str()); +- + json_object_object_add(eventDataJ, JSON_ATTR_VOICEAGENT_ID.c_str(), vaIdJ); + + int observers = 0; + if (action == aasb::bridge::ACTION_CBL_CODEPAIR_RECEIVED) { + m_logger->log(Level::INFO, TAG, "CBL codepair received: " + payload); +- json_object* payloadJ = json_object_new_string(payload.c_str()); +- json_object_object_add(eventDataJ, JSON_ATTR_PAYLOAD.c_str(), payloadJ); + observers = m_cblCodePairReceivedEvent->publishEvent(eventDataJ); + } else if (action == aasb::bridge::ACTION_CBL_CODEPAIR_EXPIRED) { + m_logger->log(Level::INFO, TAG, "CBL codepair expired: " + payload); +- json_object* payloadJ = json_object_new_string(payload.c_str()); +- json_object_object_add(eventDataJ, JSON_ATTR_PAYLOAD.c_str(), payloadJ); + observers = m_cblCodePairExpiredEvent->publishEvent(eventDataJ); + } else { + m_logger->log(Level::INFO, TAG, "Unhandled action: " + action); ++ json_object_put(eventDataJ); + } + + std::stringstream logMsg; +diff --git a/src/plugins/dispatchers/local-voice-control/car-control/CarControlDispatcher.cpp b/src/plugins/dispatchers/local-voice-control/car-control/CarControlDispatcher.cpp +index 096f72f..75108d4 100644 +--- a/src/plugins/dispatchers/local-voice-control/car-control/CarControlDispatcher.cpp ++++ b/src/plugins/dispatchers/local-voice-control/car-control/CarControlDispatcher.cpp +@@ -72,7 +72,16 @@ void CarControlDispatcher::onReceivedDirective( + + json_object* argsJ = json_object_new_object(); + json_object* actionJ = json_object_new_string(vshlCapabilityAction.c_str()); +- json_object* payloadJ = json_object_new_string(payload.c_str()); ++ json_object* payloadJ = NULL; ++ if(payload.length()) { ++ payloadJ = json_tokener_parse(payload.c_str()); ++ } else { ++ payloadJ = json_object_new_string(""); ++ } ++ if(!payloadJ) { ++ m_logger->log(Level::ERROR, TAG, "Unable to parse payload JSON: " + payload); ++ return; ++ } + json_object_object_add(argsJ, agl::alexa::JSON_ATTR_ACTION.c_str(), actionJ); + json_object_object_add(argsJ, agl::alexa::JSON_ATTR_PAYLOAD.c_str(), payloadJ); + +diff --git a/src/plugins/dispatchers/localmediasource/LocalMediaSourceDispatcher.cpp b/src/plugins/dispatchers/localmediasource/LocalMediaSourceDispatcher.cpp +index c261a56..04ac10c 100644 +--- a/src/plugins/dispatchers/localmediasource/LocalMediaSourceDispatcher.cpp ++++ b/src/plugins/dispatchers/localmediasource/LocalMediaSourceDispatcher.cpp +@@ -71,7 +71,16 @@ void LocalMediaSourceDispatcher::onReceivedDirective( + + json_object* argsJ = json_object_new_object(); + json_object* actionJ = json_object_new_string(vshlCapabilityAction.c_str()); +- json_object* payloadJ = json_object_new_string(payload.c_str()); ++ json_object* payloadJ = NULL; ++ if(payload.length()) { ++ payloadJ = json_tokener_parse(payload.c_str()); ++ } else { ++ payloadJ = json_object_new_string(""); ++ } ++ if(!payloadJ) { ++ m_logger->log(Level::ERROR, TAG, "Unable to parse payload JSON: " + payload); ++ return; ++ } + json_object_object_add(argsJ, agl::alexa::JSON_ATTR_ACTION.c_str(), actionJ); + json_object_object_add(argsJ, agl::alexa::JSON_ATTR_PAYLOAD.c_str(), payloadJ); + +diff --git a/src/plugins/dispatchers/navigation/NavigationDispatcher.cpp b/src/plugins/dispatchers/navigation/NavigationDispatcher.cpp +index 55a6017..283b42b 100644 +--- a/src/plugins/dispatchers/navigation/NavigationDispatcher.cpp ++++ b/src/plugins/dispatchers/navigation/NavigationDispatcher.cpp +@@ -68,7 +68,16 @@ void NavigationDispatcher::onReceivedDirective( + + json_object* argsJ = json_object_new_object(); + json_object* actionJ = json_object_new_string(vshlCapabilityAction.c_str()); +- json_object* payloadJ = json_object_new_string(payload.c_str()); ++ json_object* payloadJ = NULL; ++ if(payload.length()) { ++ payloadJ = json_tokener_parse(payload.c_str()); ++ } else { ++ payloadJ = json_object_new_string(""); ++ } ++ if(!payloadJ) { ++ m_logger->log(Level::ERROR, TAG, "Unable to parse payload JSON: " + payload); ++ return; ++ } + json_object_object_add(argsJ, agl::alexa::JSON_ATTR_ACTION.c_str(), actionJ); + json_object_object_add(argsJ, agl::alexa::JSON_ATTR_PAYLOAD.c_str(), payloadJ); + +diff --git a/src/plugins/dispatchers/phonecall/PhoneCallDispatcher.cpp b/src/plugins/dispatchers/phonecall/PhoneCallDispatcher.cpp +index 29ad96a..3432892 100644 +--- a/src/plugins/dispatchers/phonecall/PhoneCallDispatcher.cpp ++++ b/src/plugins/dispatchers/phonecall/PhoneCallDispatcher.cpp +@@ -86,7 +86,16 @@ void PhoneCallDispatcher::onReceivedDirective( + + json_object* argsJ = json_object_new_object(); + json_object* actionJ = json_object_new_string(vshlCapabilityAction.c_str()); +- json_object* payloadJ = json_object_new_string(payload.c_str()); ++ json_object* payloadJ = NULL; ++ if(payload.length()) { ++ payloadJ = json_tokener_parse(payload.c_str()); ++ } else { ++ payloadJ = json_object_new_string(""); ++ } ++ if(!payloadJ) { ++ m_logger->log(Level::ERROR, TAG, "Unable to parse payload JSON: " + payload); ++ return; ++ } + json_object_object_add(argsJ, agl::alexa::JSON_ATTR_ACTION.c_str(), actionJ); + json_object_object_add(argsJ, agl::alexa::JSON_ATTR_PAYLOAD.c_str(), payloadJ); + diff --git a/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-service/alexa.json b/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-service/alexa.json new file mode 100644 index 00000000..48918015 --- /dev/null +++ b/meta-agl-devel/meta-speech-framework/meta-aac/recipes-apis/alexa-voiceagent-service/alexa-voiceagent-service/alexa.json @@ -0,0 +1,14 @@ +{ + "id": "VA-001", + "active": true, + "name": "Alexa", + "api": "alexa-voiceagent", + "wakewords": [ + "alexa", + "computer", + "echo" + ], + "activewakeword": "alexa", + "description": "Alexa voice assistant by Amazon.", + "vendor": "Amazon.com Services Inc" +} 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 index 296cf2d2..f0211552 100644 --- 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 @@ -17,13 +17,17 @@ DEPENDS = " \ aac-module-navigation \ aac-module-phone-control \ aac-module-gstreamer \ + ${@bb.utils.contains("ALEXA_WAKEWORD", "true", "aac-module-amazonlite pryon-lite", "", d)} \ " SRC_URI = "git://github.com/alexa/alexa-auto-sdk.git;protocol=https;branch=2.0 \ + file://alexa.json \ 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 \ + file://0005-fix-segmentation-fault-for-release-build-mode.patch \ + file://0006-fix-event-argument-json.patch \ " SRCREV = "86916d2d8c1702a8be3c88a9012ca56583bcc0c8" @@ -34,8 +38,23 @@ inherit cmake aglwgt EXTRA_OECMAKE += "-DAAC_HOME=${RECIPE_SYSROOT}/${AAC_PREFIX}" +ALEXA_WAKEWORD ??= "false" + +do_install_append() { + install -D -m 0644 ${WORKDIR}/alexa.json ${D}${sysconfdir}/xdg/AGL/voiceagents/alexa.json +} + +PACKAGES =+ "${PN}-conf" + +FILES_${PN}-conf = "${sysconfdir}/xdg/AGL/voiceagents/*" + # NOTE: curl and opus are from the base SDK libraries, sqlite3 from the # core module -RDEPENDS_${PN} += "libcurl libopus libsqlite3" - -RPROVIDES_${PN} += "virtual/voiceagent" +RDEPENDS_${PN} += " \ + libcurl \ + libopus \ + libsqlite3 \ + ${PN}-conf \ + ${@bb.utils.contains("ALEXA_WAKEWORD", "true", "pryon-lite", "", d)} \ + gstreamer1.0-plugins-bad-hls \ +" diff --git a/meta-agl-devel/meta-speech-framework/meta-aac/recipes-platform/packagegroups/packagegroup-agl-ivi-services.bbappend b/meta-agl-devel/meta-speech-framework/meta-aac/recipes-platform/packagegroups/packagegroup-agl-ivi-services.bbappend new file mode 100644 index 00000000..43836942 --- /dev/null +++ b/meta-agl-devel/meta-speech-framework/meta-aac/recipes-platform/packagegroups/packagegroup-agl-ivi-services.bbappend @@ -0,0 +1,4 @@ +RDEPENDS_${PN} += " \ + alexa-voiceagent-service \ + ${@bb.utils.contains("DISTRO_FEATURES", "agl-demo-preload", "virtual/alexa-voiceagent-config", "",d)} \ +" diff --git a/meta-agl-devel/meta-speech-framework/meta-aac/recipes-platform/packagegroups/packagegroup-agl-voiceagent-alexa.bb b/meta-agl-devel/meta-speech-framework/meta-aac/recipes-platform/packagegroups/packagegroup-agl-voiceagent-alexa.bb new file mode 100644 index 00000000..5f38e7ef --- /dev/null +++ b/meta-agl-devel/meta-speech-framework/meta-aac/recipes-platform/packagegroups/packagegroup-agl-voiceagent-alexa.bb @@ -0,0 +1,15 @@ +SUMMARY = "The software for the AGL Alexa voiceagent feature" +DESCRIPTION = "The software for the AGL Alexa voiceagent feature" + +LICENSE = "MIT" + +inherit packagegroup + +PACKAGES = "\ + packagegroup-agl-voiceagent-alexa \ +" + +RDEPENDS_${PN} += " \ + alexa-voiceagent-service \ + ${@bb.utils.contains("DISTRO_FEATURES", "agl-demo-preload", "virtual/alexa-voiceagent-config", "",d)} \ +" 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 index efeba097..6ab4da9c 100644 --- 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 @@ -6,14 +6,12 @@ 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" +DEPENDS = "libafb-helpers libappcontroller nlohmann-json" -SRC_URI = "gitsm://gerrit.automotivelinux.org/gerrit/apps/agl-service-voice-high-capabilities.git;protocol=https;branch=${AGL_BRANCH}" +SRC_URI = "git://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" +inherit cmake pkgconfig aglwgt 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 index 9b9fa928..b8ee77fd 100644 --- 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 @@ -6,7 +6,9 @@ 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}" +DEPENDS = "json-c systemd af-binder libafb-helpers libappcontroller nlohmann-json glib-2.0" + +SRC_URI = "git://gerrit.automotivelinux.org/gerrit/apps/agl-service-voice-high;protocol=https;branch=${AGL_BRANCH}" SRCREV = "${AGL_APP_REVISION}" PV = "1.0+git${SRCPV}" @@ -14,4 +16,3 @@ 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-apis/agl-service-voice-high/default-voice-high-config/voice-high.json b/meta-agl-devel/meta-speech-framework/recipes-apis/agl-service-voice-high/default-voice-high-config/voice-high.json new file mode 100644 index 00000000..1b72b8c8 --- /dev/null +++ b/meta-agl-devel/meta-speech-framework/recipes-apis/agl-service-voice-high/default-voice-high-config/voice-high.json @@ -0,0 +1 @@ +{ "default": "" } diff --git a/meta-agl-devel/meta-speech-framework/recipes-apis/agl-service-voice-high/default-voice-high-config_1.0.bb b/meta-agl-devel/meta-speech-framework/recipes-apis/agl-service-voice-high/default-voice-high-config_1.0.bb new file mode 100644 index 00000000..b015dd5d --- /dev/null +++ b/meta-agl-devel/meta-speech-framework/recipes-apis/agl-service-voice-high/default-voice-high-config_1.0.bb @@ -0,0 +1,20 @@ +SUMMARY = "High level voice service binding default voiceagent configuration" +DESCRIPTION = "Default voiceagent JSON configuration file for agl-service-voice-high binding" +HOMEPAGE = "https://gerrit.automotivelinux.org/gerrit/apps/agl-service-voice-high" +SECTION = "apps" + +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10" + +SRC_URI = "file://voice-high.json" + +inherit allarch + +do_compile[noexec] = "1" + +do_install () { + install -D -m 644 ${WORKDIR}/voice-high.json ${D}${sysconfdir}/xdg/AGL/voice-high.json +} + +RPROVIDES_${PN} += "virtual/voice-high-config" + 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 deleted file mode 100644 index 42fc5e58..00000000 --- a/meta-agl-devel/meta-speech-framework/recipes-platform/packagegroups/packagegroup-agl-core-services.bbappend +++ /dev/null @@ -1,7 +0,0 @@ -# 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/meta-speech-framework/recipes-platform/packagegroups/packagegroup-agl-ivi-services.bbappend b/meta-agl-devel/meta-speech-framework/recipes-platform/packagegroups/packagegroup-agl-ivi-services.bbappend new file mode 100644 index 00000000..7e918671 --- /dev/null +++ b/meta-agl-devel/meta-speech-framework/recipes-platform/packagegroups/packagegroup-agl-ivi-services.bbappend @@ -0,0 +1,5 @@ +RDEPENDS_${PN} += " \ + agl-service-voice-high \ + agl-service-voice-high-capabilities \ + ${PREFERRED_RPROVIDER_virtual/voice-high-config} \ +" 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 deleted file mode 100644 index 952ef4ea..00000000 --- a/meta-agl-devel/templates/feature/agl-html5-framework/50_bblayers.conf.inc +++ /dev/null @@ -1,5 +0,0 @@ - -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 deleted file mode 100644 index d992009c..00000000 --- a/meta-agl-devel/templates/feature/agl-html5-framework/README_feature_agl-html5-framework.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -description: Feature agl-html5-framework -authors: Jacobo Aragunde Pérez ---- - -### 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-profile-graphical-html5/50_bblayers.conf.inc b/meta-agl-devel/templates/feature/agl-profile-graphical-html5/50_bblayers.conf.inc new file mode 100644 index 00000000..a7e9da1d --- /dev/null +++ b/meta-agl-devel/templates/feature/agl-profile-graphical-html5/50_bblayers.conf.inc @@ -0,0 +1,5 @@ + +BBLAYERS =+ " \ + ${METADIR}/meta-agl-devel/meta-agl-profile-graphical-html5 \ + " + diff --git a/meta-agl-devel/templates/feature/agl-profile-graphical-html5/50_local.conf.inc b/meta-agl-devel/templates/feature/agl-profile-graphical-html5/50_local.conf.inc new file mode 100644 index 00000000..0b2d7002 --- /dev/null +++ b/meta-agl-devel/templates/feature/agl-profile-graphical-html5/50_local.conf.inc @@ -0,0 +1,3 @@ + +IMAGE_INSTALL_append = " packagegroup-agl-profile-graphical-html5" + diff --git a/meta-agl-devel/templates/feature/agl-profile-graphical-html5/README_feature_agl-profile-graphical-html5.md b/meta-agl-devel/templates/feature/agl-profile-graphical-html5/README_feature_agl-profile-graphical-html5.md new file mode 100644 index 00000000..dc00f94c --- /dev/null +++ b/meta-agl-devel/templates/feature/agl-profile-graphical-html5/README_feature_agl-profile-graphical-html5.md @@ -0,0 +1,8 @@ +--- +description: Feature agl-profile-graphical-html5 +authors: Jacobo Aragunde Pérez +--- + +### Feature agl-profile-graphical-html5 + +Packages required to run web applications in AGL. The provided image agl-image-graphical-html5 includes the minimum set of packages required for this purpose. diff --git a/meta-agl-devel/templates/feature/agl-profile-graphical-html5/included.dep b/meta-agl-devel/templates/feature/agl-profile-graphical-html5/included.dep new file mode 100644 index 00000000..032609b8 --- /dev/null +++ b/meta-agl-devel/templates/feature/agl-profile-graphical-html5/included.dep @@ -0,0 +1 @@ +agl-profile-graphical diff --git a/meta-agl-devel/templates/feature/agl-voiceagent-alexa-wakeword/50_bblayers.conf.inc b/meta-agl-devel/templates/feature/agl-voiceagent-alexa-wakeword/50_bblayers.conf.inc new file mode 100644 index 00000000..31f4dca8 --- /dev/null +++ b/meta-agl-devel/templates/feature/agl-voiceagent-alexa-wakeword/50_bblayers.conf.inc @@ -0,0 +1,6 @@ +BBLAYERS =+ " \ + ${METADIR}/external/alexa-auto-sdk/extensions/extras/amazonlite/meta-aac-amazonlite \ +" + +# Include the recipe for the required module as well +BBFILES += "${METADIR}/external/alexa-auto-sdk/extensions/extras/amazonlite/modules/*/*.bb" diff --git a/meta-agl-devel/templates/feature/agl-voiceagent-alexa-wakeword/50_local.conf.inc b/meta-agl-devel/templates/feature/agl-voiceagent-alexa-wakeword/50_local.conf.inc new file mode 100644 index 00000000..41af3db8 --- /dev/null +++ b/meta-agl-devel/templates/feature/agl-voiceagent-alexa-wakeword/50_local.conf.inc @@ -0,0 +1 @@ +ALEXA_WAKEWORD = "true" diff --git a/meta-agl-devel/templates/feature/agl-voiceagent-alexa-wakeword/README_feature_agl-voiceagent-alexa-wakeword.md b/meta-agl-devel/templates/feature/agl-voiceagent-alexa-wakeword/README_feature_agl-voiceagent-alexa-wakeword.md new file mode 100644 index 00000000..e8491289 --- /dev/null +++ b/meta-agl-devel/templates/feature/agl-voiceagent-alexa-wakeword/README_feature_agl-voiceagent-alexa-wakeword.md @@ -0,0 +1,10 @@ +--- +description: Feature agl-voiceagent-alexa-wakeword +authors: Scott Murray +--- + +### Feature agl-voiceagent-alexa-wakeword + +Enables building the Amazon Alexa voiceagent binding with included wakeword engine support. + +Note that this features assumes that the amazonlite wakeword engine ZIP file (e.g. amazonlite-2.0.zip) containing the required additional files has been decompressed to external/alexa-auto-sdk/extensions/extras/amazonlite in the tree. Without this, attempting to build with bitbake will fail. Please contact your Amazon Alexa developer account representative if you wish to obtain the wakeword engine. diff --git a/meta-agl-devel/templates/feature/agl-voiceagent-alexa-wakeword/included.dep b/meta-agl-devel/templates/feature/agl-voiceagent-alexa-wakeword/included.dep new file mode 100644 index 00000000..71688dda --- /dev/null +++ b/meta-agl-devel/templates/feature/agl-voiceagent-alexa-wakeword/included.dep @@ -0,0 +1 @@ +agl-voiceagent-alexa -- cgit 1.2.3-korg