Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions lib/membrane/children_spec.ex
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,9 @@ defmodule Membrane.ChildrenSpec do
via_in(builder, :input)
end
|> Builder.finish_link(child_name)
|> then(&%Builder{&1 | children: [child_spec | &1.children]})
|> then(fn %Builder{} = builder ->
%Builder{builder | children: [child_spec | builder.children]}
end)
end

@doc """
Expand All @@ -465,7 +467,9 @@ defmodule Membrane.ChildrenSpec do
:ok = validate_pad_name(pad)

get_child({Membrane.Bin, :itself})
|> then(&%Builder{&1 | status: :from_pad, from_pad: pad, from_pad_props: %{}})
|> then(fn %Builder{} = builder ->
%Builder{builder | status: :from_pad, from_pad: pad, from_pad_props: %{}}
end)
end

@doc """
Expand All @@ -488,7 +492,9 @@ defmodule Membrane.ChildrenSpec do
else
via_out(builder, :output)
end
|> then(&%Builder{&1 | status: :to_pad, to_pad: pad, to_pad_props: %{}})
|> then(fn %Builder{} = builder ->
%Builder{builder | status: :to_pad, to_pad: pad, to_pad_props: %{}}
end)
|> get_child({Membrane.Bin, :itself})
end

Expand Down Expand Up @@ -541,7 +547,7 @@ defmodule Membrane.ChildrenSpec do
"Invalid link specification: input #{inspect(pad)} placed after another input"
end

def via_in(%Builder{links: [%{to: {Membrane.Bin, :itself}} | _]}, pad, _props) do
def via_in(%Builder{links: [%{to: {Membrane.Bin, :itself}} | _rest]}, pad, _props) do
raise ParentError,
"Invalid link specification: input #{inspect(pad)} placed after bin's output"
end
Expand Down Expand Up @@ -572,7 +578,9 @@ defmodule Membrane.ChildrenSpec do
else
via_out(builder, :output)
end
|> then(&%Builder{&1 | status: :to_pad, to_pad: pad, to_pad_props: Enum.into(props, %{})})
|> then(fn %Builder{} = builder ->
%Builder{builder | status: :to_pad, to_pad: pad, to_pad_props: Enum.into(props, %{})}
end)
end

