package nbtool.gui.logviews.sound.whistle;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.util.LinkedList;
import javax.swing.AbstractAction;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.KeyStroke;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import nbtool.data.log.Block;
import nbtool.data.log.Log;
import nbtool.data.log.LogReference;
import nbtool.data.log.LogSorting;
import nbtool.gui.ToolMessage;
import nbtool.gui.logviews.misc.ViewParent;
import nbtool.io.CommonIO.IOFirstResponder;
import nbtool.io.CommonIO.IOInstance;
import nbtool.nio.CrossServer;
import nbtool.nio.CrossServer.CrossInstance;
import nbtool.nio.FileIO;
import nbtool.util.Debug;
public class DetectView extends ViewParent implements IOFirstResponder {
static boolean play = false;
static final int SPECTRUM_OUTPUT_LENGTH = 2048;
FloatBuffer buff = null;
SoundPane pane = null;
JScrollPane scroll = new JScrollPane();
JCheckBox containsBox = new JCheckBox("annotate:");
JLabel detection = new JLabel();
JLabel channel = new JLabel();
int channel_index = 0;
int max_index = 0;
@Override
public void setupDisplay() {
Debug.info("view!");
this.setLayout(new BorderLayout());
if (alsoSelected.size() > 0) {
Debug.warn("starting merge of %d logs", alsoSelected.size() + 1);
LinkedList<LogReference> logRefs = new LinkedList<>();
if (this.displayedLog.getReference() != null)
logRefs.add(this.displayedLog.getReference());
for (Log lg : this.alsoSelected) {
if (lg.getReference() != null)
logRefs.add(lg.getReference());
}
LogSorting.sort(LogSorting.Sort.BY_FILENAME, logRefs);
int total = 0;
byte[][] all = new byte[logRefs.size()][];
for (int i = 0; i <logRefs.size(); ++i) {
LogReference ref = logRefs.get(i);
all[i] = ref.get().blocks.get(0).data;
total += all[i].length;
Debug.info("\t%d bytes from", all[i].length, ref.toString());
}
byte[] all_bytes = new byte[total];
int pos = 0;
for (int i = 0; i < all.length; ++i) {
System.arraycopy(all[i], 0, all_bytes, pos, all[i].length);
pos += all[i].length;
}
Log out = Log.emptyLog();
out.logClass = "DetectAmplitude";
out.blocks.add(Block.explicit(all_bytes, "SoundAmplitude"));
String name = String.format("merged_%dlogs_%d_%d.nblog",
logRefs.size(), logRefs.get(0).thisID, logRefs.getLast().thisID);
try {
FileIO.writeLogToPath(logRefs.get(0).loadPath().getParent().resolve(name), out);
ToolMessage.displayWarn("merged %d logs to %s", logRefs.size(), name);
} catch (IOException e1) {
e1.printStackTrace();
}
}
if (this.displayedLog.getReference() != null && this.displayedLog.getReference().loadPath() != null)
Debug.print("load: %d from %s", this.displayedLog.getReference().thisID, this.displayedLog.getReference().loadPath().getFileName());
final JCheckBox playBox = new JCheckBox();
playBox.setText("play sound on selection");
playBox.setSelected(play);
playBox.addChangeListener(new ChangeListener(){
@Override
public void stateChanged(ChangeEvent e) {
play = playBox.isSelected();
}
});
this.add(playBox, BorderLayout.SOUTH);
if (play) {
final byte[] dataToPlay = displayedLog.blocks.get(0).data;
PlaySound.play(dataToPlay);
}
if (displayedLog.logClass.equals("DetectAmplitude")) {
CrossInstance ci = CrossServer.instanceByIndex(0);
if (ci == null) return;
ci.tryAddCall(this, "whistle_detect", this.displayedLog);
this.add(scroll, BorderLayout.CENTER);
scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
JPanel container = new JPanel(new BorderLayout());
container.add(detection, BorderLayout.CENTER);
container.add(containsBox, BorderLayout.WEST);
container.add(channel, BorderLayout.EAST);
this.add(container, BorderLayout.NORTH);
if (displayedLog.topLevelDictionary.get("WhistleHeard") != null)
containsBox.setSelected(displayedLog.topLevelDictionary.get("WhistleHeard").asBoolean().bool());
containsBox.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
displayedLog.topLevelDictionary.put("WhistleHeard", containsBox.isSelected());
if (!displayedLog.temporary()) {
try {
displayedLog.saveChangesToLoadFile();
} catch (Exception e1) {
e1.printStackTrace();
ToolMessage.displayError("could not write log!!");
}
}
}
});
channel.setText(String.format(" (%d / %d)", channel_index, max_index ));
this.getActionMap().put("NextIndex", new AbstractAction(){
@Override
public void actionPerformed(ActionEvent e) {
channel_index = Math.min(channel_index + 1, max_index);
Debug.print("channel index: %d", channel_index);
channel.setText(String.format(" (%d / %d)", channel_index, max_index ));
repaint();
}
});
this.getActionMap().put("PrevIndex", new AbstractAction(){
@Override
public void actionPerformed(ActionEvent e) {
channel_index = Math.max(channel_index - 1, 0);
Debug.print("channel index: %d", channel_index);
channel.setText(String.format(" (%d / %d)", channel_index, max_index ));
repaint();
}
});
this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
KeyStroke.getKeyStroke(KeyEvent.VK_CLOSE_BRACKET, 0)
, "NextIndex");
this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
KeyStroke.getKeyStroke(KeyEvent.VK_OPEN_BRACKET, 0)
, "PrevIndex");
}
}
@Override
public String[] displayableTypes() {
return new String[]{"DetectAmplitude", "soundStuff"};
}
@Override
public void ioFinished(IOInstance instance) { }
@Override
public void ioReceived(IOInstance inst, int ret, Log... out) {
assert(out.length == 1);
int total = 0;
for (Block b : out[0].blocks) {
total += b.data.length;
}
byte[] all = new byte[total];
int offset = 0;
for (Block b : out[0].blocks) {
System.arraycopy(b.data, 0, all, offset, b.data.length);
offset += b.data.length;
}
max_index = out[0].blocks.size() - 1;
buff = new FloatBuffer(new Block(all, ""), out[0].blocks.size(),
SPECTRUM_OUTPUT_LENGTH);
if (pane != null) {
scroll.remove(pane);
}
detection.setText("detect: " + out[0].topLevelDictionary.get("WhistleHeard").asBoolean().bool());
pane = new SoundPane(1, 2048) {
@Override
public int pixels(int c, int f, int radius) {
return (int) ((buff.get(f, channel_index) / buff.max()) * radius * -1);
}
@Override
public String peakString() {
return "max = " + buff.max;
}
@Override
public String selectionString(int c, int f) {
String fmat = String.format("c%df%d: %f", channel_index, f, buff.get(f, channel_index));
Debug.print("%s", fmat);
return fmat;
}
};
scroll.setViewportView(pane);
repaint();
}
@Override
public boolean ioMayRespondOnCenterThread(IOInstance inst) {
return false;
}
}