Packages
membrane_core
1.3.4
1.3.4
1.3.3
1.3.2
1.3.1
1.3.0
1.2.7
1.2.6
1.2.5
retired
1.2.4
1.2.3
1.2.2
1.2.1
1.2.0
1.2.0-rc1
1.1.2
1.1.1
1.1.0
1.1.0-rc1
1.1.0-rc0
1.0.1
1.0.0
1.0.0-rc1
1.0.0-rc0
0.12.9
0.12.8
0.12.7
0.12.6
0.12.5
0.12.4
0.12.3
0.12.2
0.12.1
0.12.0
retired
0.11.5
0.11.4
0.11.3
0.11.2
0.11.1
0.11.0
0.10.2
0.10.1
0.10.0
0.9.0
0.8.2
0.8.1
0.8.0
0.7.0
0.6.1
0.6.0
0.5.3
0.5.2
0.5.1
0.5.0
0.4.3
0.4.2
0.4.1
0.4.0
0.3.2
0.3.1
0.3.0
0.2.2
0.2.1
0.2.0
0.1.1
0.1.0
Membrane Multimedia Framework (Core)
Current section
Files
Jump to
Current section
Files
lib/mix/tasks/membrane.demo.ex
defmodule Mix.Tasks.Membrane.Demo do
@shortdoc "Download Membrane demos and examples"
@moduledoc """
Download Membrane demos and examples. Requires `git` installed.
$ mix membrane.demo [-a] [-l] [-d <repo_path>] [<demos> ...]
## Options
* `-l, --list` - List all demos available and their brief descriptions.
* `-a, --all` - Pull the repository with all demos.
* `-d, --directory` - Specify a directory where the demos should be placed in. By default they're placed in the current working directory
"""
use Mix.Task
@switches [
list: :boolean,
all: :boolean,
directory: :string
]
@aliases [
l: :list,
a: :all,
d: :directory
]
@demos_readme_url "https://raw.githubusercontent.com/membraneframework/membrane_demo/refs/heads/master/README.md"
@demos_clone_url "https://github.com/membraneframework/membrane_demo.git"
@impl true
def run([]) do
Mix.Tasks.Help.run(["membrane.demo"])
end
def run(argv) do
{opts, demos_names} = OptionParser.parse!(argv, aliases: @aliases, switches: @switches)
if opts[:list] do
list_available_demos()
end
target_dir = Path.expand(opts[:directory] || ".")
cond do
opts[:all] -> copy_all_demos(target_dir)
demos_names != [] -> copy_specific_demos(target_dir, demos_names)
true -> :ok
end
end
defp list_available_demos() do
{:ok, _apps} = Application.ensure_all_started([:inets, :ssl])
case :httpc.request(:get, {~c"#{@demos_readme_url}", []}, [{:autoredirect, true}], []) do
{:ok, {{_version, 200, _reason}, _headers, body}} ->
fetch_demos_info(body)
{:ok, {{_version, status, reason}, _headers, _body}} ->
Mix.raise("Failed to fetch demos list: HTTP #{status} #{reason}")
{:error, reason} ->
Mix.raise("Failed to fetch demos list: #{inspect(reason)}")
end
end
defp fetch_demos_info(body) do
demos_info =
List.to_string(body)
|> String.split("\n")
|> Enum.map(&Regex.named_captures(~r/^- \[(?<name>.*?)\]\(.*?\) - (?<description>.*)/, &1))
|> Enum.filter(&(&1 != nil))
|> Enum.map(
&Map.update!(
&1,
"description",
fn description -> Regex.replace(~r/\[(.*?)\]\(.*?\)/, description, "\\1") end
)
)
max_name_length =
demos_info
|> Enum.map(&String.length(&1["name"]))
|> Enum.max()
demos_table =
demos_info
|> Enum.map_join("\n", fn %{"name" => name, "description" => description} ->
dots_line = String.duplicate(".", max_name_length - String.length(name) + 3)
" | #{name} #{dots_line} | #{description}"
end)
Mix.shell().info(demos_table)
end
defp copy_all_demos(target_dir) do
repo_path = Path.join(target_dir, "membrane_demo")
execute_git_command(["clone", "-q", "--depth", "1", @demos_clone_url, repo_path])
end
defp copy_specific_demos(target_dir, demos_names) do
repo_path = Path.join(target_dir, "membrane_demo")
execute_git_command(["clone", "-q", "--depth", "1", "-n", @demos_clone_url, repo_path])
Enum.each(demos_names, fn demo_name ->
case copy_demo(target_dir, demo_name) do
:error ->
Mix.shell().error(
"No demo named #{demo_name}, run this task with -l to list all available demos"
)
:ok ->
Mix.shell().info("`#{demo_name}` demo created at #{Path.join(target_dir, demo_name)}")
end
end)
File.rm_rf!(repo_path)
end
defp copy_demo(target_dir, demo_name) do
repo_path = Path.join(target_dir, "membrane_demo")
demo_path = Path.join(repo_path, demo_name)
execute_git_command(["sparse-checkout", "set", demo_name], repo_path)
execute_git_command(["checkout"], repo_path)
case File.cp_r(demo_path, Path.join(target_dir, demo_name)) do
{:ok, _files} -> :ok
{:error, :enoent, _dir} -> :error
end
end
defp execute_git_command(argv, dir \\ ".") do
case System.cmd("git", argv, stderr_to_stdout: true, cd: dir) do
{_output, 0} ->
:ok
{output, exit_code} ->
Mix.shell().error("""
Git command `git #{Enum.join(argv, " ")} exited with code #{exit_code}. Output:
#{output}
""")
end
end
end