Current section

Files

Jump to
mediasoup_elixir lib wrap.ex
Raw

lib/wrap.ex

defmodule Mediasoup.NifWrap do
@moduledoc false
# Utilities for wrap Nif
defmodule EventProxy do
@moduledoc false
# Event proxy module for rustler because rustler(nif) can only use local pid.
use GenServer
def start(opt) do
pid = Keyword.fetch!(opt, :pid)
GenServer.start(__MODULE__, %{pid: pid}, [])
end
def init(%{pid: pid} = init_arg) do
Process.monitor(pid)
{:ok, init_arg}
end
def handle_info(
{:EXIT, _pid, reason},
state
) do
{:stop, reason, state}
end
def handle_info(
{:DOWN, _ref, :process, _shutdownpid, reason},
state
) do
{:stop, reason, state}
end
def handle_info(message, %{pid: pid} = state) do
send(pid, message)
{:noreply, state}
end
def wrap_if_remote_node(pid) do
try do
if Process.alive?(pid) do
pid
else
nil
end
rescue
_e in ArgumentError ->
{:ok, wrapped} = EventProxy.start(pid: pid)
wrapped
end
end
end
@spec def_handle_call_nif(any) ::
{:__block__, [], [{:@, [...], [...]} | {:def, [...], [...]}, ...]}
defmacro def_handle_call_nif(nif_call_map) do
quote do
@nif_map unquote(nif_call_map)
@nif_keylist Map.keys(@nif_map)
def handle_call(
{function, arg},
_from,
%{reference: reference} = state
)
when function in @nif_keylist do
result = apply(Map.fetch!(@nif_map, function), [reference | arg])
{:reply, result, state}
end
end
end
def handle_create_result(create_result, module, supervisor) do
with {:ok, ref} <- create_result,
{:ok, pid} <-
DynamicSupervisor.start_child(
supervisor,
{module, [reference: ref]}
) do
{:ok, module.struct_from_pid_and_ref(pid, ref)}
else
error -> error
end
end
end