Skip to content

Commit

Permalink
improvements & fixes for pa_devices
Browse files Browse the repository at this point in the history
  • Loading branch information
mat-hek committed Jul 10, 2024
1 parent b2cf225 commit c8b4df5
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 34 deletions.
58 changes: 28 additions & 30 deletions c_src/membrane_portaudio_plugin/pa_devices.c
Original file line number Diff line number Diff line change
@@ -1,40 +1,38 @@
#include "pa_devices.h"

UNIFEX_TERM list(UnifexEnv *env) {
UNIFEX_TERM result;
Pa_Initialize();
int numDevices = Pa_GetDeviceCount();
device devices[numDevices];
if (numDevices < 0) {
printf("\nERROR: Pa_CountDevices returned 0x%x\n", numDevices);
return list_result(env, devices, numDevices);
} else if (numDevices == 0) {
return list_result(env, devices, numDevices);
} else {
int default_input_id = Pa_GetDefaultInputDevice();
int default_output_id = Pa_GetDefaultOutputDevice();
for (int i = 0; i < numDevices; i++) {
const PaDeviceInfo *device_info = Pa_GetDeviceInfo(i);

if (i == default_input_id) {
devices[i].default_device = DEFAULT_DEVICE_INPUT;
} else if (i == default_output_id) {
devices[i].default_device = DEFAULT_DEVICE_OUTPUT;
} else {
devices[i].default_device = DEFAULT_DEVICE_FALSE;
}

devices[i].name = malloc(strlen(device_info->name) + 1);
if (device_info->name != NULL) {
strcpy(devices[i].name, device_info->name);
}
int num_devices = Pa_GetDeviceCount();
if (num_devices < 0) {
char error[2048];
sprintf(error, "Pa_CountDevices returned error, code: %d", num_devices);
result = unifex_raise(env, error);
goto list_error;
}
device *devices = unifex_alloc(sizeof(device) * num_devices);
int default_input_id = Pa_GetDefaultInputDevice();
int default_output_id = Pa_GetDefaultOutputDevice();
for (int i = 0; i < num_devices; i++) {
const PaDeviceInfo *device_info = Pa_GetDeviceInfo(i);

devices[i].id = i;
devices[i].max_output_channels = device_info->maxOutputChannels;
devices[i].max_input_channels = device_info->maxInputChannels;
devices[i].default_sample_rate = device_info->defaultSampleRate;
if (i == default_input_id) {
devices[i].default_device = DEFAULT_DEVICE_INPUT;
} else if (i == default_output_id) {
devices[i].default_device = DEFAULT_DEVICE_OUTPUT;
} else {
devices[i].default_device = DEFAULT_DEVICE_FALSE;
}

devices[i].name = (char *)device_info->name;
devices[i].id = i;
devices[i].max_output_channels = device_info->maxOutputChannels;
devices[i].max_input_channels = device_info->maxInputChannels;
devices[i].default_sample_rate = device_info->defaultSampleRate;
}

result = list_result(env, devices, num_devices);
list_error:
Pa_Terminate();
return list_result(env, devices, numDevices);
return result;
}
16 changes: 14 additions & 2 deletions lib/membrane_portaudio.ex
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,21 @@ defmodule Membrane.PortAudio do
"""
@spec print_devices() :: :ok
def print_devices() do
Application.ensure_all_started(:membrane_portaudio_plugin)
IO.inspect(list_devices(),
pretty: true,
limit: :infinity,
syntax_colors: IO.ANSI.syntax_colors()
)

:ok
end

@doc """
Returns a list of available audio devices.
"""
@spec list_devices() :: [Membrane.PortAudio.Device.t()]
def list_devices() do
Application.ensure_all_started(:membrane_portaudio_plugin)
__MODULE__.SyncExecutor.apply(__MODULE__.Devices, :list, [])
|> IO.inspect()
end
end
21 changes: 19 additions & 2 deletions lib/membrane_portaudio_plugin/device.ex
Original file line number Diff line number Diff line change
@@ -1,10 +1,27 @@
defmodule Membrane.PortAudio.Device do
defstruct [
@moduledoc """
Struct carrying information about an audio device.
See `Membrane.PortAudio.list_devices/0` and `Membrane.PortAudio.print_devices/0`.
"""

@type t :: %__MODULE__{
id: non_neg_integer(),
name: String.t(),
max_input_channels: non_neg_integer(),
max_output_channels: non_neg_integer(),
default_device: false | :input | :output,
default_sample_rate: float()
}

@enforce_keys [
:id,
:name,
:max_input_channels,
:max_output_channels,
:is_default,
:default_device,
:default_sample_rate
]

defstruct @enforce_keys
end
8 changes: 8 additions & 0 deletions test/membrane_portaudio_plugin/devices_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
defmodule Membrane.Portaudio.DevicesTest do
use ExUnit.Case, async: true

test "list devices" do
devices = Membrane.PortAudio.list_devices()
Enum.each(devices, &assert(%Membrane.PortAudio.Device{} = &1))
end
end

0 comments on commit c8b4df5

Please sign in to comment.