diff --git a/src/main/java/io/github/dsheirer/dsp/filter/channelizer/PolyphaseChannelManager.java b/src/main/java/io/github/dsheirer/dsp/filter/channelizer/PolyphaseChannelManager.java
index dd57205a..33ee5d3f 100644
--- a/src/main/java/io/github/dsheirer/dsp/filter/channelizer/PolyphaseChannelManager.java
+++ b/src/main/java/io/github/dsheirer/dsp/filter/channelizer/PolyphaseChannelManager.java
@@ -1,18 +1,24 @@
-/*******************************************************************************
- * sdr-trunk
- * Copyright (C) 2014-2018 Dennis Sheirer
+/*
*
- * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
+ * * ******************************************************************************
+ * * Copyright (C) 2014-2019 Dennis Sheirer
+ * *
+ * * This program is free software: you can redistribute it and/or modify
+ * * it under the terms of the GNU General Public License as published by
+ * * the Free Software Foundation, either version 3 of the License, or
+ * * (at your option) any later version.
+ * *
+ * * This program is distributed in the hope that it will be useful,
+ * * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * * GNU General Public License for more details.
+ * *
+ * * You should have received a copy of the GNU General Public License
+ * * along with this program. If not, see
+ * * *****************************************************************************
*
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along with this program.
- * If not, see
- *
- ******************************************************************************/
+ */
package io.github.dsheirer.dsp.filter.channelizer;
import io.github.dsheirer.dsp.filter.FilterFactory;
@@ -299,6 +305,7 @@ public class PolyphaseChannelManager implements ISourceEventProcessor
case NOTIFICATION_FREQUENCY_AND_SAMPLE_RATE_LOCKED:
case NOTIFICATION_FREQUENCY_AND_SAMPLE_RATE_UNLOCKED:
case NOTIFICATION_FREQUENCY_CORRECTION_CHANGE:
+ case NOTIFICATION_RECORDING_FILE_LOADED:
//no-op
break;
default:
diff --git a/src/main/java/io/github/dsheirer/source/tuner/TunerViewPanel.java b/src/main/java/io/github/dsheirer/source/tuner/TunerViewPanel.java
index f4b14208..746e2ab3 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/TunerViewPanel.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/TunerViewPanel.java
@@ -28,7 +28,7 @@ import io.github.dsheirer.preference.swing.JTableColumnWidthMonitor;
import io.github.dsheirer.record.RecorderManager;
import io.github.dsheirer.sample.Listener;
import io.github.dsheirer.source.tuner.TunerEvent.Event;
-import io.github.dsheirer.source.tuner.recording.RecordingTuner;
+import io.github.dsheirer.source.tuner.recording.AddRecordingTunerDialog;
import net.miginfocom.swing.MigLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -49,6 +49,7 @@ import javax.swing.table.TableRowSorter;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
+import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
@@ -180,9 +181,17 @@ public class TunerViewPanel extends JPanel
@Override
public void actionPerformed(ActionEvent e)
{
- RecordingTuner recordingTuner = new RecordingTuner(mUserPreferences);
- mTunerModel.addTuner(recordingTuner);
- addRecordingTunerButton.setEnabled(mTunerModel.canAddRecordingTuner());
+ AddRecordingTunerDialog dialog = new AddRecordingTunerDialog(mUserPreferences, mTunerModel);
+ dialog.setLocationRelativeTo(TunerViewPanel.this);
+
+ EventQueue.invokeLater(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ dialog.setVisible(true);
+ }
+ });
}
});
tunerTablePanel.add(addRecordingTunerButton);
diff --git a/src/main/java/io/github/dsheirer/source/tuner/recording/AddRecordingTunerDialog.java b/src/main/java/io/github/dsheirer/source/tuner/recording/AddRecordingTunerDialog.java
new file mode 100644
index 00000000..f2da0707
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/source/tuner/recording/AddRecordingTunerDialog.java
@@ -0,0 +1,259 @@
+/*
+ *
+ * * ******************************************************************************
+ * * Copyright (C) 2014-2019 Dennis Sheirer
+ * *
+ * * This program is free software: you can redistribute it and/or modify
+ * * it under the terms of the GNU General Public License as published by
+ * * the Free Software Foundation, either version 3 of the License, or
+ * * (at your option) any later version.
+ * *
+ * * This program is distributed in the hope that it will be useful,
+ * * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * * GNU General Public License for more details.
+ * *
+ * * You should have received a copy of the GNU General Public License
+ * * along with this program. If not, see
+ * * *****************************************************************************
+ *
+ *
+ */
+
+package io.github.dsheirer.source.tuner.recording;
+
+import io.github.dsheirer.preference.UserPreferences;
+import io.github.dsheirer.properties.SystemProperties;
+import io.github.dsheirer.source.tuner.TunerModel;
+import net.miginfocom.swing.MigLayout;
+import org.apache.commons.lang3.Validate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.swing.JButton;
+import javax.swing.JFileChooser;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.filechooser.FileFilter;
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Dialog to select a recording and specify a center frequency for use in adding a Recording Tuner
+ */
+public class AddRecordingTunerDialog extends JFrame
+{
+ private final static Logger mLog = LoggerFactory.getLogger(AddRecordingTunerDialog.class);
+ private static final String SELECT_A_FILE = "Please select a recording file";
+ private static final String LAST_FILE_BROWSE_LOCATION_KEY = "AddRecordingTunerDialog.lastBrowseLocation";
+ private UserPreferences mUserPreferences;
+ private TunerModel mTunerModel;
+ private JButton mSelectFileButton;
+ private File mSelectedRecording;
+ private JLabel mRecordingFileLabel;
+ private JLabel mFrequencyLabel;
+ private JTextField mFrequencyTextField;
+ private JButton mAddButton;
+ private JButton mCancelButton;
+ private static final Pattern TUNER_RECORDING_PATTERN = Pattern.compile("TUNER_(\\d*)_baseband_\\d{8}_\\d{6}\\.wav");
+
+ public AddRecordingTunerDialog(UserPreferences userPreferences, TunerModel tunerModel)
+ {
+ Validate.notNull(userPreferences, "UserPreferences cannot be null");
+ Validate.notNull(tunerModel, "TunerModel cannot be null");
+
+ if(!tunerModel.canAddRecordingTuner())
+ {
+ JOptionPane.showMessageDialog(AddRecordingTunerDialog.this,
+ "Cannot add a recording tuner. Only one recording tuner can be loaded at any time",
+ "Cannot Add Recording Tuner",
+ JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+
+ mTunerModel = tunerModel;
+ mUserPreferences = userPreferences;
+
+ setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+ setTitle("Select Recording File");
+ setSize(new Dimension(500, 250));
+
+ JPanel content = new JPanel();
+ content.setLayout(new MigLayout("", "[align right][][]",
+ "[][][grow][]"));
+
+ mSelectFileButton = new JButton("Select ...");
+ mSelectFileButton.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ JFileChooser fileChooser = new JFileChooser();
+ String lastBrowsedDirectory = SystemProperties.getInstance().get(LAST_FILE_BROWSE_LOCATION_KEY, "");
+
+ File browseDirectory;
+
+ if(lastBrowsedDirectory != null && !lastBrowsedDirectory.isEmpty())
+ {
+ browseDirectory = new File(lastBrowsedDirectory);
+ }
+ else
+ {
+ browseDirectory = mUserPreferences.getDirectoryPreference().getDefaultRecordingDirectory().toFile();
+ }
+
+ fileChooser.setCurrentDirectory(browseDirectory);
+ fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
+ fileChooser.setFileFilter(new FileFilter()
+ {
+ @Override
+ public boolean accept(File f)
+ {
+ return f.getAbsolutePath().endsWith(".wav") || f.isDirectory();
+ }
+
+ @Override
+ public String getDescription()
+ {
+ return "Recordings (*.wav)";
+ }
+ });
+
+ int returnVal = fileChooser.showOpenDialog(AddRecordingTunerDialog.this);
+
+ File lastDirectory = fileChooser.getCurrentDirectory();
+
+ if(lastDirectory != null)
+ {
+ SystemProperties.getInstance().set(LAST_FILE_BROWSE_LOCATION_KEY, lastDirectory.getAbsolutePath());
+ }
+
+ if(returnVal == JFileChooser.APPROVE_OPTION)
+ {
+ mSelectedRecording = fileChooser.getSelectedFile();
+
+ if(mSelectedRecording != null &&
+ (mFrequencyTextField.getText() == null || mFrequencyTextField.getText().isEmpty()))
+ {
+ Matcher m = TUNER_RECORDING_PATTERN.matcher(mSelectedRecording.getName());
+
+ if(m.matches())
+ {
+ mFrequencyTextField.setText(m.group(1));
+ }
+ }
+ }
+ else
+ {
+ mSelectedRecording = null;
+ }
+
+ mRecordingFileLabel.setText(mSelectedRecording != null ? mSelectedRecording.getName() : SELECT_A_FILE);
+ }
+ });
+ content.add(mSelectFileButton);
+
+ mRecordingFileLabel = new JLabel(SELECT_A_FILE);
+ content.add(mRecordingFileLabel, "span 2,wrap");
+
+ mFrequencyLabel = new JLabel("Frequency (Hz):");
+ content.add(mFrequencyLabel);
+
+ mFrequencyTextField = new JTextField("");
+ mFrequencyTextField.setToolTipText("Center frequency for the recording in Hertz (Hz)");
+ content.add(mFrequencyTextField, "span 2,grow,wrap");
+
+ content.add(new JLabel(""), "wrap");
+
+ content.add(new JLabel(""));
+
+ mAddButton = new JButton("Add");
+ mAddButton.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ if(mSelectedRecording == null)
+ {
+ JOptionPane.showMessageDialog(AddRecordingTunerDialog.this,
+ "Please select a recording file",
+ "Select a Recording File",
+ JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+
+ long frequency = getFrequency();
+
+ if(frequency <= 0 || frequency > Integer.MAX_VALUE)
+ {
+ JOptionPane.showMessageDialog(AddRecordingTunerDialog.this,
+ "Please provide a recording center frequency (1 Hz to 2.14 GHz)",
+ "Center Frequency Required",
+ JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+
+ mLog.info("Adding recording tuner = frequency [" + frequency +
+ "] recording [" + mSelectedRecording.getAbsolutePath() + "]");
+
+
+ try
+ {
+ RecordingTuner tuner = new RecordingTuner(mUserPreferences);
+ mTunerModel.addTuner(tuner);
+ RecordingTunerController controller = tuner.getTunerController();
+ RecordingTunerConfiguration config = new RecordingTunerConfiguration();
+ config.setFrequency(frequency);
+ config.setPath(mSelectedRecording.getAbsolutePath());
+ controller.apply(config);
+ }
+ catch(Exception ex)
+ {
+ mLog.error("Error adding recording tuner", ex);
+ }
+
+ AddRecordingTunerDialog.this.setVisible(false);
+ }
+ });
+ content.add(mAddButton, "grow,push");
+
+ mCancelButton = new JButton("Cancel");
+ mCancelButton.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ AddRecordingTunerDialog.this.setVisible(false);
+ }
+ });
+ content.add(mCancelButton, "grow,push");
+
+ setContentPane(content);
+ }
+
+ private long getFrequency()
+ {
+ String text = mFrequencyTextField.getText();
+
+ if(text != null && !text.isEmpty())
+ {
+ try
+ {
+ return Long.parseLong(text);
+ }
+ catch(Exception e)
+ {
+ //Do nothing, we couldn't parse the frequency value
+ }
+ }
+
+ return 0l;
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/recording/RecordingTuner.java b/src/main/java/io/github/dsheirer/source/tuner/recording/RecordingTuner.java
index 62e8061c..ba7d5e6e 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/recording/RecordingTuner.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/recording/RecordingTuner.java
@@ -60,8 +60,6 @@ public class RecordingTuner extends Tuner
{
ChannelizerType channelizerType = userPreferences.getTunerPreference().getChannelizerType();
- mLog.debug("Using Channelizer Type: " + channelizerType);
-
if(channelizerType == ChannelizerType.POLYPHASE)
{
setChannelSourceManager(new PolyphaseChannelSourceManager(getTunerController()));