package tim.prune.correlate; import java.awt.FlowLayout; import java.awt.GridLayout; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTable; import tim.prune.App; import tim.prune.DataSubscriber; import tim.prune.I18nManager; import tim.prune.UpdateMessageBroker; import tim.prune.config.TimezoneHelper; import tim.prune.data.AudioClip; import tim.prune.data.AudioList; import tim.prune.data.DataPoint; import tim.prune.data.MediaObject; import tim.prune.data.MediaList; import tim.prune.data.TimeDifference; import tim.prune.data.Timestamp; import tim.prune.data.TimestampUtc; import tim.prune.undo.UndoCorrelateAudios; /** * Class to manage the automatic correlation of audio clips to points * which is very similar to the PhotoCorrelator apart from the clip lengths */ public class AudioCorrelator extends Correlator { private AudioTimestampSelector _fileTimesSelector = null, _correlTimesSelector = null; /** * Constructor * @param inApp App object */ public AudioCorrelator(App inApp) { super(inApp); } /** * @return name key */ public String getNameKey() { return "function.correlateaudios"; } /** @return type key */ protected String getMediaTypeKey() { return "audio"; } /** @return photo list*/ protected MediaList getMediaList() { return _app.getTrackInfo().getAudioList(); } /** * @return first gui panel including timestamp specification (beginning, middle, end) */ protected JPanel makeFirstPanel() { // First panel for timestamp stuff JPanel card1 = new JPanel(); card1.setLayout(new FlowLayout(FlowLayout.CENTER)); JPanel grid1 = new JPanel(); grid1.setLayout(new GridLayout(0, 1)); _fileTimesSelector = new AudioTimestampSelector("dialog.correlate.filetimes", "dialog.correlate.filetimes2"); grid1.add(_fileTimesSelector); _correlTimesSelector = new AudioTimestampSelector("dialog.correlate.correltimes", null); grid1.add(_correlTimesSelector); card1.add(grid1); return card1; } /** * @return array of boolean flags denoting availability of cards */ protected boolean[] getCardEnabledFlags() { boolean[] cards = super.getCardEnabledFlags(); cards[0] = getAudioLengthAvailability(_app.getTrackInfo().getAudioList()); return cards; } /** * @param inAudios AudioList object * @return true if there are any audio lengths available */ private static boolean getAudioLengthAvailability(AudioList inAudios) { for (int i=0; i 0) {return true;} } return false; } /** * Create a preview of the correlate action using the selected time difference * @param inTimeDiff TimeDifference to use for preview * @param inShowWarning true to show warning if all points out of range */ protected void createPreview(TimeDifference inTimeDiff, boolean inShowWarning) { TimeDifference timeLimit = parseTimeLimit(); double angDistLimit = parseDistanceLimit(); MediaPreviewTableModel model = new MediaPreviewTableModel("dialog.correlate.select.audioname"); AudioList audios = _app.getTrackInfo().getAudioList(); // Loop through audios deciding whether to set correlate flag or not int numAudios = audios.getNumAudios(); for (int i=0; i 0.0 && correlateAudio) { final double angDistPair = DataPoint.calculateRadiansBetween(pair.getPointBefore(), pair.getPointAfter()); double frac = pair.getFraction(); if (frac > 0.5) {frac = 1 - frac;} final double angDistPhoto = angDistPair * frac; correlateAudio = (angDistPhoto < angDistLimit); } // Don't select audios which are already correlated to the same point if (pair.getSecondsBefore() == 0L && pair.getPointBefore().isDuplicate(audio.getDataPoint())) { correlateAudio = false; } row.setCorrelateFlag(correlateAudio); model.addRow(row); } _previewTable.setModel(model); // Set distance units model.setDistanceUnits(getSelectedDistanceUnits()); // Set column widths _previewTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); final int[] colWidths = {150, 160, 100, 100, 50}; for (int i=0; i 0 && secsToAdd != 0) { mediaMillis += (secsToAdd * 1000L); tstamp = new TimestampUtc(mediaMillis); // Here we create a Utc timestamp but it's only temporary for the correlation // so it will never have to react to timezone changes } } catch (ClassCastException cce) {} return tstamp; } /** * Finish the correlation by modifying the track * and passing the Undo information back to the App */ protected void finishCorrelation() { // TODO: Probably should be able to combine this into the Correlator? PointMediaPair[] pointPairs = getPointPairs(); if (pointPairs == null || pointPairs.length <= 0) {return;} // begin to construct undo information UndoCorrelateAudios undo = new UndoCorrelateAudios(_app.getTrackInfo()); // loop over Audios int arraySize = pointPairs.length; int i = 0, numAudios = 0; int numPointsToCreate = 0; PointMediaPair pair = null; for (i=0; i 0) { // make new array for added points DataPoint[] addedPoints = new DataPoint[numPointsToCreate]; int pointNum = 0; DataPoint pointToAdd = null; for (i=0; i 0L) { // interpolate point pointToAdd = DataPoint.interpolate(pair.getPointBefore(), pair.getPointAfter(), pair.getFraction()); } if (pointToAdd != null) { // link audio to point pointToAdd.setAudio((AudioClip) pair.getMedia()); pair.getMedia().setDataPoint(pointToAdd); // set to start of segment so not joined in track pointToAdd.setSegmentStart(true); // add to point array addedPoints[pointNum] = pointToAdd; pointNum++; } } } // expand track _app.getTrackInfo().getTrack().appendPoints(addedPoints); } // send undo information back to controlling app undo.setNumAudiosCorrelated(numAudios); _app.completeFunction(undo, ("" + numAudios + " " + (numAudios==1?I18nManager.getText("confirm.correlateaudios.single"):I18nManager.getText("confirm.correlateaudios.multi")))); // observers already informed by track update if new points created if (numPointsToCreate == 0) { UpdateMessageBroker.informSubscribers(DataSubscriber.SELECTION_CHANGED); } } }