001package jmri.jmrit.display.configurexml; 002 003import jmri.jmrit.audio.AudioBuffer; 004import jmri.jmrit.audio.AudioSource; 005import jmri.configurexml.JmriConfigureXmlException; 006import jmri.jmrit.catalog.NamedIcon; 007import jmri.jmrit.display.*; 008 009import org.jdom2.Attribute; 010import org.jdom2.Element; 011 012/** 013 * Handle configuration for display.AudioIcon objects. 014 * 015 * @author Daniel Bergqvist (C) 2023 016 */ 017public class AudioIconXml extends PositionableLabelXml { 018 019 /** 020 * Default implementation for storing the contents of a AudioIcon 021 * 022 * @param o Object to store, of type AudioIcon 023 * @return Element containing the complete info 024 */ 025 @Override 026 public Element store(Object o) { 027 AudioIcon p = (AudioIcon) o; 028 029 if (!p.isActive()) { 030 return null; // if flagged as inactive, don't store 031 } 032 Element element = new Element("audioicon"); 033 storeCommonAttributes(p, element); 034 035 element.addContent(new Element("Identity").addContent(Integer.toString(p.getIdentity()))); 036 037 AudioSource source = (AudioSource)p.getAudio(); 038 if (source != null) { 039 element.setAttribute("audio", source.getSystemName()); 040 041 AudioBuffer buffer = (AudioBuffer) jmri.InstanceManager.getDefault(jmri.AudioManager.class) 042 .getAudio(source.getAssignedBufferName()); 043 if (buffer != null) { 044 // We need to use the attribute "sound" instead of the element "sound" 045 // since the method jmri.web.server.WebServer.portablePathToURI() 046 // converts paths in attributes to portable paths, but not paths 047 // in elements. 048 element.setAttribute("sound", buffer.getURL()); 049 } 050 } 051 052 if (p.isText()) { 053 if (p.getUnRotatedText() != null) { 054 element.setAttribute("text", p.getUnRotatedText()); 055 } 056 storeTextInfo(p, element); 057 } 058 059 if (p.isIcon() && p.getIcon() != null) { 060 element.setAttribute("icon", "yes"); 061 element.addContent(storeIcon("icon", (NamedIcon) p.getIcon())); 062 } 063 064 element.setAttribute("onClickOperation", p.getOnClickOperation().name()); 065 element.setAttribute("playSoundWhenJmriPlays", p.getPlaySoundWhenJmriPlays() ? "yes" : "no"); 066 element.setAttribute("stopSoundWhenJmriStops", p.getStopSoundWhenJmriStops() ? "yes" : "no"); 067 068 storeLogixNG_Data(p, element); 069 070 element.setAttribute("class", "jmri.jmrit.display.configurexml.AudioIconXml"); 071 return element; 072 } 073 074 /** 075 * Create a AudioIcon, then add to a target JLayeredPane 076 * 077 * @param element Top level Element to unpack. 078 * @param o Editor as an Object 079 * @throws JmriConfigureXmlException when a error prevents creating the objects as as 080 * required by the input XML 081 */ 082 @Override 083 public void load(Element element, Object o) throws JmriConfigureXmlException { 084 // create the objects 085 AudioIcon l = null; 086 087 int identity = Integer.parseInt(element.getChildText("Identity")); 088 089 // get object class and determine editor being used 090 Editor editor = (Editor) o; 091 092 String audioName; 093 Attribute attr = element.getAttribute("audio"); 094 if (attr == null) { 095 log.error("incorrect information for audio; must use audio name"); 096 editor.loadFailed(); 097 return; 098 } else { 099 audioName = attr.getValue(); 100 } 101 102 if (element.getAttribute("icon") != null) { 103 NamedIcon icon; 104 String name = element.getAttribute("icon").getValue(); 105 if (name.equals("yes")) { 106 icon = getNamedIcon("icon", element, "AudioIcon ", editor); 107 } else { 108 icon = NamedIcon.getIconByName(name); 109 if (icon == null) { 110 icon = editor.loadFailed("AudioIcon", name); 111 if (icon == null) { 112 log.info("AudioIcon icon removed for url= {}", name); 113 return; 114 } 115 } 116 } 117 // abort if name != yes and have null icon 118 if (icon == null && !name.equals("yes")) { 119 log.info("AudioIcon icon removed for url= {}", name); 120 return; 121 } 122 l = new AudioIcon(identity, icon, editor); 123 try { 124 Attribute a = element.getAttribute("rotate"); 125 if (a != null && icon != null) { 126 int rotation = element.getAttribute("rotate").getIntValue(); 127 icon.setRotation(rotation, l); 128 } 129 } catch (org.jdom2.DataConversionException e) { 130 } 131 132 if (name.equals("yes")) { 133 NamedIcon nIcon = loadIcon(l, "icon", element, "AudioIcon ", editor); 134 if (nIcon != null) { 135 l.updateIcon(nIcon); 136 } else { 137 log.info("AudioIcon icon removed for url= {}", name); 138 return; 139 } 140 } else { 141 l.updateIcon(icon); 142 } 143 } 144 145 if (element.getAttribute("text") != null) { 146 if (l == null) { 147 l = new AudioIcon(identity, element.getAttribute("text").getValue(), editor); 148 } 149 loadTextInfo(l, element); 150 151 } else if (l == null) { 152 log.error("AudioIcon is null!"); 153 if (log.isDebugEnabled()) { 154 java.util.List<Attribute> attrs = element.getAttributes(); 155 log.debug("\tElement Has {} Attributes:", attrs.size()); 156 for (Attribute a : attrs) { 157 log.debug(" attribute: {} = {}", a.getName(), a.getValue()); 158 } 159 java.util.List<Element> kids = element.getChildren(); 160 log.debug("\tElementHas {} children:", kids.size()); 161 for (Element e : kids) { 162 log.debug(" child: {} = \"{}\"", e.getName(), e.getValue()); 163 } 164 } 165 editor.loadFailed(); 166 return; 167 } 168 169 l.setAudio(audioName); 170 171 String onClickOperation = element.getAttribute("onClickOperation").getValue(); 172 l.setOnClickOperation(AudioIcon.OnClickOperation.valueOf(onClickOperation)); 173 174 String yesno = element.getAttribute("playSoundWhenJmriPlays").getValue(); 175 if ((yesno != null) && (!yesno.equals(""))) { 176 l.setPlaySoundWhenJmriPlays(yesno.equals("yes")); 177 } 178 179 yesno = element.getAttribute("stopSoundWhenJmriStops").getValue(); 180 if ((yesno != null) && (!yesno.equals(""))) { 181 l.setStopSoundWhenJmriStops(yesno.equals("yes")); 182 } 183 184 try { 185 editor.putItem(l); 186 } catch (Positionable.DuplicateIdException e) { 187 // This should never happen 188 log.error("Editor.putItem() with null id has thrown DuplicateIdException", e); 189 } 190 191 loadLogixNG_Data(l, element); 192 193 // load individual item's option settings after editor has set its global settings 194 loadCommonAttributes(l, Editor.LABELS, element); 195 } 196 197 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(AudioIconXml.class); 198}