1/* FluidSynth - A Software Synthesizer 2 * 3 * Copyright (C) 2003 Peter Hanappe and others. 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Library General Public License 7 * as published by the Free Software Foundation; either version 2 of 8 * the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, but 11 * WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Library General Public License for more details. 14 * 15 * You should have received a copy of the GNU Library General Public 16 * License along with this library; if not, write to the Free 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 18 * 02111-1307, USA 19 */ 20 21/* This module: 3/2002 22 * Author: Markus Nentwig, nentwig@users.sourceforge.net 23 */ 24 25#define PrintErrorMessage -1 26 27#include "fluidsynth_priv.h" 28 29#ifdef LADSPA 30#include <assert.h> 31 32/* Dynamic library functions */ 33#include <dlfcn.h> 34 35#include "fluid_ladspa.h" 36#include "fluid_synth.h" 37#include "fluid_io.h" 38 39/* Logging to stdout. */ 40//#define L(x) x;printf("\n"); 41#define L(x); 42 43fluid_LADSPA_FxUnit_t* new_fluid_LADSPA_FxUnit(fluid_synth_t* synth){ 44 fluid_LADSPA_FxUnit_t* FxUnit=FLUID_NEW(fluid_LADSPA_FxUnit_t); 45 assert(FxUnit); 46 assert(synth); 47 /* The default state is 'bypassed'. The Fx unit has to be turned on explicitly by the user. */ 48 /* Those settings have to be done in order to allow fluid_LADSPA_clean. */ 49 FxUnit->Bypass=fluid_LADSPA_Bypassed; 50 FxUnit->NumberNodes=0; 51 FxUnit->NumberPlugins=0; 52 FxUnit->NumberLibs=0; 53 FxUnit->NumberCommands=0; 54 FxUnit->NumberUserControlNodes=0; 55 FxUnit->synth=synth; 56 pthread_cond_init(&FxUnit->cond,NULL); 57 return FxUnit; 58}; 59 60/* Purpose: 61 * Creates the system nodes to get data into and out of the Fx unit. 62 */ 63void fluid_LADSPA_CreateSystemNodes(fluid_LADSPA_FxUnit_t* FxUnit){ 64 char str[99]; 65 int nr_input_nodes; 66 int nr_fx_input_nodes; 67 int nr_output_nodes; 68 int temp; 69 int i; 70 71 /* Retrieve the number of synth / audio out / Fx send nodes */ 72 assert(fluid_settings_getint(FxUnit->synth->settings, "synth.audio-groups", &temp)); 73 nr_input_nodes=(int) temp; 74 printf("%i audio groups\n", nr_input_nodes); 75 76 assert(fluid_settings_getint(FxUnit->synth->settings, "synth.audio-channels", &temp)); 77 nr_output_nodes=temp; 78 79 assert(fluid_settings_getint(FxUnit->synth->settings, "synth.effects-channels", &temp)); 80 nr_fx_input_nodes=temp; 81 82 /* Create regular input nodes (associated with audio groups) */ 83 for (i=0; i < nr_input_nodes; i++){ 84 sprintf(str, "in%i_L",(i+1)); 85 fluid_LADSPA_CreateNode(FxUnit, str, fluid_LADSPA_node_is_audio | fluid_LADSPA_node_is_source); 86 sprintf(str, "in%i_R",(i+1)); 87 fluid_LADSPA_CreateNode(FxUnit, str, fluid_LADSPA_node_is_audio | fluid_LADSPA_node_is_source); 88 }; 89 90 /* Create effects send nodes (for example reverb, chorus send) */ 91 for (i=0; i < nr_fx_input_nodes; i++){ 92 sprintf(str, "send%i_L",(i+1)); 93 fluid_LADSPA_CreateNode(FxUnit, str, fluid_LADSPA_node_is_audio | fluid_LADSPA_node_is_source); 94 sprintf(str, "send%i_R",(i+1)); 95 fluid_LADSPA_CreateNode(FxUnit, str, fluid_LADSPA_node_is_audio | fluid_LADSPA_node_is_source); 96 }; 97 98 /* Create output nodes (usually towards the sound card) */ 99 for (i=0; i < nr_input_nodes; i++){ 100 sprintf(str, "out%i_L",(i+1)); 101 fluid_LADSPA_CreateNode(FxUnit, str, fluid_LADSPA_node_is_audio | fluid_LADSPA_node_is_sink); 102 sprintf(str, "out%i_R",(i+1)); 103 fluid_LADSPA_CreateNode(FxUnit, str, fluid_LADSPA_node_is_audio | fluid_LADSPA_node_is_sink); 104 }; 105}; 106 107/* Purpose: 108 * Creates predeclared nodes for control of the Fx unit during operation. 109 */ 110void fluid_LADSPA_CreateUserControlNodes(fluid_LADSPA_FxUnit_t* FxUnit){ 111 int i; 112 fluid_LADSPA_Node_t* CurrentNode; 113 114 for (i=0; i<FxUnit->NumberUserControlNodes; i++){ 115 CurrentNode=fluid_LADSPA_CreateNode(FxUnit,FxUnit->UserControlNodeNames[i],fluid_LADSPA_node_is_control); 116 assert(CurrentNode); 117 CurrentNode->buf[0]=FxUnit->UserControlNodeValues[i]; 118 CurrentNode->InCount++; /* The constant counts as input */ 119 CurrentNode->flags=fluid_LADSPA_node_is_source | fluid_LADSPA_node_is_user_ctrl; /* It is a user control node */ 120 }; 121}; 122 123/* Purpose: 124 * Returns the pointer to the shared library loaded using 'LibraryFilename' (if it has been loaded). 125 * Return NULL otherwise. 126 * If not: Clear Fx and abort. 127 */ 128void * fluid_LADSPA_RetrieveSharedLibrary(fluid_LADSPA_FxUnit_t* FxUnit, char * LibraryFilename){ 129 void * CurrentLib=NULL; 130 int LibCount; 131 for (LibCount=0; LibCount<FxUnit->NumberLibs; LibCount++){ 132 assert(FxUnit->ppvPluginLibNames[LibCount]); 133 if (FLUID_STRCMP(FxUnit->ppvPluginLibNames[LibCount],LibraryFilename)==0){ 134 CurrentLib=FxUnit->ppvPluginLibs[LibCount]; 135 }; 136 }; 137 return CurrentLib; 138}; 139 140/* Purpose: 141 * Loads a shared LADSPA library. 142 * Return NULL, if failed. 143 * TODO: use LADSPA_PATH 144 */ 145void * fluid_LADSPA_LoadSharedLibrary(fluid_LADSPA_FxUnit_t* FxUnit, char * LibraryFilename){ 146 void * LoadedLib; 147 assert(LibraryFilename); 148 LoadedLib=dlopen(LibraryFilename,RTLD_NOW); 149 if (!LoadedLib){ 150 return NULL; 151 }; 152 FxUnit->ppvPluginLibs[FxUnit->NumberLibs]=LoadedLib; 153 FxUnit->ppvPluginLibNames[FxUnit->NumberLibs]=FLUID_STRDUP(LibraryFilename); 154 FxUnit->NumberLibs++; 155 return LoadedLib; 156}; 157 158/* Purpose: 159 * Retrieves a descriptor to the plugin labeled 'PluginLabel' from the shared library. 160 */ 161const LADSPA_Descriptor * fluid_LADSPA_Retrieve_Plugin_Descriptor(void * CurrentLib, char * PluginLabel){ 162 LADSPA_Descriptor_Function pfDescriptorFunction; 163 unsigned long lPluginIndex=0; 164 const LADSPA_Descriptor * psDescriptor; 165 pfDescriptorFunction = (LADSPA_Descriptor_Function)dlsym(CurrentLib,"ladspa_descriptor"); 166 while (pfDescriptorFunction(lPluginIndex)){ 167 psDescriptor = pfDescriptorFunction(lPluginIndex); 168 if (FLUID_STRCMP(psDescriptor->Label, PluginLabel) == 0){ 169 return psDescriptor; 170 }; 171 lPluginIndex++; 172 }; 173 return NULL; 174}; 175 176/* Purpose: 177 * Finds out, if 'PortName' starts with 'PluginPort'. 178 * Spaces and underscore mean the same. 179 * The comparison is not case sensitive. 180 * The result distinguishes between a full match (strings are equal), and a partial match (PortName starts with Plugin_Port, but is longer). 181 */ 182 183fluid_LADSPA_Stringmatch_t fluid_LADSPA_Check_SubString_Match(const char * Plugin_Port, const char * PortName){ 184 unsigned int CharCount; 185 char a; 186 char b; 187 for(CharCount=0; CharCount<FLUID_STRLEN(Plugin_Port); CharCount++){ 188 a=PortName[CharCount]; 189 b=Plugin_Port[CharCount]; 190 if (a>='a' && a <='z'){a-=32;} 191 if (b>='a' && b <='z'){b-=32;} 192 if (a == ' '){a='_';}; 193 if (b == ' '){b='_';}; 194 if ( a != b){ 195 return fluid_LADSPA_NoMatch; 196 }; 197 }; 198 if (FLUID_STRLEN(Plugin_Port) == FLUID_STRLEN(PortName)){ 199 return fluid_LADSPA_FullMatch; 200 }; 201 return fluid_LADSPA_PartialMatch; 202 203}; 204 205/* Purpose: 206 * Load the plugins added with 'ladspa_add' and then start the Fx unit. 207 */ 208 209int 210fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out){ 211 fluid_LADSPA_FxUnit_t* FxUnit; 212 int CommandLineCount; 213 char * LibraryFilename; 214 char * PluginLabel; 215 char ** TokenSequence; 216 void * CurrentLib; 217 int NodeCount; //x 218 int IngoingSignalCount; // Count signals going into LADSPA Fx section 219 int OutgoingSignalCount; // Count signals going out of LADSPA Fx section 220 int ReturnVal=FLUID_OK; /* If warnings occur, this is set to -1. */ 221 char * LADSPA_Path = getenv("LADSPA_PATH"); 222 223 L(fluid_ostream_printf(out,"ladspa_start: starting...")); 224 assert(synth); 225 FxUnit=synth->LADSPA_FxUnit; assert(FxUnit); 226 227 /* When calling fluid_ladspastart, the Fx unit must be 'cleared' (no plugins, no libs, no nodes). Verify this here. */ 228 if (FxUnit->NumberPlugins || FxUnit->NumberLibs){ 229 fluid_ostream_printf(out, "***Error006***\n" 230 "Fx unit is currently in use!\n" 231 "Please run the ladspa_clear command before attempting to use ladspa_add!\n"); 232 /* In this case do _not_ clear the Fx unit. */ 233 return(PrintErrorMessage); 234 }; 235 if (!FxUnit->NumberCommands){ 236 fluid_ostream_printf(out, "***Error007***\n" 237 "Refusing to start the Fx unit without any plugin.\n" 238 "Use ladspa_add first!\n"); 239 fluid_LADSPA_clear(FxUnit); 240 return(PrintErrorMessage); 241 }; 242 243 /* Create predefined nodes */ 244 L(fluid_ostream_printf(out,"ladspa_start: creating predefined nodes...")); 245 fluid_LADSPA_CreateSystemNodes(FxUnit); 246 247 /* Create predeclared nodes, that will allow to control the Fx unit during operation */ 248 L(fluid_ostream_printf(out,"ladspa_start: creating user control nodes...")); 249 fluid_LADSPA_CreateUserControlNodes(FxUnit); 250 251 L(fluid_ostream_printf(out,"ladspa_start: Processing command lines...")); 252 for (CommandLineCount=0; CommandLineCount<FxUnit->NumberCommands; CommandLineCount++){ 253 int CurrentPlugin_PortConnected[FLUID_LADSPA_MaxTokens/3]; /* For example: 100 tokens corresponds to roughly 30 ports. */ 254 char LibFullPath[FLUID_LADSPA_MaxPathLength]; 255 const LADSPA_Descriptor * CurrentPluginDescriptor; 256 LADSPA_Handle CurrentPlugin; 257 unsigned long PortCount; 258 int TokenCount=0; 259 char * Search; 260 int HasASlash=0; 261 262 if (FxUnit->NumberPlugins>=FLUID_LADSPA_MaxPlugins){ 263 fluid_ostream_printf(out, "***Error003***\n" 264 "Too many plugins at the same time (%i).\n" 265 "Change FLUID_LADSPA_MaxPlugins!\n", 266 FxUnit->NumberPlugins); 267 fluid_LADSPA_clear(FxUnit); 268 return(PrintErrorMessage); 269 }; 270 271 L(fluid_ostream_printf(out,"Processing plugin nr. %i",FxUnit->NumberPlugins)); 272 273 TokenSequence=FxUnit->LADSPA_Command_Sequence[CommandLineCount]; 274 assert(TokenSequence); 275 276 /* Check, if the library is already loaded. If not, load. */ 277 LibraryFilename=TokenSequence[TokenCount++]; assert(LibraryFilename); 278 279 L(fluid_ostream_printf(out,"Library name from ladspa_add: %s",LibraryFilename)); 280 /* A slash-free filename refers to the LADSPA_PATH directory. Add that path, if needed. */ 281 282 283 284 /* Determine, if the library filename contains a slash. 285 * If no, try to retrieve the environment variable LADSPA_PATH. 286 * If that fails, signal error. 287 * Otherwise leave the filename as it is. 288 */; 289 290 /* Determine, if the library name is just the filename, or a path (including a slash) */ 291 Search=LibraryFilename; 292 while (*Search != '\0') { 293 if ((*Search)== '/'){ 294 HasASlash=1; 295 }; 296 Search++; 297 }; 298 299 if (!HasASlash){ 300 if (!LADSPA_Path){ 301 fluid_ostream_printf(out, "***Error018***\n" 302 "The library file name %s does not include a path.\n" 303 "The environment variable LADSPA_PATH is not set.\n" 304 "- Use an absolute path (i.e. /home/myself/mylib.so)\n" 305 "- For the current directory use ./mylib.so\n" 306 "- set the environment variable LADSPA_PATH (export LADSPA_PATH=/usr/lib/ladspa)\n" 307 "- depending on your shell, try 'setenv' instead of 'export'\n", 308 LibraryFilename); 309 fluid_LADSPA_clear(FxUnit); 310 return(PrintErrorMessage); 311 }; /* if no LADSPA_PATH */ 312 snprintf(LibFullPath,FLUID_LADSPA_MaxPathLength,"%s/%s",LADSPA_Path,LibraryFilename); 313 /* If no slash in filename */ 314 } else { 315 snprintf(LibFullPath,FLUID_LADSPA_MaxPathLength,"%s",LibraryFilename); 316 }; 317 318 L(fluid_ostream_printf(out,"Full Library path name: %s",LibFullPath)); 319 320 CurrentLib=fluid_LADSPA_RetrieveSharedLibrary(FxUnit, LibFullPath); 321 if (!CurrentLib){ 322 LADSPA_Descriptor_Function pfDescriptorFunction; 323 324 L(fluid_ostream_printf(out,"Library %s not yet loaded. Loading.",LibFullPath)); 325 326 if (FxUnit->NumberLibs>=FLUID_LADSPA_MaxLibs){ 327 fluid_ostream_printf(out, "***Error004***\n" 328 "Too many libraries open (%i)\n" 329 "Change FLUID_LADSPA_MaxLibs",FxUnit->NumberPlugins); 330 fluid_LADSPA_clear(FxUnit); 331 return(PrintErrorMessage); 332 }; 333 334 /* Load a LADSPA plugin library and store it for future use.*/ 335 CurrentLib=fluid_LADSPA_LoadSharedLibrary(FxUnit, LibFullPath); 336 337 if (!CurrentLib){ 338 fluid_ostream_printf(out, "***Error008***\n" 339 "Failed to load plugin library %s.", 340 LibraryFilename); 341 fluid_LADSPA_clear(FxUnit); 342 return(PrintErrorMessage); 343 }; 344 345 346 dlerror(); 347 pfDescriptorFunction = (LADSPA_Descriptor_Function)dlsym(CurrentLib,"ladspa_descriptor"); 348 if (!pfDescriptorFunction) { 349 const char * pcError = dlerror(); 350 if (!pcError) {pcError="Huh?! No error from lib!";}; 351 fluid_ostream_printf(out, "***Error015***\n" 352 "Unable to find ladspa_descriptor() function in plugin library file \"%s\": %s.\n" 353 "Are you sure this is a LADSPA plugin file?\n", 354 LibraryFilename, 355 pcError); 356 fluid_LADSPA_clear(FxUnit); 357 return(PrintErrorMessage); 358 }; 359 360 L(fluid_ostream_printf(out,"Library loaded.")); 361 }; 362 363 PluginLabel=TokenSequence[TokenCount++]; assert(PluginLabel); 364 L(fluid_ostream_printf(out,"Plugin Label from ladspa_add: %s",PluginLabel)); 365 /* Retrieve a 'plugin descriptor' from the library. */ 366 L(fluid_ostream_printf(out,"Looking for the plugin labeled %s",PluginLabel)); 367 368 CurrentPluginDescriptor=fluid_LADSPA_Retrieve_Plugin_Descriptor(CurrentLib, PluginLabel); 369 370 371 /* Check, that the plugin was actually found.*/ 372 if (CurrentPluginDescriptor==NULL){ 373 fluid_ostream_printf(out, "***Error016***\n" 374 "Unable to find the plugin labeled \"%s\" in plugin library file \"%s\".\n" 375 "Hint: run analyzeplugin %s from the command line to get a list of valid plugin labels.\n", 376 PluginLabel, 377 LibraryFilename, 378 LibraryFilename); 379 fluid_LADSPA_clear(FxUnit); 380 return(PrintErrorMessage); 381 }; 382 383 /* Create an instance of the plugin type from the descriptor */ 384 L(fluid_ostream_printf(out,"instantiating plugin %s",PluginLabel)); 385 CurrentPlugin=CurrentPluginDescriptor 386 ->instantiate(CurrentPluginDescriptor,44100); /* Sample rate hardcoded */ 387 assert(CurrentPlugin); 388 389 /* The descriptor ("type of plugin") and the instance are stored for each plugin instantiation. 390 If one plugin type is instantiated several times, they will have the same descriptor, only 391 different instances.*/ 392 FxUnit->PluginDescriptorTable[FxUnit->NumberPlugins]=CurrentPluginDescriptor; 393 FxUnit->PluginInstanceTable[FxUnit->NumberPlugins]=CurrentPlugin; 394 395 /* 396 * 397 * Wire up the inputs and outputs 398 * 399 */ 400 401 /* List for checking, that each plugin port is exactly connected once */ 402 for (PortCount=0; PortCount<CurrentPluginDescriptor->PortCount; PortCount++){ 403 CurrentPlugin_PortConnected[PortCount]=0; 404 }; 405 406 /* Note: There are three NULL tokens at the end. The last condition may be evaluated even if the first one already detects the end. */ 407 while (TokenSequence[TokenCount] && TokenSequence[TokenCount+1] && TokenSequence[TokenCount+2]){ 408 int CurrentPort_StringMatchCount; 409 LADSPA_PortDescriptor CurrentPort_Descriptor; 410 char * Plugin_Port=TokenSequence[TokenCount++]; 411 char * Direction=TokenSequence[TokenCount++]; 412 char * FLUID_Node=TokenSequence[TokenCount++]; 413 fluid_LADSPA_Node_t* Current_Node; 414 const char * PortName=NULL; 415 int CurrentPort_Index=-1; 416 fluid_LADSPA_Stringmatch_t StringMatchType=fluid_LADSPA_NoMatch; 417 fluid_LADSPA_Stringmatch_t CurrentPort_StringMatchType=fluid_LADSPA_NoMatch; 418 CurrentPort_StringMatchCount=0; 419 420 L(fluid_ostream_printf(out,"Wiring %s %s %s",Plugin_Port, Direction, FLUID_Node)); 421 422 /* Find the port number on the plugin, that belongs to "Plugin_Port". 423 * Match the identifier specified by the user against the first characters 424 * of the port name. 425 * 426 * If the given identifier matches several port names only partly, then the input is ambiguous, an error 427 * message results. 428 * 429 * Example: cmt.so, limit_peak: This plugin uses the labels 430 * - Output Envelope Attack (s) 431 * - Output Envelope Decay (s) 432 * - Output 433 * 434 * The user input 'Output' matches the first two labels partly, the third fully. This will be accepted. 435 * The user input 'Out' matches all three only partly, this results in an error message. 436 */ 437 438 for (PortCount=0; PortCount<CurrentPluginDescriptor->PortCount; PortCount++){ 439 PortName=CurrentPluginDescriptor->PortNames[PortCount]; 440 441 StringMatchType=fluid_LADSPA_Check_SubString_Match(Plugin_Port, PortName); 442 /* If a full-string match has been found earlier, reject all partial matches. */ 443 if (StringMatchType==fluid_LADSPA_FullMatch || 444 (StringMatchType==fluid_LADSPA_PartialMatch && CurrentPort_StringMatchType != fluid_LADSPA_FullMatch)){ 445 446 if(StringMatchType==fluid_LADSPA_FullMatch && CurrentPort_StringMatchType==fluid_LADSPA_FullMatch){ 447 fluid_ostream_printf(out, "***Error027***\n" 448 "While processing plugin %s: The port label %s appears more than once!\n" 449 "This is an error in the plugin itself. Please correct it or use another plugin.",PluginLabel, Plugin_Port); 450 fluid_LADSPA_clear(FxUnit); 451 return(PrintErrorMessage); 452 }; 453 454 CurrentPort_Index=PortCount; 455 CurrentPort_StringMatchType=StringMatchType; 456 CurrentPort_StringMatchCount++; 457 458 }; /* if suitable match */ 459 }; /* For port count */ 460 461 /* Several partial matches? Then the identifier is not unique. */ 462 if (CurrentPort_StringMatchCount > 1 && CurrentPort_StringMatchType == fluid_LADSPA_PartialMatch){ 463 fluid_ostream_printf(out, "***Error019***\n" 464 "While processing plugin %s: The identifier %s matches more than one plugin port.\n" 465 "Please use more letters for the port name. If needed, replace spaces with underscores (_).\n" 466 "This error will not occur, if you use the full name of a port.\n",PluginLabel, Plugin_Port); 467 fluid_LADSPA_clear(FxUnit); 468 return(PrintErrorMessage); 469 }; 470 471 if (CurrentPort_Index<0){ 472 fluid_ostream_printf(out, "***Error017***\n" 473 "Unable to find port '%s' on plugin %s\n" 474 "Port names are:\n",Plugin_Port,PluginLabel); 475 for (PortCount=0; PortCount<CurrentPluginDescriptor->PortCount; PortCount++){ 476 printf("- `%s'\n",CurrentPluginDescriptor->PortNames[PortCount]); 477 }; 478 479 fluid_LADSPA_clear(FxUnit); 480 return(PrintErrorMessage); 481 }; 482 CurrentPort_Descriptor=CurrentPluginDescriptor->PortDescriptors[CurrentPort_Index]; 483 assert(CurrentPort_Descriptor); 484 485 /* Retrieve the node with the right name. */ 486 Current_Node=fluid_LADSPA_RetrieveNode(FxUnit,FLUID_Node); 487#define PortIsAudio LADSPA_IS_PORT_AUDIO(CurrentPort_Descriptor) && !(LADSPA_IS_PORT_CONTROL(CurrentPort_Descriptor)) 488#define PortIsControl LADSPA_IS_PORT_CONTROL(CurrentPort_Descriptor) && !(LADSPA_IS_PORT_AUDIO(CurrentPort_Descriptor)) 489 if (!Current_Node){ 490 /* Doesn't exist? Then create it. */ 491 if (FxUnit->NumberNodes>=FLUID_LADSPA_MaxNodes){ 492 fluid_ostream_printf(out, "***Error005***\n" 493 "Too many nodes (%i)\n" 494 "Change FLUID_LADSPA_MaxNodes",FxUnit->NumberNodes); 495 fluid_LADSPA_clear(FxUnit); 496 return(PrintErrorMessage); 497 }; 498 if (PortIsAudio){ 499 Current_Node=fluid_LADSPA_CreateNode(FxUnit,FLUID_Node,fluid_LADSPA_node_is_audio); 500 } else if (PortIsControl){ 501 Current_Node=fluid_LADSPA_CreateNode(FxUnit,FLUID_Node,fluid_LADSPA_node_is_control); 502 } else { 503 fluid_ostream_printf(out, "***Error025***\n" 504 "Plugin port number %i is neither input nor output!\n" 505 "This is an error in the plugin.\n" 506 "Please check plugin sourcecode.\n", 507 CurrentPort_Index); 508 fluid_LADSPA_clear(FxUnit); 509 return(PrintErrorMessage); 510 }; 511 }; 512 assert(Current_Node); 513 514 /* 515 * 516 * Check flowgraph for some possible errors. 517 * 518 */ 519 520 if (FLUID_STRCMP(Direction,"->")==0){ 521 /* Data from plugin to FLUID, into node 522 * 523 * *** Rule: **** 524 * A node may not have more than one data source.*/ 525 if (Current_Node->InCount !=0){ 526 fluid_ostream_printf(out, "***Error009***\n" 527 "Plugin %s tries to feed data from output %s into node %s, which is already connected to a data source.\n",PluginLabel,Plugin_Port,FLUID_Node); 528 fluid_LADSPA_clear(FxUnit); 529 return(PrintErrorMessage); 530 }; 531 Current_Node->InCount++; 532 } else if (FLUID_STRCMP(Direction,"<-")==0){ 533 /* Data from FLUID to plugin, out of node 534 * 535 * This check verifies the integrity of the flow graph: 536 * *** Rule *** 537 * The execution order of the plugins is the order, in which they are programmed. 538 * The plugins must be ordered so, that the input of a plugin is already computed at the time of its execution. 539 * If the user tries to read data out of a node that has not yet an input, then something is wrong.*/ 540 assert(Current_Node->InCount<=1); 541 if (Current_Node->InCount !=1){ 542 fluid_ostream_printf(out, "***Error010***\n" 543 "Plugin %s tries to read data through input %s from node %s.\n" 544 "But at this point there is no valid data at that node.\n" 545 "Please check the flowgraph and especially the execution order!\n",PluginLabel,Plugin_Port,FLUID_Node); 546 fluid_LADSPA_clear(FxUnit); 547 return(PrintErrorMessage); 548 }; 549 Current_Node->OutCount++; 550 } else { 551 fluid_ostream_printf(out, "***Error024***\n" 552 "Syntax error: Illegal `arrow' `%s', expecting -> or <-\n", 553 Direction); 554 fluid_LADSPA_clear(FxUnit); 555 return(PrintErrorMessage); 556 }; 557 558 /* In any case, there must be a valid data source for the port at this time. */ 559 assert(Current_Node->InCount==1); 560 561 /* Keep track on the number of connections to each port. 562 * This error occurs only, if an attempt is made to connect one port twice (i.e. ladspa_add libname pluginname port <- nodex port <- nodey) */ 563 if (CurrentPlugin_PortConnected[CurrentPort_Index]){ 564 fluid_ostream_printf(out, "***Error011***\n" 565 "Refusing to connect twice to port %s on plugin %s.\n",CurrentPluginDescriptor->PortNames[CurrentPort_Index], PluginLabel); 566 fluid_LADSPA_clear(FxUnit); 567 return(PrintErrorMessage); 568 }; 569 570 /* 571 * 572 * Connect the port 573 * 574 */ 575 576 L(fluid_ostream_printf(out,"Connecting %i",CurrentPort_Index)); 577 CurrentPluginDescriptor->connect_port 578 (CurrentPlugin, 579 CurrentPort_Index, 580 Current_Node->buf 581 ); 582 CurrentPlugin_PortConnected[CurrentPort_Index]++; 583 584 }; /* While Tokensequence (more connections) */ 585 586 /* 587 * 588 * Check for left-over tokens 589 * 590 */ 591 592 if (TokenSequence[TokenCount]){ 593 char * T1="";char * T2="";char * T3=""; 594 if (TokenSequence[TokenCount]){T1=TokenSequence[TokenCount];}; 595 if (TokenSequence[TokenCount+1]){T2=TokenSequence[TokenCount+1];}; 596 if (TokenSequence[TokenCount+2]){T3=TokenSequence[TokenCount+2];}; 597 fluid_ostream_printf(out, "***Error012***\n" 598 "Leftover tokens: %s %s %s...\n",T1,T2,T3); 599 fluid_LADSPA_clear(FxUnit); 600 return(PrintErrorMessage); 601 }; 602 603 /* 604 * 605 * Check, that all plugin ports are connected 606 * 607 */ 608 L(fluid_ostream_printf(out,"Checking left-over ports")); 609 assert(CurrentPluginDescriptor); 610 for (PortCount=0; PortCount<CurrentPluginDescriptor->PortCount; PortCount++){ 611 assert(CurrentPlugin_PortConnected[PortCount] <=1); 612 if (CurrentPlugin_PortConnected[PortCount] !=1){ 613 fluid_ostream_printf(out, "***Error013***\nPlugin: %s. Port %s is unconnected!\n",PluginLabel, CurrentPluginDescriptor->PortNames[PortCount]); 614 fluid_LADSPA_clear(FxUnit); 615 return(PrintErrorMessage); 616 }; 617 }; 618 619 /* 620 * 621 *Run activate function on plugin, where possible 622 * 623 */ 624 625 if (CurrentPluginDescriptor->activate !=NULL){ 626 CurrentPluginDescriptor->activate(CurrentPlugin); 627 }; 628 629 FxUnit->NumberPlugins++; 630 }; /* For CommandLineCount: once for each new command (i.e. plugin instantiation request from user */ 631 632 /* 633 * 634 * Further flow graph checks 635 * 636 */ 637 638 L(fluid_ostream_printf(out,"Checking flow graph")); 639 640 IngoingSignalCount=0; 641 OutgoingSignalCount=0; 642 643 for (NodeCount=0; NodeCount<FxUnit->NumberNodes; NodeCount++){ 644 fluid_LADSPA_Node_t* Current_Node; 645 Current_Node=FxUnit->Nodelist[NodeCount]; 646 assert(Current_Node); 647 if (Current_Node->flags & fluid_LADSPA_node_is_source){ 648 IngoingSignalCount+=Current_Node->OutCount; 649 } else if (Current_Node->flags & fluid_LADSPA_node_is_sink){ 650 OutgoingSignalCount+=Current_Node->InCount; 651 } else { 652 653 /* A node without any input doesn't make sense. 654 * The flow graph check aborts with an error. This case cannot happen. 655 */ 656 if (Current_Node->InCount==0 && !Current_Node->flags & fluid_LADSPA_node_is_dummy){ /* There can only be one warning at a time. */ 657 fluid_ostream_printf(out, "***Warning020***" 658 "No input into node %s.\n" 659 "Use '_' as first char in nodename to suppress this warning.\n" 660 "Hint: Check for typos in the node name.\n",Current_Node->Name); 661 /* A warning can also be printed as an error message (check fluid_cmd.c). The only difference between 662 the return values -1 and 0 is, that -1 prints the result. */ 663 }; 664 ReturnVal=PrintErrorMessage; 665 }; 666 667 /* A node without any output doesn't make sense. */ 668 if (Current_Node->OutCount==0 && !Current_Node->flags & fluid_LADSPA_node_is_dummy){ 669 fluid_ostream_printf(out, "***Warning021***\n" 670 "No output from node %s.\n" 671 "Use '_' as first char in nodename to suppress this warning.\n" 672 "Hint: Check for typos in the node name.\n",Current_Node->Name); 673 ReturnVal=PrintErrorMessage; 674 }; 675 /* A free-flying node simply cannot happen. */ 676 assert(Current_Node->OutCount+Current_Node->InCount); 677 }; /* Foreach node */ 678 679 /* Issue a warning, if no signal goes into the Fx section. */ 680 if (IngoingSignalCount==0){ 681 fluid_ostream_printf(out, "***Warning022***\n" 682 "You have not connected anything to the synthesizer section (in1_L, in1_R).\n"); 683 ReturnVal=PrintErrorMessage; 684 }; 685 686 /* Issue a warning, if no signal leaves the Fx section. */ 687 if (OutgoingSignalCount==0){ 688 fluid_ostream_printf(out, "***Warning023***\n" 689 "You have not connected anything to the output (out1_L, out1_R).\n"); 690 }; 691 692 /* Finally turn on the Fx unit. */ 693 FxUnit->Bypass=fluid_LADSPA_Active; 694 L(fluid_ostream_printf(out,"LADSPA Init OK")); 695 return(ReturnVal); 696}; 697 698void 699fluid_LADSPA_run(fluid_LADSPA_FxUnit_t* FxUnit, fluid_real_t* left_buf[], fluid_real_t* right_buf[], fluid_real_t* fx_left_buf[], fluid_real_t* fx_right_buf[]){ 700 int i; 701 int ii; 702 703 704 int nr_audio_channels; 705 int nr_fx_sends; 706 int nr_groups; 707 int byte_size = FLUID_BUFSIZE * sizeof(fluid_real_t); 708 char str[99]; 709 fluid_LADSPA_Node_t* n; 710 int temp; 711 712 /* Retrieve the number of synth / audio out / Fx send nodes */ 713 assert(fluid_settings_getint(FxUnit->synth->settings, "synth.audio-groups", &temp)); 714 nr_groups=(int) temp; 715 716 assert(fluid_settings_getint(FxUnit->synth->settings, "synth.audio-channels", &temp)); 717 nr_audio_channels=temp; 718 719 assert(fluid_settings_getint(FxUnit->synth->settings, "synth.effects-channels", &temp)); 720 nr_fx_sends=temp; 721 722 /* Fixme: Retrieving nodes via names is inefficient 723 * (but not that bad, because the interesting nodes are always at the start of the list). 724 */ 725 726 /* Input and output are processed via the same buffers. Therefore the effect is bypassed by just skipping everything else. */ 727 if (FxUnit->Bypass==fluid_LADSPA_Bypassed){ 728 return; 729 }; 730 731 if (FxUnit->Bypass==fluid_LADSPA_BypassRequest){ 732 FxUnit->Bypass=fluid_LADSPA_Bypassed; 733 pthread_mutex_lock(&FxUnit->mutex); 734 pthread_cond_broadcast(&FxUnit->cond); 735 pthread_mutex_unlock(&FxUnit->mutex); 736 L(printf("LADSPA_Run: Command line asked for bypass of Fx unit. Acknowledged.")); 737 return; 738 }; 739 740 assert(FxUnit); 741 742 /* Clear the output buffers, if they are not connected anywhere */ 743 for (ii=0; ii < nr_audio_channels; ii++){ 744 745 sprintf(str, "out%i_L",(ii+1)); 746 n=fluid_LADSPA_RetrieveNode(FxUnit, str); assert(n); 747 if (n->InCount == 0){ 748/* printf("Output node %s is not connected -> clear buffer\n", str); */ 749 FLUID_MEMSET(n->buf, 0, byte_size); 750 }; 751 752 sprintf(str, "out%i_R",(ii+1)); 753 n=fluid_LADSPA_RetrieveNode(FxUnit, str); assert(n); 754 if (n->InCount == 0){ 755/* printf("Output node %s is not connected -> clear buffer\n", str); */ 756 FLUID_MEMSET(n->buf, 0, byte_size); 757 }; 758 }; 759 760 /* Prepare the incoming data: 761 * Convert fluid_real_t data type to LADSPA_Data type */ 762 for (ii=0; ii < nr_groups; ii++){ 763 fluid_real_t* src_buf=left_buf[ii]; 764 sprintf(str, "in%i_L",(ii+1)); 765 n=fluid_LADSPA_RetrieveNode(FxUnit, str); assert(n); 766 767 assert(FLUID_BUFSIZE % 2 == 0); 768 769 /* Add a very small high frequency signal. This avoids denormal number problems. */ 770 for (i=0; i<FLUID_BUFSIZE;){ 771 n->buf[i]=(LADSPA_Data)(src_buf[i]+1.e-15); 772 i++; 773 n->buf[i]=(LADSPA_Data)(src_buf[i]); 774 i++; 775 }; 776 777 src_buf=right_buf[ii]; 778 sprintf(str, "in%i_R",(ii+1)); 779 n=fluid_LADSPA_RetrieveNode(FxUnit, str); assert(n); 780 781 /* Add a very small high frequency signal. This avoids denormal number problems. */ 782 for (i=0; i<FLUID_BUFSIZE;){ 783 n->buf[i]=(LADSPA_Data)(src_buf[i]+1.e-15); 784 i++; 785 n->buf[i]=(LADSPA_Data)(src_buf[i]); 786 i++; 787 }; 788 }; 789 790 /* Effect send paths */ 791 for (ii=0; ii < nr_fx_sends; ii++){ 792 sprintf(str, "send%i_L",(ii+1)); 793 n=fluid_LADSPA_RetrieveNode(FxUnit, str); assert(n); 794 for (i=0; i<FLUID_BUFSIZE; i++){ 795 n->buf[i]=(LADSPA_Data)(fx_left_buf[ii][i]); 796 }; 797 798 sprintf(str, "send%i_R",(ii+1)); 799 n=fluid_LADSPA_RetrieveNode(FxUnit, str); assert(n); 800 for (i=0; i<FLUID_BUFSIZE; i++){ 801 n->buf[i]=(LADSPA_Data)(fx_right_buf[ii][i]); 802 }; 803 }; 804 805 /* Run each plugin on a block of data. 806 * The execution order has been checked during setup.*/ 807 for (i=0; i<FxUnit->NumberPlugins; i++){ 808 FxUnit->PluginDescriptorTable[i]->run(FxUnit->PluginInstanceTable[i],FLUID_BUFSIZE); 809 }; 810 811 /* Copy the data from the output nodes back to the synth. */ 812 for (ii=0; ii < nr_audio_channels; ii++){ 813 fluid_real_t* dest_buf=left_buf[ii]; 814 sprintf(str, "out%i_L",(ii+1)); 815 n=fluid_LADSPA_RetrieveNode(FxUnit, str); assert(n); 816 for (i=0; i<FLUID_BUFSIZE; i++){ 817 dest_buf[i]=(fluid_real_t)n->buf[i]; 818 }; 819 820 dest_buf=right_buf[ii]; 821 sprintf(str, "out%i_R",(ii+1)); 822 n=fluid_LADSPA_RetrieveNode(FxUnit, str); assert(n); 823 for (i=0; i<FLUID_BUFSIZE; i++){ 824 dest_buf[i]=(fluid_real_t)n->buf[i]; 825 }; 826 }; 827}; 828 829fluid_LADSPA_Node_t* 830fluid_LADSPA_RetrieveNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name){ 831 int i=0; 832 assert(FxUnit);assert(Name); 833 for (i=0; i<FxUnit->NumberNodes; i++){ 834 assert(FxUnit->Nodelist[i]); 835 if (FLUID_STRCMP(FxUnit->Nodelist[i]->Name,Name)==0){ 836 return FxUnit->Nodelist[i]; 837 }; 838 }; 839 return NULL; 840}; 841 842 843/* Purpose: 844 * Creates a new node from the node name given by the user. 845 */ 846fluid_LADSPA_Node_t* 847fluid_LADSPA_CreateNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name, int flags){ 848 int Dummy=0; 849 fluid_LADSPA_Node_t* NewNode; 850 assert(FxUnit); 851 assert(Name); 852// printf("Flags is %i\n",flags); 853 L(printf("Create node: %s",Name)); 854 if (FxUnit->NumberNodes>=FLUID_LADSPA_MaxNodes){ 855 printf( "***Error014***\n" 856 "Too many nodes (%i)\n" 857 "Change FLUID_LADSPA_MaxNodes.\n",FxUnit->NumberNodes); 858 fluid_LADSPA_clear(FxUnit); 859 return NULL; 860 }; 861 862 /* Don't allow node names, which start with -, 0..9 */ 863 if (Name[0] == '-' || (Name[0]>='0' && Name[0]<='9')){ 864 printf( "***Error026***\n" 865 "The node name %s starts with a digit / minus sign!\n" 866 "Please use a letter to start a node name.\n" 867 "A constant node is created by using `#' as first character,\n" 868 "for example #-2.5.\n", 869 Name); 870 fluid_LADSPA_clear(FxUnit); 871 return NULL; 872 }; 873 874 /* A nodename starting with "_" is a possible dummy node, which may (but need not) act as a data sink or source (dummy node). */ 875 if (Name[0] == ' '){ /* ??? Should be '_' ??? */ 876 Dummy=1; 877 }; 878 NewNode=FLUID_NEW(fluid_LADSPA_Node_t);assert(NewNode); 879 if (flags && fluid_LADSPA_node_is_audio){ 880 /* Audio node contains buffer. */ 881 NewNode->buf=FLUID_ARRAY(LADSPA_Data, (FLUID_BUFSIZE));assert(NewNode->buf); 882 /* It is permitted to use a dummy node without input. Therefore clear all node buffers at startup. */ 883 FLUID_MEMSET(NewNode->buf, 0, (FLUID_BUFSIZE*sizeof(LADSPA_Data))); 884 } else if (flags & fluid_LADSPA_node_is_control){ 885 /* Control node contains single value. */ 886 NewNode->buf=FLUID_ARRAY(LADSPA_Data, 1);assert(NewNode->buf); 887 } else { 888 assert(0); 889 }; 890 NewNode->Name=FLUID_STRDUP(Name);assert(NewNode->Name); 891 if (Dummy){ 892 flags |= fluid_LADSPA_node_is_dummy; 893 }; 894 NewNode->InCount=0; 895 NewNode->OutCount=0; 896 NewNode->flags=flags; 897 898 /* A nodename starting with "#" means that the node holds a constant value. */ 899 if (NewNode->Name[0] == '#'){ 900 assert(flags & fluid_LADSPA_node_is_control); 901 /* Skip the first character => +1 */ 902 NewNode->buf[0]=(LADSPA_Data)atof(NewNode->Name+1); 903 NewNode->InCount++; 904 }; 905 if (flags & fluid_LADSPA_node_is_source){ 906 NewNode->InCount++; 907// printf("****************************** Source!\n"); 908 } else if (flags & fluid_LADSPA_node_is_sink){ 909 NewNode->OutCount++; 910 }; 911 FxUnit->Nodelist[FxUnit->NumberNodes++]=NewNode; 912 913 L(printf("Node %s created.",Name)); 914 return NewNode; 915}; 916 917void fluid_LADSPA_clear(fluid_LADSPA_FxUnit_t* FxUnit){ 918 int i; 919 int ii; 920 L(printf("ladspa_clear")); 921 assert(FxUnit); 922 923 if (FxUnit->Bypass==fluid_LADSPA_Active){ 924 L(printf("clear: Requesting bypass from synthesis thread")); 925 /* Bypass the Fx unit before anything else. 926 * Reason: Not a good idea to release plugins, while another thread runs them. 927 */ 928 FxUnit->Bypass=fluid_LADSPA_BypassRequest; 929 pthread_mutex_lock(&FxUnit->mutex); 930 pthread_cond_wait(&FxUnit->cond,&FxUnit->mutex); 931 pthread_mutex_unlock(&FxUnit->mutex); 932 L(printf("clear: Synthesis thread has switched to bypass.")); 933 } else { 934 L(printf("clear: Fx unit was already bypassed. No action needed.")); 935 }; 936 937 L(printf("Clear all user control node declarations")); 938 for (i=0; i<FxUnit->NumberUserControlNodes; i++){ 939 FLUID_FREE(FxUnit->UserControlNodeNames[i]); 940 }; 941 FxUnit->NumberUserControlNodes=0; 942 943 L(printf("Clear all plugin instances")); 944 for (i=0; i<FxUnit->NumberPlugins; i++){ 945 assert(FxUnit->PluginDescriptorTable[i]); 946 assert(FxUnit->PluginInstanceTable[i]); 947 948 /* Run deactivate function on plugin, if possible */ 949 if (FxUnit->PluginDescriptorTable[i]->deactivate){ 950 FxUnit->PluginDescriptorTable[i]->deactivate(FxUnit->PluginInstanceTable[i]); 951 }; 952 FxUnit->PluginDescriptorTable[i]->cleanup(FxUnit->PluginInstanceTable[i]); 953 }; 954 FxUnit->NumberPlugins=0; 955 956 L(printf("Clear all nodes")); /* Only after removing plugins! */ 957 for (i=0; i<FxUnit->NumberNodes; i++){ 958 FLUID_FREE(FxUnit->Nodelist[i]->buf); 959 FLUID_FREE(FxUnit->Nodelist[i]); 960 }; 961 FxUnit->NumberNodes=0; 962 963 964 L(printf("Clear all plugin libraries")); 965 for (i=0; i<FxUnit->NumberLibs; i++){ 966 967 assert(FxUnit->ppvPluginLibs[i]); 968 dlclose(FxUnit->ppvPluginLibs[i]); 969 970 assert(FxUnit->ppvPluginLibNames[i]); 971 FLUID_FREE(FxUnit->ppvPluginLibNames[i]); 972 }; 973 FxUnit->NumberLibs=0; 974 975 L(printf("Clear all command lines")); 976 for (i=0; i<FxUnit->NumberCommands;i++){ 977 ii=0; 978 assert(FxUnit->LADSPA_Command_Sequence[i]); 979 while (FxUnit->LADSPA_Command_Sequence[i][ii]){ 980 FLUID_FREE(FxUnit->LADSPA_Command_Sequence[i][ii]); 981 ii++; 982 }; 983 FLUID_FREE(FxUnit->LADSPA_Command_Sequence[i]); 984 }; 985 FxUnit->NumberCommands=0; 986}; 987 988int fluid_LADSPA_handle_add(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out){ 989 int i; 990 char * Token; 991 char ** CommandLine; 992 fluid_LADSPA_FxUnit_t* FxUnit; 993 assert(synth); 994 FxUnit=synth->LADSPA_FxUnit; assert(FxUnit); 995 if (ac>=FLUID_LADSPA_MaxTokens){ 996 /* Can't be tested. fluidsynth limits the number of tokens. */ 997 printf("***Error001***\n" 998 "Too many ports.\nChange FLUID_LADSPA_MaxTokens!"); 999 fluid_LADSPA_clear(FxUnit); 1000 return(PrintErrorMessage); 1001 }; 1002 if (ac<2){ 1003 printf("***Error002***\n" 1004 "ladspa_add needs at least two arguments - libname and plugin name!"); 1005 fluid_LADSPA_clear(FxUnit); 1006 return(PrintErrorMessage); 1007 }; 1008 1009 if (FxUnit->NumberCommands>=FLUID_LADSPA_MaxPlugins){ 1010 printf("***Error032***\n" 1011 "Too many plugins.\nChange FLUID_LADSPA_MaxPlugins!"); 1012 fluid_LADSPA_clear(FxUnit); 1013 return(PrintErrorMessage); 1014 }; 1015 1016 /* CommandLine (token sequence) is terminated with NULL. 1017 * Add two more NULLs, so that a chunk of three tokens can be checked later without risk.*/ 1018 1019 CommandLine=FLUID_ARRAY(char*, (ac+3));assert(CommandLine); 1020 for (i=0; i<ac; i++){ 1021 CommandLine[i]=FLUID_STRDUP(av[i]);assert(CommandLine[i]); 1022 }; 1023 CommandLine[ac]=NULL; 1024 CommandLine[ac+1]=NULL; 1025 CommandLine[ac+2]=NULL; 1026 1027 FxUnit->LADSPA_Command_Sequence[FxUnit->NumberCommands]=CommandLine; 1028 FxUnit->NumberCommands++; 1029 return(FLUID_OK); 1030}; 1031 1032int fluid_LADSPA_handle_declnode(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out){ 1033 int i; 1034 char * Token; 1035 char ** CommandLine; 1036 char * NodeName; 1037 fluid_real_t NodeValue; 1038 fluid_LADSPA_FxUnit_t* FxUnit; 1039 assert(synth); 1040 FxUnit=synth->LADSPA_FxUnit; assert(FxUnit); 1041 1042 if (ac<2){ 1043 printf("***Error028***\n" 1044 "ladspa_declnode needs two arguments - node name and value!\n"); 1045 fluid_LADSPA_clear(FxUnit); 1046 return(PrintErrorMessage); 1047 }; 1048 1049 if (FxUnit->NumberUserControlNodes>=FLUID_LADSPA_MaxNodes){ 1050 printf("***Error033***\n" 1051 "Too many user-control nodes.\nChange FLUID_LADSPA_MaxNodes!"); 1052 fluid_LADSPA_clear(FxUnit); 1053 return(PrintErrorMessage); 1054 }; 1055 1056 NodeName=FLUID_STRDUP(av[0]); assert(NodeName); 1057 NodeValue=atof(av[1]); 1058 FxUnit->UserControlNodeNames[FxUnit->NumberUserControlNodes]=NodeName; 1059 FxUnit->UserControlNodeValues[FxUnit->NumberUserControlNodes]=NodeValue; 1060 FxUnit->NumberUserControlNodes++; 1061 return(FLUID_OK); 1062}; 1063int fluid_LADSPA_handle_setnode(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out){ 1064 int i; 1065 char * Token; 1066 char * NodeName; 1067 fluid_real_t NodeValue; 1068 fluid_LADSPA_FxUnit_t* FxUnit; 1069 fluid_LADSPA_Node_t* CurrentNode; 1070 assert(synth); 1071 FxUnit=synth->LADSPA_FxUnit; assert(FxUnit); 1072 1073 if (ac!=2){ 1074 printf("***Error029***\n" 1075 "ladspa_setnode needs two arguments - node name and value!\n"); 1076 /* Do not clear the Fx unit (no fluid_LADSPA_clear). */ 1077 return(PrintErrorMessage); 1078 }; 1079 1080 NodeName=av[0]; assert(NodeName); 1081 NodeValue=atof(av[1]); 1082 1083 CurrentNode=fluid_LADSPA_RetrieveNode(FxUnit,NodeName); 1084 if (!CurrentNode){ 1085 printf("***Error030***\n" 1086 "The node %s was not found. Please use the full name of a node, that was\n" 1087 "previously declared with ladspa_declnode.\n",NodeName); 1088 /* Do not clear the Fx unit (no fluid_LADSPA_clear). */ 1089 return(PrintErrorMessage); 1090 }; 1091 if (!(CurrentNode->flags & fluid_LADSPA_node_is_user_ctrl)){ 1092 printf("***Error031***\n" 1093 "The node %s is an ordinary control node.\n" 1094 "Only user control nodes can be modified with ladspa_setnode.\n",NodeName); 1095 /* Do not clear the Fx unit (no fluid_LADSPA_clear). */ 1096 return(PrintErrorMessage); 1097 }; 1098 L(printf("ladspa_setnode: Assigning value %f",NodeValue)); 1099 CurrentNode->buf[0]=NodeValue; 1100 return(FLUID_OK); 1101}; 1102 1103int fluid_LADSPA_handle_clear(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out){ 1104 fluid_LADSPA_FxUnit_t* FxUnit; 1105 assert(synth); 1106 FxUnit=synth->LADSPA_FxUnit; assert(FxUnit); 1107 fluid_LADSPA_clear(FxUnit); 1108 return(FLUID_OK); 1109}; 1110 1111void fluid_LADSPA_shutdown(fluid_LADSPA_FxUnit_t* FxUnit){ 1112 /* The synthesis thread is not running anymore. 1113 * Set the bypass switch, so that fluid_LADSPA_clear can proceed.*/ 1114 FxUnit->Bypass=fluid_LADSPA_Bypassed; 1115 fluid_LADSPA_clear(FxUnit); 1116 pthread_cond_destroy(&FxUnit->cond); /* pro forma */ 1117}; 1118#endif /*LADSPA*/ 1119