| author | Stephen Paul Weber
<singpolyma@singpolyma.net> 2025-10-23 06:05:24 UTC |
| committer | Stephen Paul Weber
<singpolyma@singpolyma.net> 2025-10-23 06:05:24 UTC |
| parent | c8ed3a863d711e1110bd69cbbf249e8fa8d5864e |
| HaxeCBridge.hx | +39 | -7 |
| borogove/calls/PeerConnection.cpp.hx | +2 | -6 |
diff --git a/HaxeCBridge.hx b/HaxeCBridge.hx index 9fb3046..815a8f0 100644 --- a/HaxeCBridge.hx +++ b/HaxeCBridge.hx @@ -182,6 +182,13 @@ class HaxeCBridge { if (field.access.contains(AOverride)) { field.meta.push({name: "HaxeCBridge.noemit", pos: field.pos}); } + final gcFree = field.meta.filter(m -> m.name == "HaxeCBridge.gcFree").map(m -> + switch (m.params[0].expr) { + case EConst(CIdent(id)): id; + default: null; + } + ); + field.meta = field.meta.filter(m -> m.name != "HaxeCBridge.gcFree"); if (field.access.contains(APublic) && !field.access.contains(AOverride) && !field.meta.exists((m) -> m.name == "HaxeCBridge.noemit")) { switch field.kind { case FFun(fun): @@ -208,19 +215,44 @@ class HaxeCBridge { aret = convertSecondaryType(aret).args[0]; args.push({name: arg.name, type: TPath({name: "Callable", pack: ["cpp"], params: [TPType(TFunction(Lambda.flatten(aargs.map(aarg -> aarg.args)).concat([TPath({name: "RawPointer", pack: ["cpp"], params: [TPType(TPath({ name: "Void", pack: ["cpp"] }))]})]), aret))]})}); args.push({name: arg.name + "__context", type: TPath({name: "RawPointer", pack: ["cpp"], params: [TPType(TPath({ name: "Void", pack: ["cpp"] }))]})}); - final lambdaargs = Lambda.flatten(aargs.mapi((i, a) -> + final lambdaargs = []; + final lambdabody = Lambda.flatten(aargs.mapi((i, a) -> if (a.retainType == "Array") { - [macro $i{"a" + i}, macro $i{"a" + i}.length]; + final t = a.args[0]; + lambdaargs.push(macro $i{"x" + i}); + lambdaargs.push(macro $i{"xl" + i}); + final x = "x" + i; + final xl = "xl" + i; + [macro final $x : $t = $i{"a" + i}].concat([macro final $xl = $i{"a" + i}.length]); } else if (a.retainType == "String") { - [macro HaxeCBridge.retainHaxeString($i{"a" + i})]; + lambdaargs.push(macro $i{"x" + i}); + final name = "x" + i; + [macro final $name = HaxeCBridge.retainHaxeString($i{"a" + i})]; } else if (a.retainType == "Object") { - [macro HaxeCBridge.retainHaxeObject($i{"a" + i})]; + lambdaargs.push(macro $i{"x" + i}); + final name = "x" + i; + [macro final $name = HaxeCBridge.retainHaxeObject($i{"a" + i})]; } else { - [macro $i{"a" + i}]; + lambdaargs.push(macro $i{"a" + i}); + []; } - )).concat([macro $i{arg.name + "__context"}]); + )); + lambdaargs.push(macro $i{arg.name + "__context"}); + if (gcFree.contains(arg.name)) lambdabody.push(macro cpp.NativeGc.enterGCFreeZone()); + switch (aret) { + case TPath(_.sub => "Void"): + lambdabody.push(macro $i{arg.name}($a{lambdaargs})); + default: + lambdabody.push(macro final ret = $i{arg.name}($a{lambdaargs})); + } + if (gcFree.contains(arg.name)) lambdabody.push(macro cpp.NativeGc.exitGCFreeZone()); + switch (aret) { + case TPath(_.sub => "Void"): + default: + lambdabody.push(macro return ret); + } final lambdafargs = aargs.mapi((i, a) -> {name: "a" + i, meta: null, opt: false, type: null, value: null}); - passArgs.push({expr: EFunction(null, { args: lambdafargs, expr: macro return $i{arg.name}($a{lambdaargs}) }), pos: field.pos}); + passArgs.push({expr: EFunction(null, { args: lambdafargs, expr: macro $b{lambdabody} }), pos: field.pos}); case TPath(path) if (path.name == "Array"): wrap = true; final isString = switch path.params[0] { diff --git a/borogove/calls/PeerConnection.cpp.hx b/borogove/calls/PeerConnection.cpp.hx index a5168b7..0b29c93 100644 --- a/borogove/calls/PeerConnection.cpp.hx +++ b/borogove/calls/PeerConnection.cpp.hx @@ -464,6 +464,7 @@ class MediaStreamTrack { @param callback takes three arguments, the Signed 16-bit PCM data, the clock rate, and the number of channels **/ + @HaxeCBridge.gcFree(callback) public function addPCMListener(callback: (Array<cpp.Int16>,Int,Int)->Void) { pcmCallback = callback; } @@ -501,9 +502,7 @@ class MediaStreamTrack { s16[i] = ULAW_DECODE[cast msg.at(i)]; } if (pcmCallback != null) { - cpp.vm.Gc.enterGCFreeZone(); pcmCallback(s16.toData(), rtp.clockRate, channels); - cpp.vm.Gc.exitGCFreeZone(); } } else if (format == "opus") { final s16 = new haxe.ds.Vector(5760).toData(); // 5760 is the max size needed for 48khz @@ -512,9 +511,7 @@ class MediaStreamTrack { final decoded = OpusDecoder.decode(opus, cast msg.data(), msg.size(), cpp.Pointer.ofArray(s16), Std.int(s16.length / channels), false); s16.resize(decoded * channels); if (pcmCallback != null) { - cpp.vm.Gc.enterGCFreeZone(); pcmCallback(s16, rtp.clockRate, channels); - cpp.vm.Gc.exitGCFreeZone(); } } else { trace("Ignoring audio frame with format", format); @@ -527,6 +524,7 @@ class MediaStreamTrack { @param callback **/ + @HaxeCBridge.gcFree(callback) public function addReadyForPCMListener(callback: ()->Void) { readyForPCMCallback = callback; if (untyped __cpp__("track") && track.ref.isOpen()) { @@ -543,9 +541,7 @@ class MediaStreamTrack { waitForQ = true; mutex.release(); } else { - cpp.vm.Gc.enterGCFreeZone(); readyForPCMCallback(); - cpp.vm.Gc.exitGCFreeZone(); } }); }