summaryrefslogtreecommitdiffstats
path: root/default-floating.xml
blob: 2de998fa08aa9e63a395ed7d695ed8cb10e506f2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
<?xml version="1.0" encoding="UTF-8"?>
<manifest>

  <!-- remote servers to query -->
  <remote name="agl"
         fetch="https://gerrit.automotivelinux.org/gerrit/"
         review="https://gerrit.automotivelinux.org/gerrit/"
         pushurl="ssh://gerrit.automotivelinux.org:29418"
  />
  <remote name="yocto" fetch="https://git.yoctoproject.org/git/" />
  <remote name="github" fetch="https://github.com/" />
  <remote name="openembedded" fetch="https://git.openembedded.org/" />

  <!-- defaults -->
  <default remote="agl" sync-j="4" revision="master"/>


  <!-- CORE -->

  <!-- use agl revisions/branches here -->

  <!-- AGL things. -->
  <project name="AGL/meta-agl" path="meta-agl" />
  <project name="AGL/meta-agl-demo" path="meta-agl-demo" />
  <project name="AGL/meta-agl-devel" path="meta-agl-devel" />


  <!-- FLOATING has no fixed revision for external repos ! -->

  <!-- YOCTO & OE -->

  <!-- Yocto/OpenEmbedded things. -->
  <project name="poky" path="external/poky" remote="yocto" revision="kirkstone" />
  <project name="openembedded/meta-openembedded" path="external/meta-openembedded" remote="github" revision="kirkstone" />
  <project name="meta-lts-mixins" path="external/meta-lts-mixins_rust-1.68" remote="yocto" revision="kirkstone/rust-1.68" />


  <!-- UPSTREAM COMPONENTS -->

  <!-- meta-virtualization -->
  <project name="meta-virtualization" path="external/meta-virtualization" remote="yocto" revision="kirkstone"/>

  <!-- Qt things -->
  <project name="meta-qt5/meta-qt5" path="external/meta-qt5" remote="github" revision="kirkstone"/>

  <!-- Security layer -->
  <project name="meta-security" path="external/meta-security" remote="yocto" revision="kirkstone"/>

  <!-- SELinux layer -->
  <project name="meta-selinux" path="external/meta-selinux" remote="yocto" revision="kirkstone"/>

  <!-- meta-codescanner - support for using CodeScanner during the build -->
  <project name="dl9pf/meta-codechecker" path="external/meta-codechecker" remote="github" revision="master"/>

  <!-- meta-spdxscanner - support for fossology -->
  <project name="meta-spdxscanner" path="external/meta-spdxscanner" remote="yocto" revision="master"/>

  <!-- clang support -->
  <project name="kraj/meta-clang" path="external/meta-clang" remote="github" revision="kirkstone"/>

  <!-- meta-python2 as stop-gap to allow chromium to build until upstream fixes the dependencies -->
  <project name="meta-python2" path="external/meta-python2" remote="openembedded" revision="kirkstone" />

  <!-- meta-flutter -->
  <project name="meta-flutter/meta-flutter" path="external/meta-flutter" remote="github" revision="kirkstone"/>

  <!-- BSPs -->

  <!-- Renesas Gen3 specific things -->
  <project name="renesas-rcar/meta-renesas" path="bsp/meta-renesas" remote="github" revision="kirkstone-dev"/>
  <project name="CogentEmbedded/meta-rcar" path="bsp/meta-rcar" remote="github" revision="kirkstone-Yocto-v5.9.0"/>
  <project name="AGL/meta-agl-refhw" path="bsp/meta-agl-refhw" />

  <!-- consolidate on meta-freescale from git.yoctoproject.org -->
  <project name="meta-freescale" path="bsp/meta-freescale" remote="yocto" revision="kirkstone"/>
  <project name="Freescale/meta-freescale-3rdparty" path="bsp/meta-freescale-3rdparty" remote="github" revision="kirkstone"/>

  <!-- TI Vayu / Jacinto 6 / DRA7 -->
  <project name="meta-arm" path="bsp/meta-arm" remote="yocto" revision="kirkstone"/>
  <project name="meta-ti" path="bsp/meta-ti" remote="yocto" revision="kirkstone"/>

  <!-- Raspberry Pi 3, 3B+, and 4 -->
  <project name="meta-raspberrypi" path="bsp/meta-raspberrypi" remote="yocto" revision="kirkstone"/>

  <!-- Sancloud BSP layers -->
  <project name="SanCloudLtd/meta-sancloud" path="bsp/meta-sancloud" remote="github" revision="kirkstone"/>
  <project name="EmbeddedAndroid/meta-rtlwifi" path="bsp/meta-rtlwifi" remote="github" revision="master"/>

  <!-- Sifive BSP -->
  <project name="dl9pf/meta-sifive" path="bsp/meta-sifive" remote="github" revision="master"/>

