diff --git a/concat.py b/concat.py new file mode 100644 index 000000000..103585aa3 --- /dev/null +++ b/concat.py @@ -0,0 +1,28 @@ +import os + +def concatenate_files(dir_path, output_file): + """ + Concatenates the content of all text files located in the directory and sub-directories. + + :param dir_path: String, path of the directory to search for files to concatenate. + :param output_file: String, path of the file where all content will be saved. + """ + with open(output_file, 'w') as outfile: # Opening the file that will hold all the contents. + for root, dirs, files in os.walk(dir_path): # Traversing directory tree. + print(files) + for filename in files: + filepath = os.path.join(root, filename) # Creating full path to the file. + try: + with open(filepath, 'r') as readfile: # Opening each file safely with 'with'. + content = readfile.read() + outfile.write("Content of " + filepath + ":\n" + content + "\n") # Writing content followed by a newline. + except Exception as e: + print(f"Failed to read file {filepath}: {e}") + +# Usage +# directory_path = '~/membrane/membrane_core' # Set your directory path here. +directory_path = os.getcwd() + "/lib" +output_path = 'combined_output.txt' +concatenate_files(directory_path, output_path) + +print(f"All files have been concatenated into {output_path}.") \ No newline at end of file diff --git a/guides/timer.md b/guides/timer.md new file mode 100644 index 000000000..7648402e6 --- /dev/null +++ b/guides/timer.md @@ -0,0 +1,102 @@ +# Timer usage examples +Exampls below illustrate how to use `:start_timer`, `:timer_interval` and `:stop_timer` actions on the example of `Membrane.Source`, but the API looks the same for all kinds of the Membrane Components + +### Emit empty buffer every 100 milliseconds +```elixir +defmodule MySource do + use Membrane.Source + + def_output_pad :output, accepted_format: SomeFormat + + @impl true + def handle_init(_ctx, _opts), do: {[], %{}} + + @impl true + def handle_playing(_ctx, state) do + interval_in_millis = 100 + interval = Membrane.Time.milliseconds(interval_in_millis) + + actions = [ + stream_format: %SomeFormat{}, + start_timer: {:some_timer, interval} + ] + + {actions, state} + end + + @impl true + def handle_tick(:some_timer, _ctx, state) do + buffer = %Membrane.Buffer{payload: ""} + actions = [buffer: {:output, buffer}] + {actions, state} + end +end +``` + +### Emit empty buffer every 100 millisecond if parent hasn't stopped you +The source below accepts following notifications from the parent: + - `:pause` - after receiving it the source will pause sending buffers. The paused soure can be resumed again. + - `:resume` - resumes sending buffers from the paused source. + - `:stop` - the stopped source won't send any buffer again. + +```elixir +defmodule MyComplexSource + use Membrane.Source + + def_output_pad :output, accepted_format: SomeFormat + + @one_hundred_millis = Membrane.Time.milliseconds(100) + + @impl true + def handle_init(_ctx, _opts), do: {[], %{status: nil}} + + @impl true + def handle_playing(_ctx, state) do + interval_in_millis = 100 + interval = Membrane.Time.milliseconds(interval_in_millis) + + actions = [ + stream_format: %SomeFormat{}, + start_timer: {:some_timer, interval} + ] + + {actions, %{state | status: :resumed}} + end + + @impl true + def handle_parent_notification(notification, ctx, _state) when ctx.playback == :stopped do + raise "Cannot handle parent notification: #{inspect(notification)} before handle_palaying" + end + + @impl true + def handle_parent_notification(notification, _ctx, state) when notification in [:pause, :resume, :stop] do + case notification do + :pause when state.status == :resumed -> + {[], %{state | status: :pause_on_next_handle_tick}} + + :resume when state.status == :paused -> + actions = [timer_interval: {:some_timer, @one_hundred_millis}] + {actions, %{state | status: :resumed}} + + :resume when state.status == :pause_on_next_handle_tick -> + {[], %{state | status: :resumed}} + + :stop -> + {[stop_timer: :some_timer], %{state | status: :stopped}} + end + end + + @impl true + def handle_tick(:some_timer, _ctx, state) do + case state.status do + :resumed -> + buffer = %Membrane.Buffer{payload: ""} + {[buffer: {:output, buffer}], state} + + :pause_on_next_handle_tick -> + actions = [timer_interval: :no_interval] + {actions, %{state | status: :paused}} + end + end +end +``` diff --git a/lib/membrane/element/action.ex b/lib/membrane/element/action.ex index 0d5db32a9..4c23da802 100644 --- a/lib/membrane/element/action.ex +++ b/lib/membrane/element/action.ex @@ -223,6 +223,8 @@ defmodule Membrane.Element.Action do This action sets the latency for the element. This action is permitted only in callback `c:Membrane.Element.Base.handle_init/2`. + + The example of usage of this actions is [there](../../../guides/timer.md) """ @type latency :: {:latency, latency :: Membrane.Time.non_neg()} diff --git a/mix.exs b/mix.exs index c1fab8be5..4e6649ab3 100644 --- a/mix.exs +++ b/mix.exs @@ -68,6 +68,7 @@ defmodule Membrane.Mixfile do "guides/upgrading/v1.0.0-rc0.md", "guides/upgrading/v1.0.0-rc1.md", "guides/upgrading/v1.0.0.md", + "guides/timer.md", LICENSE: [title: "License"] ], formatters: ["html"], diff --git a/mix.lock b/mix.lock index d7ed3e717..87d275ae4 100644 --- a/mix.lock +++ b/mix.lock @@ -6,14 +6,14 @@ "dialyxir": {:hex, :dialyxir, "1.4.4", "fb3ce8741edeaea59c9ae84d5cec75da00fa89fe401c72d6e047d11a61f65f70", [:mix], [{:erlex, ">= 0.2.7", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "cd6111e8017ccd563e65621a4d9a4a1c5cd333df30cebc7face8029cacb4eff6"}, "earmark_parser": {:hex, :earmark_parser, "1.4.41", "ab34711c9dc6212dda44fcd20ecb87ac3f3fce6f0ca2f28d4a00e4154f8cd599", [:mix], [], "hexpm", "a81a04c7e34b6617c2792e291b5a2e57ab316365c2644ddc553bb9ed863ebefa"}, "erlex": {:hex, :erlex, "0.2.7", "810e8725f96ab74d17aac676e748627a07bc87eb950d2b83acd29dc047a30595", [:mix], [], "hexpm", "3ed95f79d1a844c3f6bf0cea61e0d5612a42ce56da9c03f01df538685365efb0"}, - "ex_doc": {:hex, :ex_doc, "0.34.2", "13eedf3844ccdce25cfd837b99bea9ad92c4e511233199440488d217c92571e8", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "5ce5f16b41208a50106afed3de6a2ed34f4acfd65715b82a0b84b49d995f95c1"}, + "ex_doc": {:hex, :ex_doc, "0.35.1", "de804c590d3df2d9d5b8aec77d758b00c814b356119b3d4455e4b8a8687aecaf", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "2121c6402c8d44b05622677b761371a759143b958c6c19f6558ff64d0aed40df"}, "excoveralls": {:hex, :excoveralls, "0.18.3", "bca47a24d69a3179951f51f1db6d3ed63bca9017f476fe520eb78602d45f7756", [:mix], [{:castore, "~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "746f404fcd09d5029f1b211739afb8fb8575d775b21f6a3908e7ce3e640724c6"}, "file_system": {:hex, :file_system, "1.0.1", "79e8ceaddb0416f8b8cd02a0127bdbababe7bf4a23d2a395b983c1f8b3f73edd", [:mix], [], "hexpm", "4414d1f38863ddf9120720cd976fce5bdde8e91d8283353f0e31850fa89feb9e"}, "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, "junit_formatter": {:hex, :junit_formatter, "3.4.0", "d0e8db6c34dab6d3c4154c3b46b21540db1109ae709d6cf99ba7e7a2ce4b1ac2", [:mix], [], "hexpm", "bb36e2ae83f1ced6ab931c4ce51dd3dbef1ef61bb4932412e173b0cfa259dacd"}, - "makeup": {:hex, :makeup, "1.1.2", "9ba8837913bdf757787e71c1581c21f9d2455f4dd04cfca785c70bbfff1a76a3", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cce1566b81fbcbd21eca8ffe808f33b221f9eee2cbc7a1706fc3da9ff18e6cac"}, + "makeup": {:hex, :makeup, "1.2.1", "e90ac1c65589ef354378def3ba19d401e739ee7ee06fb47f94c687016e3713d1", [:mix], [{:nimble_parsec, "~> 1.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "d36484867b0bae0fea568d10131197a4c2e47056a6fbe84922bf6ba71c8d17ce"}, "makeup_diff": {:hex, :makeup_diff, "0.1.1", "01498f8c95970081297837eaf4686b6f3813e535795b8421f15ace17a59aea37", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "fadb0bf014bd328badb7be986eadbce1a29955dd51c27a9e401c3045cf24184e"}, - "makeup_elixir": {:hex, :makeup_elixir, "0.16.2", "627e84b8e8bf22e60a2579dad15067c755531fea049ae26ef1020cad58fe9578", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "41193978704763f6bbe6cc2758b84909e62984c7752b3784bd3c218bb341706b"}, + "makeup_elixir": {:hex, :makeup_elixir, "1.0.1", "e928a4f984e795e41e3abd27bfc09f51db16ab8ba1aebdba2b3a575437efafc2", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "7284900d412a3e5cfd97fdaed4f5ed389b8f2b4cb49efc0eb3bd10e2febf9507"}, "makeup_erlang": {:hex, :makeup_erlang, "1.0.1", "c7f58c120b2b5aa5fd80d540a89fdf866ed42f1f3994e4fe189abebeab610839", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "8a89a1eeccc2d798d6ea15496a6e4870b75e014d1af514b1b71fa33134f57814"}, "mox": {:hex, :mox, "1.2.0", "a2cd96b4b80a3883e3100a221e8adc1b98e4c3a332a8fc434c39526babafd5b3", [:mix], [{:nimble_ownership, "~> 1.0", [hex: :nimble_ownership, repo: "hexpm", optional: false]}], "hexpm", "c7b92b3cc69ee24a7eeeaf944cd7be22013c52fcb580c1f33f50845ec821089a"}, "nimble_ownership": {:hex, :nimble_ownership, "1.0.0", "3f87744d42c21b2042a0aa1d48c83c77e6dd9dd357e425a038dd4b49ba8b79a1", [:mix], [], "hexpm", "7c16cc74f4e952464220a73055b557a273e8b1b7ace8489ec9d86e9ad56cb2cc"},