@doc """
Expand All @@ -598,7 +606,7 @@ defmodule Membrane.ChildrenSpec do
raise ParentError, "Invalid link specification: output #{inspect(pad)} placed after an input"
end

def via_out(%Builder{links: [%{to: {Membrane.Bin, :itself}} | _]}, pad, _props) do
def via_out(%Builder{links: [%{to: {Membrane.Bin, :itself}} | _rest]}, pad, _props) do
raise ParentError,
"Invalid link specification: output #{inspect(pad)} placed after bin's output"
end
Expand Down
2 changes: 1 addition & 1 deletion lib/membrane/core/child/pad_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ defmodule Membrane.Core.Child.PadController do
map | no_return
def parse_pad_options!(pad_name, options, state) do
{_pad_name, pad_spec} =
PadSpecHandler.get_pads(state) |> Enum.find(fn {k, _} -> k == pad_name end)
PadSpecHandler.get_pads(state) |> Enum.find(fn {k, _desc} -> k == pad_name end)

bunch_field_specs =
Bunch.KVList.map_values(pad_spec.options || [], &Keyword.take(&1, [:default]))
Expand Down
2 changes: 1 addition & 1 deletion lib/membrane/core/child/pads_specs.ex
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ defmodule Membrane.Core.Child.PadsSpecs do
def generate_docs_from_pads_specs(pads_specs) do
pads_docs =
pads_specs
|> Enum.sort_by(fn {_, config} -> config[:direction] end)
|> Enum.sort_by(fn {_pad_name, config} -> config[:direction] end)
|> Enum.map(&generate_docs_from_pad_specs/1)
|> Enum.reduce(fn x, acc ->
quote do
Expand Down
6 changes: 5 additions & 1 deletion lib/membrane/core/element.ex
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ defmodule Membrane.Core.Element do
end
end

# Suppress false positive dialyzer warnings resulting from
# broken handling of opaque types - in this case MapSet.t()
# https://github.com/elixir-lang/elixir/issues/14576
@dialyzer {:nowarn_function, do_init: 1}
defp do_init(options) do
Process.link(options.parent_supervisor)

Expand Down Expand Up @@ -141,9 +145,9 @@ defmodule Membrane.Core.Element do
state =
%State{
module: options.module,
type: options.module.membrane_element_type(),
name: options.name,
parent_pid: options.parent,
type: options.module.membrane_element_type(),
synchronization: %{
parent_clock: options.parent_clock,
timers: %{},
Expand Down
11 changes: 6 additions & 5 deletions lib/membrane/core/element/action_handler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,13 @@ defmodule Membrane.Core.Element.ActionHandler do
end

@impl CallbackHandler
def handle_action({action, _}, :handle_init, _params, _state)
def handle_action({action, _arg}, :handle_init, _params, _state)
when action not in [:latency, :notify_parent] do
raise ActionError, action: action, reason: {:invalid_callback, :handle_init}
end

@impl CallbackHandler
def handle_action({action, _}, _cb, _params, %State{playback: playback})
def handle_action({action, _arg}, _cb, _params, %State{playback: playback})
when playback != :playing and
action in [
:buffer,
Expand Down Expand Up @@ -291,12 +291,13 @@ defmodule Membrane.Core.Element.ActionHandler do
actions
|> Bunch.Enum.chunk_by_prev(
fn
{:buffer, {pad, _}}, {:buffer, {pad, _}} -> true
{:buffer, {pad, _buffer1}}, {:buffer, {pad, _buffer2}} -> true
_prev_action, _action -> false
end,
fn
[{:buffer, {pad, _}} | _] = buffers ->
{:buffer, {pad, buffers |> Enum.map(fn {_, {_, b}} -> [b] end) |> List.flatten()}}
[{:buffer, {pad, _buffer}} | _rest] = buffers ->
{:buffer,
{pad, buffers |> Enum.map(fn {:buffer, {_pad, b}} -> [b] end) |> List.flatten()}}

[other] ->
other
Expand Down
4 changes: 4 additions & 0 deletions lib/membrane/core/element/auto_flow_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,10 @@ defmodule Membrane.Core.Element.AutoFlowController do
|> Map.put(:popping_auto_flow_queue?, false)
end

# Suppress false positive dialyzer warnings resulting from
# broken handling of opaque types - in this case MapSet.t()
# https://github.com/elixir-lang/elixir/issues/14576
@dialyzer {:nowarn_function, bump_demand: 1}
defp bump_demand(state) do
if state.effective_flow_control == :pull and
state.satisfied_auto_output_pads == @empty_map_set do
Expand Down
2 changes: 1 addition & 1 deletion lib/membrane/core/element/event_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ defmodule Membrane.Core.Element.EventController do

use Bunch

alias Membrane.{Event, Pad, Sync}
alias Membrane.Core.{CallbackHandler, Events, Message, Telemetry}
alias Membrane.Core.Child.PadModel

Expand All @@ -19,6 +18,7 @@ defmodule Membrane.Core.Element.EventController do
}

alias Membrane.Core.Element.ManualFlowController.InputQueue
alias Membrane.{Event, Pad, Sync}

require Membrane.Core.Child.PadModel
require Membrane.Core.Message
Expand Down
2 changes: 1 addition & 1 deletion lib/membrane/core/element/lifecycle_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ defmodule Membrane.Core.Element.LifecycleController do
end

@spec handle_playing(State.t()) :: State.t()
def handle_playing(state) do
def handle_playing(%State{} = state) do
Membrane.Logger.debug("Got play request")

state =
Expand Down
4 changes: 2 additions & 2 deletions lib/membrane/core/element/manual_flow_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ defmodule Membrane.Core.Element.ManualFlowController do
|> handle_delayed_demands()
end

defp do_supply_demand(pad_ref, state) do
defp do_supply_demand(pad_ref, %State{} = state) do
# marking is state that actual demand supply has been started (note changing back to false when finished)
state = %State{state | delay_demands?: true}

Expand All @@ -90,7 +90,7 @@ defmodule Membrane.Core.Element.ManualFlowController do
InputQueue.take(pad_data.input_queue, pad_data.manual_demand_size)

state = PadModel.set_data!(state, pad_ref, :input_queue, new_input_queue)
state = handle_input_queue_output(pad_ref, popped_data, state)
%State{} = state = handle_input_queue_output(pad_ref, popped_data, state)
%State{state | delay_demands?: false}
end

Expand Down
3 changes: 2 additions & 1 deletion lib/membrane/core/element/playback_queue.ex
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ defmodule Membrane.Core.Element.PlaybackQueue do

@spec eval(State.t()) :: State.t()
def eval(%State{playback_queue: playback_queue} = state) do
state =
%State{} =
state =
playback_queue
|> List.foldr(state, fn function, state -> function.(state) end)

Expand Down
30 changes: 15 additions & 15 deletions lib/membrane/core/element/state.ex
Original file line number Diff line number Diff line change
Expand Up @@ -15,38 +15,38 @@ defmodule Membrane.Core.Element.State do

@type t :: %__MODULE__{
module: module(),
type: Element.type(),
name: Element.name(),
parent_pid: pid(),
playback: Membrane.Playback.t(),
type: Element.type(),
internal_state: Element.state() | nil,
pads_info: PadModel.pads_info() | nil,
pads_data: PadModel.pads_data() | nil,
parent_pid: pid(),
delay_demands?: boolean(),
delayed_demands: MapSet.t({Pad.ref(), :supply | :redemand}),
handle_demand_loop_counter: non_neg_integer(),
synchronization: %{
timers: %{Timer.id() => Timer.t()},
parent_clock: Clock.t(),
latency: Membrane.Time.non_neg(),
stream_sync: Sync.t(),
clock: Clock.t() | nil
},
auto_input_pads: [Pad.ref()],
delayed_demands: MapSet.t({Pad.ref(), :supply | :redemand}),
effective_flow_control: EffectiveFlowController.effective_flow_control(),
initialized?: boolean(),
playback: Membrane.Playback.t(),
playback_queue: Membrane.Core.Element.PlaybackQueue.t(),
resource_guard: Membrane.ResourceGuard.t(),
subprocess_supervisor: pid(),
terminating?: boolean(),
setup_incomplete_returned?: boolean(),
effective_flow_control: EffectiveFlowController.effective_flow_control(),
delay_demands?: boolean(),
popping_auto_flow_queue?: boolean(),
pads_to_snapshot: MapSet.t(),
stalker: Membrane.Core.Stalker.t(),
resource_guard: Membrane.ResourceGuard.t(),
subprocess_supervisor: pid(),
handle_demand_loop_counter: non_neg_integer(),
pads_to_snapshot: MapSet.t(),
playback_queue: Membrane.Core.Element.PlaybackQueue.t(),
diamond_detection_state: DiamondDatectionState.t(),
pads_data: PadModel.pads_data() | nil,
satisfied_auto_output_pads: MapSet.t(),
awaiting_auto_input_pads: MapSet.t(),
resume_delayed_demands_loop_in_mailbox?: boolean(),
diamond_detection_state: DiamondDatectionState.t()
auto_input_pads: [Pad.ref()],
resume_delayed_demands_loop_in_mailbox?: boolean()
Comment thread
mat-hek marked this conversation as resolved.
}

# READ THIS BEFORE ADDING NEW FIELD!!!
Expand Down
2 changes: 1 addition & 1 deletion lib/membrane/core/element/stream_format_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ defmodule Membrane.Core.Element.StreamFormatController do

use Bunch

alias Membrane.{Pad, StreamFormat}
alias Membrane.Core.{CallbackHandler, Telemetry}
alias Membrane.Core.Child.PadModel

Expand All @@ -18,6 +17,7 @@ defmodule Membrane.Core.Element.StreamFormatController do
}

alias Membrane.Core.Element.ManualFlowController.InputQueue
alias Membrane.{Pad, StreamFormat}

require Membrane.Core.Child.PadModel
require Membrane.Core.Telemetry
Expand Down
4 changes: 4 additions & 0 deletions lib/membrane/core/filter_aggregator/context.ex
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ defmodule Membrane.Core.FilterAggregator.Context do
@type action :: Element.Action.t() | Membrane.Core.FilterAggregator.InternalAction.t()

@spec build_context!(Element.name(), module(), t()) :: t()
# Suppress false positive dialyzer warnings resulting from
# broken handling of opaque types - in this case MapSet.t()
# https://github.com/elixir-lang/elixir/issues/14576
@dialyzer {:nowarn_function, build_context!: 3}
def build_context!(name, module, agg_ctx) do
pad_descriptions = module.membrane_pads()
pads = pad_descriptions |> MapSet.new(fn {k, _v} -> k end)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,14 @@ defmodule Membrane.Core.Parent.ChildLifeController.CrashGroupUtils do

update_in(
state.crash_groups[group.name],
&%CrashGroup{
&1
| detonating?: true,
crash_initiator: crash_initiator,
crash_reason: reason
}
fn %CrashGroup{} = group ->
%CrashGroup{
group
| detonating?: true,
crash_initiator: crash_initiator,
crash_reason: reason
}
end
)
end

Expand Down
28 changes: 15 additions & 13 deletions lib/membrane/core/parent/child_life_controller/link_utils.ex
Original file line number Diff line number Diff line change
Expand Up @@ -156,12 +156,14 @@ defmodule Membrane.Core.Parent.ChildLifeController.LinkUtils do
links =
Enum.map(
links,
&%Link{
&1
| spec_ref: spec_ref,
from: resolve_endpoint(&1.from, state),
to: resolve_endpoint(&1.to, state)
}
fn %Link{} = link ->
%Link{
link
| spec_ref: spec_ref,
from: resolve_endpoint(link.from, state),
to: resolve_endpoint(link.to, state)
}
end
)

:ok = validate_links(links, state)
Expand Down Expand Up @@ -235,13 +237,12 @@ defmodule Membrane.Core.Parent.ChildLifeController.LinkUtils do
end
end

defp resolve_endpoint(endpoint, state) do
%Endpoint{child: child, pad_spec: pad_spec} = endpoint
child_data = Parent.ChildrenModel.get_child_data!(state, child)
pad_name = Pad.name_by_ref(pad_spec)
defp resolve_endpoint(%Endpoint{} = endpoint, state) do
child_data = Parent.ChildrenModel.get_child_data!(state, endpoint.child)
pad_name = Pad.name_by_ref(endpoint.pad_spec)

withl pad: {:ok, pad_info} <- Keyword.fetch(child_data.module.membrane_pads(), pad_name),
ref: {:ok, ref} <- make_pad_ref(pad_spec, pad_info.availability) do
ref: {:ok, ref} <- make_pad_ref(endpoint.pad_spec, pad_info.availability) do
%Endpoint{
endpoint
| pid: child_data.pid,
Expand All @@ -251,11 +252,12 @@ defmodule Membrane.Core.Parent.ChildLifeController.LinkUtils do
}
else
pad: :error ->
raise LinkError, "Child #{inspect(child)} does not have pad #{inspect(pad_spec)}"
raise LinkError,
"Child #{inspect(endpoint.child)} does not have pad #{inspect(endpoint.pad_spec)}"

ref: {:error, :invalid_availability} ->
raise LinkError,
"Dynamic pad ref #{inspect(pad_spec)} passed for static pad of child #{inspect(child)}"
"Dynamic pad ref #{inspect(endpoint.pad_spec)} passed for static pad of child #{inspect(endpoint.child)}"
end
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ defmodule Membrane.Core.Parent.ChildLifeController.StartupUtils do
:ok
end

defp start_child(child, node, syncs, log_metadata, group, state) do
defp start_child(%ChildEntry{} = child, node, syncs, log_metadata, group, state) do
%ChildEntry{name: name, module: module, options: options} = child

Membrane.Logger.debug(
Expand Down
4 changes: 2 additions & 2 deletions lib/membrane/core/parent/specification_parser.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ defmodule Membrane.Core.Parent.SpecificationParser do
@moduledoc false
use Bunch

alias Membrane.{ChildrenSpec, Element, Pad, ParentError}
alias Membrane.Core.Parent.Link
alias Membrane.Core.Parent.Link.Endpoint
alias Membrane.{ChildrenSpec, Element, Pad, ParentError}

require Membrane.Logger

Expand All @@ -28,7 +28,7 @@ defmodule Membrane.Core.Parent.SpecificationParser do
%ChildrenSpec.Builder{links: links, children: children, status: :done} = builder ->
if links == [] and children == [] do
Membrane.Logger.warning(
"The specification you have passed: #{builder} has no effect - it doesn't produce any children nor links."
"The specification you have passed: #{inspect(builder)} has no effect - it doesn't produce any children nor links."
)
end

Expand Down
2 changes: 1 addition & 1 deletion lib/membrane/core/pipeline.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ defmodule Membrane.Core.Pipeline do
alias __MODULE__.{ActionHandler, State}
alias Membrane.{Clock, ResourceGuard}
alias Membrane.Core.{CallbackHandler, ProcessHelper, Stalker, SubprocessSupervisor}
alias Membrane.Core.Pipeline.CallbackContext
alias Membrane.Core.Parent.{ChildLifeController, LifecycleController}
alias Membrane.Core.Pipeline.CallbackContext
alias Membrane.Core.TimerController

require Membrane.Core.Utils, as: Utils
Expand Down
Loading