#include "carla.h" #include #include #include #include // Initialize Carla host int carla_init(CarlaHost *host, jack_client_t *client) { if (!host) return -1; memset(host, 0, sizeof(CarlaHost)); host->client = client; // Initialize all channel racks for (int ch = 0; ch < 8; ch++) { host->channel_racks[ch].num_plugins = 0; host->channel_racks[ch].volume = 1.0f; host->channel_racks[ch].bypassed = false; } host->num_available_plugins = 0; host->available_plugins = NULL; host->initialized = true; printf("Carla host initialized\n"); return 0; } void carla_cleanup(CarlaHost *host) { if (!host) return; if (host->available_plugins) { for (int i = 0; i < host->num_available_plugins; i++) { free(host->available_plugins[i]); } free(host->available_plugins); } for (int ch = 0; ch < 8; ch++) { ChannelRack *rack = &host->channel_racks[ch]; for (int p = 0; p < rack->num_plugins; p++) { PluginInfo *plugin = &rack->plugins[p]; if (plugin->parameters) { free(plugin->parameters); } if (plugin->parameter_names) { for (int i = 0; i < plugin->num_parameters; i++) { free(plugin->parameter_names[i]); } free(plugin->parameter_names); } } } host->initialized = false; } static int add_gain_plugin(CarlaHost *host, int channel) { if (channel < 0 || channel >= 8) return -1; ChannelRack *rack = &host->channel_racks[channel]; if (rack->num_plugins >= 16) return -1; PluginInfo *plugin = &rack->plugins[rack->num_plugins]; strcpy(plugin->name, "Gain"); strcpy(plugin->uri, "internal://gain"); plugin->type = PLUGIN_TYPE_INTERNAL; plugin->carla_plugin_id = -1; plugin->num_parameters = 1; plugin->parameters = malloc(sizeof(float)); plugin->parameters[0] = 1.0f; plugin->parameter_names = malloc(sizeof(char*)); plugin->parameter_names[0] = strdup("Gain"); rack->num_plugins++; return rack->num_plugins - 1; } int carla_add_plugin(CarlaHost *host, int channel, const char *uri, PluginType type) { if (!host || !host->initialized) return -1; if (channel < 0 || channel >= 8) return -1; if (!uri) return -1; ChannelRack *rack = &host->channel_racks[channel]; if (rack->num_plugins >= 16) return -1; PluginInfo *plugin = &rack->plugins[rack->num_plugins]; // Parse URI to determine plugin type and name if (strstr(uri, "internal://") == uri) { // Internal plugin plugin->type = PLUGIN_TYPE_INTERNAL; strncpy(plugin->uri, uri, sizeof(plugin->uri) - 1); plugin->uri[sizeof(plugin->uri) - 1] = '\0'; const char *name = uri + strlen("internal://"); if (strcmp(name, "gain") == 0) { strcpy(plugin->name, "Gain"); plugin->num_parameters = 1; plugin->parameters = malloc(sizeof(float)); plugin->parameters[0] = 1.0f; plugin->parameter_names = malloc(sizeof(char*)); plugin->parameter_names[0] = strdup("Gain"); } else if (strcmp(name, "reverb") == 0) { strcpy(plugin->name, "Reverb"); plugin->num_parameters = 2; plugin->parameters = malloc(2 * sizeof(float)); plugin->parameters[0] = 0.5f; // Mix plugin->parameters[1] = 0.5f; // Decay plugin->parameter_names = malloc(2 * sizeof(char*)); plugin->parameter_names[0] = strdup("Mix"); plugin->parameter_names[1] = strdup("Decay"); } else if (strcmp(name, "delay") == 0) { strcpy(plugin->name, "Delay"); plugin->num_parameters = 2; plugin->parameters = malloc(2 * sizeof(float)); plugin->parameters[0] = 0.3f; // Feedback plugin->parameters[1] = 0.5f; // Mix plugin->parameter_names = malloc(2 * sizeof(char*)); plugin->parameter_names[0] = strdup("Feedback"); plugin->parameter_names[1] = strdup("Mix"); } else if (strcmp(name, "filter") == 0) { strcpy(plugin->name, "Filter"); plugin->num_parameters = 2; plugin->parameters = malloc(2 * sizeof(float)); plugin->parameters[0] = 1000.0f; // Cutoff plugin->parameters[1] = 1.0f; // Resonance plugin->parameter_names = malloc(2 * sizeof(char*)); plugin->parameter_names[0] = strdup("Cutoff"); plugin->parameter_names[1] = strdup("Resonance"); } else { // Unknown internal plugin, default to gain strcpy(plugin->name, "Unknown Internal"); plugin->num_parameters = 0; plugin->parameters = NULL; plugin->parameter_names = NULL; } } else { // External plugin (LV2, VST, etc.) - store URI for future Carla integration plugin->type = type; strncpy(plugin->uri, uri, sizeof(plugin->uri) - 1); plugin->uri[sizeof(plugin->uri) - 1] = '\0'; // Extract a display name from the URI const char *last_slash = strrchr(uri, '/'); if (last_slash) { strncpy(plugin->name, last_slash + 1, sizeof(plugin->name) - 1); } else { strncpy(plugin->name, uri, sizeof(plugin->name) - 1); } plugin->name[sizeof(plugin->name) - 1] = '\0'; plugin->num_parameters = 0; plugin->parameters = NULL; plugin->parameter_names = NULL; } plugin->carla_plugin_id = -1; rack->num_plugins++; printf("Added plugin '%s' (URI: %s) to channel %d\n", plugin->name, plugin->uri, channel); return rack->num_plugins - 1; } int carla_remove_plugin(CarlaHost *host, int channel, int plugin_index) { if (!host || !host->initialized) return -1; if (channel < 0 || channel >= 8) return -1; ChannelRack *rack = &host->channel_racks[channel]; if (plugin_index < 0 || plugin_index >= rack->num_plugins) return -1; PluginInfo *plugin = &rack->plugins[plugin_index]; if (plugin->parameters) { free(plugin->parameters); } if (plugin->parameter_names) { for (int i = 0; i < plugin->num_parameters; i++) { free(plugin->parameter_names[i]); } free(plugin->parameter_names); } for (int i = plugin_index; i < rack->num_plugins - 1; i++) { rack->plugins[i] = rack->plugins[i + 1]; } rack->num_plugins--; return 0; } int carla_set_parameter(CarlaHost *host, int channel, int plugin_index, int param_index, float value) { if (!host || !host->initialized) return -1; if (channel < 0 || channel >= 8) return -1; ChannelRack *rack = &host->channel_racks[channel]; if (plugin_index < 0 || plugin_index >= rack->num_plugins) return -1; PluginInfo *plugin = &rack->plugins[plugin_index]; if (param_index < 0 || param_index >= plugin->num_parameters) return -1; plugin->parameters[param_index] = value; return 0; } float carla_get_parameter(CarlaHost *host, int channel, int plugin_index, int param_index) { if (!host || !host->initialized) return 0.0f; if (channel < 0 || channel >= 8) return 0.0f; ChannelRack *rack = &host->channel_racks[channel]; if (plugin_index < 0 || plugin_index >= rack->num_plugins) return 0.0f; PluginInfo *plugin = &rack->plugins[plugin_index]; if (param_index < 0 || param_index >= plugin->num_parameters) return 0.0f; return plugin->parameters[param_index]; } void carla_set_channel_volume(CarlaHost *host, int channel, float volume) { if (!host || !host->initialized) return; if (channel < 0 || channel >= 8) return; host->channel_racks[channel].volume = fmaxf(0.0f, fminf(2.0f, volume)); } float carla_get_channel_volume(CarlaHost *host, int channel) { if (!host || !host->initialized) return 1.0f; if (channel < 0 || channel >= 8) return 1.0f; return host->channel_racks[channel].volume; } void carla_process(CarlaHost *host, int channel, float *in_buffer, float *out_buffer, jack_nframes_t nframes) { if (!host || !host->initialized) return; if (channel < 0 || channel >= 8) return; ChannelRack *rack = &host->channel_racks[channel]; if (rack->bypassed || rack->num_plugins == 0) { for (jack_nframes_t i = 0; i < nframes; i++) { out_buffer[i] = in_buffer[i] * rack->volume; } return; } float *current_in = in_buffer; float *current_out = out_buffer; float *temp_buffer = malloc(nframes * sizeof(float)); if (!temp_buffer) { for (jack_nframes_t i = 0; i < nframes; i++) { out_buffer[i] = in_buffer[i] * rack->volume; } return; } for (int p = 0; p < rack->num_plugins; p++) { PluginInfo *plugin = &rack->plugins[p]; if (plugin->type == PLUGIN_TYPE_INTERNAL && strcmp(plugin->uri, "internal://gain") == 0) { float gain = plugin->parameters[0]; for (jack_nframes_t i = 0; i < nframes; i++) { current_out[i] = current_in[i] * gain; } } if (p < rack->num_plugins - 1) { float *swap = current_in; current_in = current_out; current_out = swap; } } for (jack_nframes_t i = 0; i < nframes; i++) { current_out[i] *= rack->volume; } if (current_out == temp_buffer) { memcpy(out_buffer, temp_buffer, nframes * sizeof(float)); } free(temp_buffer); } int carla_scan_plugins(CarlaHost *host) { if (!host || !host->initialized) return -1; if (host->available_plugins) { for (int i = 0; i < host->num_available_plugins; i++) { free(host->available_plugins[i]); } free(host->available_plugins); } const char *builtins[] = { "internal://gain - Gain (Built-in)", "internal://reverb - Reverb (Built-in)", "internal://delay - Delay (Built-in)", "internal://filter - Filter (Built-in)" }; host->num_available_plugins = 4; host->available_plugins = malloc(host->num_available_plugins * sizeof(char*)); for (int i = 0; i < host->num_available_plugins; i++) { host->available_plugins[i] = strdup(builtins[i]); } return host->num_available_plugins; } const char** carla_get_available_plugins(CarlaHost *host, int *count) { if (!host || !host->initialized) { if (count) *count = 0; return NULL; } if (count) *count = host->num_available_plugins; return (const char**)host->available_plugins; } const char* carla_get_plugin_name(CarlaHost *host, int channel, int plugin_index) { if (!host || !host->initialized) return NULL; if (channel < 0 || channel >= 8) return NULL; ChannelRack *rack = &host->channel_racks[channel]; if (plugin_index < 0 || plugin_index >= rack->num_plugins) return NULL; return rack->plugins[plugin_index].name; }