Current section
Files
Jump to
Current section
Files
src/vice_prv_sox.erl
% @hidden
-module(vice_prv_sox).
-include_lib("bucs/include/bucs.hrl").
-include("../include/vice_sox.hrl").
-behaviour(vice_encoder).
%% API
-export([
init/0
, infos/3
, info/4
, command/5
, progress/2
]).
-record(state, {
sox,
soxi
}).
-define(INFO_FORMAT, "~s ~s \"~ts\"").
-define(INFOS, #{
sample_rate => {"-r", fun bucs:to_integer/1},
number_of_channels => {"-c", fun bucs:to_integer/1},
number_of_samples => {"-s", fun bucs:to_integer/1},
duration => {"-d", fun bucs:to_binary/1},
seconds_duration => {"-D", fun bucs:to_float/1},
bits_per_sample => {"-b", fun bucs:to_integer/1},
bitrate => {"-B", fun(Value) ->
bucs:to_integer(re:replace(Value, "[^0-9]*$", "", [{return, list}]))
end},
bitrate_unit => {"-B", fun(Value) ->
re:replace(Value, "^[0-9]*", "", [{return, binary}])
end},
encoding => {"-e", fun bucs:to_binary/1},
annotations => {"-a", fun bucs:to_binary/1}
}).
init() ->
case vice_utils:find_tools(record_info(fields, state), sox) of
{error, Reason} ->
{stop, Reason};
{state, Data} ->
{ok, ?list_to_record(state, Data)}
end.
infos(State, File, Options) ->
Labels = buclists:keyfind(labels, 1, Options, atom),
{ok, maps:fold(fun(Info, _, Acc) ->
case info(State, File, Info, Options) of
{ok, Data} ->
case Labels of
binary ->
maps:put(bucs:to_binary(Info), Data, Acc);
_ ->
maps:put(Info, Data, Acc)
end;
_ ->
Acc
end
end, #{}, ?INFOS)}.
info(#state{soxi = Soxi}, File, Info, _Options) ->
case maps:get(Info, ?INFOS, undefined) of
undefined ->
{error, unavailable};
{Param, ConvertFunction} ->
Cmd = lists:flatten(io_lib:format(?INFO_FORMAT, [Soxi, Param, File])),
case bucos:run(Cmd) of
{ok, Output} ->
{ok, erlang:apply(ConvertFunction, [vice_prv_stdlib:chomp(Output)])};
Error ->
Error
end
end.
command(#state{sox = Converter}, In, Out, Options, _Multi) ->
Options1 = buclists:merge_keylists(1, [{clobber, true}, {show_progress, true}], Options),
Params = vice_prv_options:options(?OPTIONS, Options1),
InputOptions = buclists:keyfind(input, 1, Params, ""),
OutputOptions = buclists:keyfind(output, 1, Params, ""),
GlobalOptions = buclists:keyfind(global, 1, Params, ""),
EffectsOptions = buclists:keyfind(effects, 1, Params, ""),
Inputs = build_input(In, InputOptions),
{ok, lists:flatten(
io_lib:format(
"~s~s~s~s \"~ts\"~s",
[Converter, GlobalOptions, Inputs, OutputOptions, Out, EffectsOptions]))}.
build_input([X|_] = Ins, [Y|_] = InputOptions) when is_list(X), is_list(Y) ->
build_input(Ins, InputOptions, "");
build_input([X|_] = Ins, InputOptions) when is_list(X) ->
build_input(Ins, [InputOptions]);
build_input(In, [InputOptions|_]) when is_list(InputOptions) ->
build_input(In, InputOptions);
build_input(In, InputOptions) ->
lists:flatten(
io_lib:format(
"~s \"~ts\"", [InputOptions, In])).
build_input([], _, Result) ->
Result;
build_input([In|Ins], [Options|InputOptions], Result) ->
build_input(
Ins, InputOptions,
Result ++ " " ++ build_input(In, Options));
build_input([In|Ins], [], Result) ->
build_input(
Ins, [],
Result ++ build_input(In, "")).
progress(_Bytes, Sofar) ->
Sofar.
% format option
%format(FMT, Args) ->
% lists:flatten(io_lib:format(FMT, Args)).