KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > generation > XMidiGenerator


1 /*
2  * Copyright 1999-2002,2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.cocoon.generation;
17
18 import java.io.IOException JavaDoc;
19 import java.io.InputStream JavaDoc;
20 import java.util.Hashtable JavaDoc;
21 import java.util.Map JavaDoc;
22
23 import org.apache.avalon.framework.parameters.ParameterException;
24 import org.apache.avalon.framework.parameters.Parameterizable;
25 import org.apache.avalon.framework.parameters.Parameters;
26 import org.apache.cocoon.ProcessingException;
27 import org.apache.cocoon.components.midi.xmidi.ByteLen;
28 import org.apache.cocoon.components.midi.xmidi.Utils;
29 import org.apache.cocoon.components.midi.xmidi.Constants;
30 import org.apache.cocoon.components.source.SourceUtil;
31 import org.apache.cocoon.environment.SourceResolver;
32 import org.apache.excalibur.source.Source;
33 import org.apache.excalibur.source.SourceException;
34 import org.apache.excalibur.source.SourceNotFoundException;
35 import org.apache.excalibur.source.SourceValidity;
36 import org.xml.sax.SAXException JavaDoc;
37 import org.xml.sax.helpers.AttributesImpl JavaDoc;
38
39 /**
40  * Reads a standard MIDI file and generates SAX Events.
41  *
42  * The MIDI file parsing parts of this class are based on code from the XMidi project, written
43  * by Peter Arthur Loeb (http://www.palserv.com/XMidi/) and used with permission.
44  * The warranty disclaimer of the MIT license (http://www.opensource.org/licenses/mit-license.html)
45  * applies to Peter Arthur Loeb's code.
46  *
47  * @author <a HREF="mailto:mark.leicester@energyintellect.com">Mark Leicester</a>
48  * @author <a HREF="mailto:peter@palserv.com">Peter Loeb</a>
49  */

