Current section

Files

Jump to
membrane_core lib membrane core parent link.ex
Raw

lib/membrane/core/parent/link.ex

defmodule Membrane.Core.Parent.Link do
@moduledoc false
use Bunch
alias Membrane.{Pad, ParentError, ParentSpec}
alias __MODULE__.Endpoint
@enforce_keys [:from, :to]
defstruct @enforce_keys
@type t() :: %__MODULE__{from: Endpoint.t(), to: Endpoint.t()}
@type resolved_t :: %__MODULE__{
from: Endpoint.resolved_t(),
to: Endpoint.resolved_t()
}
defmodule Endpoint do
@moduledoc false
alias Membrane.Element
alias Membrane.Pad
@enforce_keys [:child, :pad_spec]
defstruct @enforce_keys ++ [pad_ref: nil, pid: nil, pad_props: []]
@type t() :: %__MODULE__{
child: Element.name_t() | {Membrane.Bin, :itself},
pad_spec: Pad.name_t() | Pad.ref_t(),
pad_ref: Pad.ref_t() | nil,
pid: pid() | nil,
pad_props: ParentSpec.pad_props_t()
}
@type resolved_t() :: %__MODULE__{
child: Element.name_t() | {Membrane.Bin, :itself},
pad_spec: Pad.name_t() | Pad.ref_t(),
pad_ref: Pad.ref_t(),
pid: pid(),
pad_props: ParentSpec.pad_props_t()
}
end
@spec from_spec(ParentSpec.links_spec_t()) :: {:ok, [t]} | no_return
def from_spec(links) when is_list(links) do
links
|> List.flatten()
|> Enum.flat_map(fn
%ParentSpec.LinkBuilder{links: links, status: :done} ->
links
%ParentSpec.LinkBuilder{links: [%{from: from} | _]} ->
raise ParentError,
"Invalid link specification: link from #{inspect(from)} lacks its destination."
links ->
from_spec(links)
end)
|> Enum.map(fn link ->
%__MODULE__{
from: %Endpoint{
child: link.from,
pad_spec: get_pad(link, :from, :output),
pad_props: Map.get(link, :output_props, [])
},
to: %Endpoint{
child: link.to,
pad_spec: get_pad(link, :to, :input),
pad_props: Map.get(link, :input_props, [])
}
}
end)
~> {:ok, &1}
end
def from_spec(links) do
raise ParentError, """
Invalid links specification: #{inspect(links)}.
See `#{inspect(ParentSpec)}` for information on specifying links.
"""
end
defp get_pad(link_spec, child, direction) do
case link_spec do
%{^direction => pad_name} -> pad_name
%{^child => {Membrane.Bin, :itself}} -> Pad.opposite_direction(direction)
_ -> direction
end
end
end