Skip to content

Instantly share code, notes, and snippets.

@mithereal
Created February 24, 2020 17:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mithereal/419f06b7e08dc6a4626086b2d04524ac to your computer and use it in GitHub Desktop.
Save mithereal/419f06b7e08dc6a4626086b2d04524ac to your computer and use it in GitHub Desktop.
supp isue
defmodule AudioConverter.Conversion.Server do
use GenServer
require Logger
@lock_interval_seconds 10000
defstruct(
filesize: [],
source: nil,
destination: nil
)
def child_spec(args) do
%{
id: __MODULE__,
start: { __MODULE__, :start_link, args},
restart: :temporary,
shutdown: 5000,
type: :worker
}
end
def start_link(args) do
# :jobs.add_queue("audio conversions", [:passive])
GenServer.start_link(__MODULE__, args)
end
def init([args]) do
init(args)
end
def init(args) do
%{destination: destination, source: source} = args
{_, file_stats} = File.stat(source)
filezise = file_stats.size
source_file = Path.basename(source)
source_file_parts = String.split(source_file, ".")
dest_filename = destination <> List.first(source_file_parts) <> ".mp3"
args = %{source: source, destination: dest_filename, filesize: [filezise]}
Logger.info("Queueing Conversion for File: " <> source)
:vice.start()
Process.send_after(self(), :file_locked?, @lock_interval_seconds)
{:ok, args}
end
def handle_info(:file_locked?, state) do
{_, file_stats} = File.stat(state.source)
filezise = file_stats.size
filesizes =
case Enum.count(state.filesize) > 3 do
true ->
last_filesizes = Enum.take(state.filesize, -4)
list_sum = Enum.sum(last_filesizes)
expected_sum = filezise * 4
case list_sum == expected_sum do
true -> Process.send_after(self(), :ready_to_encode, @lock_interval_seconds)
false -> Process.send_after(self(), :file_locked?, @lock_interval_seconds)
end
state.filesize ++ [filezise]
false ->
Process.send_after(self(), :file_locked?, @lock_interval_seconds)
state.filesize ++ [filezise]
end
new_state = %{state | filesize: filesizes}
{:noreply, new_state}
end
def handle_info(:ready_to_encode, state) do
# process input and compute result
{async, worker} = :vice.convert(state.source, state.destination)
case async do
:error ->
{error, _} = worker
Logger.error(error)
_ ->
basename = Path.basename(state.source)
Logger.info("Starting .mp3 Conversion for File: #{basename}")
# :jobs.add_queue("audio conversions counter", [
# {:standard_counter, 3},
# {:producer, dequeue()}
# ])
end
delete_source_file? = Application.get_env(:audioconversion, :remove_source)
case delete_source_file? do
true ->
args = %{worker: worker, source: state.source, destination: state.destination}
AudioConverter.Cleanup.Task.start_link(args)
false ->
nil
_ ->
nil
end
# shutdown(worker, state)
{:noreply, state}
end
def dequeue() do
:jobs.dequeue("audio conversions", 3)
end
def shutdown(worker, state) do
{status, _} = :vice.status(worker)
case status == 'running' do
true ->
shutdown(worker, state)
false ->
Logger.info("shutting down")
{:stop, {:shutdown, "Task Completed"}, state}
end
end
end
defmodule AudioConverter.Conversion.Supervisor do
use DynamicSupervisor
require Logger
@name :conversion_supervisor
def child_spec(_) do
%{
id: __MODULE__,
start: {__MODULE__, :start_link, []},
type: :supervisor
}
end
def start_child(args) do
spec = {AudioConverter.Conversion.Server, [args]}
DynamicSupervisor.start_child(__MODULE__, spec)
end
def start_link(args) do
DynamicSupervisor.start_link(__MODULE__, args, name: @name)
end
def start_link() do
DynamicSupervisor.start_link(__MODULE__, [], name: @name)
end
def init(args) do
DynamicSupervisor.init(
strategy: :one_for_one,
extra_arguments: args
)
end
def start(args) do
AudioConverter.Conversion.Server.start_link(args)
# :jobs.enqueue("audio conversions", AudioConverter.Conversion.Server.start_link(args))
end
end
defmodule AudioConverter.Watcher.Server do
use GenServer
require Logger
alias AudioConverter.Watcher.Server, as: WATCHER
@name :watcher
defstruct start_time: :erlang.system_time(),
files: 0,
watcher_pid: nil,
paths: []
def child_spec(args) do
%{
id: __MODULE__,
start: {__MODULE__, :start_link, [args]},
type: :worker
}
end
def start_link(args) do
Logger.info("Starting Directory Watcher")
GenServer.start_link(__MODULE__, args, name: @name)
end
def init(args) do
[dirs, _, _] = args
{_dirs, dirs} = dirs
source_dir =
case dirs.source_directory == "" || dirs.source_directory == nil do
true -> File.cwd!()
false -> dirs.source_directory
end
destination_dir =
case dirs.destination_directory == "" || dirs.destination_directory == nil do
true -> File.cwd!()
false -> dirs.destination_directory
end
Logger.info("The Audio Source Directory is: #{source_dir}")
Logger.info("The Converted Audio Output Directory is: #{destination_dir}")
{:ok, watcher_pid} = FileSystem.start_link(dirs: [source_dir])
FileSystem.subscribe(watcher_pid)
state = %__MODULE__{watcher_pid: watcher_pid, paths: dirs}
{:ok, state}
end
def handle_info(
{:file_event, watcher_pid, {path, events}},
%{watcher_pid: watcher_pid, paths: paths} = state
) do
state =
case events do
[:created] ->
# Logger.info("The following file has been added to the source directory: #{path}")
extension = Path.extname(path)
case extension == ".wav" do
false ->
state
true ->
## update the start time to reflect actual time of the first file created event
system_time =
case state.files == 0 do
true -> :erlang.system_time()
false -> state.start_time
end
file_paths = %{source: path, destination: paths.destination_directory}
AudioConverter.Conversion.Supervisor.start(file_paths)
state = %{state | start_time: system_time}
%{state | files: state.files + 1}
end
_ ->
state
end
{:noreply, state}
end
def handle_info(
{:file_event, watcher_pid, :stop},
%{watcher_pid: watcher_pid, paths: paths} = state
) do
# YOUR OWN LOGIC WHEN MONITOR STOP
# IO.inspect(paths)
{:noreply, state}
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment