// SPDX-License-Identifier: GPL-3.0-only // Copyright (c) 2022, Sylvain Huet, Ambermind // Minimacy (r) System const _INTERNAL_MAX_CODE=32;; struct _Internal=Stream+[];; var _InternalPipe;; var _InternalBuffer;; var _InternalHook = arrayCreate(_INTERNAL_MAX_CODE, nil);; var _InternalGrouping;; var _InternalExt = hashmapCreate(4);; fun _registerInternalHook(event, cb)=set _InternalHook[event]=cb;; fun registerInternalExt(event, f) = hashmapSet(_InternalExt, event, if f<>nil then let _This -> th in lambda(data) = threadPost(th, lambda()= call f(data)));; fun _internalExtAlive ()= 0<>hashmapCount(_InternalExt);; fun _flushInternalGrouping(except)= if _InternalGrouping<>nil then let _InternalGrouping -> [event, x, y, v] in if event<>except then ( call _InternalHook[event](x, y, v); set _InternalGrouping=nil );; fun _internalUIevent(i, event)= let signExtend32(strRead32Lsb(_InternalBuffer, i+4)) -> x in let signExtend32(strRead32Lsb(_InternalBuffer, i+8)) -> y in let signExtend32(strRead32Lsb(_InternalBuffer, i+12)) -> v in if event==_EVENT_MOUSEMOVE || event==_EVENT_VWHEEL || event==_EVENT_HWHEEL || event==_EVENT_PAINT || event==_EVENT_SIZE then ( // grouping these events _flushInternalGrouping(event); let if event==_EVENT_VWHEEL || event==_EVENT_HWHEEL then let _InternalGrouping -> [_, _, _, prevValue] in prevValue -> dv in set _InternalGrouping=[event, x, y, v+dv]; nil ) else ( if event<>_EVENT_MULTITOUCH then _flushInternalGrouping(nil); // no need for multitouch as they do not fire any user event call _InternalHook[event](x, y, v); ) ;; fun _handleInternal(i)= let strLength(_InternalBuffer) -> len in if i==len then ( set _InternalBuffer=nil; _flushInternalGrouping(nil) ) elif (i+4)>len then _flushInternalGrouping(nil) else let strRead16Lsb(_InternalBuffer, i) -> eventSize in let strRead16Lsb(_InternalBuffer, i+2) -> event in if (i+eventSize)>len then _flushInternalGrouping(nil) else ( if !bitTest(event, 0x8000) then (_internalUIevent(i, event); nil) else let hashmapGet(_InternalExt, event) -> f in if f<>nil then call f(strSlice(_InternalBuffer, i+4, eventSize-4)); _handleInternal(i+eventSize) );; fun _internalInit()= set _InternalPipe= [ _socketS=_internalOpen(), _thS=_This, _onSelectReadS = (lambda ()= _socketSetSelectRead(_InternalPipe._socketS, true); set _InternalBuffer=strConcat(_InternalBuffer, _internalRead(_InternalPipe._socketS)); _handleInternal(0); 0 ), _typeS="internal", _detailS="-" ]; _streamAddToList(_InternalPipe); _socketSetSelectRead(_InternalPipe._socketS, true);; //----------------------------------- var _Workers=arrayCreate(_WORKERS_COUNT, nil);; const _WorkersFifo= fifoCreate();; fun workerGet()= if _WORKERS_COUNT>0 then \atomic ( for i=0; i<_WORKERS_COUNT do if _Workers[i]==nil then ( // echoLn strFormat("get worker *", i); set _Workers[i]=_This; return i ); fifoIn(_WorkersFifo, _This); // echoLn "waiting for worker"; _threadHoldOn() );; fun _workerFree(i)= \atomic ( set _Workers[i]=nil; // echoLn strFormat("release worker *", i); let fifoOut(_WorkersFifo) -> th in if th<>nil then ( // echoLn "reattributed worker"; // echoLn strFormat("get worker *", i); set _Workers[i]=th; _threadUnfreeze(th, i) ) );; fun _workerCheck()= for i=0; i<_WORKERS_COUNT do let _Workers[i] -> th in if th<>nil then if th._stateT==_THREAD_DONE then _workerFree(i) else void match _workerHandle(i) with nil -> ( echoLn strFormat("> Worker * is out of memory", i); _workerFree(i); threadStop(th) ), true -> ( _workerFree(i); if th._stateT==_THREAD_WAIT then _scheduleThread(th) );; fun _workerAlive()= // for i=0; i<_WORKERS_COUNT do if _Workers[i]<>nil then (echo i; echo "|"); for i=0; i<_WORKERS_COUNT do if _Workers[i]<>nil then return true; false;; //----------------------------------- fun ipByName(hostname)= let bufferCreateWithSize(32) -> output in ( let workerGet() -> wId in if 0<_ipByName(output, hostname, wId) then strSplit("\0", strFromBuffer(output)) );; fun nameByIp(ip)= let bufferCreateWithSize(32) -> output in ( let workerGet() -> wId in if 0<_nameByIp(output, ip, wId) then strFromBuffer(output) );; //----------------------------------- fun inflate(data) = let workerGet() -> wId in let bufferCreateWithSize(3*strLength(data)) -> output in if _inflate(output, data, wId) then strFromBuffer(output);; fun deflate(data) = let workerGet() -> wId in let bufferCreateWithSize(strLength(data)) -> output in if _deflate(output, data, wId) then strFromBuffer(output);; fun deflateBytes(data) = let workerGet() -> wId in let bufferCreateWithSize(bytesLength(data)) -> output in if _deflateBytes(output, data, wId) then strFromBuffer(output);; //----------------------------------- fun lzwFromStr(data, bitLen)= let workerGet() -> wId in let bufferCreateWithSize(1024*16) -> out in if _lzwDeflate(out, data, bitLen, wId) then strFromBuffer(out);; fun strFromLzw(data, bitLen)= let workerGet() -> wId in let bufferCreateWithSize(1024*16) -> out in if _lzwInflate(out, data, bitLen, wId) then strFromBuffer(out);; #ifdef _mp3Decode fun mp3Decode(mp3) = let workerGet() -> wId in let bufferCreateWithSize(1024+10*strLength(mp3)) -> buffer in if _mp3Decode(buffer, mp3) then strFromBuffer(buffer);; #endif