feat: add editable internal instruments, automation and versioned presets

This commit is contained in:
Johannes Findeisen 2026-11-05 23:47:54 +01:00
commit 159fa939a1
21 changed files with 295 additions and 52 deletions

View file

@ -147,7 +147,47 @@ static void transport(unsigned int id)
assert(!memcmp(x,y,sizeof(x)));
xtc_midi_plan_destroy(plan);xtc_midi_plan_destroy(fresh);xtc_project_destroy(project);
}
static void editable(void)
{
xtc_plugin_spec s,legacy,t;xtc_plugin *a=NULL,*b=NULL;float x[256],y[256];size_t k;
xtc_midi_event events[]={{0,XTC_MIDI_NOTE_ON,0,60,100},{64,XTC_MIDI_BEND,0,0,127}};
char path[]="/tmp/xtc-preset-XXXXXX";int fd=mkstemp(path);assert(fd>=0);close(fd);
assert(xtc_plugin_probe(XTC_BUILTIN_PATH,0,48000,&s)==XTC_OK && s.control_count==5);
legacy=s;legacy.control_count=0;
assert(xtc_plugin_create(&s,48000,256,&a)==XTC_OK && xtc_plugin_create(&legacy,48000,256,&b)==XTC_OK);
assert(xtc_plugin_process_midi(a,events,1,x,256)==XTC_OK && xtc_plugin_process_midi(b,events,1,y,256)==XTC_OK);
assert(!memcmp(x,y,sizeof(x)));xtc_plugin_destroy(a);xtc_plugin_destroy(b);
assert(xtc_plugin_create(&s,48000,256,&a)==XTC_OK && xtc_plugin_create(&s,48000,256,&b)==XTC_OK);
assert(xtc_plugin_process_midi(a,events,2,x,256)==XTC_OK && xtc_plugin_process_midi(b,events,1,y,256)==XTC_OK);
assert(!memcmp(x,y,64*sizeof(float)) && memcmp(x+65,y+65,191*sizeof(float)));
xtc_plugin_destroy(a);xtc_plugin_destroy(b);
/* Migrate an actual v13 fixed-preset binding; no new records existed there. */
assert(xtc_plugin_preset_save(&legacy,path)==XTC_OK);
{FILE *f=fopen(path,"r");char lines[32768],line[2048];size_t used=0;assert(f);
while(fgets(line,sizeof(line),f)) {
if(!strncmp(line,"INSTRUMENT_CONTROLS",19) || !strncmp(line,"INSTRUMENT_AUTOMATION",21))continue;
if(!strncmp(line,"XTC_PROJECT 14",14))strcpy(line,"XTC_PROJECT 13\n");
assert(used+strlen(line)<sizeof(lines));strcpy(lines+used,line);used+=strlen(line);
}fclose(f);f=fopen(path,"w");assert(f && fwrite(lines,1,used,f)==used);fclose(f);}
assert(xtc_plugin_preset_load(path,&t)==XTC_OK && !t.control_count && t.index==0);
s.values[3]=700;s.values[1]=100;s.values[2]=400;
s.point_count=2;s.points[0]=(xtc_plugin_point){0,0,0,0};s.points[1]=(xtc_plugin_point){100,0,0,1};
assert(xtc_plugin_preset_save(&s,path)==XTC_OK && xtc_plugin_preset_load(path,&t)==XTC_OK);
assert(!memcmp(s.values,t.values,sizeof(s.values)) && t.point_count==2);
assert(xtc_plugin_create(&s,48000,256,&a)==XTC_OK && xtc_plugin_create(&t,48000,256,&b)==XTC_OK);
for(k=0;k<200;++k) {
assert(xtc_plugin_process_midi(a,events,k==0 ? 2 : 0,x,256)==XTC_OK);
assert(xtc_plugin_process_midi(b,events,k==0 ? 2 : 0,y,128)==XTC_OK);
assert(xtc_plugin_process_midi(b,NULL,0,y+128,128)==XTC_OK);
assert(!memcmp(x,y,sizeof(x)));
}
xtc_plugin_destroy(a);xtc_plugin_destroy(b);
s.values[3]=NAN;assert(xtc_plugin_spec_validate(&s)!=XTC_OK);
{unsigned char bend[]={0xe3,0,64};xtc_midi_event e;
assert(xtc_midi_decode(bend,3,7,&e)==XTC_OK && e.type==XTC_MIDI_BEND && e.channel==3 && e.velocity==64);}
unlink(path);
}
int main(void) {
transport(0);transport(1);automation();roundtrip(0,2);roundtrip(1,3);effects(2);effects(3);synth(0);synth(1);
editable();transport(0);transport(1);automation();roundtrip(0,2);roundtrip(1,3);effects(2);effects(3);synth(0);synth(1);
synth_partition(0);synth_partition(1);puts("Built-in devices passed.");return 0;
}