</manifest>
eT *handle = (apiHandleT*) afb_request_get_vcbdata(request); int error, doClose = 0, doQuiet = 0, doToggle = 0, doMute = -1; long mute, volume; json_object *responseJ, *volumeJ = NULL, *rampJ = NULL, *argsJ = afb_request_json(request); SoftMixerT *mixer = handle->mixer; AlsaSndCtlT *sndcard = handle->sndcard; assert(mixer && sndcard); error = wrap_json_unpack(argsJ, "{s?b s?b,s?b,s?b,s?o,s?o !}" , "quiet", &doQuiet , "close", &doClose , "mute", &doMute , "toggle", &doToggle , "volume", &volumeJ , "ramp", &rampJ ); if (error) { AFB_ReqFailF(request, "syntax-error", "Missing 'close|mute|volume|quiet' args=%s", json_object_get_string(argsJ)); goto OnErrorExit; } if (doClose) { AFB_ReqFailF(request, "internal-error", "(Fulup) Close action still to be done mixer=%s stream=%s", mixer->uid, handle->stream->uid); goto OnErrorExit; } if (doToggle) { error += AlsaCtlNumidGetLong(mixer, sndcard, handle->stream->mute, &mute); error += AlsaCtlNumidSetLong(mixer, sndcard, handle->stream->mute, !mute); } if (volumeJ) { long curvol, newvol; const char*volString; error = AlsaCtlNumidGetLong(mixer, handle->sndcard, handle->stream->volume, &curvol); if (error) { AFB_ReqFailF(request, "invalid-numid", "Fail to get volume numid=%d value=%ld", handle->stream->volume, volume); goto OnErrorExit; } switch (json_object_get_type(volumeJ)) { case json_type_string: volString = json_object_get_string(volumeJ); switch (volString[0]) { case '+': sscanf(&volString[1], "%ld", &newvol); newvol = curvol + newvol; break; case '-': sscanf(&volString[1], "%ld", &newvol); newvol = curvol - newvol; break; default: error = sscanf(&volString[0], "%ld", &newvol); if (error != 1) { AFB_ReqFailF(request, "not-integer", "relative volume should start by '+|-' value=%s", json_object_get_string(volumeJ)); goto OnErrorExit; } } break; case json_type_int: newvol = json_object_get_int(volumeJ); break; default: AFB_ReqFailF(request, "not-integer", "volume should be string or integer value=%s", json_object_get_string(volumeJ)); goto OnErrorExit; } error = AlsaCtlNumidSetLong(mixer, handle->sndcard, handle->stream->volume, newvol); if (error) { AFB_ReqFailF(request, "StreamApiVerbCB", "Fail to set stream volume numid=%d value=%ld", handle->stream->volume, newvol); goto OnErrorExit; } } if (rampJ) { error = AlsaVolRampApply(mixer, handle->sndcard, handle->stream, rampJ); if (error) { AFB_ReqFailF(request, "StreamApiVerbCB", "Fail to set stream volram numid=%d value=%s", handle->stream->volume, json_object_get_string(rampJ)); goto OnErrorExit; } } if (doMute != -1) { error = AlsaCtlNumidSetLong(mixer, handle->sndcard, handle->stream->mute, !mute); if (error) { AFB_ReqFailF(request, "StreamApiVerbCB", "Fail to set stream volume numid=%d value=%d", handle->stream->volume, !mute); goto OnErrorExit; } } // if not in quiet mode return effective selected control values if (doQuiet) responseJ = NULL; else { error += AlsaCtlNumidGetLong(mixer, handle->sndcard, handle->stream->volume, &volume); error += AlsaCtlNumidGetLong(mixer, handle->sndcard, handle->stream->mute, &mute); if (error) { AFB_ReqFailF(request, "StreamApiVerbCB", "Fail to get stream numids volume=%ld mute=%ld", volume, mute); goto OnErrorExit; } wrap_json_pack(&responseJ, "{si,sb}", "volume", volume, "mute", !mute); } AFB_ReqSucess(request, responseJ, NULL); return; OnErrorExit: return; } PUBLIC int CreateOneStream(SoftMixerT *mixer, AlsaStreamAudioT *stream) { int error; long value; AlsaSndLoopT *loop = NULL; AlsaPcmCtlT *streamPcm; AlsaSndCtlT *captureCard; AlsaDevInfoT *captureDev = alloca(sizeof (AlsaDevInfoT)); AlsaLoopSubdevT *loopDev; char * captureName; loopDev = ApiLoopFindSubdev(mixer, stream->uid, stream->source, &loop); if (loopDev) { // create a valid PCM reference and try to open it. captureDev->devpath = NULL; captureDev->cardid = NULL; captureDev->cardidx = loop->sndcard->cid.cardidx; captureDev->device = loop->capture; captureDev->subdev = loopDev->index; captureCard = loop->sndcard; } else { // if capture UID is not present in loop search on sources AlsaSndCtlT *sourceDev = ApiSourceFindSubdev(mixer, stream->source); if (sourceDev) { captureDev->devpath = NULL; captureDev->cardid = NULL; captureDev->cardidx = sourceDev->cid.cardidx; captureDev->device = sourceDev->cid.device; captureDev->subdev = sourceDev->cid.subdev; captureCard = sourceDev; } else { AFB_ApiError(mixer->api, "CreateOneStream: mixer=%s stream=%s not found in loops/sources", mixer->uid, stream->uid); goto OnErrorExit; } } // check PCM is valid and get its full name AlsaPcmCtlT *capturePcm = AlsaByPathOpenPcm(mixer, captureDev, SND_PCM_STREAM_CAPTURE); if (!capturePcm) goto OnErrorExit; // Registry capturePcm PCM for active/pause event if (loopDev && loopDev->numid) { error = AlsaCtlRegister(mixer, captureCard, capturePcm, FONTEND_NUMID_RUN, loopDev->numid); if (error) goto OnErrorExit; } AlsaSndZoneT *zone = ApiZoneGetByUid(mixer, stream->sink); if (!zone) { AFB_ApiError(mixer->api, "CreateOneStream: mixer=%s stream=%s fail to find sink zone='%s'", mixer->uid, stream->uid, stream->sink); goto OnErrorExit; } // retrieve channel count from route and push it to stream stream->params->channels = zone->ccount; // create mute control and Registry it as pause/resume ctl) char *runName; (void) asprintf(&runName, "pause-%s", stream->uid); int pauseNumid = AlsaCtlCreateControl(mixer, captureCard, runName, 1, 0, 1, 1, stream->mute); if (pauseNumid <= 0) goto OnErrorExit; // Registry stop/play as a pause/resume control error = AlsaCtlRegister(mixer, captureCard, capturePcm, FONTEND_NUMID_PAUSE, pauseNumid); if (error) goto OnErrorExit; char *volName; (void) asprintf(&volName, "vol-%s", stream->uid); // create stream and delay pcm opening until vol control is created streamPcm = AlsaCreateSoftvol(mixer, stream, zone, captureCard, volName, VOL_CONTROL_MAX, 0); if (!streamPcm) { AFB_ApiError(mixer->api, "CreateOneStream: mixer=%s stream=%s fail to create stream", mixer->uid, stream->uid); goto OnErrorExit; } // create volume control before softvol pcm is opened int volNumid = AlsaCtlCreateControl(mixer, captureCard, volName, stream->params->channels, VOL_CONTROL_MIN, VOL_CONTROL_MAX, VOL_CONTROL_STEP, stream->volume); if (volNumid <= 0) goto OnErrorExit; if ((zone->params->rate != stream->params->rate) || (zone->params->format != stream->params->format)) { char *rateName; (void) asprintf(&rateName, "rate-%s", stream->uid); streamPcm = AlsaCreateRate(mixer, rateName, streamPcm, zone->params, 0); if (!streamPcm) { AFB_ApiError(mixer->api, "StreamsAttach: mixer=%s stream=%s fail to create rate converter", mixer->uid, stream->uid); goto OnErrorExit; } captureName = rateName; } else { captureName = (char*) streamPcm->cid.cardid; } // everything is not ready to open playback pcm error = snd_pcm_open(&streamPcm->handle, captureName, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); if (error) { AFB_ApiError(mixer->api, "CreateOneStream: mixer=%s stream=%s fail to open capturePcm=%s error=%s", mixer->uid, stream->uid, streamPcm->cid.cardid, snd_strerror(error)); goto OnErrorExit; } // start stream pcm copy (at this both capturePcm & sink pcm should be open, we use output params to configure both in+outPCM) error = AlsaPcmCopy(mixer, stream, capturePcm, streamPcm, stream->params); if (error) goto OnErrorExit; error = AlsaCtlRegister(mixer, captureCard, capturePcm, FONTEND_NUMID_IGNORE, volNumid); if (error) goto OnErrorExit; // when using loopdev check if subdev is active or not to prevent thread from reading empty packet if (loopDev && loopDev->numid) { // retrieve active/pause control and set PCM status accordingly error = AlsaCtlNumidGetLong(mixer, captureCard, loopDev->numid, &value); if (error) goto OnErrorExit; // toggle pause/resume (should be done after pcm_start) if ((error = snd_pcm_pause(capturePcm->handle, !value)) < 0) { AFB_ApiWarning(mixer->api, "CreateOneStream: mixer=%s [capturePcm=%s] fail to pause error=%s", mixer->uid, captureDev->cardid, snd_strerror(error)); } } // return alsa URI only when loopback is used if (loop) { (void) asprintf((char**)&stream->source, "hw:%d,%d,%d", captureDev->cardidx, loop->playback, capturePcm->cid.subdev); } else { stream->source=NULL; } // create a dedicated verb for this stream apiHandleT *apiHandle = calloc(1, sizeof (apiHandleT)); apiHandle->mixer = mixer; apiHandle->stream = stream; apiHandle->sndcard = captureCard; apiHandle->pcm = capturePcm->handle; // replace stream volume/mute values with corresponding ctl control stream->volume = volNumid; stream->mute = pauseNumid; error = afb_dynapi_add_verb(mixer->api, stream->uid, stream->info, StreamApiVerbCB, apiHandle, NULL, 0); if (error) { AFB_ApiError(mixer->api, "CreateOneStream mixer=%s fail to Register API verb stream=%s", mixer->uid, stream->uid); goto OnErrorExit; } // Debug Alsa Config //AlsaDumpElemConfig (source, "\n\nAlsa_Config\n------------\n", "pcm"); //AlsaDumpPcmInfo(source, "\n\nPcm_config\n-----------\n", streamPcm->handle); AFB_ApiNotice(mixer->api, "CreateOneStream: mixer=%s stream=%s done", mixer->uid, stream->uid); return 0; OnErrorExit: return -1; } STATIC AlsaStreamAudioT * AttachOneStream(SoftMixerT *mixer, const char *uid, json_object *streamJ) { AlsaStreamAudioT *stream = calloc(1, sizeof (AlsaStreamAudioT)); int error; json_object *paramsJ = NULL; // Make sure default runs stream->volume = ALSA_DEFAULT_PCM_VOLUME; stream->mute = 0; stream->info = NULL; error = wrap_json_unpack(streamJ, "{ss,s?s,ss,s?s,s?i,s?b,s?o,s?s !}" , "uid", &stream->uid , "info", &stream->info , "zone", &stream->sink , "source", &stream->source , "volume", &stream->volume , "mute", &stream->mute , "params", &paramsJ , "ramp", &stream->ramp ); if (error) { AFB_ApiNotice(mixer->api, "ProcessOneStream hal=%s missing 'uid|[info]|zone|source||[volume]|[mute]|[params]' error=%s stream=%s", uid, wrap_json_get_error_string(error), json_object_get_string(streamJ)); goto OnErrorExit; } stream->params = ApiPcmSetParams(mixer, stream->uid, paramsJ); if (!stream->params) { AFB_ApiError(mixer->api, "ProcessOneSndCard: hal=%s stream=%s invalid params=%s", uid, stream->uid, json_object_get_string(paramsJ)); goto OnErrorExit; } // make sure remain valid even when json object is removed stream->uid = strdup(stream->uid); if (stream->sink)stream->sink = strdup(stream->sink); if (stream->source)stream->source = strdup(stream->source); // implement stream PCM with corresponding thread and controls error = CreateOneStream(mixer, stream); if (error) goto OnErrorExit; return stream; OnErrorExit: free(stream); return NULL; } PUBLIC int ApiStreamAttach(SoftMixerT *mixer, AFB_ReqT request, const char *uid, json_object * argsJ) { if (!mixer->loops) { AFB_ApiError(mixer->api, "StreamsAttach: mixer=%s No Loop found [should Registry snd_loop first]", mixer->uid); goto OnErrorExit; } int index; for (index = 0; index < mixer->max.streams; index++) { if (!mixer->streams[index]) break; } if (index == mixer->max.streams) { AFB_ReqFailF(request, "too-small", "mixer=%s max stream=%d argsJ= %s", mixer->uid, mixer->max.streams, json_object_get_string(argsJ)); goto OnErrorExit; } switch (json_object_get_type(argsJ)) { long count; case json_type_object: mixer->streams[index] = AttachOneStream(mixer, uid, argsJ); if (!mixer->streams[index]) { AFB_ReqFailF(request, "invalid-syntax", "mixer=%s invalid stream= %s", mixer->uid, json_object_get_string(argsJ)); goto OnErrorExit; } break; case json_type_array: count = json_object_array_length(argsJ); if (count > (mixer->max.streams - count)) { AFB_ReqFailF(request, "too-small", "mixer=%s max stream=%d argsJ= %s", mixer->uid, mixer->max.streams, json_object_get_string(argsJ)); goto OnErrorExit; } for (int idx = 0; idx < count; idx++) { json_object *streamJ = json_object_array_get_idx(argsJ, idx); mixer->streams[index + idx] = AttachOneStream(mixer, uid, streamJ); if (!mixer->streams[index + idx]) { AFB_ReqFailF(request, "invalid-syntax", "mixer=%s invalid stream= %s", mixer->uid, json_object_get_string(streamJ)); goto OnErrorExit; } } break; default: AFB_ReqFailF(request, "invalid-syntax", "mixer=%s streams invalid argsJ= %s", mixer->uid, json_object_get_string(argsJ)); goto OnErrorExit; } return 0; OnErrorExit: return -1; }