void parseConfigurationLine (void *inst, const char * fname, int lineNumber, char * oneLine) { char delim[] = "=\n"; char * s = oneLine; char * name; char * value; while (isspace (*s)) s++; /* Skip over leading spaces */ if (*s == '\0') return; /* Skip empty lines */ if (*s == '#') return; /* Skip comment lines */ if (*s == '=') { fprintf (stderr, "%s:line %d: empty parameter name.\n", fname, lineNumber); return; } if ((name = strtok (s, delim)) != NULL) { int i; for (i = strlen (name) - 1; isspace (name[i]); name[i] = '\0', i--); if ((value = strtok (NULL, delim)) != NULL) { char * t; while (isspace (value[0])) value++; for (t = value; *t != '\0'; t++) { if (*t == '#') { /* Terminate value at comment */ *t = '\0'; break; } } i = strlen (value); if (0 < i) { for (i = i - 1; isspace (value[i]); value[i] = '\0', i--); } } if (strcasecmp (name, "config.read") == 0) { parseConfigurationFile (inst, value); } else if (strcasecmp (name, "program.read") == 0) { loadProgrammeFile (((b_instance*)inst)->progs, value); } else { ConfigContext cfg; cfg.fname = fname; cfg.linenr = lineNumber; cfg.name = name; cfg.value = value ? value : ""; distributeParameter ((b_instance*) inst, & cfg); } } }
static LV2_Handle instantiate(const LV2_Descriptor* descriptor, double rate, const char* bundle_path, const LV2_Feature* const* features) { B3S* b3s = (B3S*)malloc(sizeof(B3S)); if(!b3s) { return NULL; } memset(b3s, 0, sizeof(B3S)); SampleRateD = rate; int i; for (i=0; features[i]; ++i) { if (!strcmp(features[i]->URI, LV2_URID__map)) { b3s->map = (LV2_URID_Map*)features[i]->data; } else if (!strcmp(features[i]->URI, LV2_WORKER__schedule)) { b3s->schedule = (LV2_Worker_Schedule*)features[i]->data; } } if (!b3s->map || !b3s->schedule) { fprintf(stderr, "B3Lv2 error: Host does not support urid:map or work:schedule\n"); free(b3s); return NULL; } map_setbfree_uris(b3s->map, &b3s->uris); lv2_atom_forge_init(&b3s->forge, b3s->map); srand ((unsigned int) time (NULL)); b3s->suspend_ui_msg = 1; b3s->boffset = BUFFER_SIZE_SAMPLES; b3s->swap_instances = 0; b3s->update_gui_now = 0; b3s->update_pgm_now = 0; b3s->queue_panic = 0; b3s->inst = (b_instance*) calloc(1, sizeof(struct b_instance)); b3s->inst_offline = NULL; allocSynth(b3s->inst); #ifdef JACK_DESCRIPT // CODE DUP src/main.c char * defaultConfigFile = NULL; char * defaultProgrammeFile = NULL; #ifdef _WIN32 char wintmp[1024] = ""; if (ExpandEnvironmentStrings("%localappdata%\\setBfree\\default.cfg", wintmp, 1024)) { defaultConfigFile = strdup (wintmp); } wintmp[0] = '\0'; if (ExpandEnvironmentStrings("%localappdata%\\setBfree\\default.pgm", wintmp, 1024)) { defaultProgrammeFile = strdup (wintmp); } #else // unices: prefer XDG_CONFIG_HOME if (getenv("XDG_CONFIG_HOME")) { size_t hl = strlen(getenv("XDG_CONFIG_HOME")); defaultConfigFile=(char*) malloc(hl+22); defaultProgrammeFile=(char*) malloc(hl+22); sprintf(defaultConfigFile, "%s/setBfree/default.cfg", getenv("XDG_CONFIG_HOME")); sprintf(defaultProgrammeFile, "%s/setBfree/default.pgm", getenv("XDG_CONFIG_HOME")); } else if (getenv("HOME")) { size_t hl = strlen(getenv("HOME")); # ifdef __APPLE__ defaultConfigFile=(char*) malloc(hl+42); defaultProgrammeFile=(char*) malloc(hl+42); sprintf(defaultConfigFile, "%s/Library/Preferences/setBfree/default.cfg", getenv("HOME")); sprintf(defaultProgrammeFile, "%s/Library/Preferences/setBfree/default.pgm", getenv("HOME")); # else // linux, BSD, etc defaultConfigFile=(char*) malloc(hl+30); defaultProgrammeFile=(char*) malloc(hl+30); sprintf(defaultConfigFile, "%s/.config/setBfree/default.cfg", getenv("HOME")); sprintf(defaultProgrammeFile, "%s/.config/setBfree/default.pgm", getenv("HOME")); # endif } #endif if (access (defaultConfigFile, R_OK) == 0) { parseConfigurationFile (b3s->inst, defaultConfigFile); } #endif setControlFunctionCallback(b3s->inst->midicfg, mctl_cb, b3s); initSynth(b3s->inst, rate); #ifdef JACK_DESCRIPT if (access (defaultProgrammeFile, R_OK) == 0) { loadProgrammeFile (b3s->inst->progs, defaultProgrammeFile); } free(defaultConfigFile); free(defaultProgrammeFile); #endif strcpy(b3s->lv2nfo, "v" VERSION); b3s->thirtysec = 0; #ifdef WITH_SIGNATURE { b3s->thirtysec = 30 * rate; b3s->counter = 0; b3s->sin_phase = 0; gp3_initialize (); load_master_key (); // in header WITH_SIGNATURE gp3_loglevel (GP3L_SILENT); int rc = -1; char signature_file0[1024] = ""; char signature_file1[1024] = ""; #ifdef _WIN32 ExpandEnvironmentStrings("%localappdata%\\"SIGFILE, signature_file0, 1024); ExpandEnvironmentStrings("%localappdata%\\x42_license.txt", signature_file1, 1024); #else const char * home = getenv("HOME"); if (home && (strlen(home) + strlen(SIGFILE) + 3) < 1024) { sprintf(signature_file0, "%s/.%s", home, SIGFILE); } if (home && (strlen(home) + 18) < 1024) { sprintf(signature_file1, "%s/.x42_license.txt", home); } #endif if (!access(signature_file0, R_OK)) { rc = gp3_checksigfile (signature_file0); } else if (!access(signature_file1, R_OK)) { rc = gp3_checksigfile (signature_file1); } if (rc == 0) { bool ok = false; char data[8192]; char *tmp=NULL; uint32_t len = gp3_get_text(data, sizeof(data)); if (len == sizeof(data)) data[sizeof(data)-1] = '\0'; else data[len] = '\0'; if ((tmp = strchr(data, '\n'))) *tmp = 0; b3s->lv2nfo[sizeof(b3s->lv2nfo) - 1] = 0; if (tmp++ && *tmp) { if ((tmp = strstr(tmp, SB3_URI))) { char *t1, *t2; ok = true; t1 = tmp + 1 + strlen(SB3_URI); t2 = strchr(t1, '\n'); if (t2) { *t2 = 0; } if (strlen(t1) > 0 && strncmp(t1, VERSION, strlen(t1))) { ok = false; } } } if (ok) { b3s->thirtysec = 0; strncat(b3s->lv2nfo, " ", sizeof(b3s->lv2nfo) - strlen(b3s->lv2nfo)); strncat(b3s->lv2nfo, data, sizeof(b3s->lv2nfo) - strlen(b3s->lv2nfo)); } } gp3_cleanup (); } #endif return (LV2_Handle)b3s; }
/* LV2 -- worker */ static LV2_Worker_Status work(LV2_Handle instance, LV2_Worker_Respond_Function respond, LV2_Worker_Respond_Handle handle, uint32_t size, const void* data) { B3S* b3s = (B3S*)instance; FILE *x; if (size != sizeof(struct worknfo)) { return LV2_WORKER_ERR_UNKNOWN; } struct worknfo *w = (struct worknfo*) data; switch(w->cmd) { case CMD_PURGE: if (b3s->inst_offline) { // this should not happen fprintf(stderr, "B3LV2: re-init in progress\n"); w->status = -1; } else { fprintf(stderr, "B3LV2: reinitialize\n"); b3s->inst_offline = (b_instance*) calloc(1, sizeof(struct b_instance)); allocSynth(b3s->inst_offline); // clone midi map only rc_loop_state(b3s->inst->state, clone_map_cb, b3s->inst_offline); // copy program info memcpy(b3s->inst_offline->progs, b3s->inst->progs, sizeof(struct b_programme)); initSynth(b3s->inst_offline, SampleRateD); // replay CCs after synth init rc_loop_state(b3s->inst->state, clone_cb_mcc, b3s->inst_offline); w->status = 0; } break; case CMD_RESET: if (b3s->inst_offline) { // this should not happen fprintf(stderr, "B3LV2: reset ignored. re-init in progress\n"); w->status = -1; } else { fprintf(stderr, "B3LV2: factory reset\n"); b3s->inst_offline = (b_instance*) calloc(1, sizeof(struct b_instance)); allocSynth(b3s->inst_offline); initSynth(b3s->inst_offline, SampleRateD); w->status = 0; } break; case CMD_SETCFG: if (b3s->inst_offline) { // this should not happen fprintf(stderr, "B3LV2: setcfg ignored. re-init in progress\n"); w->status = -1; } else { // fprintf(stderr, "B3LV2: adding cfg line: %s\n", w->msg); b3s->inst_offline = (b_instance*) calloc(1, sizeof(struct b_instance)); allocSynth(b3s->inst_offline); LOCALEGUARD_START; // clone current state... rc_loop_state(b3s->inst->state, clone_cb_cfg, b3s->inst_offline); // copy program info memcpy(b3s->inst_offline->progs, b3s->inst->progs, sizeof(struct b_programme)); // add user-config parseConfigurationLine (b3s->inst_offline, "LV2", 0, w->msg); initSynth(b3s->inst_offline, SampleRateD); // replay CCs after synth init rc_loop_state(b3s->inst->state, clone_cb_mcc, b3s->inst_offline); LOCALEGUARD_END; w->status = 0; } break; case CMD_LOADPGM: fprintf(stderr, "B3LV2: loading pgm file: %s\n", w->msg); if (!(w->status=loadProgrammeFile(b3s->inst->progs, w->msg))) { b3s->update_pgm_now = 1; } break; case CMD_LOADCFG: if (b3s->inst_offline) { fprintf(stderr, "B3LV2: restore ignored. re-init in progress\n"); return LV2_WORKER_ERR_UNKNOWN; } fprintf(stderr, "B3LV2: loading cfg file: %s\n", w->msg); b3s->inst_offline = (b_instance*) calloc(1, sizeof(struct b_instance)); allocSynth(b3s->inst_offline); w->status = parseConfigurationFile (b3s->inst_offline, w->msg); initSynth(b3s->inst_offline, SampleRateD); break; case CMD_SAVECFG: create_containing_dir (w->msg); x = fopen(w->msg, "w"); if (x) { fprintf(x, "# setBfree config file\n# modificaions on top of default config\n"); LOCALEGUARD_START; rc_loop_state(b3s->inst->state, rcsave_cb, (void*) x); LOCALEGUARD_END; fclose(x); w->status = 0; } else { w->status = -1; } break; case CMD_SAVEPGM: create_containing_dir (w->msg); x = fopen(w->msg, "w"); if (x) { fprintf(x, "# setBfree midi program file\n"); int i; for (i=0 ; i < 128; ++i) { int pgmNr = i + b3s->inst->progs->MIDIControllerPgmOffset; if (!(b3s->inst->progs->programmes[pgmNr].flags[0] & FL_INUSE)) { continue; } writeProgramm(pgmNr, &b3s->inst->progs->programmes[pgmNr], "\n ", x); } fclose(x); w->status = 0; } else { w->status = -1; } break; case CMD_FREE: #ifdef DEBUGPRINT fprintf(stderr, "free offline instance\n"); #endif freeSynth(b3s->inst_offline); b3s->inst_offline = NULL; break; } respond(handle, sizeof(struct worknfo), data); return LV2_WORKER_SUCCESS; }
/* * Main program. */ int main (int argc, char * argv []) { int i,c,k; int doDefaultConfig = TRUE; int doDefaultProgram = TRUE; int printCCTable = FALSE; int doDefaultCC = TRUE; char * configOverride [NOF_CFG_OVERS]; int configOverEnd = 0; int loadProgram = -1; unsigned int randomPreset[9]; unsigned int defaultPreset[9] = {8,8,8, 0,0,0,0, 0,0}; unsigned int * presetSelect = defaultPreset; char *midnam = NULL; char * alternateProgrammeFile = NULL; char * alternateConfigFile = NULL; memset(&inst, 0, sizeof(b_instance)); srand ((unsigned int) time (NULL)); for (i=0;i<AUDIO_CHANNELS; i++) jack_port[i] = NULL; jack_ports = strdup("system:playback_"); const char *optstring = "c:CdDhHl:M:p:PrU:V"; const struct option long_options[] = { { "help", no_argument, 0, 'H' }, { "program", required_argument, 0, 'p' }, { "config", required_argument, 0, 'c' }, { "noconfig", no_argument, 0, 'C' }, { "dumpcc", no_argument, 0, 'd' }, { "noCC", no_argument, 0, 'D' }, { "midnam", required_argument, 0, 'M' }, { "noprogram", no_argument, 0, 'P' }, { "randomize", no_argument, 0, 'r' }, { "upper", required_argument, 0, 'U' }, { "version", no_argument, 0, 'V' }, { 0, 0, 0, 0 } }; while ((c = getopt_long(argc, argv, optstring, long_options, NULL)) != -1) { switch (c) { case 'c': alternateConfigFile = optarg; break; case 'C': doDefaultConfig = FALSE; break; case 'd': printCCTable = TRUE; break; case 'D': doDefaultCC = FALSE; break; case 'h': Usage(0); return (0); break; case 'H': Usage(1); return (0); break; case 'l': loadProgram = atoi(optarg); break; case 'M': midnam = optarg; break; case 'r': for (k = 0; k < 9; k++) randomPreset[k] = rand () % 9; fprintf (stderr, "Random Preset: " "%d%d %d%d%d%d %d%d%d\n", randomPreset[0], randomPreset[1], randomPreset[2], randomPreset[3], randomPreset[4], randomPreset[5], randomPreset[6], randomPreset[7], randomPreset[8]); presetSelect = randomPreset; break; case 'p': alternateProgrammeFile = optarg; break; case 'P': doDefaultProgram = FALSE; break; case 'U': parse_preset(defaultPreset, optarg); break; case 'V': PrintVersion(); return(0); default: fprintf(stderr, "invalid argument.\n"); Usage(0); return(1); } } for (i = optind; i < argc; ++i) { char * av = argv[i]; if (strchr (av, '=') != NULL) { /* Remember this as a config parameter */ if (configOverEnd < NOF_CFG_OVERS) { configOverride[configOverEnd++] = av; } else { fprintf (stderr, "Too many configuration parameters (%d), please consider using a\n" "configuration file instead of the commandline.\n", NOF_CFG_OVERS); return(1); } } } /* * allocate data structures, instances. */ allocAll(); /* * evaluate configuration */ if (getenv("XDG_CONFIG_HOME")) { size_t hl = strlen(getenv("XDG_CONFIG_HOME")); defaultConfigFile=(char*) malloc(hl+32); defaultProgrammeFile=(char*) malloc(hl+32); sprintf(defaultConfigFile, "%s/setBfree/default.cfg", getenv("XDG_CONFIG_HOME")); sprintf(defaultProgrammeFile, "%s/setBfree/default.pgm", getenv("XDG_CONFIG_HOME")); } else if (getenv("HOME")) { size_t hl = strlen(getenv("HOME")); defaultConfigFile=(char*) malloc(hl+30); defaultProgrammeFile=(char*) malloc(hl+30); sprintf(defaultConfigFile, "%s/.config/setBfree/default.cfg", getenv("HOME")); sprintf(defaultProgrammeFile, "%s/.config/setBfree/default.pgm", getenv("HOME")); } /* * Here we call modules that need to execute code in order to arrange * static initializations that is not practical to achieve in source code. */ initControllerTable (inst.midicfg); if (doDefaultCC) { midiPrimeControllerMapping (inst.midicfg); } /* * Commandline arguments are parsed. If we are of a mind to try the * default configuration file we do that now. */ if (doDefaultConfig == TRUE && defaultConfigFile) { if (access (defaultConfigFile, R_OK) == 0) { fprintf(stderr, "loading cfg: %s\n", defaultConfigFile); parseConfigurationFile (&inst, defaultConfigFile); } } if (alternateConfigFile) { if (access (alternateConfigFile, R_OK) == 0) { fprintf(stderr, "loading cfg: %s\n", alternateConfigFile); parseConfigurationFile (&inst, alternateConfigFile); } } /* * Then apply any configuration parameters collected from the commandline. * These must be applied last so that they can override the parameters * read from the files (if any). */ for (i = 0; i < configOverEnd; i++) { parseConfigurationLine (&inst, "commandline argument", 0, configOverride[i]); } /* * Having configured the initialization phase we can now actually do it. */ #ifndef _WIN32 if (mlockall (MCL_CURRENT | MCL_FUTURE)) { fprintf(stderr, "Warning: Can not lock memory.\n"); } #endif initAll (); /* * We are initialized and now load the programme file. */ if (doDefaultProgram == TRUE && defaultProgrammeFile) { if (access (defaultProgrammeFile, R_OK) == 0) loadProgrammeFile (inst.progs, defaultProgrammeFile); } else { walkProgrammes(inst.progs, 1); // clear built-in default program } if (alternateProgrammeFile != NULL) loadProgrammeFile (inst.progs, alternateProgrammeFile); if (walkProgrammes(inst.progs, 0)) { listProgrammes (inst.progs, stderr); } initMidiTables(inst.midicfg); if (printCCTable) { listCCAssignments(inst.midicfg, stderr); } if (midnam) { FILE *fp = fopen(midnam, "w"); if (fp) { save_midname(&inst, fp); fclose(fp); } else { fprintf(stderr, "failed to write midnam to '%s'\n", midnam); } } /* * With the programmes eager and ready to go, we spawn off the MIDI * listener thread. The thread will initialize the MIDI device. */ #ifdef HAVE_ASEQ pthread_t t_midi; if (!use_jack_midi) { if (!aseq_open(midi_port)) { k = pthread_create(&t_midi, NULL, aseq_run, &inst); if (k != 0) { fprintf (stderr, "%d : %s\n", k, "pthread_create : MIDIInReader thread"); return (1); } } else { return (1); } } #endif setMIDINoteShift (inst.midicfg, 0); setDrawBars (&inst, 0, presetSelect); #if 0 // initial values are assigned in tonegen.c initToneGenerator() setDrawBars (&inst, 1, presetSelect); /* 838 000 000 */ setDrawBars (&inst, 2, presetSelect); /* 86 - */ #endif const int pgm_off = inst.progs->MIDIControllerPgmOffset; if (loadProgram >= 0 && loadProgram >= pgm_off) { installProgram(&inst, (loadProgram - pgm_off)); } #ifndef _WIN32 signal (SIGHUP, catchsig); signal (SIGINT, catchsig); #endif connect_jack_ports(); synth_ready = 1; fprintf(stderr,"All systems go. press CTRL-C, or send SIGINT or SIGHUP to terminate\n"); while (j_client) /* jack callback is doing this the work now */ #ifdef _WIN32 Sleep (1000); #else sleep (1); #endif /* shutdown and cleanup */ #ifdef HAVE_ASEQ if (!use_jack_midi) { aseq_stop=1; pthread_join(t_midi, NULL); aseq_close(); } #endif free(defaultConfigFile); free(defaultProgrammeFile); free(j_output_bufferptrs); free(j_output_port); free(midi_port); free(jack_ports); for (i=0;i<AUDIO_CHANNELS; i++) free(jack_port[i]); freeAll(); #ifndef _WIN32 munlockall(); #endif fprintf(stderr, "bye\n"); return 0; }