From f15745f659d32b6f32fc2a7172477d18a7e03600 Mon Sep 17 00:00:00 2001 From: varsill Date: Tue, 12 Jul 2022 11:14:30 +0200 Subject: [PATCH 1/6] Bump dependency to Ratio to v3.0. Update the code so that to support new Ratio API --- lib/membrane/clock.ex | 8 ++++---- lib/membrane/core/timer.ex | 7 +++++-- lib/membrane/time.ex | 23 +++++++---------------- mix.exs | 2 +- mix.lock | 2 +- test/membrane/clock_test.exs | 8 ++++---- 6 files changed, 22 insertions(+), 28 deletions(-) diff --git a/lib/membrane/clock.ex b/lib/membrane/clock.ex index 401bbf7d2..a9a3dc176 100644 --- a/lib/membrane/clock.ex +++ b/lib/membrane/clock.ex @@ -212,9 +212,9 @@ defmodule Membrane.Clock do end defp handle_clock_update(till_next, state) do - use Ratio + use Numbers, overload_operators: true - if till_next < 0 do + if Ratio.lt?(till_next, 0) do raise "Clock update time cannot be negative, received: #{inspect(till_next)}" end @@ -227,10 +227,10 @@ defmodule Membrane.Clock do end defp do_handle_clock_update(till_next, state) do - use Ratio + use Numbers, overload_operators: true %{till_next: from_previous, clock_time: clock_time} = state clock_time = clock_time + from_previous - ratio = clock_time / (state.time_provider.() - state.init_time) + ratio = Ratio.div(Ratio.new(clock_time), Ratio.new(state.time_provider.() - state.init_time)) state = %{state | clock_time: clock_time, till_next: till_next} broadcast_and_update_ratio(ratio, state) end diff --git a/lib/membrane/core/timer.ex b/lib/membrane/core/timer.ex index be7dad19a..c84051676 100644 --- a/lib/membrane/core/timer.ex +++ b/lib/membrane/core/timer.ex @@ -44,7 +44,7 @@ defmodule Membrane.Core.Timer do end def tick(timer) do - use Ratio + use Numbers, overload_operators: true %__MODULE__{ id: id, @@ -55,7 +55,10 @@ defmodule Membrane.Core.Timer do } = timer time_passed = time_passed + interval - time = (init_time + time_passed / ratio) |> Ratio.floor() |> Time.round_to_milliseconds() + + time = + (init_time + Ratio.new(time_passed, ratio)) |> Ratio.floor() |> Time.round_to_milliseconds() + timer_ref = Process.send_after(self(), Message.new(:timer_tick, id), time, abs: true) %__MODULE__{timer | time_passed: time_passed, timer_ref: timer_ref} end diff --git a/lib/membrane/time.ex b/lib/membrane/time.ex index 14eff56ad..2e4a831d8 100644 --- a/lib/membrane/time.ex +++ b/lib/membrane/time.ex @@ -11,6 +11,8 @@ defmodule Membrane.Time do that do not touch hardware clock, you should use Membrane units for consistency. """ + require Ratio + @compile {:inline, native_units: 1, native_unit: 0, nanoseconds: 1, nanosecond: 0, second: 0, seconds: 1} @@ -30,7 +32,7 @@ defmodule Membrane.Time do # Difference between 01.01.1900 (start of NTP epoch) and 01.01.1970 (start of Unix epoch) in seconds @ntp_unix_epoch_diff 2_208_988_800 - @two_to_pow_32 Ratio.pow(2, 32) + @two_to_pow_32 Ratio.pow(Ratio.new(2, 1), 32) |> Ratio.trunc() @doc """ Checks whether a value is `Membrane.Time.t`. @@ -246,12 +248,10 @@ defmodule Membrane.Time do end # credo:disable-for-next-line Credo.Check.Readability.Specs - def unquote(unit.plural)(number) do - if not Ratio.is_rational?(number) do - raise "Only integers and rationals can be converted with Membrane.Time.#{unquote(unit.plural)}" - end + def unquote(unit.plural)(number) when Ratio.is_rational(number) do + use Numbers, overload_operators: true - Ratio.*(number, unquote(unit.duration)) + (number * unquote(unit.duration)) |> round_rational() end @@ -274,7 +274,7 @@ defmodule Membrane.Time do @spec unquote(as_fun_name)(t) :: integer | Ratio.t() # credo:disable-for-next-line Credo.Check.Readability.Specs def unquote(as_fun_name)(time) when is_time(time) do - Ratio./(time, unquote(unit.duration)) + Ratio.new(time, unquote(unit.duration)) end end) @@ -284,7 +284,6 @@ defmodule Membrane.Time do end defp round_rational(ratio) do - ratio = make_rational(ratio) trunced = Ratio.trunc(ratio) if 2 * sign_of_rational(ratio) * @@ -294,14 +293,6 @@ defmodule Membrane.Time do else: trunced end - defp make_rational(number) do - if Ratio.is_rational?(number) do - number - else - %Ratio{numerator: number, denominator: 1} - end - end - defp sign_of_rational(ratio) do if ratio.numerator == 0, do: 0, else: Ratio.sign(ratio) end diff --git a/mix.exs b/mix.exs index 9bb2ca709..53b847391 100644 --- a/mix.exs +++ b/mix.exs @@ -124,7 +124,7 @@ defmodule Membrane.Mixfile do {:qex, "~> 0.3"}, {:telemetry, "~> 1.0"}, {:bunch, "~> 1.3"}, - {:ratio, "~> 2.0"}, + {:ratio, "~> 3.0"}, # Development {:ex_doc, "~> 0.28", only: :dev, runtime: false}, {:dialyxir, "~> 1.1", only: :dev, runtime: false}, diff --git a/mix.lock b/mix.lock index 7d47bc9d3..a9a706456 100644 --- a/mix.lock +++ b/mix.lock @@ -26,7 +26,7 @@ "numbers": {:hex, :numbers, "5.2.4", "f123d5bb7f6acc366f8f445e10a32bd403c8469bdbce8ce049e1f0972b607080", [:mix], [{:coerce, "~> 1.0", [hex: :coerce, repo: "hexpm", optional: false]}, {:decimal, "~> 1.9 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "eeccf5c61d5f4922198395bf87a465b6f980b8b862dd22d28198c5e6fab38582"}, "parse_trans": {:hex, :parse_trans, "3.3.1", "16328ab840cc09919bd10dab29e431da3af9e9e7e7e6f0089dd5a2d2820011d8", [:rebar3], [], "hexpm", "07cd9577885f56362d414e8c4c4e6bdf10d43a8767abb92d24cbe8b24c54888b"}, "qex": {:hex, :qex, "0.5.1", "0d82c0f008551d24fffb99d97f8299afcb8ea9cf99582b770bd004ed5af63fd6", [:mix], [], "hexpm", "935a39fdaf2445834b95951456559e9dc2063d0a055742c558a99987b38d6bab"}, - "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"}, + "ratio": {:hex, :ratio, "3.0.1", "de461c63575b4ede4700813227d9192a9df6ccb989ee87bfc5e78a1f5f465996", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:numbers, "~> 5.2.0", [hex: :numbers, repo: "hexpm", optional: false]}], "hexpm", "8830d1b05c025138914543227f3fce95f7ed5559ef3b26ce03aa4e2135ceae72"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"}, "telemetry": {:hex, :telemetry, "1.1.0", "a589817034a27eab11144ad24d5c0f9fab1f58173274b1e9bae7074af9cbee51", [:rebar3], [], "hexpm", "b727b2a1f75614774cff2d7565b64d0dfa5bd52ba517f16543e6fc7efcc0df48"}, "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, diff --git a/test/membrane/clock_test.exs b/test/membrane/clock_test.exs index 62b20ed28..b76ec5b54 100644 --- a/test/membrane/clock_test.exs +++ b/test/membrane/clock_test.exs @@ -1,5 +1,6 @@ defmodule Membrane.ClockTest do use ExUnit.Case + use Numbers, overload_operators: true @module Membrane.Clock @@ -16,7 +17,8 @@ defmodule Membrane.ClockTest do refute_receive {:membrane_clock_ratio, ^clock, _ratio} send(clock, {:membrane_clock_update, 2}) send(clock, time: 13) - assert_receive {:membrane_clock_ratio, ^clock, 2} + two = Ratio.new(2, 1) + assert_receive {:membrane_clock_ratio, ^clock, ^two} send(clock, {:membrane_clock_update, random_time()}) send(clock, time: 33) ratio = Ratio.new(20 + 2, 33 - 3) @@ -24,8 +26,6 @@ defmodule Membrane.ClockTest do end test "should handle different ratio formats" do - use Ratio - {:ok, clock} = @module.start_link(time_provider: fn -> receive do: (time: t -> ms_to_ns(t)) end) @@ -38,7 +38,7 @@ defmodule Membrane.ClockTest do send(clock, {:membrane_clock_update, 5}) send(clock, time: 20) @module.subscribe(clock) - ratio = (5 + Ratio.new(1, 3) * 2) / (20 - 5) + ratio = Ratio.div(5 + Ratio.new(1, 3) * 2, Ratio.new(20 - 5)) assert_receive {:membrane_clock_ratio, ^clock, ^ratio} end From 25d2b392075189048f7b4362747fc2b87d2ad505 Mon Sep 17 00:00:00 2001 From: varsill Date: Thu, 24 Nov 2022 11:26:46 +0100 Subject: [PATCH 2/6] Update ratio to v3.0.2. Format files --- lib/membrane/core/timer.ex | 4 +++- mix.lock | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/membrane/core/timer.ex b/lib/membrane/core/timer.ex index 626075c04..e257e8f1f 100644 --- a/lib/membrane/core/timer.ex +++ b/lib/membrane/core/timer.ex @@ -62,7 +62,9 @@ defmodule Membrane.Core.Timer do # Next tick time converted to BEAM clock time beam_next_tick_time = - (init_time + Ratio.new(next_tick_time, ratio)) |> Ratio.floor() |> Time.round_to_milliseconds() + (init_time + Ratio.new(next_tick_time, ratio)) + |> Ratio.floor() + |> Time.round_to_milliseconds() timer_ref = Process.send_after(self(), Message.new(:timer_tick, id), beam_next_tick_time, abs: true) diff --git a/mix.lock b/mix.lock index 5b5e091c4..0941989de 100644 --- a/mix.lock +++ b/mix.lock @@ -7,7 +7,7 @@ "dialyxir": {:hex, :dialyxir, "1.2.0", "58344b3e87c2e7095304c81a9ae65cb68b613e28340690dfe1a5597fd08dec37", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "61072136427a851674cab81762be4dbeae7679f85b1272b6d25c3a839aff8463"}, "earmark_parser": {:hex, :earmark_parser, "1.4.29", "149d50dcb3a93d9f3d6f3ecf18c918fb5a2d3c001b5d3305c926cddfbd33355b", [:mix], [], "hexpm", "4902af1b3eb139016aed210888748db8070b8125c2342ce3dcae4f38dcc63503"}, "erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"}, - "ex_doc": {:hex, :ex_doc, "0.29.0", "4a1cb903ce746aceef9c1f9ae8a6c12b742a5461e6959b9d3b24d813ffbea146", [:mix], [{:earmark_parser, "~> 1.4.19", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "f096adb8bbca677d35d278223361c7792d496b3fc0d0224c9d4bc2f651af5db1"}, + "ex_doc": {:hex, :ex_doc, "0.29.1", "b1c652fa5f92ee9cf15c75271168027f92039b3877094290a75abcaac82a9f77", [:mix], [{:earmark_parser, "~> 1.4.19", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "b7745fa6374a36daf484e2a2012274950e084815b936b1319aeebcf7809574f6"}, "excoveralls": {:hex, :excoveralls, "0.15.0", "ac941bf85f9f201a9626cc42b2232b251ad8738da993cf406a4290cacf562ea4", [:mix], [{:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "9631912006b27eca30a2f3c93562bc7ae15980afb014ceb8147dc5cdd8f376f1"}, "file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"}, "hackney": {:hex, :hackney, "1.18.1", "f48bf88f521f2a229fc7bae88cf4f85adc9cd9bcf23b5dc8eb6a1788c662c4f6", [:rebar3], [{:certifi, "~>2.9.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "a4ecdaff44297e9b5894ae499e9a070ea1888c84afdd1fd9b7b2bc384950128e"}, @@ -25,7 +25,7 @@ "numbers": {:hex, :numbers, "5.2.4", "f123d5bb7f6acc366f8f445e10a32bd403c8469bdbce8ce049e1f0972b607080", [:mix], [{:coerce, "~> 1.0", [hex: :coerce, repo: "hexpm", optional: false]}, {:decimal, "~> 1.9 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "eeccf5c61d5f4922198395bf87a465b6f980b8b862dd22d28198c5e6fab38582"}, "parse_trans": {:hex, :parse_trans, "3.3.1", "16328ab840cc09919bd10dab29e431da3af9e9e7e7e6f0089dd5a2d2820011d8", [:rebar3], [], "hexpm", "07cd9577885f56362d414e8c4c4e6bdf10d43a8767abb92d24cbe8b24c54888b"}, "qex": {:hex, :qex, "0.5.1", "0d82c0f008551d24fffb99d97f8299afcb8ea9cf99582b770bd004ed5af63fd6", [:mix], [], "hexpm", "935a39fdaf2445834b95951456559e9dc2063d0a055742c558a99987b38d6bab"}, - "ratio": {:hex, :ratio, "3.0.1", "de461c63575b4ede4700813227d9192a9df6ccb989ee87bfc5e78a1f5f465996", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:numbers, "~> 5.2.0", [hex: :numbers, repo: "hexpm", optional: false]}], "hexpm", "8830d1b05c025138914543227f3fce95f7ed5559ef3b26ce03aa4e2135ceae72"}, + "ratio": {:hex, :ratio, "3.0.2", "60a5976872a4dc3d873ecc57eed1738589e99d1094834b9c935b118231297cfb", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:numbers, "~> 5.2.0", [hex: :numbers, repo: "hexpm", optional: false]}], "hexpm", "3a13ed5a30ad0bfd7e4a86bf86d93d2b5a06f5904417d38d3f3ea6406cdfc7bb"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"}, "telemetry": {:hex, :telemetry, "1.1.0", "a589817034a27eab11144ad24d5c0f9fab1f58173274b1e9bae7074af9cbee51", [:rebar3], [], "hexpm", "b727b2a1f75614774cff2d7565b64d0dfa5bd52ba517f16543e6fc7efcc0df48"}, "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, From 504f1ffc8e1cd9f40673cdcad14c409d7ea4b365 Mon Sep 17 00:00:00 2001 From: varsill Date: Fri, 25 Nov 2022 17:18:57 +0100 Subject: [PATCH 3/6] Make sure the membrane clock uses only Ratio.t() and not integers. Remove unnecessary use Number clauses --- lib/membrane/clock.ex | 22 ++++++++-------------- lib/membrane/core/timer.ex | 6 +++--- lib/membrane/core/timer_controller.ex | 2 +- 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/lib/membrane/clock.ex b/lib/membrane/clock.ex index a9a3dc176..ea6164edd 100644 --- a/lib/membrane/clock.ex +++ b/lib/membrane/clock.ex @@ -11,7 +11,7 @@ defmodule Membrane.Clock do the time passed, in practice the described approach turns out to be more convenient, as it simplifies the first update. - Basing on updates, Clock calculates the `t:ratio_t/0` of its time to the reference + Basing on updates, Clock calculates the `t:Ratio.t/0` of its time to the reference time. The reference time can be configured with `:time_provider` option. The ratio is broadcasted (see `t:ratio_message_t/0`) to _subscribers_ (see `subscribe/2`) - processes willing to synchronize to the custom clock. Subscribers can adjust @@ -34,11 +34,6 @@ defmodule Membrane.Clock do @type t :: pid - @typedoc """ - Ratio of the Clock time to the reference time. - """ - @type ratio_t :: Ratio.t() | non_neg_integer - @typedoc """ Update message received by the Clock. It should contain the time till the next update. @@ -48,13 +43,13 @@ defmodule Membrane.Clock do milliseconds :: non_neg_integer | Ratio.t() - | {numerator :: non_neg_integer, denominator :: pos_integer}} + | {numerator :: non_neg_integer, denominator :: non_neg_integer()}} @typedoc """ Ratio message sent by the Clock to all its subscribers. It contains the ratio of the custom clock time to the reference time. """ - @type ratio_message_t :: {:membrane_clock_ratio, clock :: pid, ratio_t} + @type ratio_message_t :: {:membrane_clock_ratio, clock :: pid, Ratio.t()} @typedoc """ Options accepted by `start_link/2` and `start/2` functions. @@ -200,7 +195,7 @@ defmodule Membrane.Clock do defp get_proxy_options(true, _proxy_for), do: %{proxy: true, proxy_for: nil} defp get_proxy_options(_proxy, _proxy_for), - do: %{init_time: nil, clock_time: 0, till_next: nil, proxy: false} + do: %{init_time: nil, clock_time: Ratio.new(0), till_next: nil, proxy: false} defp handle_unsubscribe(pid, state) do Process.demonitor(state.subscribers[pid].monitor, [:flush]) @@ -212,13 +207,13 @@ defmodule Membrane.Clock do end defp handle_clock_update(till_next, state) do - use Numbers, overload_operators: true + till_next = Ratio.new(till_next) if Ratio.lt?(till_next, 0) do raise "Clock update time cannot be negative, received: #{inspect(till_next)}" end - till_next = till_next * Time.millisecond() + till_next = Ratio.mult(till_next, Ratio.new(Time.millisecond())) case state.init_time do nil -> %{state | init_time: state.time_provider.(), till_next: till_next} @@ -227,10 +222,9 @@ defmodule Membrane.Clock do end defp do_handle_clock_update(till_next, state) do - use Numbers, overload_operators: true %{till_next: from_previous, clock_time: clock_time} = state - clock_time = clock_time + from_previous - ratio = Ratio.div(Ratio.new(clock_time), Ratio.new(state.time_provider.() - state.init_time)) + clock_time = Ratio.add(clock_time, from_previous) + ratio = Ratio.new(clock_time, state.time_provider.() - state.init_time) state = %{state | clock_time: clock_time, till_next: till_next} broadcast_and_update_ratio(ratio, state) end diff --git a/lib/membrane/core/timer.ex b/lib/membrane/core/timer.ex index e257e8f1f..7e062d5d7 100644 --- a/lib/membrane/core/timer.ex +++ b/lib/membrane/core/timer.ex @@ -14,12 +14,12 @@ defmodule Membrane.Core.Timer do init_time: Time.t(), clock: Clock.t(), next_tick_time: Time.t(), - ratio: Clock.ratio_t(), + ratio: Ratio.t(), timer_ref: reference() | nil } @enforce_keys [:interval, :clock, :init_time, :id] - defstruct @enforce_keys ++ [next_tick_time: 0, ratio: 1, timer_ref: nil] + defstruct @enforce_keys ++ [next_tick_time: 0, ratio: Ratio.new(1), timer_ref: nil] @spec start(id_t, interval_t, Clock.t()) :: t def start(id, interval, clock) do @@ -37,7 +37,7 @@ defmodule Membrane.Core.Timer do :ok end - @spec update_ratio(t, Clock.ratio_t()) :: t + @spec update_ratio(t, Ratio.t()) :: t def update_ratio(timer, ratio) do %__MODULE__{timer | ratio: ratio} end diff --git a/lib/membrane/core/timer_controller.ex b/lib/membrane/core/timer_controller.ex index a412380cd..c569ef907 100644 --- a/lib/membrane/core/timer_controller.ex +++ b/lib/membrane/core/timer_controller.ex @@ -74,7 +74,7 @@ defmodule Membrane.Core.TimerController do state end - @spec handle_clock_update(Timer.id_t(), Clock.ratio_t(), Component.state_t()) :: + @spec handle_clock_update(Timer.id_t(), Ratio.t(), Component.state_t()) :: Component.state_t() def handle_clock_update(clock, ratio, state) do update_in( From 0a262385e36735fe3216038f7dd18c66bcab228b Mon Sep 17 00:00:00 2001 From: varsill Date: Fri, 25 Nov 2022 17:24:36 +0100 Subject: [PATCH 4/6] Improve the typespec in Membrane.Clock --- lib/membrane/clock.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/membrane/clock.ex b/lib/membrane/clock.ex index ea6164edd..354e2f09f 100644 --- a/lib/membrane/clock.ex +++ b/lib/membrane/clock.ex @@ -43,7 +43,7 @@ defmodule Membrane.Clock do milliseconds :: non_neg_integer | Ratio.t() - | {numerator :: non_neg_integer, denominator :: non_neg_integer()}} + | {numerator :: non_neg_integer, denominator :: pos_integer()}} @typedoc """ Ratio message sent by the Clock to all its subscribers. It contains the ratio From d65d6792c1c0340ae61f5e878d9397f70c92f101 Mon Sep 17 00:00:00 2001 From: varsill Date: Tue, 29 Nov 2022 09:31:34 +0100 Subject: [PATCH 5/6] Remove all the usages of 'use Numbers'. Fix a bug with a timer ratio being an integer --- lib/membrane/clock.ex | 15 ++++++++++----- lib/membrane/core/timer.ex | 12 +++++------- lib/membrane/core/timer_controller.ex | 2 +- lib/membrane/time.ex | 4 +--- test/membrane/clock_test.exs | 7 ++++--- 5 files changed, 21 insertions(+), 19 deletions(-) diff --git a/lib/membrane/clock.ex b/lib/membrane/clock.ex index 354e2f09f..4e715ebfb 100644 --- a/lib/membrane/clock.ex +++ b/lib/membrane/clock.ex @@ -11,7 +11,7 @@ defmodule Membrane.Clock do the time passed, in practice the described approach turns out to be more convenient, as it simplifies the first update. - Basing on updates, Clock calculates the `t:Ratio.t/0` of its time to the reference + Basing on updates, Clock calculates the `t:ratio_t/0` of its time to the reference time. The reference time can be configured with `:time_provider` option. The ratio is broadcasted (see `t:ratio_message_t/0`) to _subscribers_ (see `subscribe/2`) - processes willing to synchronize to the custom clock. Subscribers can adjust @@ -34,6 +34,11 @@ defmodule Membrane.Clock do @type t :: pid + @typedoc """ + Ratio of the Clock time to the reference time. + """ + @type ratio_t :: Ratio.t() + @typedoc """ Update message received by the Clock. It should contain the time till the next update. @@ -42,14 +47,14 @@ defmodule Membrane.Clock do {:membrane_clock_update, milliseconds :: non_neg_integer - | Ratio.t() + | ratio_t | {numerator :: non_neg_integer, denominator :: pos_integer()}} @typedoc """ Ratio message sent by the Clock to all its subscribers. It contains the ratio of the custom clock time to the reference time. """ - @type ratio_message_t :: {:membrane_clock_ratio, clock :: pid, Ratio.t()} + @type ratio_message_t :: {:membrane_clock_ratio, clock :: pid, ratio_t} @typedoc """ Options accepted by `start_link/2` and `start/2` functions. @@ -135,7 +140,7 @@ defmodule Membrane.Clock do subscribe(proxy_for) state else - broadcast_and_update_ratio(1, state) + broadcast_and_update_ratio(Ratio.new(1), state) end {:noreply, state} @@ -224,7 +229,7 @@ defmodule Membrane.Clock do defp do_handle_clock_update(till_next, state) do %{till_next: from_previous, clock_time: clock_time} = state clock_time = Ratio.add(clock_time, from_previous) - ratio = Ratio.new(clock_time, state.time_provider.() - state.init_time) + ratio = Ratio.div(clock_time, Ratio.new(state.time_provider.() - state.init_time)) state = %{state | clock_time: clock_time, till_next: till_next} broadcast_and_update_ratio(ratio, state) end diff --git a/lib/membrane/core/timer.ex b/lib/membrane/core/timer.ex index 7e062d5d7..226c6e226 100644 --- a/lib/membrane/core/timer.ex +++ b/lib/membrane/core/timer.ex @@ -14,7 +14,7 @@ defmodule Membrane.Core.Timer do init_time: Time.t(), clock: Clock.t(), next_tick_time: Time.t(), - ratio: Ratio.t(), + ratio: Clock.ratio_t(), timer_ref: reference() | nil } @@ -37,7 +37,7 @@ defmodule Membrane.Core.Timer do :ok end - @spec update_ratio(t, Ratio.t()) :: t + @spec update_ratio(t, Clock.ratio_t()) :: t def update_ratio(timer, ratio) do %__MODULE__{timer | ratio: ratio} end @@ -48,8 +48,6 @@ defmodule Membrane.Core.Timer do end def tick(timer) do - use Numbers, overload_operators: true - %__MODULE__{ id: id, interval: interval, @@ -58,18 +56,18 @@ defmodule Membrane.Core.Timer do ratio: ratio } = timer - next_tick_time = next_tick_time + interval + next_tick_time = Ratio.add(Ratio.new(next_tick_time), Ratio.new(interval)) # Next tick time converted to BEAM clock time beam_next_tick_time = - (init_time + Ratio.new(next_tick_time, ratio)) + Ratio.add(Ratio.new(init_time), Ratio.div(next_tick_time, ratio)) |> Ratio.floor() |> Time.round_to_milliseconds() timer_ref = Process.send_after(self(), Message.new(:timer_tick, id), beam_next_tick_time, abs: true) - %__MODULE__{timer | next_tick_time: next_tick_time, timer_ref: timer_ref} + %__MODULE__{timer | next_tick_time: next_tick_time |> Ratio.floor(), timer_ref: timer_ref} end @spec set_interval(t, interval_t) :: t diff --git a/lib/membrane/core/timer_controller.ex b/lib/membrane/core/timer_controller.ex index c569ef907..a412380cd 100644 --- a/lib/membrane/core/timer_controller.ex +++ b/lib/membrane/core/timer_controller.ex @@ -74,7 +74,7 @@ defmodule Membrane.Core.TimerController do state end - @spec handle_clock_update(Timer.id_t(), Ratio.t(), Component.state_t()) :: + @spec handle_clock_update(Timer.id_t(), Clock.ratio_t(), Component.state_t()) :: Component.state_t() def handle_clock_update(clock, ratio, state) do update_in( diff --git a/lib/membrane/time.ex b/lib/membrane/time.ex index d66672492..ec887e8f3 100644 --- a/lib/membrane/time.ex +++ b/lib/membrane/time.ex @@ -263,9 +263,7 @@ defmodule Membrane.Time do # credo:disable-for-next-line Credo.Check.Readability.Specs def unquote(unit.plural)(number) when Ratio.is_rational(number) do - use Numbers, overload_operators: true - - (number * unquote(unit.duration)) + Ratio.mult(number, Ratio.new(unquote(unit.duration))) |> round_rational() end diff --git a/test/membrane/clock_test.exs b/test/membrane/clock_test.exs index df9802e57..dabe31aa0 100644 --- a/test/membrane/clock_test.exs +++ b/test/membrane/clock_test.exs @@ -1,6 +1,5 @@ defmodule Membrane.ClockTest do use ExUnit.Case - use Numbers, overload_operators: true @module Membrane.Clock @@ -17,7 +16,7 @@ defmodule Membrane.ClockTest do refute_receive {:membrane_clock_ratio, ^clock, _ratio} send(clock, {:membrane_clock_update, 2}) send(clock, time: 13) - two = Ratio.new(2, 1) + two = Ratio.new(2) assert_receive {:membrane_clock_ratio, ^clock, ^two} send(clock, {:membrane_clock_update, random_time()}) send(clock, time: 33) @@ -38,7 +37,9 @@ defmodule Membrane.ClockTest do send(clock, {:membrane_clock_update, 5}) send(clock, time: 20) @module.subscribe(clock) - ratio = Ratio.div(5 + Ratio.new(1, 3) * 2, Ratio.new(20 - 5)) + two = Ratio.new(2) + five = Ratio.new(5) + ratio = Ratio.div(Ratio.add(five, Ratio.mult(Ratio.new(1, 3), two)), Ratio.new(20 - 5)) assert_receive {:membrane_clock_ratio, ^clock, ^ratio} end From 3276e55fb880d3bbcae2bf2cf6ca6bda79d3f1de Mon Sep 17 00:00:00 2001 From: varsill Date: Tue, 29 Nov 2022 09:55:42 +0100 Subject: [PATCH 6/6] Make sure ratio in Timer struct is always a Ratio. Update the tests accordingly --- lib/membrane/clock.ex | 2 +- test/membrane/clock_test.exs | 2 +- test/membrane/core/element_test.exs | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/membrane/clock.ex b/lib/membrane/clock.ex index 4e715ebfb..2db8325f0 100644 --- a/lib/membrane/clock.ex +++ b/lib/membrane/clock.ex @@ -118,7 +118,7 @@ defmodule Membrane.Clock do state = %{ - ratio: 1, + ratio: Ratio.new(1), subscribers: %{}, time_provider: options |> Keyword.get(:time_provider, fn -> Time.monotonic_time() end) } diff --git a/test/membrane/clock_test.exs b/test/membrane/clock_test.exs index dabe31aa0..2ec21c895 100644 --- a/test/membrane/clock_test.exs +++ b/test/membrane/clock_test.exs @@ -3,7 +3,7 @@ defmodule Membrane.ClockTest do @module Membrane.Clock - @initial_ratio 1 + @initial_ratio Ratio.new(1) test "should calculate proper ratio and send it to subscribers on each (but the first) update" do {:ok, clock} = diff --git a/test/membrane/core/element_test.exs b/test/membrane/core/element_test.exs index b8f551e13..1ffda3101 100644 --- a/test/membrane/core/element_test.exs +++ b/test/membrane/core/element_test.exs @@ -257,9 +257,10 @@ defmodule Membrane.Core.ElementTest do {:ok, clock} = Membrane.Clock.start_link() state = Membrane.Core.TimerController.start_timer(:timer, 1000, clock, get_state()) - assert {:noreply, state} = Element.handle_info({:membrane_clock_ratio, clock, 123}, state) + assert {:noreply, state} = + Element.handle_info({:membrane_clock_ratio, clock, Ratio.new(123)}, state) - assert state.synchronization.timers.timer.ratio == 123 + assert state.synchronization.timers.timer.ratio == Ratio.new(123) end test "should set stream sync" do