001package jmri.jmrix.loconet.sdf; 002 003import java.util.ArrayList; 004 005/** 006 * Implement the INITIATE_SOUND macro from the Digitrax sound definition 007 * language 008 * 009 * @author Bob Jacobsen Copyright (C) 2007 010 */ 011public class InitiateSound extends SdfMacro { 012 013 public InitiateSound(int byte1, int byte2) { 014 this.byte1 = byte1; 015 this.byte2 = byte2; 016 this.trigger = byte2 & 0x7f; 017 this.prempt = (byte1 & 0x7) + (byte2 & 0x80); 018 } 019 020 @Override 021 public String name() { 022 return "INITIATE_SOUND"; // NOI18N 023 } 024 025 int prempt; 026 int trigger; 027 int byte1, byte2; 028 029 public int getTrigger() { 030 return trigger; 031 } 032 033 public void setTrigger(int t) { 034 trigger = t & 0x7f; 035 byte2 = (byte2 & 0x80) | (t & 0x7f); 036 } 037 038 public int getPrempt() { 039 return prempt; 040 } 041 042 public void setPrempt(int prempt) { 043 byte1 = (byte1 & 0xF8) | (prempt & 0x7); 044 byte2 = (byte2 & 0x7F) | (prempt & 0x80); 045 this.prempt = (byte1 & 0x7) + (byte2 & 0x80); 046 } 047 048 @Override 049 public int length() { 050 return 2; 051 } 052 053 String premptVal() { 054 return decodeFlags(prempt, premptCodes, premptMasks, premptNames); 055 } 056 057 String triggerVal() { 058 String trigName = jmri.util.StringUtil.getNameFromState(trigger, triggerCodes, triggerNames); 059 if (trigName != null) { 060 return trigName; 061 } 062 return "(trigger = 0x" + jmri.util.StringUtil.twoHexFromInt(trigger) + ")"; // NOI18N 063 } 064 065 static public SdfMacro match(SdfBuffer buff) { 066 if ((buff.getAtIndex() & 0xF8) != 0x90) { 067 return null; 068 } 069 int byte1 = buff.getAtIndexAndInc(); 070 int byte2 = buff.getAtIndexAndInc(); 071 InitiateSound result = new InitiateSound(byte1, byte2); 072 073 // gather leaves underneath 074 SdfMacro next; 075 while (buff.moreData()) { 076 // look ahead at next instruction 077 int peek = buff.getAtIndex() & 0xFF; 078 079 // if SKEME_START, CHANNEL_START, done 080 // Note that INITIATE_SOUND can be nested, so isn't here 081 if (peek == 0xF1 082 || peek == 0x81) { 083 break; 084 } 085 086 // if this is a INITIATE_SOUND, process it _without_ 087 // allowing recursion 088 if ((peek & 0xF8) == 0x90) { 089 // manually create next 090 byte1 = buff.getAtIndexAndInc(); 091 byte2 = buff.getAtIndexAndInc(); 092 next = new InitiateSound(byte1, byte2); 093 } else { 094 // next is leaf, keep it 095 next = decodeInstruction(buff); 096 } 097 if (result.children == null) { 098 result.children = new ArrayList<SdfMacro>(); // make sure it's initialized 099 } 100 result.children.add(next); 101 102 // if this was an END_SOUND, we're done now that we've included it 103 if (peek == 0x00) { 104 break; 105 } 106 } 107 return result; 108 } 109 110 /** 111 * Store into a buffer. 112 */ 113 @Override 114 public void loadByteArray(SdfBuffer buffer) { 115 // data 116 buffer.setAtIndexAndInc(byte1); 117 buffer.setAtIndexAndInc(byte2); 118 119 // store children 120 super.loadByteArray(buffer); 121 } 122 123 @Override 124 public String toString() { 125 return "Define Sequence " + triggerVal() + "," + premptVal() + '\n'; 126 } 127 128 @Override 129 public String oneInstructionString() { 130 return name() + " " + triggerVal() + "," + premptVal() + '\n'; 131 } 132 133 @Override 134 public String allInstructionString(String indent) { 135 StringBuilder output = new StringBuilder(indent); 136 output.append(oneInstructionString()); 137 if (children == null) { 138 return output.toString(); 139 } 140 for (int i = 0; i < children.size(); i++) { 141 output.append(children.get(i).allInstructionString(indent + " ")); 142 } 143 return output.toString(); 144 } 145}