#include "rack_au.h"
#include <iostream>
#include <iomanip>
#include <cstring>
#include <cmath>
#include <memory>
void test_invalid_unique_id() {
std::cout << "Test 1: Invalid unique_id handling\n";
std::cout << "-----------------------------------\n";
RackAUPlugin* plugin = rack_au_plugin_new(nullptr);
if (plugin != nullptr) {
std::cerr << "FAIL: Expected nullptr for NULL unique_id, got valid pointer\n";
rack_au_plugin_free(plugin);
return;
}
std::cout << "PASS: nullptr for NULL unique_id\n";
plugin = rack_au_plugin_new("invalid-format");
if (plugin != nullptr) {
std::cerr << "FAIL: Expected nullptr for invalid unique_id format\n";
rack_au_plugin_free(plugin);
return;
}
std::cout << "PASS: nullptr for invalid format\n";
plugin = rack_au_plugin_new("ffffffff-ffffffff-ffffffff");
if (plugin != nullptr) {
std::cerr << "FAIL: Expected nullptr for non-existent plugin\n";
rack_au_plugin_free(plugin);
return;
}
std::cout << "PASS: nullptr for non-existent plugin\n\n";
}
void test_plugin_lifecycle() {
std::cout << "Test 2: Plugin lifecycle\n";
std::cout << "------------------------\n";
RackAUScanner* scanner = rack_au_scanner_new();
if (!scanner) {
std::cerr << "FAIL: Failed to create scanner\n";
return;
}
int count = rack_au_scanner_scan(scanner, nullptr, 0);
if (count <= 0) {
std::cerr << "SKIP: No plugins found to test with\n\n";
rack_au_scanner_free(scanner);
return;
}
RackAUPluginInfo* plugins = new(std::nothrow) RackAUPluginInfo[count];
if (!plugins) {
std::cerr << "FAIL: Failed to allocate memory\n";
rack_au_scanner_free(scanner);
return;
}
int filled = rack_au_scanner_scan(scanner, plugins, count);
if (filled <= 0) {
std::cerr << "FAIL: Failed to scan plugins\n";
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
const char* unique_id = nullptr;
const char* plugin_name = nullptr;
for (int i = 0; i < filled; i++) {
if (plugins[i].plugin_type == RACK_AU_TYPE_EFFECT ||
plugins[i].plugin_type == RACK_AU_TYPE_INSTRUMENT) {
unique_id = plugins[i].unique_id;
plugin_name = plugins[i].name;
break;
}
}
if (!unique_id) {
unique_id = plugins[0].unique_id;
plugin_name = plugins[0].name;
}
std::cout << "Loading plugin: " << plugin_name << "\n";
std::cout << "Unique ID: " << unique_id << "\n";
RackAUPlugin* plugin = rack_au_plugin_new(unique_id);
if (!plugin) {
std::cerr << "FAIL: Failed to create plugin instance\n";
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
std::cout << "PASS: Plugin instance created\n";
int is_init = rack_au_plugin_is_initialized(plugin);
if (is_init != 0) {
std::cerr << "FAIL: Plugin should not be initialized yet\n";
rack_au_plugin_free(plugin);
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
std::cout << "PASS: Plugin not initialized initially\n";
double sample_rate = 48000.0;
uint32_t max_block_size = 512;
int result = rack_au_plugin_initialize(plugin, sample_rate, max_block_size);
if (result != RACK_AU_OK) {
std::cerr << "FAIL: Failed to initialize plugin (error: " << result << ")\n";
rack_au_plugin_free(plugin);
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
std::cout << "PASS: Plugin initialized successfully\n";
is_init = rack_au_plugin_is_initialized(plugin);
if (is_init != 1) {
std::cerr << "FAIL: Plugin should be initialized now\n";
rack_au_plugin_free(plugin);
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
std::cout << "PASS: Plugin is initialized\n";
result = rack_au_plugin_initialize(plugin, sample_rate, max_block_size);
if (result != RACK_AU_OK) {
std::cerr << "FAIL: Re-initialization should succeed\n";
rack_au_plugin_free(plugin);
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
std::cout << "PASS: Re-initialization succeeded\n";
rack_au_plugin_free(plugin);
std::cout << "PASS: Plugin cleaned up\n";
rack_au_plugin_free(nullptr);
std::cout << "PASS: free(nullptr) is safe\n";
delete[] plugins;
rack_au_scanner_free(scanner);
std::cout << "\n";
}
void test_invalid_parameters() {
std::cout << "Test 3: Invalid parameter handling\n";
std::cout << "-----------------------------------\n";
int result = rack_au_plugin_initialize(nullptr, 48000.0, 512);
if (result != RACK_AU_ERROR_INVALID_PARAM) {
std::cerr << "FAIL: Expected INVALID_PARAM for nullptr plugin\n";
return;
}
std::cout << "PASS: initialize(nullptr) returns INVALID_PARAM\n";
int is_init = rack_au_plugin_is_initialized(nullptr);
if (is_init != 0) {
std::cerr << "FAIL: is_initialized(nullptr) should return 0\n";
return;
}
std::cout << "PASS: is_initialized(nullptr) returns 0\n\n";
}
void test_audio_processing() {
std::cout << "Test 4: Audio processing\n";
std::cout << "------------------------\n";
RackAUScanner* scanner = rack_au_scanner_new();
if (!scanner) {
std::cerr << "FAIL: Failed to create scanner\n";
return;
}
int count = rack_au_scanner_scan(scanner, nullptr, 0);
if (count <= 0) {
std::cerr << "SKIP: No plugins found to test with\n\n";
rack_au_scanner_free(scanner);
return;
}
RackAUPluginInfo* plugins = new(std::nothrow) RackAUPluginInfo[count];
if (!plugins) {
std::cerr << "FAIL: Failed to allocate memory\n";
rack_au_scanner_free(scanner);
return;
}
int filled = rack_au_scanner_scan(scanner, plugins, count);
if (filled <= 0) {
std::cerr << "FAIL: Failed to scan plugins\n";
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
const char* unique_id = nullptr;
const char* plugin_name = nullptr;
for (int i = 0; i < filled; i++) {
if (plugins[i].plugin_type == RACK_AU_TYPE_EFFECT) {
unique_id = plugins[i].unique_id;
plugin_name = plugins[i].name;
break;
}
}
if (!unique_id) {
std::cout << "SKIP: No effect plugins found for processing test\n\n";
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
std::cout << "Testing audio processing with: " << plugin_name << "\n";
RackAUPlugin* plugin = rack_au_plugin_new(unique_id);
if (!plugin) {
std::cerr << "FAIL: Failed to create plugin instance\n";
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
int result = rack_au_plugin_initialize(plugin, 48000.0, 512);
if (result != RACK_AU_OK) {
std::cerr << "FAIL: Failed to initialize plugin (error: " << result << ")\n";
rack_au_plugin_free(plugin);
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
const uint32_t frames = 512;
const uint32_t num_channels = 2;
float* left_in = new float[frames];
float* right_in = new float[frames];
float* left_out = new float[frames];
float* right_out = new float[frames];
const float frequency = 440.0f; const float sample_rate = 48000.0f;
for (uint32_t i = 0; i < frames; i++) {
float sample = sinf(2.0f * 3.14159265f * frequency * i / sample_rate) * 0.5f;
left_in[i] = sample;
right_in[i] = sample;
}
const float* inputs[2] = { left_in, right_in };
float* outputs[2] = { left_out, right_out };
result = rack_au_plugin_process(plugin, inputs, num_channels, outputs, num_channels, frames);
if (result != RACK_AU_OK) {
std::cerr << "FAIL: Audio processing failed (error: " << result << ")\n";
delete[] left_in;
delete[] right_in;
delete[] left_out;
delete[] right_out;
rack_au_plugin_free(plugin);
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
std::cout << "PASS: Audio processing succeeded\n";
bool has_signal = false;
for (uint32_t i = 0; i < frames; i++) {
if (left_out[i] != 0.0f || right_out[i] != 0.0f) {
has_signal = true;
break;
}
}
if (has_signal) {
std::cout << "PASS: Output contains audio signal\n";
} else {
std::cout << "WARN: Output is silent (may be expected for some effects)\n";
}
delete[] left_in;
delete[] right_in;
delete[] left_out;
delete[] right_out;
rack_au_plugin_free(plugin);
delete[] plugins;
rack_au_scanner_free(scanner);
std::cout << "\n";
}
void test_parameter_operations() {
std::cout << "Test 5: Parameter operations\n";
std::cout << "-----------------------------\n";
RackAUScanner* scanner = rack_au_scanner_new();
if (!scanner) {
std::cerr << "FAIL: Failed to create scanner\n";
return;
}
int count = rack_au_scanner_scan(scanner, nullptr, 0);
if (count <= 0) {
std::cerr << "SKIP: No plugins found to test with\n\n";
rack_au_scanner_free(scanner);
return;
}
RackAUPluginInfo* plugins = new(std::nothrow) RackAUPluginInfo[count];
if (!plugins) {
std::cerr << "FAIL: Failed to allocate memory\n";
rack_au_scanner_free(scanner);
return;
}
int filled = rack_au_scanner_scan(scanner, plugins, count);
if (filled <= 0) {
std::cerr << "FAIL: Failed to scan plugins\n";
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
const char* unique_id = nullptr;
const char* plugin_name = nullptr;
for (int i = 0; i < filled; i++) {
if (plugins[i].plugin_type == RACK_AU_TYPE_EFFECT) {
unique_id = plugins[i].unique_id;
plugin_name = plugins[i].name;
break;
}
}
if (!unique_id) {
std::cout << "SKIP: No effect plugins found for parameter test\n\n";
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
std::cout << "Testing parameters with: " << plugin_name << "\n";
RackAUPlugin* plugin = rack_au_plugin_new(unique_id);
if (!plugin) {
std::cerr << "FAIL: Failed to create plugin instance\n";
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
int result = rack_au_plugin_initialize(plugin, 48000.0, 512);
if (result != RACK_AU_OK) {
std::cerr << "FAIL: Failed to initialize plugin (error: " << result << ")\n";
rack_au_plugin_free(plugin);
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
int param_count = rack_au_plugin_parameter_count(plugin);
std::cout << " Parameter count: " << param_count << "\n";
std::cout << "PASS: Parameter count retrieved\n";
if (param_count == 0) {
std::cout << " Plugin has no parameters, skipping parameter tests\n\n";
rack_au_plugin_free(plugin);
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
char name[256];
char unit[32];
float min_val = 0.0f;
float max_val = 0.0f;
float default_val = 0.0f;
result = rack_au_plugin_parameter_info(plugin, 0, name, sizeof(name), &min_val, &max_val, &default_val, unit, sizeof(unit));
if (result != RACK_AU_OK) {
std::cerr << "FAIL: Failed to get parameter info (error: " << result << ")\n";
rack_au_plugin_free(plugin);
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
std::cout << " Parameter 0: " << name;
if (unit[0] != '\0') {
std::cout << " (" << unit << ")";
}
std::cout << "\n";
std::cout << " Range: " << min_val << " - " << max_val << "\n";
std::cout << " Default: " << default_val << "\n";
std::cout << "PASS: Parameter info retrieved\n";
float value = 0.0f;
result = rack_au_plugin_get_parameter(plugin, 0, &value);
if (result != RACK_AU_OK) {
std::cerr << "FAIL: Failed to get parameter (error: " << result << ")\n";
rack_au_plugin_free(plugin);
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
std::cout << " Current value: " << std::fixed << std::setprecision(4) << value << " (normalized)\n";
std::cout << "PASS: Parameter value retrieved\n";
float original_value = value;
result = rack_au_plugin_set_parameter(plugin, 0, 0.75f);
if (result != RACK_AU_OK) {
std::cerr << "FAIL: Failed to set parameter (error: " << result << ")\n";
rack_au_plugin_free(plugin);
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
result = rack_au_plugin_get_parameter(plugin, 0, &value);
if (result != RACK_AU_OK) {
std::cerr << "FAIL: Failed to get parameter after set (error: " << result << ")\n";
rack_au_plugin_free(plugin);
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
if (std::abs(value - 0.75f) > 0.01f) {
std::cerr << "FAIL: Parameter value should be ~0.75, got " << value << "\n";
rack_au_plugin_free(plugin);
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
std::cout << " New value: " << value << " (normalized)\n";
std::cout << "PASS: Parameter set and verified\n";
rack_au_plugin_set_parameter(plugin, 0, original_value);
result = rack_au_plugin_get_parameter(plugin, param_count + 10, &value);
if (result == RACK_AU_OK) {
std::cerr << "FAIL: Should fail for out-of-bounds index\n";
rack_au_plugin_free(plugin);
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
std::cout << "PASS: Out-of-bounds index rejected\n";
rack_au_plugin_free(plugin);
delete[] plugins;
rack_au_scanner_free(scanner);
std::cout << "\n";
}
void test_midi_operations() {
std::cout << "Test 6: MIDI operations\n";
std::cout << "------------------------\n";
RackAUScanner* scanner = rack_au_scanner_new();
if (!scanner) {
std::cerr << "FAIL: Failed to create scanner\n";
return;
}
int count = rack_au_scanner_scan(scanner, nullptr, 0);
if (count <= 0) {
std::cerr << "SKIP: No plugins found to test with\n\n";
rack_au_scanner_free(scanner);
return;
}
RackAUPluginInfo* plugins = new(std::nothrow) RackAUPluginInfo[count];
if (!plugins) {
std::cerr << "FAIL: Failed to allocate memory\n";
rack_au_scanner_free(scanner);
return;
}
int filled = rack_au_scanner_scan(scanner, plugins, count);
if (filled <= 0) {
std::cerr << "FAIL: Failed to scan plugins\n";
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
const char* unique_id = nullptr;
const char* plugin_name = nullptr;
for (int i = 0; i < filled; i++) {
if (plugins[i].plugin_type == RACK_AU_TYPE_INSTRUMENT) {
unique_id = plugins[i].unique_id;
plugin_name = plugins[i].name;
break;
}
}
if (!unique_id) {
std::cout << "SKIP: No instrument plugins found for MIDI test\n\n";
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
std::cout << "Testing MIDI with: " << plugin_name << "\n";
RackAUPlugin* plugin = rack_au_plugin_new(unique_id);
if (!plugin) {
std::cerr << "FAIL: Failed to create plugin instance\n";
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
int result = rack_au_plugin_initialize(plugin, 48000.0, 512);
if (result != RACK_AU_OK) {
std::cerr << "FAIL: Failed to initialize plugin (error: " << result << ")\n";
rack_au_plugin_free(plugin);
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
RackAUMidiEvent events[3];
events[0].sample_offset = 0;
events[0].status = RACK_AU_MIDI_NOTE_ON;
events[0].data1 = 60;
events[0].data2 = 100;
events[0].channel = 0;
events[1].sample_offset = 0;
events[1].status = RACK_AU_MIDI_NOTE_ON;
events[1].data1 = 64;
events[1].data2 = 100;
events[1].channel = 0;
events[2].sample_offset = 0;
events[2].status = RACK_AU_MIDI_NOTE_ON;
events[2].data1 = 67;
events[2].data2 = 100;
events[2].channel = 0;
result = rack_au_plugin_send_midi(plugin, events, 3);
if (result != RACK_AU_OK) {
std::cerr << "FAIL: Failed to send MIDI events (error: " << result << ")\n";
rack_au_plugin_free(plugin);
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
std::cout << "PASS: MIDI events sent successfully (C major chord)\n";
const uint32_t frames = 512;
const uint32_t num_channels = 2;
float* left_in = new float[frames];
float* right_in = new float[frames];
float* left_out = new float[frames];
float* right_out = new float[frames];
memset(left_in, 0, frames * sizeof(float));
memset(right_in, 0, frames * sizeof(float));
memset(left_out, 0, frames * sizeof(float));
memset(right_out, 0, frames * sizeof(float));
const float* inputs[2] = { left_in, right_in };
float* outputs[2] = { left_out, right_out };
result = rack_au_plugin_process(plugin, inputs, num_channels, outputs, num_channels, frames);
if (result != RACK_AU_OK) {
std::cerr << "FAIL: Audio processing failed after MIDI (error: " << result << ")\n";
delete[] left_in;
delete[] right_in;
delete[] left_out;
delete[] right_out;
rack_au_plugin_free(plugin);
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
bool has_signal = false;
for (uint32_t i = 0; i < frames; i++) {
if (left_out[i] != 0.0f || right_out[i] != 0.0f) {
has_signal = true;
break;
}
}
if (has_signal) {
std::cout << "PASS: Output contains audio from MIDI notes\n";
} else {
std::cout << "WARN: Output is silent (plugin may need more time or different MIDI setup)\n";
}
events[0].status = RACK_AU_MIDI_NOTE_OFF;
events[1].status = RACK_AU_MIDI_NOTE_OFF;
events[2].status = RACK_AU_MIDI_NOTE_OFF;
result = rack_au_plugin_send_midi(plugin, events, 3);
if (result != RACK_AU_OK) {
std::cerr << "FAIL: Failed to send Note Off events (error: " << result << ")\n";
delete[] left_in;
delete[] right_in;
delete[] left_out;
delete[] right_out;
rack_au_plugin_free(plugin);
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
std::cout << "PASS: Note Off events sent successfully\n";
events[0].channel = 20;
result = rack_au_plugin_send_midi(plugin, events, 1);
if (result == RACK_AU_OK) {
std::cerr << "FAIL: Should reject invalid MIDI channel\n";
delete[] left_in;
delete[] right_in;
delete[] left_out;
delete[] right_out;
rack_au_plugin_free(plugin);
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
std::cout << "PASS: Invalid MIDI channel rejected\n";
result = rack_au_plugin_send_midi(plugin, nullptr, 0);
if (result != RACK_AU_OK) {
std::cerr << "FAIL: Empty MIDI array should succeed\n";
delete[] left_in;
delete[] right_in;
delete[] left_out;
delete[] right_out;
rack_au_plugin_free(plugin);
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
std::cout << "PASS: Empty MIDI event array handled correctly\n";
delete[] left_in;
delete[] right_in;
delete[] left_out;
delete[] right_out;
rack_au_plugin_free(plugin);
delete[] plugins;
rack_au_scanner_free(scanner);
std::cout << "\n";
}
void test_preset_operations() {
std::cout << "Test 7: Preset operations\n";
std::cout << "--------------------------\n";
RackAUScanner* scanner = rack_au_scanner_new();
if (!scanner) {
std::cerr << "FAIL: Failed to create scanner\n";
return;
}
int count = rack_au_scanner_scan(scanner, nullptr, 0);
if (count <= 0) {
std::cerr << "SKIP: No plugins found to test with\n\n";
rack_au_scanner_free(scanner);
return;
}
RackAUPluginInfo* plugins = new(std::nothrow) RackAUPluginInfo[count];
if (!plugins) {
std::cerr << "FAIL: Failed to allocate memory\n";
rack_au_scanner_free(scanner);
return;
}
int filled = rack_au_scanner_scan(scanner, plugins, count);
if (filled <= 0) {
std::cerr << "FAIL: Failed to scan plugins\n";
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
const char* unique_id = nullptr;
const char* plugin_name = nullptr;
for (int i = 0; i < filled; i++) {
if (plugins[i].plugin_type == RACK_AU_TYPE_EFFECT ||
plugins[i].plugin_type == RACK_AU_TYPE_INSTRUMENT) {
unique_id = plugins[i].unique_id;
plugin_name = plugins[i].name;
break;
}
}
if (!unique_id) {
std::cout << "SKIP: No suitable plugins found for preset test\n\n";
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
std::cout << "Testing presets with: " << plugin_name << "\n";
RackAUPlugin* plugin = rack_au_plugin_new(unique_id);
if (!plugin) {
std::cerr << "FAIL: Failed to create plugin instance\n";
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
int result = rack_au_plugin_initialize(plugin, 48000.0, 512);
if (result != RACK_AU_OK) {
std::cerr << "FAIL: Failed to initialize plugin (error: " << result << ")\n";
rack_au_plugin_free(plugin);
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
int preset_count = rack_au_plugin_get_preset_count(plugin);
std::cout << " Preset count: " << preset_count << "\n";
std::cout << "PASS: Preset count retrieved\n";
if (preset_count == 0) {
std::cout << " Plugin has no presets, skipping preset load test\n";
} else {
char name[256];
int32_t preset_number = 0;
result = rack_au_plugin_get_preset_info(plugin, 0, name, sizeof(name), &preset_number);
if (result != RACK_AU_OK) {
std::cerr << "FAIL: Failed to get preset info (error: " << result << ")\n";
rack_au_plugin_free(plugin);
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
std::cout << " Preset 0: " << name << " (number: " << preset_number << ")\n";
std::cout << "PASS: Preset info retrieved\n";
result = rack_au_plugin_load_preset(plugin, preset_number);
if (result != RACK_AU_OK) {
std::cerr << "FAIL: Failed to load preset (error: " << result << ")\n";
rack_au_plugin_free(plugin);
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
std::cout << "PASS: Preset loaded successfully\n";
result = rack_au_plugin_get_preset_info(plugin, preset_count + 10, name, sizeof(name), &preset_number);
if (result == RACK_AU_OK) {
std::cerr << "FAIL: Should fail for out-of-bounds preset index\n";
rack_au_plugin_free(plugin);
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
std::cout << "PASS: Out-of-bounds preset index rejected\n";
}
int state_size = rack_au_plugin_get_state_size(plugin);
if (state_size <= 0) {
std::cerr << "FAIL: Failed to get state size\n";
rack_au_plugin_free(plugin);
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
std::cout << " State size: " << state_size << " bytes\n";
std::cout << "PASS: State size retrieved\n";
std::unique_ptr<uint8_t[]> state_data(new uint8_t[state_size]);
size_t actual_size = state_size;
result = rack_au_plugin_get_state(plugin, state_data.get(), &actual_size);
if (result != RACK_AU_OK) {
std::cerr << "FAIL: Failed to get state (error: " << result << ")\n";
rack_au_plugin_free(plugin);
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
std::cout << " Actual state size: " << actual_size << " bytes\n";
std::cout << "PASS: State retrieved\n";
int param_count = rack_au_plugin_parameter_count(plugin);
float original_param_value = 0.0f;
if (param_count > 0) {
rack_au_plugin_get_parameter(plugin, 0, &original_param_value);
rack_au_plugin_set_parameter(plugin, 0, 0.99f);
float new_value = 0.0f;
rack_au_plugin_get_parameter(plugin, 0, &new_value);
std::cout << " Modified parameter 0: " << original_param_value << " -> " << new_value << "\n";
}
result = rack_au_plugin_set_state(plugin, state_data.get(), actual_size);
if (result != RACK_AU_OK) {
std::cerr << "FAIL: Failed to restore state (error: " << result << ")\n";
rack_au_plugin_free(plugin);
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
std::cout << "PASS: State restored\n";
if (param_count > 0) {
float restored_value = 0.0f;
rack_au_plugin_get_parameter(plugin, 0, &restored_value);
if (std::abs(restored_value - original_param_value) > 0.01f) {
std::cerr << "FAIL: Parameter not restored correctly (expected " << original_param_value
<< ", got " << restored_value << ")\n";
rack_au_plugin_free(plugin);
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
std::cout << " Parameter 0 restored to: " << restored_value << "\n";
std::cout << "PASS: Parameter restored correctly\n";
}
result = rack_au_plugin_set_state(plugin, nullptr, 0);
if (result == RACK_AU_OK) {
std::cerr << "FAIL: Should reject null state data\n";
rack_au_plugin_free(plugin);
delete[] plugins;
rack_au_scanner_free(scanner);
return;
}
std::cout << "PASS: Null state data rejected\n";
rack_au_plugin_free(plugin);
delete[] plugins;
rack_au_scanner_free(scanner);
std::cout << "\n";
}
int main() {
std::cout << "AudioUnit Plugin Instance Test\n";
std::cout << "===============================\n\n";
test_invalid_unique_id();
test_plugin_lifecycle();
test_invalid_parameters();
test_audio_processing();
test_parameter_operations();
test_midi_operations();
test_preset_operations();
std::cout << "All tests completed!\n";
return 0;
}