Skip to content

Commit

Permalink
Merge pull request #1 from membraneframework/release
Browse files Browse the repository at this point in the history
Release v0.1.0
  • Loading branch information
mickel8 authored Dec 28, 2020
2 parents 286d6f3 + f2a6243 commit 75c4f57
Show file tree
Hide file tree
Showing 8 changed files with 168 additions and 32 deletions.
48 changes: 38 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,62 @@
# Membrane Multimedia Framework: Template Plugin
# Membrane Funnel plugin

[![Hex.pm](https://img.shields.io/hexpm/v/membrane_template_plugin.svg)](https://hex.pm/packages/membrane_template_plugin)
[![CircleCI](https://circleci.com/gh/membraneframework/membrane_template_plugin.svg?style=svg)](https://circleci.com/gh/membraneframework/membrane_template_plugin)
[![Hex.pm](https://img.shields.io/hexpm/v/membrane_template_plugin.svg)](https://hex.pm/packages/membrane_funnel_plugin)
[![API Docs](https://img.shields.io/badge/api-docs-yellow.svg?style=flat)](https://hexdocs.pm/membrane_funnel_plugin/)
[![CircleCI](https://circleci.com/gh/membraneframework/membrane_template_plugin.svg?style=svg)](https://circleci.com/gh/membraneframework/membrane_funnel_plugin)

This repository contains a template for new elements.
Membrane plugin for funneling.

Check out different branches for other flavours of template.
It can be used for collecting data from multiple inputs and sending it through one output.

It is part of [Membrane Multimedia Framework](https://membraneframework.org).

## Installation

The package can be installed by adding `membrane_template_plugin` to your list of dependencies in `mix.exs`:
The package can be installed by adding `membrane_funnel_plugin` to your list of dependencies in `mix.exs`:

```elixir
def deps do
[
{:membrane_template_plugin, "~> 0.1.0"}
{:membrane_funnel_plugin, "~> 0.1.0"}
]
end
```

## Usage
Playing this pipeline should merge two files `a.txt` and `b.txt` into file `c.txt`

TODO
```elixir
defmodule FunnelDemo do
use Membrane.Pipeline

def handle_init(_) do
children = [
a_source: %Membrane.File.Source{location: "a.txt"},
b_source: %Membrane.File.Source{location: "b.txt"},
funnel: Membrane.Funnel,
sink: %Membrane.File.Sink{location: "c.txt"}
]

links = [
link(:a_source) |> to(:funnel),
link(:b_source) |> to(:funnel),
link(:funnel) |> to(:sink)
]

spec = %ParentSpec{children: children, links: links}
{{:ok, spec: spec}, %{}}
end
end
```

For more examples please refer to our [echo demo](https://github.com/membraneframework/membrane_demo/tree/echo/webrtc/echo)
where we use funnel plugin to send two RTP streams using the same connection, or our integration
tests.

## Copyright and License

Copyright 2020, [Software Mansion](https://swmansion.com/?utm_source=git&utm_medium=readme&utm_campaign=membrane_template_plugin)
Copyright 2020, [Software Mansion](https://swmansion.com/?utm_source=git&utm_medium=readme&utm_campaign=membrane_funnel_plugin)

[![Software Mansion](https://logo.swmansion.com/logo?color=white&variant=desktop&width=200&tag=membrane-github)](https://swmansion.com/?utm_source=git&utm_medium=readme&utm_campaign=membrane_template_plugin)
[![Software Mansion](https://logo.swmansion.com/logo?color=white&variant=desktop&width=200&tag=membrane-github)](https://swmansion.com/?utm_source=git&utm_medium=readme&utm_campaign=membrane_funnel_plugin)

Licensed under the [Apache License, Version 2.0](LICENSE)
9 changes: 9 additions & 0 deletions lib/membrane_funnel_plugin/event.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
defmodule Membrane.Funnel.NewInputEvent do
@moduledoc """
Event sent each time new element is linked (via funnel input pad) after playing pipeline.
"""
@derive Membrane.EventProtocol

@type t :: %__MODULE__{}
defstruct []
end
61 changes: 61 additions & 0 deletions lib/membrane_funnel_plugin/membrane_funnel.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
defmodule Membrane.Funnel do
@moduledoc """
Element that can be used for collecting data from multiple inputs and sending it through one
output.
"""
use Membrane.Filter

alias Membrane.Funnel

def_input_pad :input, demand_unit: :buffers, caps: :any, availability: :on_request
def_output_pad :output, caps: :any

def_options end_of_stream: [spec: :on_last_pad | :never, default: :on_last_pad]

@impl true
def handle_init(opts) do
{:ok, Map.from_struct(opts)}
end

@impl true
def handle_demand(:output, _size, :buffers, ctx, state) do
demands = ctx |> inputs_data() |> Enum.map(&{:demand, {&1.ref, 1}})
{{:ok, demands}, state}
end

@impl true
def handle_process(Pad.ref(:input, _id), buffer, _ctx, state) do
{{:ok, buffer: {:output, buffer}, redemand: :output}, state}
end

@impl true
def handle_pad_added(Pad.ref(:input, _id) = pad, %{playback_state: :playing}, state) do
{{:ok, [demand: {pad, 1}, event: {:output, %Funnel.NewInputEvent{}}]}, state}
end

@impl true
def handle_pad_added(Pad.ref(:input, _id), _ctx, state) do
{:ok, state}
end

@impl true
def handle_end_of_stream(Pad.ref(:input, _id), _ctx, %{end_of_stream: :never} = state) do
{:ok, state}
end

@impl true
def handle_end_of_stream(Pad.ref(:input, _id), ctx, %{end_of_stream: :on_last_pad} = state) do
if ctx |> inputs_data() |> Enum.all?(& &1.end_of_stream?) do
{{:ok, end_of_stream: :output}, state}
else
{:ok, state}
end
end

defp inputs_data(ctx) do
Enum.flat_map(ctx.pads, fn
{_ref, %{direction: :input} = data} -> [data]
_output -> []
end)
end
end
2 changes: 0 additions & 2 deletions lib/membrane_template.ex

This file was deleted.

18 changes: 9 additions & 9 deletions mix.exs
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
defmodule Membrane.Template.Mixfile do
defmodule Membrane.Funnel.Plugin.Mixfile do
use Mix.Project

@version "0.1.0"
@github_url "https://github.com/membraneframework/membrane_template_plugin"
@github_url "https://github.com/membraneframework/membrane_funnel_plugin"

def project do
[
app: :membrane_template_plugin,
app: :membrane_funnel_plugin,
version: @version,
elixir: "~> 1.10",
elixirc_paths: elixirc_paths(Mix.env()),
start_permanent: Mix.env() == :prod,
deps: deps(),

# hex
description: "Template Plugin for Membrane Multimedia Framework",
description: "Membrane plugin for funneling",
package: package(),

# docs
name: "Membrane Plugin: Template",
name: "Membrane Funnel plugin",
source_url: @github_url,
homepage_url: "https://membraneframework.org",
docs: docs()
Expand All @@ -36,10 +36,10 @@ defmodule Membrane.Template.Mixfile do

defp deps do
[
{:membrane_core, "~> 0.6.0"},
{:ex_doc, "~> 0.22", only: :dev, runtime: false},
{:membrane_core, "~> 0.6.1"},
{:ex_doc, "~> 0.23", only: :dev, runtime: false},
{:dialyxir, "~> 1.0.0", only: :dev, runtime: false},
{:credo, "~> 1.4", only: :dev, runtime: false}
{:credo, "~> 1.5", only: :dev, runtime: false}
]
end

Expand All @@ -59,7 +59,7 @@ defmodule Membrane.Template.Mixfile do
main: "readme",
extras: ["README.md", "LICENSE"],
source_ref: "v#{@version}",
nest_modules_by_prefix: [Membrane.Template]
nest_modules_by_prefix: [Membrane.Funnel]
]
end
end
21 changes: 11 additions & 10 deletions mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@
"bunch": {:hex, :bunch, "1.3.0", "51b4423088b7fb9e21eae6d6bc5e5d219d955ea5556fbd6130bfb6213df4be32", [:mix], [], "hexpm", "9ad233a2bacc0dae8aa6553a9b9057f27446443b1c5903c3479b6f9f3820ce2d"},
"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"},
"coerce": {:hex, :coerce, "1.0.1", "211c27386315dc2894ac11bc1f413a0e38505d808153367bd5c6e75a4003d096", [:mix], [], "hexpm", "b44a691700f7a1a15b4b7e2ff1fa30bebd669929ac8aa43cffe9e2f8bf051cf1"},
"credo": {:hex, :credo, "1.4.0", "92339d4cbadd1e88b5ee43d427b639b68a11071b6f73854e33638e30a0ea11f5", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "1fd3b70dce216574ce3c18bdf510b57e7c4c85c2ec9cad4bff854abaf7e58658"},
"credo": {:hex, :credo, "1.5.3", "f345253655f2efe1e4693a03437606462681e91303ebc9e3909c14268effc37a", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "f7e238c10051cc22515e3f75754200b567d93c00d93be81fc59d47bc3dfdc5be"},
"dialyxir": {:hex, :dialyxir, "1.0.0", "6a1fa629f7881a9f5aaf3a78f094b2a51a0357c843871b8bc98824e7342d00a5", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "aeb06588145fac14ca08d8061a142d52753dbc2cf7f0d00fc1013f53f8654654"},
"earmark": {:hex, :earmark, "1.4.5", "62ffd3bd7722fb7a7b1ecd2419ea0b458c356e7168c1f5d65caf09b4fbdd13c8", [:mix], [], "hexpm", "b7d0e6263d83dc27141a523467799a685965bf8b13b6743413f19a7079843f4f"},
"earmark_parser": {:hex, :earmark_parser, "1.4.10", "6603d7a603b9c18d3d20db69921527f82ef09990885ed7525003c7fe7dc86c56", [:mix], [], "hexpm", "8e2d5370b732385db2c9b22215c3f59c84ac7dda7ed7e544d7c459496ae519c0"},
"earmark_parser": {:hex, :earmark_parser, "1.4.12", "b245e875ec0a311a342320da0551da407d9d2b65d98f7a9597ae078615af3449", [:mix], [], "hexpm", "711e2cc4d64abb7d566d43f54b78f7dc129308a63bc103fbd88550d2174b3160"},
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
"ex_doc": {:hex, :ex_doc, "0.22.2", "03a2a58bdd2ba0d83d004507c4ee113b9c521956938298eba16e55cc4aba4a6c", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "cf60e1b3e2efe317095b6bb79651f83a2c1b3edcb4d319c421d7fcda8b3aff26"},
"jason": {:hex, :jason, "1.2.1", "12b22825e22f468c02eb3e4b9985f3d0cb8dc40b9bd704730efa11abd2708c44", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "b659b8571deedf60f79c5a608e15414085fa141344e2716fbd6988a084b5f993"},
"makeup": {:hex, :makeup, "1.0.3", "e339e2f766d12e7260e6672dd4047405963c5ec99661abdc432e6ec67d29ef95", [:mix], [{:nimble_parsec, "~> 0.5", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "2e9b4996d11832947731f7608fed7ad2f9443011b3b479ae288011265cdd3dad"},
"makeup_elixir": {:hex, :makeup_elixir, "0.14.1", "4f0e96847c63c17841d42c08107405a005a2680eb9c7ccadfd757bd31dabccfb", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f2438b1a80eaec9ede832b5c41cd4f373b38fd7aa33e3b22d9db79e640cbde11"},
"membrane_core": {:hex, :membrane_core, "0.6.0", "7f8bef262c9f68c174f6e95acd9c445f4289a2a0fed56801d573f821f96e47f3", [:mix], [{:bunch, "~> 1.3", [hex: :bunch, repo: "hexpm", optional: false]}, {:qex, "~> 0.3", [hex: :qex, repo: "hexpm", optional: false]}, {:ratio, "~> 2.0", [hex: :ratio, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "46163606a3183c4ea46b14c1c199374822388cbb567f54a8a3e66a098b2432a5"},
"nimble_parsec": {:hex, :nimble_parsec, "0.6.0", "32111b3bf39137144abd7ba1cce0914533b2d16ef35e8abc5ec8be6122944263", [:mix], [], "hexpm", "27eac315a94909d4dc68bc07a4a83e06c8379237c5ea528a9acff4ca1c873c52"},
"numbers": {:hex, :numbers, "5.2.1", "8a6e9eeacfb19f4ac30a52c304f565dc53f8e0813b7193812a5b15b93210780c", [:mix], [{:coerce, "~> 1.0", [hex: :coerce, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "1fd66efe26b67456ad0b80a038f553b89702d073a6942ecd34ce1a3e10af4c92"},
"ex_doc": {:hex, :ex_doc, "0.23.0", "a069bc9b0bf8efe323ecde8c0d62afc13d308b1fa3d228b65bca5cf8703a529d", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "f5e2c4702468b2fd11b10d39416ddadd2fcdd173ba2a0285ebd92c39827a5a16"},
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
"jason": {:hex, :jason, "1.2.2", "ba43e3f2709fd1aa1dce90aaabfd039d000469c05c56f0b8e31978e03fa39052", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "18a228f5f0058ee183f29f9eae0805c6e59d61c3b006760668d8d18ff0d12179"},
"makeup": {:hex, :makeup, "1.0.5", "d5a830bc42c9800ce07dd97fa94669dfb93d3bf5fcf6ea7a0c67b2e0e4a7f26c", [:mix], [{:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cfa158c02d3f5c0c665d0af11512fed3fba0144cf1aadee0f2ce17747fba2ca9"},
"makeup_elixir": {:hex, :makeup_elixir, "0.15.0", "98312c9f0d3730fde4049985a1105da5155bfe5c11e47bdc7406d88e01e4219b", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.1", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "75ffa34ab1056b7e24844c90bfc62aaf6f3a37a15faa76b07bc5eba27e4a8b4a"},
"membrane_core": {:hex, :membrane_core, "0.6.1", "7c0396564ec1ac3533c253cd2410c87716cff24dee8acb8065dcf1f78b4b1785", [:mix], [{:bunch, "~> 1.3", [hex: :bunch, repo: "hexpm", optional: false]}, {:qex, "~> 0.3", [hex: :qex, repo: "hexpm", optional: false]}, {:ratio, "~> 2.0", [hex: :ratio, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7f74eca2b1b5247e4e3869066117a586799a4d3d77516803956a4104b9b8ee56"},
"nimble_parsec": {:hex, :nimble_parsec, "1.1.0", "3a6fca1550363552e54c216debb6a9e95bd8d32348938e13de5eda962c0d7f89", [:mix], [], "hexpm", "08eb32d66b706e913ff748f11694b17981c0b04a33ef470e33e11b3d3ac8f54b"},
"numbers": {:hex, :numbers, "5.2.3", "d721b0702e3d8ebfaaa64af3419b9b49ffbc3836bd7511b935796499d51141ca", [:mix], [{:coerce, "~> 1.0", [hex: :coerce, repo: "hexpm", optional: false]}, {:decimal, "~> 1.9", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "ec62408c8bc02d79c6b9f798de321f65876afdcf7f8654190601df2cfe60cc18"},
"qex": {:hex, :qex, "0.5.0", "5a3a9becf67d4006377c4c247ffdaaa8ae5b3634a0caadb788dc24d6125068f4", [:mix], [], "hexpm", "4ad6f6421163cd8204509a119a5c9813cbb969cfb8d802a9dc49b968bffbac2a"},
"ratio": {:hex, :ratio, "2.4.1", "ecf989f3a1483cf892b867ab00ffe8e0784cbe748cd32a610a4ac4c4fd11f46d", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:numbers, "~> 5.2.0", [hex: :numbers, repo: "hexpm", optional: false]}], "hexpm", "3988235b59285b8fef9a55867c0b82125b59915ac80808de064b33ff57b0d54c"},
"ratio": {:hex, :ratio, "2.4.2", "c8518f3536d49b1b00d88dd20d49f8b11abb7819638093314a6348139f14f9f9", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:numbers, "~> 5.2.0", [hex: :numbers, repo: "hexpm", optional: false]}], "hexpm", "441ef6f73172a3503de65ccf1769030997b0d533b1039422f1e5e0e0b4cbf89e"},
"telemetry": {:hex, :telemetry, "0.4.2", "2808c992455e08d6177322f14d3bdb6b625fbcfd233a73505870d8738a2f4599", [:rebar3], [], "hexpm", "2d1419bd9dda6a206d7b5852179511722e2b18812310d304620c7bd92a13fcef"},
}
39 changes: 39 additions & 0 deletions test/membrane_funnel_plugin/membrane_funnel_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
defmodule Membrane.FunnelTest do
use ExUnit.Case

import Membrane.Testing.Assertions

alias Membrane.{Buffer, Funnel, Testing}

test "Collects multiple inputs" do
import Membrane.ParentSpec
data = 1..10

{:ok, pipeline} =
%Testing.Pipeline.Options{
elements: [
src1: %Testing.Source{output: data},
src2: %Testing.Source{output: data},
funnel: Funnel,
sink: Testing.Sink
],
links: [
link(:src1) |> to(:funnel),
link(:src2) |> to(:funnel),
link(:funnel) |> to(:sink)
]
}
|> Testing.Pipeline.start_link()

:ok = Testing.Pipeline.play(pipeline)

data
|> Enum.flat_map(&[&1, &1])
|> Enum.each(fn payload ->
assert_sink_buffer(pipeline, :sink, %Buffer{payload: ^payload})
end)

assert_end_of_stream(pipeline, :sink)
refute_sink_buffer(pipeline, :sink, _buffer, 0)
end
end
2 changes: 1 addition & 1 deletion test/test_helper.exs
Original file line number Diff line number Diff line change
@@ -1 +1 @@
ExUnit.start()
ExUnit.start(capture_log: true)

0 comments on commit 75c4f57

Please sign in to comment.