// c'tor: starts app by adding an initial window: NanoDotApp::NanoDotApp() : BApplication("application/x-vnd.eamoon-nanodot-r1"), m_pMidiSynth(NULL) { // initialize synth: initSynth(); // get a list of available ports: enumeratePorts(); // add first window: addWindow(new NanoDotWindow()); }
enum plugin_status plugin_start(const void* parameter) { int retval = 0; PLUGIN_IRAM_INIT(rb) rb->lcd_setfont(0); #if defined(HAVE_ADJUSTABLE_CPU_FREQ) rb->cpu_boost(true); #endif #ifdef RB_PROFILE rb->profile_thread(); #endif if (initSynth(NULL, ROCKBOX_DIR "/patchset/patchset.cfg", ROCKBOX_DIR "/patchset/drums.cfg") == -1) { printf("\nINIT ERROR\n"); return -1; } //#ifndef SIMULATOR rb->pcm_play_stop(); #if INPUT_SRC_CAPS != 0 /* Select playback */ rb->audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK); rb->audio_set_output_source(AUDIO_SRC_PLAYBACK); #endif rb->pcm_set_frequency(SAMPLE_RATE); // 44100 22050 11025 retval = beatboxmain(); #ifdef RB_PROFILE rb->profstop(); #endif rb->pcm_play_stop(); rb->pcm_set_frequency(HW_SAMPR_DEFAULT); #if defined(HAVE_ADJUSTABLE_CPU_FREQ) rb->cpu_boost(false); #endif if(retval == -1) return PLUGIN_ERROR; return PLUGIN_OK; }
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; }
static LV2_State_Status restore(LV2_Handle instance, LV2_State_Retrieve_Function retrieve, LV2_State_Handle handle, uint32_t flags, const LV2_Feature* const* features) { B3S* b3s = (B3S*)instance; size_t size; uint32_t type; uint32_t valflags; const void* value = retrieve(handle, b3s->uris.sb3_state, &size, &type, &valflags); if (!value) { return LV2_STATE_ERR_UNKNOWN; } if (b3s->inst_offline) { fprintf(stderr, "B3LV2: restore ignored. re-init in progress\n"); return LV2_STATE_ERR_UNKNOWN; } b3s->inst_offline = (b_instance*) calloc(1, sizeof(struct b_instance)); allocSynth(b3s->inst_offline); const char* cfg = (const char*)value; const char *te, *ts = cfg; LOCALEGUARD_START; /* pass1 - evaulate CFG -- before initializing synth */ while (ts && *ts && (te=strchr(ts, '\n'))) { char *val; char kv[1024]; memcpy(kv, ts, te-ts); kv[te-ts]=0; #ifdef DEBUGPRINT fprintf(stderr, "B3LV2 CFG Pass1: %s\n", kv); #endif if(kv[0]=='C' && (val=strchr(kv,'='))) { *val=0; #ifdef DEBUGPRINT fprintf(stderr, "B3LV2: evaluateConfigKeyValue(..,\"%s\", \"%s\");\n", kv+2, val+1); #endif evaluateConfigKeyValue((void*)b3s->inst_offline, kv+2, val+1); } else if(kv[0]=='P') { #ifdef DEBUGPRINT printf("PGM '%s'\n", kv+2); #endif loadProgrammeString(b3s->inst_offline->progs, kv+2); } ts=te+1; } initSynth(b3s->inst_offline, SampleRateD); /* pass2 - replay CC's after initializing synth */ ts = cfg; while (ts && *ts && (te=strchr(ts, '\n'))) { char *val; char kv[1024]; memcpy(kv, ts, te-ts); kv[te-ts]=0; #ifdef DEBUGPRINT fprintf(stderr, "B3LV2 CFG Pass2: %s\n", kv); #endif if(kv[0]=='M' && (val=strchr(kv,'='))) { *val=0; #ifdef DEBUGPRINT fprintf(stderr, "B3LV2: callMIDIControlFunction(..,\"%s\", %d);\n", kv+2, atoi(val+1)); #endif callMIDIControlFunction(b3s->inst_offline->midicfg, kv+2, atoi(val+1)); } ts=te+1; } LOCALEGUARD_END; b3s->swap_instances = 1; return LV2_STATE_SUCCESS; }
static int midimain(const void * filename) { int a, notes_used, vol; bool is_playing = true; /* false = paused */ #if defined(HAVE_ADJUSTABLE_CPU_FREQ) rb->cpu_boost(true); #endif midi_debug("Loading file"); mf = loadFile(filename); if (mf == NULL) { midi_debug("Error loading file."); #if defined(HAVE_ADJUSTABLE_CPU_FREQ) rb->cpu_boost(false); #endif return -1; } if (initSynth(mf, ROCKBOX_DIR "/patchset/patchset.cfg", ROCKBOX_DIR "/patchset/drums.cfg") == -1) { #if defined(HAVE_ADJUSTABLE_CPU_FREQ) rb->cpu_boost(false); #endif return -1; } rb->pcm_play_stop(); #if INPUT_SRC_CAPS != 0 /* Select playback */ rb->audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK); rb->audio_set_output_source(AUDIO_SRC_PLAYBACK); #endif rb->pcm_set_frequency(SAMPLE_RATE); /* 44100 22050 11025 */ /* * tick() will do one MIDI clock tick. Then, there's a loop here that * will generate the right number of samples per MIDI tick. The whole * MIDI playback is timed in terms of this value.. there are no forced * delays or anything. It just produces enough samples for each tick, and * the playback of these samples is what makes the timings right. * * This seems to work quite well. On a laptop, anyway. */ midi_debug("Okay, starting sequencing"); bpm = mf->div*1000000/tempo; number_of_samples = SAMPLE_RATE/bpm; /* Skip over any junk in the beginning of the file, so start playing */ /* after the first note event */ do { notes_used = 0; for (a = 0; a < MAX_VOICES; a++) if (voices[a].isUsed) notes_used++; tick(); } while (notes_used == 0); #if defined(HAVE_ADJUSTABLE_CPU_FREQ) rb->cpu_boost(false); #endif playing_time = 0; samples_this_second = 0; synthbuf(); rb->pcm_play_data(&get_more, NULL, NULL, 0); while (!quit) { #ifndef SYNC synthbuf(); #endif rb->yield(); /* Prevent idle poweroff */ rb->reset_poweroff_timer(); /* Code taken from Oscilloscope plugin */ switch (rb->button_get(false)) { case MIDI_VOL_UP: case MIDI_VOL_UP | BUTTON_REPEAT: { vol = rb->global_settings->volume; if (vol < rb->sound_max(SOUND_VOLUME)) { vol++; rb->sound_set(SOUND_VOLUME, vol); rb->global_settings->volume = vol; } break; } case MIDI_VOL_DOWN: case MIDI_VOL_DOWN | BUTTON_REPEAT: { vol = rb->global_settings->volume; if (vol > rb->sound_min(SOUND_VOLUME)) { vol--; rb->sound_set(SOUND_VOLUME, vol); rb->global_settings->volume = vol; } break; } case MIDI_REWIND: { /* Rewinding is tricky. Basically start the file over */ /* but run through the tracks without the synth running */ rb->pcm_play_stop(); #if defined(HAVE_ADJUSTABLE_CPU_FREQ) rb->cpu_boost(true); #endif seekBackward(5); #if defined(HAVE_ADJUSTABLE_CPU_FREQ) rb->cpu_boost(false); #endif lastswap = !swap; synthbuf(); midi_debug("Rewind to %d:%02d\n", playing_time/60, playing_time%60); if (is_playing) rb->pcm_play_data(&get_more, NULL, NULL, 0); break; } case MIDI_FFWD: { rb->pcm_play_stop(); seekForward(5); lastswap = !swap; synthbuf(); midi_debug("Skip to %d:%02d\n", playing_time/60, playing_time%60); if (is_playing) rb->pcm_play_data(&get_more, NULL, NULL, 0); break; } case MIDI_PLAYPAUSE: { if (is_playing) { midi_debug("Paused at %d:%02d\n", playing_time/60, playing_time%60); is_playing = false; rb->pcm_play_stop(); } else { midi_debug("Playing from %d:%02d\n", playing_time/60, playing_time%60); is_playing = true; rb->pcm_play_data(&get_more, NULL, NULL, 0); } break; } #ifdef MIDI_RC_QUIT case MIDI_RC_QUIT: #endif case MIDI_QUIT: quit = true; } } return 0; }
int midimain(void * filename) { printf("\nHello.\n"); rb->splash(HZ/5, true, "LOADING MIDI"); struct MIDIfile * mf = loadFile(filename); rb->splash(HZ/5, true, "LOADING PATCHES"); if (initSynth(mf, "/.rockbox/patchset/patchset.cfg", "/.rockbox/patchset/drums.cfg") == -1) { return -1; } /* * This lets you hear the music through the sound card if you are on Simulator * Make a symlink, archos/dsp.raw and make it point to /dev/dsp or whatever * your sound device is. */ #if defined(LOCAL_DSP) fd=rb->open("/dsp.raw", O_WRONLY); int arg, status; int bit, samp, ch; arg = 16; /* sample size */ status = ioctl(fd, SOUND_PCM_WRITE_BITS, &arg); status = ioctl(fd, SOUND_PCM_READ_BITS, &arg); bit=arg; arg = 2; /* Number of channels, 1=mono */ status = ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &arg); status = ioctl(fd, SOUND_PCM_READ_CHANNELS, &arg); ch=arg; arg = SAMPLE_RATE; /* Yeah. sampling rate */ status = ioctl(fd, SOUND_PCM_WRITE_RATE, &arg); status = ioctl(fd, SOUND_PCM_READ_RATE, &arg); samp=arg; #else /* xxx2wav stuff, removed for now, will move to the real way of outputting sound soon */ /* file_info_struct file_info; file_info.samplerate = SAMPLE_RATE; file_info.infile = fd; file_info.channels = 2; file_info.bitspersample = 16; local_init("/miditest.tmp", "/miditest.wav", &file_info, rb); fd = file_info.outfile; */ #endif rb->splash(HZ/5, true, " I hope this works... "); /* * tick() will do one MIDI clock tick. Then, there's a loop here that * will generate the right number of samples per MIDI tick. The whole * MIDI playback is timed in terms of this value.. there are no forced * delays or anything. It just produces enough samples for each tick, and * the playback of these samples is what makes the timings right. * * This seems to work quite well. */ printf("\nOkay, starting sequencing"); currentSample=0; /* Sample counting variable */ outputBufferPosition = 0; bpm=mf->div*1000000/tempo; numberOfSamples=SAMPLE_RATE/bpm; /* Tick() will return 0 if there are no more events left to play */ while(tick(mf)) { /* * Tempo recalculation moved to sequencer.c to be done on a tempo event only * */ for(currentSample=0; currentSample<numberOfSamples; currentSample++) { synthSample(&outputSampleOne, &outputSampleTwo); /* * 16-bit audio because, well, it's better * But really because ALSA's OSS emulation sounds extremely * noisy and distorted when in 8-bit mode. I still do not know * why this happens. */ outputBuffer[outputBufferPosition]=outputSampleOne&0XFF; // Low byte first outputBufferPosition++; outputBuffer[outputBufferPosition]=outputSampleOne>>8; //High byte second outputBufferPosition++; outputBuffer[outputBufferPosition]=outputSampleTwo&0XFF; // Low byte first outputBufferPosition++; outputBuffer[outputBufferPosition]=outputSampleTwo>>8; //High byte second outputBufferPosition++; /* * As soon as we produce 2000 bytes of sound, * write it to the sound card. Why 2000? I have * no idea. It's 1 AM and I am dead tired. */ if(outputBufferPosition>=2000) { rb->write(fd, outputBuffer, 2000); outputBufferPosition=0; } } } printf("\n"); #if !defined(LOCAL_DSP) /* again, xxx2wav stuff, removed for now */ /* close_wav(&file_info); */ #else rb->close(fd); #endif return 0; }