@*Intro. The automated sequencing system of Organ Acusticum in Pite{\aa}, Sweden, is able to store its combination settings in a USB stick. Those settings, for a piece named \.{foo}, appear on the stick in a file named \.{foo.xst}. That file represents the information as hexadecimal codes using an internal XML format called \.{Setter}, which was defined as part of the software made for the organ by the firm of Otto Heu{\ss}. This program reads such a file (|stdin|) and translates it into human-readable form (|stdout|). @d bufsize 80 @c #include #include #include unsigned long long data[10000][4]; char buf[bufsize]; char title[bufsize]; char stop[209][32]=@; int codepos[209]=@; main() { register int d,i,ii,j,k,count,t=0,endfound=0; register unsigned long acc; @; @; } @*The repertoire of stops. The stop names include some accented letters; my compiler handles them by using the UTF-8 encoding behind the scenes. This seems to work with lots of my software, including \.{emacs} and \.{lpr} on my local Linux system, but not with \.{more} or with \TeX. @= { "", @, /* 1--39 */ @, /* 40--104 */ @, /* 105--143 */ @, /* 144--169 */ @ /* 170--208 */ } @ @= "I Bordun 32", /* 001 */ "I Principal 16", /* 002 */ "I Bordun 16", /* 003 */ "I Principal 8", /* 004 */ "I Flûte harm. 8", /* 005 */ "I Violoncelle 8", /* 006 */ "I Viola da Gamba 8", /* 007 */ "I Rohrflöte 8", /* 008 */ "I Groß Quinte 5 1/3", /* 009 */ "I Octave 4", /* 010 */ "I Flöte 4", /* 011 */ "I Gross Tierce 3 1/5", /* 012 */ "I Quinte 2 2/3", /* 013 */ "I Octave 2", /* 014 */ "I Flöte 2", /* 015 */ "I Sesquialtera 3fach", /* 016 */ "I Cornet Progressio 5fach", /* 017 */ "I Gross Cornet 8fach", /* 018 */ "I Gross Mixtur 6fach", /* 019 */ "I Mixtur 4fach", /* 020 */ "I Cimbel 3fach", /* 021 */ "I Trompete 16", /* 022 */ "I Trompete 8", /* 023 */ "I Bombarde 16", /* 024 */ "I Trompette 8", /* 025 */ "I Clairon 4", /* 026 */ "I Tuba mirabilis 8", /* 027 */ "I Corno 4", /* 028 */ "I Trompette en chamade 8", /* 029 */ "I Tremulant I", /* 030 */ "I (031)", /* 031 */ "I (032)", /* 032 */ "II-I", /* 033 */ "III-I", /* 034 */ "IV-I", /* 035 */ "I/16", /* 036 */ "II-I/16", /* 037 */ "III-I/16", /* 038 */ "IV-I/16" /* 039 */ @ @= "P Infrabaß 64", /* 040 */ "P Untersatz 32", /* 041 */ "P Groß Bordun 32", /* 042 */ "P Salicetbaß 32", /* 043 */ "P Principal 16", /* 044 */ "P Kontrabaß 16", /* 045 */ "P Subbaß 16", /* 046 */ "P Violon 16", /* 047 */ "P Gedacktbaß 16", /* 048 */ "P Quintbaß 10 2/3", /* 049 */ "P Octavbaß 8", /* 050 */ "P Flöte 8", /* 051 */ "P Cello 8", /* 052 */ "P Gedackt 8", /* 053 */ "P Terzbaß 6 2/5", /* 054 */ "P Quinte 5 1/3", /* 055 */ "P Octave 4", /* 056 */ "P Flöte 4", /* 057 */ "P Violine 4", /* 058 */ "P Flöte douce 4", /* 059 */ "P Terz 3 1/5", /* 060 */ "P Quinte 2 2/3", /* 061 */ "P Flöte 2", /* 062 */ "P Violine 2", /* 063 */ "P Terz 1 3/5", /* 064 */ "P Quinte 1 1/3", /* 065 */ "P Bauernflöte 1", /* 066 */ "P Contra Cornet 5fach", /* 067 */ "P Bass Cornet 8fach", /* 068 */ "P Mixtur 4-6fach", /* 069 */ "P Groß Posaune 32", /* 070 */ "P Posaune 16", /* 071 */ "P Trompete 8", /* 072 */ "P Bombarde 16", /* 073 */ "P Trompete 4", /* 074 */ "P Clairon 4", /* 075 */ "P Tuba mirabilis 8", /* 076 */ "P Corno 4", /* 077 */ "P Chamade 4", /* 078 */ "P Trompette en chamade 2", /* 079 */ "P Basson 16", /* 080 */ "P Fagott 8", /* 081 */ "P Cornetto 4", /* 082 */ "P (prepared)", /* 083 */ "P Glocken 4", /* 084 */ "P (085)", /* 085 */ "P (086)", /* 086 */ "I-P", /* 087 */ "II-P", /* 088 */ "III-I", /* 089 */ "IV-I", /* 090 */ "(prepared)", /* 091 */ "P Trommelwirbel A", /* 092 */ "P Paukenwirbel A#", /* 093 */ "P Gran Cassa H", /* 094 */ "Klangplatten", /* 095 */ "Winddrossel I Baß", /* 096 */ "Winddrossel I Diskant", /* 097 */ "Winddrossel III Baß", /* 098 */ "Winddrossel III Diskant", /* 099 */ "Winddrossel gesamt", /* 100 */ "MIDI", /* 101 */ "klassischer Wind", /* 102 */ "Licht", /* 103 */ "Crescendo" /* 104 */ @ @= "IV Gamba 16", /* 105 */ "IV Bordun 16", /* 106 */ "IV Doppelflöte 8", /* 107 */ "IV Violoncello 8", /* 108 */ "IV Voix celeste 8", /* 109 */ "IV Viole d'orchestre 3fach", /* 110 */ "IV Bordun 8", /* 111 */ "IV Flöte 4", /* 112 */ "IV Viola 4", /* 113 */ "IV Flöte 2", /* 114 */ "IV Violone 2", /* 115 */ "IV Solo Cornet 6-10fach", /* 116 */ "IV Carillon 4fach", /* 117 */ "IV Bombarde 16", /* 118 */ "IV Trompette 8", /* 119 */ "IV Tuba mirabilis 16", /* 120 */ "IV Tuba mirabilis 8", /* 121 */ "IV Trompette en chamade 8", /* 122 */ "IV Corno 4", /* 123 */ "IV Clarinette 16", /* 124 */ "IV Clarinette 8", /* 125 */ "IV (prepared)", /* 126 */ "IV Tremulant stark", /* 127 */ "IV (128)", /* 128 */ "IV (129)", /* 129 */ "IV (130)", /* 130 */ "IV/16", /* 131 */ "IV/4", /* 132 */ "IV (133)", /* 133 */ "IV Glocken 8", /* 134 */ "IV Celesta 8", /* 135 */ "IV Vibraphon 8", /* 136 */ "IV (137)", /* 137 */ "IV (138)", /* 138 */ "IV (139)", /* 139 */ "IV Glockengeläute", /* 140 */ "IV Zimbelstern stärker", /* 141 */ "IV Zimbelstern leiser", /* 142 */ "IV Vogelgeschrei" /* 143 */ @ @= "III Bourdon 16", /* 144 */ "III Diapason 8", /* 145 */ "III Flûte traversière 8", /* 146 */ "III Viole de Gambe 8", /* 147 */ "III Voix céleste 8", /* 148 */ "III Cor de nuit 8", /* 149 */ "III Flûte octaviante 4", /* 150 */ "III Dulciane 4", /* 151 */ "III Quinte 2 2/3", /* 152 */ "III Octavin 2", /* 153 */ "III Tierce harm. 1 3/5", /* 154 */ "III Septième harm. 1 1/7", /* 155 */ "III None harm. 8/9", /* 156 */ "IV-III", /* 157 */ "III/16", /* 158 */ "IV-III/16", /* 159 */ "III (160)", /* 160 */ "III Cymbale 3fach", /* 161 */ "III Bombarde 16", /* 162 */ "III Trompette harm. 8", /* 163 */ "III Clairon harm. 4", /* 164 */ "III Basson Hautbois 8", /* 165 */ "III Voix humaine 8", /* 166 */ "III Tremblant fort III", /* 167 */ "III (168)", /* 168 */ "III (169)" /* 169 */ @ @= "II Quintatön 16", /* 170 */ "II Salicional 16", /* 171 */ "II Principal 8", /* 172 */ "II Gemshorn 8", /* 173 */ "II Unda maris 8", /* 174 */ "II Salicional 8", /* 175 */ "II Konzertflöte 8", /* 176 */ "II Flauto 8", /* 177 */ "II Flauto douce 8", /* 178 */ "II Quintatön 8", /* 179 */ "II Gedackt 8", /* 180 */ "II Octave 4", /* 181 */ "II Hohlflöte 4", /* 182 */ "II Viola alto 4", /* 183 */ "II Nazard 2 2/3", /* 184 */ "II Octave 2", /* 185 */ "II Blockflöte 2", /* 186 */ "II Violine 2", /* 187 */ "II Terz 1 3/5", /* 188 */ "II Larigot 1 1/3", /* 189 */ "II Sifflöte 1", /* 190 */ "II Carillon 3fach", /* 191 */ "II Sesquialtera 2fach", /* 192 */ "II Mixtur 4fach", /* 193 */ "II Cimbel 3fach", /* 194 */ "II (195)", /* 195 */ "I-II", /* 196 */ "III-II", /* 197 */ "IV-II", /* 198 */ "II/16", /* 199 */ "III-II/16", /* 200 */ "IV-II/16", /* 201 */ "II (202)", /* 202 */ "II Fagott 16", /* 203 */ "II Fagott 8", /* 204 */ "II Trompete 8", /* 205 */ "II Krummhorn 8", /* 206 */ "II Tremulant II", /* 207 */ "II Klangklappen auf" /* 208 */ @*The input phase. @ @= for (i=1;!endfound;i++) { if (!fgets(buf,bufsize,stdin)) break; switch (i) { case 1: @;@+break; case 2: @;@+break; case 3: @;@+break; case 4: @@+break; default:@+if (strncmp(buf,"",8)==0) endfound=1; else @; } } if (!endfound) { printf("Error! The input file ended prematurely after %d lines!\n", i-1); exit(-1); } @ @d check(ss) if (strncmp(buf,ss,strlen(ss))!=0) { printf("Error! Line %d of the input should have been `%s'\n but it was %s", i,ss,buf); exit(-2); } @ @= check(""); @ @= check(""); @ @<Check for the \.{NAME} line@>= check(" <NAME>"); for (j=7;buf[j] && buf[j]!='\n' && buf[j]!='<';j++) title[j-7]=buf[j]; if (buf[j]!='<') { printf("Error! Line %d of the input should have been <NAME>...</NAME>\n", i); printf(" but it was %s", buf); exit(-3); } @ @<Check for the \.{COUNT} line@>= check(" <COUNT>"); for (j=8,count=0;buf[j]>='0' && buf[j]<='9';j++) count=count*10+buf[j]-'0'; if (buf[j]!='<') { printf("Error! Line %d of the input should have had </COUNT>\n but it was %s", i,buf); exit(-4); } @ @<Input a five-line \.{CMB} entry@>= check(" <CMB>"); for (ii=1;ii<=4;ii++) { if (!fgets(buf,bufsize,stdin)) break; i++; switch (ii) { case 1: @<Check for the \.{ID} line@>;@+break; case 2: @<Check for the \.{REGLEN} line@>;@+break; case 3: @<Check for the \.{REG} line@>;@+break; default: @<Check for the \.{/CMB} line@>; t++; /* |t| is the number of combinations found so far */ } } @ @<Check for the \.{ID} line@>= check(" <ID>"); for (j=6,d=0;buf[j]>='0' && buf[j]<='9';j++) d=d*10+buf[j]-'0'; if (buf[j]!='<') { printf("Error! Line %d of the input should have had </ID>\n but it was %s", i,buf); exit(-6); } if (data[d][0]) { printf("Error! Preset combination %d has already appeared!\n line %d is %s", d,i,buf); exit(-5); } @ @<Check for the \.{REGLEN} line@>= check(" <REGLEN>26</REGLEN>"); @ @<Check for the \.{REG} line@>= check(" <REG>"); for (j=7,k=0,acc=0xffffffffffff;j<59;j++) { if (buf[j]>='0' && buf[j]<='9') acc<<=4,acc+=buf[j]-'0'; else if (buf[j]>='a' && buf[j]<='f') acc<<=4,acc+=buf[j]-'a'+10; else break; if ((j&0xf)==10) data[d][k]=acc,k++,acc=0; } if (j!=59 || strncmp(buf+59,"</REG>",6)!=0) { printf("Error! Line %d of the input should have been <REG>...</REG>\n", i); printf(" with 52 hexadecimal digits, but it was %s", buf); exit(-7); } @ @<Check for the \.{/CMB} line@>= check(" </CMB>"); @*The output phase. @<Output the translation@>= printf("Combinations for `%s':\n", title); if (t!=count) { fprintf(stderr,"(Warning: The file specified %d combinations,", t); fprintf(stderr," but said there would be %d!)\n", count); } for (k=0;k<10000;k++) if (data[k][0]) @<Output combination number |k|@>; @ @<Output combination number |k|@>= { printf("%04d:\n", k); for (j=1;j<=208;j++) { t=codepos[j]; if (data[k][t>>6]&(1LL<<(t&0x3f))) printf(" %03d %s\n", j,stop[j]); } } @ The internal wiring of the organ isn't quite consistent with the order of the stops shown on the console. Thus the following table isn't as predictable as one might expect. (Many of the stops cannot actually be activated as part of a combination. This program doesn't check for such anomalies. But the companion program {\mc TXTTOXST} does make sure that no improper stop codes get into an \.{xst}~file.) @<Code positions of the stops@>= { 16,@/ 8,9,10,11,12,13,15,14,@/ 0,1,2,3,4,5,6,7,@/ 120,121,122,123,124,125,126,127,@/ 112,113,114,115,116,117,118,119,@/ 104,105,106,107,108,109,110,111,@/ 96,97,98,99,100,101,102,103,@/ 88,89,90,91,92,93,94,95,@/ 80,81,82,83,84,85,86,87,@/ 72,73,74,75,76,77,78,79,@/ 64,65,66,67,68,69,70,71,@/ 184,185,186,187,188,189,190,191,@/ 176,177,178,179,180,181,182,183,@/ 168,169,170,171,172,173,174,175,@/ 160,161,162,163,164,165,166,167,@/ 152,153,154,155,156,157,158,159,@/ 144,145,146,147,148,149,150,151,@/ 136,137,138,139,140,141,142,143,@/ 128,129,130,131,132,133,134,135,@/ 248,249,250,251,252,253,254,255,@/ 240,241,242,243,244,245,246,247,@/ 232,233,234,235,236,237,238,239,@/ 224,225,226,227,228,229,230,231,@/ 216,217,218,219,220,221,222,223,@/ 208,209,210,211,212,213,214,215,@/ 200,201,202,203,204,205,206,207,@/ 192,193,194,195,196,197,198,199 } @*Index.