50
51 public class XMidiGenerator
52     extends AbstractGenerator
53     implements Parameterizable {
54
55     /** The input source */
56     protected Source inputSource;
57     private boolean global_verbose;
58     private boolean local_verbose;
59
60     private static final boolean VERBOSE_DEFAULT = true;
61
62     private boolean validateVerbosity(String JavaDoc verbose) {
63         if (verbose.equalsIgnoreCase("TRUE")) {
64             return true;
65         } else if (verbose.equalsIgnoreCase("FALSE")) {
66             return false;
67         }
68         return VERBOSE_DEFAULT;
69     }
70
71     public void parameterize(Parameters parameters) throws ParameterException {
72         global_verbose = validateVerbosity(parameters.getParameter(
73                     "verbose",
74                     String.valueOf(VERBOSE_DEFAULT)));
75     }
76
77     /**
78      * Recycle this component.
79      * All instance variables are set to <code>null</code>.
80      */

81     public void recycle() {
82         if (null != this.inputSource) {
83             super.resolver.release(this.inputSource);
84             this.inputSource = null;
85         }
86         // Reinitialize variables
87
initializeVariables();
88         super.recycle();
89     }
90
91     /**
92      * Setup the MIDI file generator.
93      * Try to get the last modification date of the source for caching.
94      */

95     public void setup(SourceResolver resolver,
96                       Map JavaDoc objectModel,
97                       String JavaDoc src,
98                       Parameters par)
99     throws ProcessingException, SAXException JavaDoc, IOException JavaDoc {
100         super.setup(resolver, objectModel, src, par);
101         // Initialize lookup tables
102
initializeLookupTables();
103         try {
104             this.inputSource = resolver.resolveURI(src);
105         } catch (SourceException se) {
106             throw SourceUtil.handle("Error resolving '" + src + "'.", se);
107         }
108         local_verbose =
109             validateVerbosity(
110                 parameters.getParameter(
111                     "verbose",
112                     String.valueOf(global_verbose)));
113     }
114
115     /**
116      * Generate the unique key.
117      * This key must be unique inside the space of this component.
118      *
119      * @return The generated key hashes the src
120      */

121     public java.io.Serializable JavaDoc getKey() {
122         return this.inputSource.getURI();
123     }
124
125     /**
126      * Generate the validity object.
127      *
128      * @return The generated validity object or <code>null</code> if the
129      * component is currently not cacheable.
130      */

131     public SourceValidity getValidity() {
132         return this.inputSource.getValidity();
133     }
134
135     /**
136      * Generate XML data.
137      */

138     public void generate()
139         throws IOException JavaDoc, SAXException JavaDoc, ProcessingException {
140         try {
141             if (getLogger().isDebugEnabled()) {
142                 getLogger().debug("Source " + super.source +
143                                   " resolved to " + this.inputSource.getURI());
144             }
145
146             parseMIDI(this.inputSource);
147         } catch (SAXException JavaDoc e) {
148             SourceUtil.handleSAXException(this.inputSource.getURI(), e);
149         }
150     }
151
152     private int midiFormat;
153     private Hashtable JavaDoc ffHash;
154     private String JavaDoc[] chanArray;
155     private String JavaDoc[] fArray;
156     private int numTracks;
157     private int trkCount;
158     private String JavaDoc[] notes;
159     private int[] register;
160     private Hashtable JavaDoc contHash;
161
162     /**
163      * @param source
164      */

165     private void parseMIDI(Source source)
166     throws SAXException JavaDoc, SourceNotFoundException, IOException JavaDoc, ProcessingException {
167         InputStream JavaDoc inputStream = source.getInputStream();
168
169         AttributesImpl JavaDoc attr = new AttributesImpl JavaDoc();
170         String JavaDoc text = "";
171         this.contentHandler.startDocument();
172         attr.addAttribute("", "VERSION", "VERSION", "CDATA", Constants.VERSION);
173         this.contentHandler.startElement("", "XMidi", "XMidi", attr);
174
175         boolean chunkFlag = true;
176         while (chunkFlag) { // for each chunk
177
byte[] hdr = new byte[8];
178
179             int r;
180
181             r = inputStream.read(hdr);
182             if (r == -1) {
183                 chunkFlag = false;
184                 continue;
185             }
186             if (r < 8) {
187                 this.getLogger().debug("Getting header");
188             }
189
190             // get chunk id
191
String JavaDoc cid = Utils.baToString(hdr, 0, 3);
192
193             // get chunk length
194
int len = Utils.baToInt(hdr, 4, 7);
195
196             // get rest of chunk
197
byte[] dta = new byte[len];
198             r = inputStream.read(dta);
199             if (r < len) {
200                 throw new ProcessingException("Getting data");
201             }
202
203             if (cid.equals("MThd")) {
204                 attr.clear();
205                 attr.addAttribute("", "LENGTH", "LENGTH", "CDATA", "" + len);
206                 attr.addAttribute("", "TYPE", "TYPE", "CDATA", cid);
207                 this.contentHandler.startElement("", "MThd", "MThd", attr);
208
209                 midiFormat = Utils.baToInt(dta, 0, 1);
210                 numTracks = Utils.baToInt(dta, 2, 3);
211                 String JavaDoc pnq = Utils.baToHex(dta, 4, 5);
212
213                 attr.clear();
214
215                 this.contentHandler.startElement("", "FORMAT", "FORMAT", attr);
216                 text = "" + midiFormat;
217                 this.contentHandler.characters(
218                     text.toCharArray(),
219                     0,
220                     text.length());
221                 this.contentHandler.endElement("", "FORMAT", "FORMAT");
222
223                 this.contentHandler.startElement("", "TRACKS", "TRACKS", attr);
224                 text = "" + numTracks;
225                 this.contentHandler.characters(
226                     text.toCharArray(),
227                     0,
228                     text.length());
229                 this.contentHandler.endElement("", "TRACKS", "TRACKS");
230
231                 this.contentHandler.startElement("", "PPNQ", "PPNQ", attr);
232                 text = pnq;
233                 this.contentHandler.characters(
234                     text.toCharArray(),
235                     0,
236                     text.length());
237                 this.contentHandler.endElement("", "PPNQ", "PPNQ");
238
239                 this.contentHandler.endElement("", "MThd", "MThd");
240
241             } else if (cid.equals("MTrk")) {
242                 trkCount++;
243                 if (trkCount > numTracks) {
244                     throw new ProcessingException("too many tracks");
245                 }
246                 attr.clear();
247                 attr.addAttribute("", "LENGTH", "LENGTH", "CDATA", "" + len);
248                 attr.addAttribute("", "TYPE", "TYPE", "CDATA", cid);
249                 this.contentHandler.startElement("", "MTrk", "MTrk", attr);
250                 doTrack(dta, len);
251                 this.contentHandler.endElement("", "MTrk", "MTrk");
252             } else {
253                 attr.clear();
254                 attr.addAttribute("", "LENGTH", "LENGTH", "CDATA", "" + len);
255                 attr.addAttribute("", "TYPE", "TYPE", "CDATA", cid);
256                 this.contentHandler.startElement("", "CHUNK", "CHUNK", attr);
257                 doHexData(dta, len);
258                 this.contentHandler.endElement("", "CHUNK", "CHUNK");
259             }
260
261         }
262
263         this.contentHandler.endElement("", "XMidi", "XMidi");
264         this.contentHandler.endDocument();
265     }
266
267     void initializeVariables() {
268         numTracks = 0;
269         trkCount = 0;
270     }
271
272     void initializeLookupTables() {
273         ffHash = new Hashtable JavaDoc();
274         ffHash.put("00", "Sequence Number");
275         ffHash.put("01", "Text");
276         ffHash.put("02", "Copyright");
277         ffHash.put("03", "Sequence/Track Name");
278         ffHash.put("04", "Instrument");
279         ffHash.put("05", "Lyric");
280         ffHash.put("06", "Marker");
281         ffHash.put("07", "Cue Point");
282         ffHash.put("20", "MIDI Channel");
283         ffHash.put("21", "MIDI Port");
284         ffHash.put("2F", "End of Track");
285         ffHash.put("51", "Tempo");
286         ffHash.put("54", "SMPTE Offset");
287         ffHash.put("58", "Time Signature");
288         ffHash.put("59", "Key Signature");
289         ffHash.put("7F", "Proprietary Event");
290
291         chanArray = new String JavaDoc[7];
292         chanArray[0] = "Note Off";
293         chanArray[1] = "Note On";
294         chanArray[2] = "After Touch";
295         chanArray[3] = "Control Change";
296         chanArray[4] = "Program Change";
297         chanArray[5] = "Channel Pressure";
298         chanArray[6] = "Pitch Wheel";
299
300         fArray = new String JavaDoc[16];
301         fArray[0] = "SYSEX";
302         fArray[1] = "MTC Quarter Frame Message";
303         fArray[2] = "Song Position Pointer";
304         fArray[3] = "Song Select";
305         fArray[4] = "Undefined";
306         fArray[5] = "Undefined";
307         fArray[6] = "Tune Request";
308         fArray[7] = "Unsupported";
309         fArray[8] = "MIDI Clock";
310         fArray[9] = "Undefined";
311         fArray[10] = "MIDI Start";
312         fArray[11] = "MIDI Continue";
313         fArray[12] = "MIDI Stop";
314         fArray[13] = "Undefined";
315         fArray[14] = "Active Sense";
316         fArray[15] = "NotUnderstood";
317
318         contHash = new Hashtable JavaDoc();
319         contHash.put("0", "Bank Select");
320         contHash.put("1", "Modulation Wheel (coarse)");
321         contHash.put("2", "Breath controller (coarse)");
322         contHash.put("4", "Foot Pedal (coarse)");
323         contHash.put("5", "Portamento Time (coarse)");
324         contHash.put("6", "Data Entry (coarse)");
325         contHash.put("7", "Volume (coarse)");
326         contHash.put("8", "Balance (coarse)");
327         contHash.put("10", "Pan position (coarse)");
328         contHash.put("11", "Expression (coarse)");
329         contHash.put("12", "Effect Control 1 (coarse)");
330         contHash.put("13", "Effect Control 2 (coarse)");
331         contHash.put("16", "General Purpose Slider 1");
332         contHash.put("17", "General Purpose Slider 2");
333         contHash.put("18", "General Purpose Slider 3");
334         contHash.put("19", "General Purpose Slider 4");
335         contHash.put("32", "Bank Select (fine)");
336         contHash.put("33", "Modulation Wheel (fine)");
337         contHash.put("34", "Breath controller (fine)");
338         contHash.put("36", "Foot Pedal (fine)");
339         contHash.put("37", "Portamento Time (fine)");
340         contHash.put("38", "Data Entry (fine)");
341         contHash.put("39", "Volume (fine)");
342         contHash.put("40", "Balance (fine)");
343         contHash.put("42", "Pan position (fine)");
344         contHash.put("43", "Expression (fine)");
345         contHash.put("44", "Effect Control 1 (fine)");
346         contHash.put("45", "Effect Control 2 (fine)");
347         contHash.put("64", "Hold Pedal (on/off)");
348         contHash.put("65", "Portamento (on/off)");
349         contHash.put("66", "Sustenuto Pedal (on/off)");
350         contHash.put("67", "Soft Pedal (on/off)");
351         contHash.put("68", "Legato Pedal (on/off)");
352         contHash.put("69", "Hold 2 Pedal (on/off)");
353         contHash.put("70", "Sound Variation");
354         contHash.put("71", "Sound Timbre");
355         contHash.put("72", "Sound Release Time");
356         contHash.put("73", "Sound Attack Time");
357         contHash.put("74", "Sound Brightness");
358         contHash.put("75", "Sound Control 6");
359         contHash.put("76", "Sound Control 7");
360         contHash.put("77", "Sound Control 8");
361         contHash.put("78", "Sound Control 9");
362         contHash.put("79", "Sound Control 10");
363         contHash.put("80", "General Purpose Button 1 (on/off)");
364         contHash.put("81", "General Purpose Button 2 (on/off)");
365         contHash.put("82", "General Purpose Button 3 (on/off)");
366         contHash.put("83", "General Purpose Button 4 (on/off)");
367         contHash.put("91", "Effects Level");
368         contHash.put("92", "Tremulo Level");
369         contHash.put("93", "Chorus Level");
370         contHash.put("94", "Celeste Level");
371         contHash.put("95", "Phaser Level");
372         contHash.put("96", "Data Button increment");
373         contHash.put("97", "Data Button decrement");
374         contHash.put("98", "Non-registered Parameter (fine)");
375         contHash.put("99", "Non-registered Parameter (coarse)");
376         contHash.put("100", "Registered Parameter (fine)");
377         contHash.put("101", "Registered Parameter (coarse)");
378         contHash.put("120", "All Sound Off");
379         contHash.put("121", "All Controllers Off");
380         contHash.put("122", "Local Keyboard (on/off)");
381         contHash.put("123", "All Notes Off");
382         contHash.put("124", "Omni Mode Off");
383         contHash.put("125", "Omni Mode On");
384         contHash.put("126", "Mono Operation");
385         contHash.put("127", "Poly Operation");
386
387         notes = new String JavaDoc[128];
388         register = new int[128];
389         notes[0] = "C";
390         register[0] = -5;
391         notes[1] = "C#";
392         register[1] = -5;
393         notes[2] = "D";
394         register[2] = -5;
395         notes[3] = "Eb";
396         register[3] = -5;
397         notes[4] = "E";
398         register[4] = -5;
399         notes[5] = "F";
400         register[5] = -5;
401         notes[6] = "F#";
402         register[6] = -5;
403         notes[7] = "G";
404         register[7] = -5;
405         notes[8] = "Ab";
406         register[8] = -5;
407         notes[9] = "A";
408         register[9] = -5;
409         notes[10] = "Bb";
410         register[10] = -5;
411         notes[11] = "B";
412         register[11] = -5;
413         notes[12] = "C";
414         register[12] = -4;
415         notes[13] = "C#";
416         register[13] = -4;
417         notes[14] = "D";
418         register[14] = -4;
419         notes[15] = "Eb";
420         register[15] = -4;
421         notes[16] = "E";
422         register[16] = -4;
423         notes[17] = "F";
424         register[17] = -4;
425         notes[18] = "F#";
426         register[18] = -4;
427         notes[19] = "G";
428         register[19] = -4;
429         notes[20] = "Ab";
430         register[20] = -4;
431         notes[21] = "A";
432         register[21] = -4;
433         notes[22] = "Bb";
434         register[22] = -4;
435         notes[23] = "B";
436         register[23] = -4;
437         notes[24] = "C";
438         register[24] = -3;
439         notes[25] = "C#";
440         register[25] = -3;
441         notes[26] = "D";
442         register[26] = -3;
443         notes[27] = "Eb";
444         register[27] = -3;
445         notes[28] = "E";
446         register[28] = -3;
447         notes[29] = "F";
448         register[29] = -3;
449         notes[30] = "F#";
450         register[30] = -3;
451         notes[31] = "G";
452         register[31] = -3;
453         notes[32] = "Ab";
454         register[32] = -3;
455         notes[33] = "A";
456         register[33] = -3;
457         notes[34] = "Bb";
458         register[34] = -3;
459         notes[35] = "B";
460         register[35] = -3;
461         notes[36] = "C";
462         register[36] = -2;
463         notes[37] = "C#";
464         register[37] = -2;
465         notes[38] = "D";
466         register[38] = -2;
467         notes[39] = "Eb";
468         register[39] = -2;
469         notes[40] = "E";
470         register[40] = -2;
471         notes[41] = "F";
472         register[41] = -2;
473         notes[42] = "F#";
474         register[42] = -2;
475         notes[43] = "G";
476         register[43] = -2;
477         notes[44] = "Ab";
478         register[44] = -2;
479         notes[45] = "A";
480         register[45] = -2;
481         notes[46] = "Bb";
482         register[46] = -2;
483         notes[47] = "B";
484         register[47] = -2;
485         notes[48] = "C";
486         register[48] = -1;
487         notes[49] = "C#";
488         register[49] = -1;
489         notes[50] = "D";
490         register[50] = -1;
491         notes[51] = "Eb";
492         register[51] = -1;
493         notes[52] = "E";
494         register[52] = -1;
495         notes[53] = "F";
496         register[53] = -1;
497         notes[54] = "F#";
498         register[54] = -1;
499         notes[55] = "G";
500         register[55] = -1;
501         notes[56] = "Ab";
502         register[56] = -1;
503         notes[57] = "A";
504         register[57] = -1;
505         notes[58] = "Bb";
506         register[58] = -1;
507         notes[59] = "B";
508         register[59] = -1;
509         notes[60] = "C";
510         register[60] = 0;
511         notes[61] = "C#";
512         register[61] = 0;
513         notes[62] = "D";
514         register[62] = 0;
515         notes[63] = "Eb";
516         register[63] = 0;
517         notes[64] = "E";
518         register[64] = 0;
519         notes[65] = "F";
520         register[65] = 0;
521         notes[66] = "F#";
522         register[66] = 0;
523         notes[67] = "G";
524         register[67] = 0;
525         notes[68] = "Ab";
526         register[68] = 0;
527         notes[69] = "A";
528         register[69] = 0;
529         notes[70] = "Bb";
530         register[70] = 0;
531         notes[71] = "B";
532         register[71] = 0;
533         notes[72] = "C";
534         register[72] = 1;
535         notes[73] = "C#";
536         register[73] = 1;
537         notes[74] = "D";
538         register[74] = 1;
539         notes[75] = "Eb";
540         register[75] = 1;
541         notes[76] = "E";
542         register[76] = 1;
543         notes[77] = "F";
544         register[77] = 1;
545         notes[78] = "F#";
546         register[78] = 1;
547         notes[79] = "G";
548         register[79] = 1;
549         notes[80] = "Ab";
550         register[80] = 1;
551         notes[81] = "A";
552         register[81] = 1;
553         notes[82] = "Bb";
554         register[82] = 1;
555         notes[83] = "B";
556         register[83] = 1;
557         notes[84] = "C";
558         register[84] = 2;
559         notes[85] = "C#";
560         register[85] = 2;
561         notes[86] = "D";
562         register[86] = 2;
563         notes[87] = "Eb";
564         register[87] = 2;
565         notes[88] = "E";
566         register[88] = 2;
567         notes[89] = "F";
568         register[89] = 2;
569         notes[90] = "F#";
570         register[90] = 2;
571         notes[91] = "G";
572         register[91] = 2;
573         notes[92] = "Ab";
574         register[92] = 2;
575         notes[93] = "A";
576         register[93] = 2;
577         notes[94] = "Bb";
578         register[94] = 2;
579         notes[95] = "B";
580         register[95] = 2;
581         notes[96] = "C";
582         register[96] = 3;
583         notes[97] = "C#";
584         register[97] = 3;
585         notes[98] = "D";
586         register[98] = 3;
587         notes[99] = "Eb";
588         register[99] = 3;
589         notes[100] = "E";
590         register[100] = 3;
591         notes[101] = "F";
592         register[101] = 3;
593         notes[102] = "F#";
594         register[102] = 3;
595         notes[103] = "G";
596         register[103] = 3;
597         notes[104] = "Ab";
598         register[104] = 3;
599         notes[105] = "A";
600         register[105] = 3;
601         notes[106] = "Bb";
602         register[106] = 3;
603         notes[107] = "B";
604         register[107] = 3;
605         notes[108] = "C";
606         register[108] = 4;
607         notes[109] = "C#";
608         register[109] = 4;
609         notes[110] = "D";
610         register[110] = 4;
611         notes[111] = "Eb";
612         register[111] = 4;
613         notes[112] = "E";
614         register[112] = 4;
615         notes[113] = "F";
616         register[113] = 4;
617         notes[114] = "F#";
618         register[114] = 4;
619         notes[115] = "G";
620         register[115] = 4;
621         notes[116] = "Ab";
622         register[116] = 4;
623         notes[117] = "A";
624         register[117] = 4;
625         notes[118] = "Bb";
626         register[118] = 4;
627         notes[119] = "B";
628         register[119] = 4;
629         notes[120] = "C";
630         register[120] = 5;
631         notes[121] = "C#";
632         register[121] = 5;
633         notes[122] = "D";
634         register[122] = 5;
635         notes[123] = "Eb";
636         register[123] = 5;
637         notes[124] = "E";
638         register[124] = 5;
639         notes[125] = "F";
640         register[125] = 5;
641         notes[126] = "F#";
642         register[126] = 5;
643         notes[127] = "G";
644         register[127] = 5;
645     }
646
647     /**
648      * Add track data to DOM structure
649     */

650     void doTrack(byte[] dta, int len)
651         throws SAXException JavaDoc, ProcessingException {
652         AttributesImpl JavaDoc attr = new AttributesImpl JavaDoc();
653         String JavaDoc text = "";
654
655         boolean tFlag = true;
656         int offset = 0;
657
658         // initialize variables
659
String JavaDoc edata = null;
660         String JavaDoc snam = null;
661         String JavaDoc nmData = "";
662         String JavaDoc ctag = null;
663         String JavaDoc ctagAttr[] = new String JavaDoc[4];
664         String JavaDoc ctagAttrVal[] = new String JavaDoc[4];
665         int ctagnum = 0;
666         String JavaDoc cnum = null;
667         String JavaDoc ctyp = null;
668         int slen = 0;
669         int chanType = 0;
670         int hiName = 0;
671         int status = 0;
672         int noff = 0;
673         String JavaDoc sval = null;
674         boolean ecFlag = true; // assume edata
675
boolean nFlag = true; // use slen for noff
676
boolean firstTime = true;
677
678         while (tFlag) {
679             // do delta
680
ByteLen bl = Utils.deltaToInt(dta, offset);
681             offset += bl.len;
682             String JavaDoc deltaLen = Utils.baToHex(bl.ba, 0, 3);
683
684             nFlag = true; // assume simple (slen) offset
685
// may or may not be status
686
boolean statFlag = false;
687             int first = Utils.baToInt(dta, offset, offset);
688             this.getLogger().debug(
689                 "doTrack: in loop; deltaLen="
690                     + deltaLen
691                     + ", len="
692                     + bl.len
693                     + ", first="
694                     + first);
695
696             if ((first & 128) == 128) {
697                 // it is a status byte
698
statFlag = true;
699                 sval = Utils.baToHex(dta, offset, offset);
700                 status = first;
701                 this.getLogger().debug("doTrack: have status: " + sval);
702                 if (status < 240 && status > 127) {
703                     ecFlag = false;
704                     chanType = (status - 128) / 16;
705                     snam = chanArray[chanType];
706                     ctyp = sval.substring(0, 1);
707                     cnum = sval.substring(1, 2);
708                 } else {
709                     ecFlag = true;
710                     if (status > 239 && status < 256) {
711                         hiName = status - 240;
712                         snam = fArray[hiName];
713                     } else {
714                         throw new ProcessingException(
715                             "Invalid status: " + status);
716                     }
717                 }
718                 offset++;
719             } else {
720                 this.getLogger().debug("doTrack: running status");
721             }
722
723             nmData = "";
724             if (firstTime) {
725                 firstTime = false;
726                 if (!statFlag) {
727                     throw new ProcessingException(
728                         "first time, but no status; first = " + first);
729                 }
730             }
731
732             // offset points to the byte after the status
733
// or first byte of "running status"
734

735             attr.clear();
736             attr.addAttribute("", "DTIME", "DTIME", "CDATA", "" + deltaLen);
737             this.contentHandler.startElement("", "DELTA", "DELTA", attr);
738
739             if (status > 127 && status < 144) {
740                 // note off
741
slen = 2;
742                 // set up tag
743
int pitch = Utils.baToInt(dta, offset, offset);
744                 int vel = Utils.baToInt(dta, offset + 1, offset + 1);
745                 ctag = "NOTE_OFF";
746                 ctagAttr[0] = "PITCH";
747                 ctagAttrVal[0] = "" + pitch;
748                 ctagAttr[1] = "VELOCITY";
749                 ctagAttrVal[1] = "" + vel;
750                 ctagnum = 2;
751                 if (local_verbose) {
752                     ctagAttr[2] = "NAME";
753                     ctagAttrVal[2] = notes[pitch];
754                     ctagAttr[3] = "REGISTER";
755                     ctagAttrVal[3] = "" + register[pitch];
756                     ctagnum = 4;
757                 }
758             } else if (status > 143 && status < 160) {
759                 // note on
760
slen = 2;
761                 int pitch = Utils.baToInt(dta, offset, offset);
762                 int vel = Utils.baToInt(dta, offset + 1, offset + 1);
763                 ctag = "NOTE_ON";
764                 ctagAttr[0] = "PITCH";
765                 ctagAttrVal[0] = "" + pitch;
766                 ctagAttr[1] = "VELOCITY";
767                 ctagAttrVal[1] = "" + vel;
768                 ctagnum = 2;
769                 if (local_verbose) {
770                     ctagAttr[2] = "NAME";
771                     ctagAttrVal[2] = notes[pitch];
772                     ctagAttr[3] = "REGISTER";
773                     ctagAttrVal[3] = "" + register[pitch];
774                     ctagnum = 4;
775                 }
776             } else if (status > 159 && status < 176) {
777                 // after touch
778
slen = 2;
779                 int pitch = Utils.baToInt(dta, offset, offset);
780                 int pres = Utils.baToInt(dta, offset + 1, offset + 1);
781                 ctag = "AFTER";
782                 ctagAttr[0] = "PITCH";
783                 ctagAttrVal[0] = "" + pitch;
784                 ctagAttr[1] = "PRESSURE";
785                 ctagAttrVal[1] = "" + pres;
786                 ctagnum = 2;
787                 if (local_verbose) {
788                     ctagAttr[2] = "NAME";
789                     ctagAttrVal[2] = notes[pitch];
790                     ctagAttr[3] = "REGISTER";
791                     ctagAttrVal[3] = "" + register[pitch];
792                     ctagnum = 4;
793                 }
794             } else if (status > 175 && status < 192) {
795                 // control change
796
slen = 2;
797                 int contnum = Utils.baToInt(dta, offset, offset);
798                 int contval = Utils.baToInt(dta, offset + 1, offset + 1);
799                 ctag = "CONTROL";
800                 ctagAttr[0] = "NUMBER";
801                 ctagAttrVal[0] = "" + contnum;
802                 ctagAttr[1] = "VALUE";
803                 ctagAttrVal[1] = "" + contval;
804                 ctagnum = 2;
805                 if (local_verbose) {
806                     ctagAttr[2] = "NAME";
807                     ctagAttrVal[2] = (String JavaDoc) contHash.get("" + contnum);
808                     ctagnum = 3;
809                 }
810             } else if (status > 191 && status < 208) {
811                 // program (patch) change
812
slen = 1;
813                 int patch = Utils.baToInt(dta, offset, offset);
814                 ctag = "PROGRAM";
815                 ctagAttr[0] = "NUMBER";
816                 ctagAttrVal[0] = "" + patch;
817                 ctagnum = 1;
818             } else if (status > 207 && status < 224) {
819                 // channel pressure
820
slen = 1;
821                 int pamt = Utils.baToInt(dta, offset, offset);
822                 ctag = "PRESSURE";
823                 ctagAttr[0] = "AMOUNT";
824                 ctagAttrVal[0] = "" + pamt;
825                 ctagnum = 1;
826             } else if (status > 223 && status < 240) {
827                 // pitch wheel
828
slen = 2;
829                 int pwamt = Utils.getPW(dta, offset);
830                 ctag = "WHEEL";
831                 ctagAttr[0] = "AMOUNT";
832                 ctagAttrVal[0] = "" + pwamt;
833                 ctagnum = 1;
834             } else if (status == 240) {
835                 // sysex
836
bl = Utils.deltaToInt(dta, offset);
837                 slen = Utils.baToInt(bl.ba, 0, 3);
838                 noff = bl.len;
839                 nFlag = false;
840                 edata =
841                     Utils.baToHex(dta, offset + noff, offset + noff + slen - 1);
842                 noff += slen;
843             } else if (status == 255) {
844                 // non midi (reset only in "live" midi")
845
nmData = Utils.baToHex(dta, offset, offset);
846                 // nmData = "SNMT=\""+nmDta+"\" ";
847
snam = "non-MIDI";
848                 String JavaDoc nmNam = (String JavaDoc) ffHash.get(nmData);
849                 if (nmNam != null) {
850                     snam += " - " + nmNam;
851                 } else {
852                     snam += " - Unknown";
853                 }
854                 // int nmt = baToInt(dta,offset+1,offset+1);
855
bl = Utils.deltaToInt(dta, offset + 1);
856                 slen = Utils.baToInt(bl.ba, 0, 3);
857                 noff = bl.len + 1;
858                 nFlag = false;
859                 if (slen == 0) {
860                     edata = "No data";
861                 } else {
862                     edata =
863                         Utils.baToHex(
864                             dta,
865                             offset + noff,
866                             offset + noff + slen - 1);
867                     noff += slen;
868                 }
869                 this.getLogger().debug(
870                     "doTrack: status FF" + nmData + ", edata = " + edata);
871             } else if (status == 241 || status == 243) {
872                 int tcv = dta[offset];
873                 Integer JavaDoc tc = new Integer JavaDoc(tcv);
874                 edata = tc.toString();
875                 slen = 1;
876             } else if (status == 242) {
877                 int tcv = Utils.getPW(dta, offset);
878                 Integer JavaDoc tc = new Integer JavaDoc(tcv);
879                 edata = tc.toString();
880                 slen = 2;
881             } else if (
882                 status == 246
883                     || status == 248
884                     || status == 250
885                     || status == 251
886                     || status == 252
887                     || status == 254) {
888                 edata = "No data for " + snam;
889                 slen = 0;
890             } else { // really unknown
891
int ol = Utils.getNextHiOrd(dta, offset);
892                 edata = Utils.baToHex(dta, offset + 1, ol);
893                 ol -= offset + 1;
894                 slen = ol;
895             }
896
897             if (ecFlag) {
898                 if (statFlag) {
899                     attr.clear();
900                     attr.addAttribute("", "SLEN", "SLEN", "CDATA", "" + slen);
901                     attr.addAttribute("", "SNAM", "SNAM", "CDATA", snam);
902                     if (!nmData.equals("")) {
903                         attr.addAttribute("", "SNMT", "SNMT", "CDATA", nmData);
904                     }
905                     attr.addAttribute("", "SVAL", "SVAL", "CDATA", sval);
906                     this.contentHandler.startElement(
907                         "",
908                         "STATUS",
909                         "STATUS",
910                         attr);
911
912                     attr.clear();
913                     this.contentHandler.startElement(
914                         "",
915                         "EDATA",
916                         "EDATA",
917                         attr);
918                     text = edata;
919                     this.contentHandler.characters(
920                         text.toCharArray(),
921                         0,
922                         text.length());
923                     this.contentHandler.endElement("", "EDATA", "EDATA");
924
925                     this.contentHandler.endElement("", "STATUS", "STATUS");
926                 } else {
927                     attr.clear();
928                     this.contentHandler.startElement(
929                         "",
930                         "EDATA",
931                         "EDATA",
932                         attr);
933                     text = edata;
934                     this.contentHandler.characters(
935                         text.toCharArray(),
936                         0,
937                         text.length());
938                     this.contentHandler.endElement("", "EDATA", "EDATA");
939                 }
940             } else {
941
942                 if (statFlag) {
943                     attr.clear();
944                     attr.addAttribute("", "SLEN", "SLEN", "CDATA", "" + slen);
945                     attr.addAttribute("", "SNAM", "SNAM", "CDATA", snam);
946                     if (!nmData.equals("")) {
947                         attr.addAttribute("", "SNMT", "SNMT", "CDATA", nmData);
948                     }
949                     attr.addAttribute("", "SVAL", "SVAL", "CDATA", sval);
950                     this.contentHandler.startElement(
951                         "",
952                         "STATUS",
953                         "STATUS",
954                         attr);
955
956                     attr.clear();
957                     attr.addAttribute("", "NUMBER", "NUMBER", "CDATA", cnum);
958                     attr.addAttribute("", "TYPE", "TYPE", "CDATA", ctyp);
959                     this.contentHandler.startElement(
960                         "",
961                         "CHANNEL",
962                         "CHANNEL",
963                         attr);
964
965                     attr.clear();
966                     for (int c = 0; c < ctagnum; c++) {
967                         attr.addAttribute(
968                             "",
969                             ctagAttr[c],
970                             ctagAttr[c],
971                             "CDATA",
972                             ctagAttrVal[c]);
973                     }
974                     this.contentHandler.startElement("", ctag, ctag, attr);
975                     this.contentHandler.endElement("", ctag, ctag);
976
977                     this.contentHandler.endElement("", "CHANNEL", "CHANNEL");
978                     this.contentHandler.endElement("", "STATUS", "STATUS");
979                 } else {
980                     attr.clear();
981                     attr.addAttribute("", "NUMBER", "NUMBER", "CDATA", cnum);
982                     attr.addAttribute("", "TYPE", "TYPE", "CDATA", ctyp);
983                     this.contentHandler.startElement(
984                         "",
985                         "CHANNEL",
986                         "CHANNEL",
987                         attr);
988
989                     attr.clear();
990                     for (int c = 0; c < ctagnum; c++) {
991                         attr.addAttribute(
992                             "",
993                             ctagAttr[c],
994                             ctagAttr[c],
995                             "CDATA",
996                             ctagAttrVal[c]);
997                     }
998                     this.contentHandler.startElement("", ctag, ctag, attr);
999                     this.contentHandler.endElement("", ctag, ctag);
1000
1001                    this.contentHandler.endElement("", "CHANNEL", "CHANNEL");
1002                }
1003
1004            }
1005
1006            this.contentHandler.endElement("", "DELTA", "DELTA");
1007
1008            if (nFlag) {
1009                offset += slen;
1010            } else {
1011                offset += noff;
1012            }
1013            if (offset >= len) {
1014                tFlag = false;
1015            }
1016        }
1017    }
1018
1019    /**
1020     * Write formatted hex data to file
1021     */

1022    void doHexData(byte[] dta, int len)
1023        throws ProcessingException, SAXException JavaDoc {
1024        AttributesImpl JavaDoc attr = new AttributesImpl JavaDoc();
1025        String JavaDoc text = "";
1026
1027        this.contentHandler.startElement("", "HEXDATA", "HEXDATA", attr);
1028
1029        StringBuffer JavaDoc bth = new StringBuffer JavaDoc("");
1030        int bpl = 32;
1031        int r = len % bpl;
1032        int n = len / bpl;
1033        for (int i = 0; i < n; i++) {
1034            int strt = i * bpl;
1035            bth.append(Utils.baToHex(dta, strt, strt + bpl - 1));
1036        }
1037        if (r > 0) {
1038            int strt = n * bpl;
1039            bth.append(Utils.baToHex(dta, strt, strt + r - 1));
1040        }
1041
1042        text = bth.toString();
1043        this.contentHandler.characters(text.toCharArray(), 0, text.length());
1044
1045        this.contentHandler.endElement("", "HEXDATA", "HEXDATA");
1046    }
1047}
1048
Popular Tags