mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 16:47:31 -05:00
IQ recording file playback partial checkin.
NOTE: only the gui components and settings handling have been implemented. Actual recording playback is not yet implemented. Partial checkin of initial P25 decoder development. NOTE: P25 decoder is not yet functional.
This commit is contained in:
@@ -20,14 +20,16 @@ package source;
|
||||
import javax.swing.JLabel;
|
||||
|
||||
import source.config.SourceConfiguration;
|
||||
import controller.ResourceManager;
|
||||
|
||||
public class EmptySourceEditor extends SourceEditor
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public EmptySourceEditor( SourceConfiguration config )
|
||||
public EmptySourceEditor( ResourceManager resourceManager,
|
||||
SourceConfiguration config )
|
||||
{
|
||||
super( config );
|
||||
super( resourceManager, config );
|
||||
|
||||
initGUI();
|
||||
}
|
||||
|
||||
@@ -73,7 +73,8 @@ public class SourceComponentEditor extends AbstractChannelEditor
|
||||
}
|
||||
|
||||
//Change to the new one
|
||||
mEditor = SourceEditorFactory.getPanel( config );
|
||||
mEditor = SourceEditorFactory.getPanel(
|
||||
mChannelNode.getModel().getResourceManager(), config );
|
||||
|
||||
//Add it to the jpanel
|
||||
add( mEditor, "span 2" );
|
||||
|
||||
@@ -19,15 +19,18 @@ package source;
|
||||
|
||||
import source.config.SourceConfiguration;
|
||||
import controller.Editor;
|
||||
import controller.ResourceManager;
|
||||
|
||||
public abstract class SourceEditor extends Editor
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected ResourceManager mResourceManager;
|
||||
protected SourceConfiguration mConfig;
|
||||
|
||||
public SourceEditor( SourceConfiguration config )
|
||||
public SourceEditor( ResourceManager resourceManager, SourceConfiguration config )
|
||||
{
|
||||
mResourceManager = resourceManager;
|
||||
mConfig = config;
|
||||
}
|
||||
|
||||
@@ -35,4 +38,9 @@ public abstract class SourceEditor extends Editor
|
||||
{
|
||||
return mConfig;
|
||||
}
|
||||
|
||||
public ResourceManager getResourceManager()
|
||||
{
|
||||
return mResourceManager;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,25 +19,31 @@ package source;
|
||||
|
||||
import source.config.SourceConfiguration;
|
||||
import source.mixer.MixerEditor;
|
||||
import source.recording.RecordingEditor;
|
||||
import source.tuner.TunerEditor;
|
||||
import controller.ResourceManager;
|
||||
|
||||
public class SourceEditorFactory
|
||||
{
|
||||
public static SourceEditor getPanel( SourceConfiguration config )
|
||||
public static SourceEditor getPanel( ResourceManager resourceManager,
|
||||
SourceConfiguration config )
|
||||
{
|
||||
SourceEditor configuredPanel;
|
||||
|
||||
switch( config.getSourceType() )
|
||||
{
|
||||
case MIXER:
|
||||
configuredPanel = new MixerEditor( config );
|
||||
configuredPanel = new MixerEditor( resourceManager, config );
|
||||
break;
|
||||
case TUNER:
|
||||
configuredPanel = new TunerEditor( config );
|
||||
configuredPanel = new TunerEditor( resourceManager, config );
|
||||
break;
|
||||
case RECORDING:
|
||||
configuredPanel = new RecordingEditor( resourceManager, config );
|
||||
break;
|
||||
case NONE:
|
||||
default:
|
||||
configuredPanel = new EmptySourceEditor( config );
|
||||
configuredPanel = new EmptySourceEditor( resourceManager, config );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ public class SourceManager {
|
||||
mResourceManager = resourceManager;
|
||||
}
|
||||
|
||||
public Source getSource( ProcessingChain channel )
|
||||
public Source getSource( ProcessingChain channel ) throws SourceException
|
||||
{
|
||||
Source retVal = null;
|
||||
|
||||
@@ -55,6 +55,9 @@ public class SourceManager {
|
||||
case TUNER:
|
||||
retVal = mResourceManager.getTunerManager().getSource( channel );
|
||||
break;
|
||||
case RECORDING:
|
||||
retVal = mResourceManager.getRecordingSourceManager()
|
||||
.getSource( channel );
|
||||
case NONE:
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -21,8 +21,8 @@ public enum SourceType
|
||||
{
|
||||
NONE( "No Source" ),
|
||||
MIXER( "Mixer/Sound Card" ),
|
||||
TUNER( "Tuner" );
|
||||
// WAVE( "Wave File" );
|
||||
TUNER( "Tuner" ),
|
||||
RECORDING( "IQ Recording" );
|
||||
|
||||
private String mDisplayString;
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ public class SourceConfigFactory
|
||||
}
|
||||
|
||||
public static SourceConfiguration
|
||||
getSourceConfiguration( SourceType source )
|
||||
getSourceConfiguration( SourceType source )
|
||||
{
|
||||
SourceConfiguration retVal;
|
||||
|
||||
@@ -39,6 +39,9 @@ public class SourceConfigFactory
|
||||
case TUNER:
|
||||
retVal = new SourceConfigTuner();
|
||||
break;
|
||||
case RECORDING:
|
||||
retVal = new SourceConfigRecording();
|
||||
break;
|
||||
case NONE:
|
||||
default:
|
||||
retVal = new SourceConfigNone();
|
||||
|
||||
61
src/source/config/SourceConfigRecording.java
Normal file
61
src/source/config/SourceConfigRecording.java
Normal file
@@ -0,0 +1,61 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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 <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package source.config;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
|
||||
import source.SourceType;
|
||||
|
||||
public class SourceConfigRecording extends SourceConfiguration
|
||||
{
|
||||
private String mRecordingAlias;
|
||||
private long mFrequency;
|
||||
|
||||
public SourceConfigRecording()
|
||||
{
|
||||
super( SourceType.RECORDING );
|
||||
}
|
||||
|
||||
@XmlAttribute( name = "recording_alias" )
|
||||
public String getRecordingAlias()
|
||||
{
|
||||
return mRecordingAlias;
|
||||
}
|
||||
|
||||
public void setRecordingAlias( String alias )
|
||||
{
|
||||
mRecordingAlias = alias;
|
||||
}
|
||||
|
||||
@XmlAttribute( name = "frequency" )
|
||||
public long getFrequency()
|
||||
{
|
||||
return mFrequency;
|
||||
}
|
||||
|
||||
public void setFrequency( long frequency )
|
||||
{
|
||||
mFrequency = frequency;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription()
|
||||
{
|
||||
return getRecordingAlias();
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import javax.swing.JLabel;
|
||||
import source.SourceEditor;
|
||||
import source.config.SourceConfigMixer;
|
||||
import source.config.SourceConfiguration;
|
||||
import controller.ResourceManager;
|
||||
|
||||
public class MixerEditor extends SourceEditor
|
||||
{
|
||||
@@ -36,9 +37,10 @@ public class MixerEditor extends SourceEditor
|
||||
protected Mixer.Info mSelectedMixer = null;
|
||||
|
||||
|
||||
public MixerEditor( SourceConfiguration config )
|
||||
public MixerEditor( ResourceManager resourceManager,
|
||||
SourceConfiguration config )
|
||||
{
|
||||
super( config );
|
||||
super( resourceManager, config );
|
||||
|
||||
initGUI();
|
||||
}
|
||||
|
||||
108
src/source/recording/Recording.java
Normal file
108
src/source/recording/Recording.java
Normal file
@@ -0,0 +1,108 @@
|
||||
package source.recording;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import source.SourceException;
|
||||
import source.tuner.FrequencyChangeListener;
|
||||
import source.tuner.TunerChannel;
|
||||
import source.tuner.TunerChannelProvider;
|
||||
import source.tuner.TunerChannelSource;
|
||||
import controller.ResourceManager;
|
||||
import controller.ThreadPoolManager;
|
||||
|
||||
public class Recording implements Comparable<Recording>,
|
||||
FrequencyChangeListener,
|
||||
TunerChannelProvider
|
||||
{
|
||||
private ResourceManager mResourceManager;
|
||||
private RecordingConfiguration mConfiguration;
|
||||
|
||||
private ArrayList<TunerChannelSource> mTunerChannels =
|
||||
new ArrayList<TunerChannelSource>();
|
||||
|
||||
private long mCenterFrequency;
|
||||
|
||||
public Recording( ResourceManager resourceManager,
|
||||
RecordingConfiguration configuration )
|
||||
{
|
||||
mResourceManager = resourceManager;
|
||||
mConfiguration = configuration;
|
||||
mCenterFrequency = mConfiguration.getCenterFrequency();
|
||||
}
|
||||
|
||||
public void setAlias( String alias )
|
||||
{
|
||||
mConfiguration.setAlias( alias );
|
||||
mResourceManager.getSettingsManager().save();
|
||||
}
|
||||
|
||||
public void setRecordingFile( File file ) throws SourceException
|
||||
{
|
||||
if( hasChannels() )
|
||||
{
|
||||
throw new SourceException( "Recording source - can't change "
|
||||
+ "recording file while channels are enabled against the "
|
||||
+ "current recording." );
|
||||
}
|
||||
|
||||
mConfiguration.setFilePath( file.getAbsolutePath() );
|
||||
mResourceManager.getSettingsManager().save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this recording is currently playing/providing samples to
|
||||
* tuner channel sources
|
||||
*/
|
||||
public boolean hasChannels()
|
||||
{
|
||||
return mTunerChannels.size() > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TunerChannelSource getChannel( ThreadPoolManager threadPoolManager,
|
||||
TunerChannel channel ) throws RejectedExecutionException,
|
||||
SourceException
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void releaseChannel( TunerChannelSource source )
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
public RecordingConfiguration getRecordingConfiguration()
|
||||
{
|
||||
return mConfiguration;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return mConfiguration.getAlias();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void frequencyChanged( long frequency, int bandwidth )
|
||||
{
|
||||
mConfiguration.setCenterFrequency( frequency );
|
||||
mResourceManager.getSettingsManager().save();
|
||||
|
||||
mCenterFrequency = frequency;
|
||||
|
||||
for( TunerChannelSource channel: mTunerChannels )
|
||||
{
|
||||
channel.frequencyChanged( frequency, bandwidth );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo( Recording other )
|
||||
{
|
||||
return getRecordingConfiguration().getAlias()
|
||||
.compareTo( other.getRecordingConfiguration().getAlias() );
|
||||
}
|
||||
}
|
||||
87
src/source/recording/RecordingConfiguration.java
Normal file
87
src/source/recording/RecordingConfiguration.java
Normal file
@@ -0,0 +1,87 @@
|
||||
package source.recording;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlTransient;
|
||||
|
||||
public class RecordingConfiguration
|
||||
{
|
||||
private File mRecording;
|
||||
private String mFilePath;
|
||||
private String mAlias;
|
||||
private long mCenterFrequency;
|
||||
|
||||
public RecordingConfiguration()
|
||||
{
|
||||
mAlias = "New Recording";
|
||||
}
|
||||
|
||||
public RecordingConfiguration( String filePath,
|
||||
String alias,
|
||||
long centerFrequency )
|
||||
{
|
||||
mFilePath = filePath;
|
||||
mAlias = alias;
|
||||
mCenterFrequency = centerFrequency;
|
||||
|
||||
updateFile();
|
||||
}
|
||||
|
||||
private void updateFile()
|
||||
{
|
||||
if( mFilePath != null )
|
||||
{
|
||||
try
|
||||
{
|
||||
mRecording = new File( mFilePath );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
throw new IllegalArgumentException( "There was an error while "
|
||||
+ "accessing the recording source [" + mFilePath + "]", e );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@XmlTransient
|
||||
public File getRecording()
|
||||
{
|
||||
return mRecording;
|
||||
}
|
||||
|
||||
@XmlAttribute( name = "file_path" )
|
||||
public String getFilePath()
|
||||
{
|
||||
return mFilePath;
|
||||
}
|
||||
|
||||
public void setFilePath( String filePath )
|
||||
{
|
||||
mFilePath = filePath;
|
||||
|
||||
updateFile();
|
||||
}
|
||||
|
||||
@XmlAttribute( name = "alias" )
|
||||
public String getAlias()
|
||||
{
|
||||
return mAlias;
|
||||
}
|
||||
|
||||
public void setAlias( String alias )
|
||||
{
|
||||
mAlias = alias;
|
||||
}
|
||||
|
||||
@XmlAttribute( name = "center_frequency" )
|
||||
public long getCenterFrequency()
|
||||
{
|
||||
return mCenterFrequency;
|
||||
}
|
||||
|
||||
public void setCenterFrequency( long frequency )
|
||||
{
|
||||
mCenterFrequency = frequency;
|
||||
}
|
||||
}
|
||||
120
src/source/recording/RecordingEditor.java
Normal file
120
src/source/recording/RecordingEditor.java
Normal file
@@ -0,0 +1,120 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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 <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package source.recording;
|
||||
|
||||
import gui.control.JFrequencyControl;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import source.SourceEditor;
|
||||
import source.config.SourceConfigRecording;
|
||||
import source.config.SourceConfigTuner;
|
||||
import source.config.SourceConfiguration;
|
||||
import controller.ResourceManager;
|
||||
|
||||
public class RecordingEditor extends SourceEditor
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private JComboBox<Recording> mComboRecordings;
|
||||
private JFrequencyControl mFrequencyControl;
|
||||
|
||||
public RecordingEditor( ResourceManager resourceManager,
|
||||
SourceConfiguration config )
|
||||
{
|
||||
super( resourceManager, config );
|
||||
|
||||
initGUI();
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
mFrequencyControl.setFrequency(
|
||||
((SourceConfigTuner)mConfig).getFrequency(), false );
|
||||
}
|
||||
|
||||
public void save()
|
||||
{
|
||||
SourceConfigRecording config = (SourceConfigRecording)mConfig;
|
||||
|
||||
Recording selected = (Recording)mComboRecordings.getSelectedItem();
|
||||
|
||||
if( selected != null )
|
||||
{
|
||||
config.setRecordingAlias( selected
|
||||
.getRecordingConfiguration().getAlias() );
|
||||
}
|
||||
|
||||
config.setFrequency( mFrequencyControl.getFrequency() );
|
||||
}
|
||||
|
||||
private void initGUI()
|
||||
{
|
||||
add( new JLabel( "Recording" ) );
|
||||
|
||||
mComboRecordings = new JComboBox<Recording>();
|
||||
|
||||
add( mComboRecordings, "wrap" );
|
||||
|
||||
mFrequencyControl = new JFrequencyControl();
|
||||
|
||||
mFrequencyControl.setFrequency(
|
||||
((SourceConfigRecording)mConfig).getFrequency(), false );
|
||||
|
||||
add( mFrequencyControl, "span" );
|
||||
|
||||
resetRecordings();
|
||||
}
|
||||
|
||||
private void resetRecordings()
|
||||
{
|
||||
SwingUtilities.invokeLater( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
List<Recording> recordings = getResourceManager()
|
||||
.getRecordingSourceManager().getRecordings();
|
||||
|
||||
mComboRecordings.setModel(
|
||||
new DefaultComboBoxModel<Recording>(
|
||||
recordings.toArray( new Recording[ recordings.size()] ) ) );
|
||||
|
||||
SourceConfigRecording config = (SourceConfigRecording)mConfig;
|
||||
|
||||
String recordingAlias = config.getRecordingAlias();
|
||||
|
||||
if( recordingAlias != null )
|
||||
{
|
||||
Recording selected = mResourceManager
|
||||
.getRecordingSourceManager()
|
||||
.getRecordingFromAlias( recordingAlias );
|
||||
|
||||
if( selected != null )
|
||||
{
|
||||
mComboRecordings.setSelectedItem( selected );
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
131
src/source/recording/RecordingEditorPanel.java
Normal file
131
src/source/recording/RecordingEditorPanel.java
Normal file
@@ -0,0 +1,131 @@
|
||||
package source.recording;
|
||||
|
||||
import gui.control.JFrequencyControl;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.io.File;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextField;
|
||||
|
||||
import source.tuner.FrequencyChangeListener;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
public class RecordingEditorPanel extends JPanel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private RecordingNode mRecordingNode;
|
||||
|
||||
private JTextField mRecordingAlias;
|
||||
private JLabel mFilePathLabel;
|
||||
|
||||
public RecordingEditorPanel( RecordingNode recordingNode )
|
||||
{
|
||||
mRecordingNode = recordingNode;
|
||||
|
||||
initGUI();
|
||||
}
|
||||
|
||||
private void initGUI()
|
||||
{
|
||||
setLayout( new MigLayout( "fill,wrap 2", "[right,grow][grow]", "[][][][][][grow]" ) );
|
||||
|
||||
add( new JLabel( "I/Q Recording" ), "span,align left" );
|
||||
|
||||
add( new JLabel( "Alias:" ) );
|
||||
|
||||
mRecordingAlias = new JTextField( mRecordingNode.getRecording()
|
||||
.getRecordingConfiguration().getAlias() );
|
||||
|
||||
mRecordingAlias.addFocusListener( new FocusListener()
|
||||
{
|
||||
@Override
|
||||
public void focusLost( FocusEvent arg0 )
|
||||
{
|
||||
String alias = mRecordingAlias.getText();
|
||||
|
||||
if( alias != null )
|
||||
{
|
||||
mRecordingNode.getRecording().setAlias( alias );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusGained( FocusEvent arg0 ) {}
|
||||
} );
|
||||
|
||||
add( mRecordingAlias, "wrap" );
|
||||
|
||||
JButton mFileSelectionButton = new JButton( "File ..." );
|
||||
mFileSelectionButton.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent arg0 )
|
||||
{
|
||||
if( mRecordingNode.getRecording().hasChannels() )
|
||||
{
|
||||
JOptionPane.showMessageDialog( RecordingEditorPanel.this,
|
||||
"This recording is currently in replay. Please "
|
||||
+ "disable any channels that are using this "
|
||||
+ "recording before changing the recording file." );
|
||||
}
|
||||
else
|
||||
{
|
||||
final JFileChooser fc = new JFileChooser();
|
||||
|
||||
int returnVal = fc.showOpenDialog( RecordingEditorPanel.this );
|
||||
|
||||
if ( returnVal == JFileChooser.APPROVE_OPTION )
|
||||
{
|
||||
File file = fc.getSelectedFile();
|
||||
|
||||
if( file != null && file.exists() )
|
||||
{
|
||||
mRecordingNode.getRecording()
|
||||
.getRecordingConfiguration()
|
||||
.setFilePath( file.getAbsolutePath() );
|
||||
|
||||
if( mFilePathLabel != null )
|
||||
{
|
||||
mFilePathLabel.setText( file.getName() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
add( mFileSelectionButton );
|
||||
|
||||
String filePath = mRecordingNode.getRecording()
|
||||
.getRecordingConfiguration().getFilePath();
|
||||
|
||||
if( filePath != null )
|
||||
{
|
||||
mFilePathLabel = new JLabel( filePath );
|
||||
}
|
||||
else
|
||||
{
|
||||
mFilePathLabel = new JLabel( "Please select a recording" );
|
||||
}
|
||||
|
||||
add( mFilePathLabel, "wrap" );
|
||||
|
||||
add( new JLabel( "Center Frequency:" ), "span,align left" );
|
||||
|
||||
JFrequencyControl frequencyControl = new JFrequencyControl(
|
||||
mRecordingNode.getRecording().getRecordingConfiguration()
|
||||
.getCenterFrequency() );
|
||||
|
||||
frequencyControl.addListener( mRecordingNode.getRecording() );
|
||||
|
||||
add( frequencyControl, "span,align left" );
|
||||
}
|
||||
}
|
||||
91
src/source/recording/RecordingGroupNode.java
Normal file
91
src/source/recording/RecordingGroupNode.java
Normal file
@@ -0,0 +1,91 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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 <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package source.recording;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JPopupMenu;
|
||||
|
||||
import controller.BaseNode;
|
||||
|
||||
public class RecordingGroupNode extends BaseNode
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public RecordingGroupNode()
|
||||
{
|
||||
super( null );
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "Recordings [" + this.getChildCount() + "]";
|
||||
}
|
||||
|
||||
public JPopupMenu getContextMenu()
|
||||
{
|
||||
JPopupMenu menu = new JPopupMenu();
|
||||
|
||||
JMenuItem addRecordingItem = new JMenuItem( "Add Recording" );
|
||||
|
||||
addRecordingItem.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
RecordingConfiguration config = new RecordingConfiguration();
|
||||
|
||||
getModel().getResourceManager().getSettingsManager()
|
||||
.addRecordingConfiguration( config );
|
||||
|
||||
Recording recording = getModel().getResourceManager()
|
||||
.getRecordingSourceManager().addRecording( config );
|
||||
|
||||
RecordingNode node = new RecordingNode( recording );
|
||||
|
||||
getModel().addNode( node, RecordingGroupNode.this, 0 );
|
||||
|
||||
sort();
|
||||
|
||||
node.show();
|
||||
}
|
||||
} );
|
||||
|
||||
menu.add( addRecordingItem );
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
public void loadRecordings()
|
||||
{
|
||||
List<Recording> recordings = getModel().getResourceManager()
|
||||
.getRecordingSourceManager().getRecordings();
|
||||
|
||||
for( Recording recording: recordings )
|
||||
{
|
||||
RecordingNode node = new RecordingNode( recording );
|
||||
|
||||
getModel().addNode( node, this, 0 );
|
||||
}
|
||||
|
||||
sort();
|
||||
}
|
||||
}
|
||||
79
src/source/recording/RecordingNode.java
Normal file
79
src/source/recording/RecordingNode.java
Normal file
@@ -0,0 +1,79 @@
|
||||
package source.recording;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JPopupMenu;
|
||||
|
||||
import controller.BaseNode;
|
||||
|
||||
public class RecordingNode extends BaseNode
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JPanel mEditor;
|
||||
|
||||
public RecordingNode( Recording recording )
|
||||
{
|
||||
super( recording );
|
||||
}
|
||||
|
||||
public Recording getRecording()
|
||||
{
|
||||
return (Recording)getUserObject();
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return getRecording().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JPanel getEditor()
|
||||
{
|
||||
if( mEditor == null )
|
||||
{
|
||||
mEditor = new RecordingEditorPanel( this );
|
||||
}
|
||||
|
||||
return mEditor;
|
||||
}
|
||||
|
||||
public JPopupMenu getContextMenu()
|
||||
{
|
||||
JPopupMenu menu = new JPopupMenu();
|
||||
|
||||
JMenuItem deleteItem = new JMenuItem( "Delete" );
|
||||
|
||||
deleteItem.addActionListener( new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e )
|
||||
{
|
||||
if( getRecording().hasChannels() )
|
||||
{
|
||||
JOptionPane.showMessageDialog( getModel().getTree(),
|
||||
"Can't delete recording - currently in use. Please"
|
||||
+ " disable any channel(s) that are using this "
|
||||
+ "recording before deleting it",
|
||||
"Can't delete recording",
|
||||
JOptionPane.ERROR_MESSAGE );
|
||||
}
|
||||
else
|
||||
{
|
||||
getModel().getResourceManager().getRecordingSourceManager()
|
||||
.removeRecording( getRecording() );
|
||||
|
||||
getModel().removeNodeFromParent( RecordingNode.this );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
menu.add( deleteItem );
|
||||
|
||||
return menu;
|
||||
}
|
||||
}
|
||||
152
src/source/recording/RecordingSourceManager.java
Normal file
152
src/source/recording/RecordingSourceManager.java
Normal file
@@ -0,0 +1,152 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 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 <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package source.recording;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import log.Log;
|
||||
import settings.SettingsManager;
|
||||
import source.Source;
|
||||
import source.SourceException;
|
||||
import source.config.SourceConfigRecording;
|
||||
import source.tuner.TunerChannel;
|
||||
import source.tuner.TunerChannelSource;
|
||||
import controller.ResourceManager;
|
||||
import controller.channel.ProcessingChain;
|
||||
|
||||
public class RecordingSourceManager
|
||||
{
|
||||
private ResourceManager mResourceManager;
|
||||
|
||||
private ArrayList<Recording> mRecordings = new ArrayList<Recording>();
|
||||
|
||||
public RecordingSourceManager( ResourceManager resourceManager )
|
||||
{
|
||||
mResourceManager = resourceManager;
|
||||
|
||||
loadRecordings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates current recordings to get a tuner channel source for the frequency
|
||||
* specified in the channel config's source config object
|
||||
*/
|
||||
public Source getSource( ProcessingChain processingChain )
|
||||
throws SourceException
|
||||
{
|
||||
TunerChannelSource retVal = null;
|
||||
|
||||
if( processingChain.getChannel().getSourceConfiguration()
|
||||
instanceof SourceConfigRecording )
|
||||
{
|
||||
TunerChannel tunerChannel =
|
||||
processingChain.getChannel().getTunerChannel();
|
||||
|
||||
SourceConfigRecording config = (SourceConfigRecording)processingChain
|
||||
.getChannel().getSourceConfiguration();
|
||||
|
||||
Recording recording = getRecordingFromAlias( config.getRecordingAlias() );
|
||||
|
||||
if( recording != null )
|
||||
{
|
||||
retVal = recording.getChannel(
|
||||
mResourceManager.getThreadPoolManager(),
|
||||
tunerChannel );
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new SourceException( "Recording with alias name [" +
|
||||
config.getRecordingAlias() + "] is not currently available" );
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public Recording getRecordingFromAlias( String alias )
|
||||
{
|
||||
for( Recording recording: mRecordings )
|
||||
{
|
||||
if( recording.getRecordingConfiguration()
|
||||
.getAlias().contentEquals( alias ) )
|
||||
{
|
||||
return recording;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of loaded IQ files
|
||||
*/
|
||||
public List<Recording> getRecordings()
|
||||
{
|
||||
Collections.sort( mRecordings );
|
||||
|
||||
return mRecordings;
|
||||
}
|
||||
|
||||
public void addRecording( Recording recording )
|
||||
{
|
||||
mRecordings.add( recording );
|
||||
}
|
||||
|
||||
public Recording addRecording( RecordingConfiguration config )
|
||||
{
|
||||
Recording recording = new Recording( mResourceManager, config );
|
||||
|
||||
mRecordings.add( recording );
|
||||
|
||||
return recording;
|
||||
}
|
||||
|
||||
public void removeRecording( Recording recording )
|
||||
{
|
||||
/* Remove the config from the settings manager */
|
||||
mResourceManager.getSettingsManager().removeRecordingConfiguration(
|
||||
recording.getRecordingConfiguration() );
|
||||
|
||||
mRecordings.remove( recording );
|
||||
}
|
||||
|
||||
private void loadRecordings()
|
||||
{
|
||||
if( mResourceManager != null )
|
||||
{
|
||||
SettingsManager settingsManager = mResourceManager.getSettingsManager();
|
||||
|
||||
if( settingsManager != null )
|
||||
{
|
||||
ArrayList<RecordingConfiguration> recordingConfigurations =
|
||||
settingsManager.getRecordingConfigurations();
|
||||
|
||||
Log.info( "RecordingSourceManager - discovered [" + recordingConfigurations.size() + "] recording configurations" );
|
||||
|
||||
for( RecordingConfiguration config: recordingConfigurations )
|
||||
{
|
||||
Recording recording = new Recording( mResourceManager, config );
|
||||
|
||||
mRecordings.add( recording );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,8 @@ import controller.ThreadPoolManager;
|
||||
* Tuner - provides tuner channel sources, representing a channel frequency
|
||||
*/
|
||||
public abstract class Tuner implements FrequencyChangeBroadcaster,
|
||||
FrequencyChangeListener
|
||||
FrequencyChangeListener,
|
||||
TunerChannelProvider
|
||||
{
|
||||
private String mName;
|
||||
|
||||
|
||||
28
src/source/tuner/TunerChannelProvider.java
Normal file
28
src/source/tuner/TunerChannelProvider.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package source.tuner;
|
||||
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import source.SourceException;
|
||||
import controller.ThreadPoolManager;
|
||||
|
||||
public interface TunerChannelProvider
|
||||
{
|
||||
/**
|
||||
* Returns a tuner frequency channel source, tuned to the correct frequency
|
||||
*
|
||||
* @param frequency - desired frequency
|
||||
*
|
||||
* @return - source for 48k sample rate
|
||||
*/
|
||||
public abstract TunerChannelSource getChannel( ThreadPoolManager threadPoolManager,
|
||||
TunerChannel channel ) throws RejectedExecutionException, SourceException;
|
||||
|
||||
/**
|
||||
* Releases the tuned channel resources
|
||||
*
|
||||
* @param channel - previously obtained tuner channel
|
||||
*/
|
||||
public abstract void releaseChannel( TunerChannelSource source );
|
||||
|
||||
|
||||
}
|
||||
@@ -21,15 +21,17 @@ import gui.control.JFrequencyControl;
|
||||
import source.SourceEditor;
|
||||
import source.config.SourceConfigTuner;
|
||||
import source.config.SourceConfiguration;
|
||||
import controller.ResourceManager;
|
||||
|
||||
public class TunerEditor extends SourceEditor
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private JFrequencyControl mFrequencyControl;
|
||||
|
||||
public TunerEditor( SourceConfiguration config )
|
||||
public TunerEditor( ResourceManager resourceManager,
|
||||
SourceConfiguration config )
|
||||
{
|
||||
super( config );
|
||||
super( resourceManager, config );
|
||||
|
||||
initGUI();
|
||||
}
|
||||
|
||||
@@ -65,15 +65,15 @@ public class TunerManager
|
||||
* Iterates current tuners to get a tuner channel source for the frequency
|
||||
* specified in the channel config's source config object
|
||||
*/
|
||||
public Source getSource( ProcessingChain channel )
|
||||
public Source getSource( ProcessingChain processingChain )
|
||||
{
|
||||
TunerChannelSource retVal = null;
|
||||
|
||||
|
||||
if( channel.getChannel().getSourceConfiguration()
|
||||
if( processingChain.getChannel().getSourceConfiguration()
|
||||
instanceof SourceConfigTuner )
|
||||
{
|
||||
TunerChannel tunerChannel = channel.getChannel().getTunerChannel();
|
||||
TunerChannel tunerChannel = processingChain.getChannel().getTunerChannel();
|
||||
|
||||
Iterator<Tuner> it = mTuners.iterator();
|
||||
|
||||
|
||||
@@ -368,16 +368,24 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
|
||||
if( claim( iface ) )
|
||||
{
|
||||
Log.debug( "RTL2832 - usb interface claimed" );
|
||||
|
||||
/* Perform a dummy write to see if the device needs reset */
|
||||
writeRegister( device, Block.USB, Address.USB_SYSCTL.getAddress(), 0x09, 1 );
|
||||
|
||||
Log.debug( "RTL2832 - initializing baseband" );
|
||||
|
||||
/* Initialize the baseband */
|
||||
initBaseband( device );
|
||||
|
||||
Log.debug( "RTL2832 - enabling I2C repeater" );
|
||||
|
||||
enableI2CRepeater( device, true );
|
||||
|
||||
boolean controlI2CRepeater = false;
|
||||
|
||||
Log.debug( "RTL2832 - testing for tuner types" );
|
||||
|
||||
/* Test for each tuner type until we find the correct one */
|
||||
if( isE4000Tuner( device, controlI2CRepeater ) )
|
||||
{
|
||||
@@ -404,15 +412,19 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
tunerClass = TunerType.FITIPOWER_FC0012;
|
||||
}
|
||||
|
||||
Log.debug( "RTL2832 - disabling I2C repeater" );
|
||||
|
||||
enableI2CRepeater( device, false );
|
||||
|
||||
Log.debug( "RTL2832 - releasing USB interface" );
|
||||
|
||||
iface.release();
|
||||
}
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
Log.error( "RTL2832TunerController - error while determining "
|
||||
+ "tuner type - " + e.getLocalizedMessage() );
|
||||
+ "tuner type - ", e );
|
||||
}
|
||||
|
||||
return tunerClass;
|
||||
@@ -927,6 +939,8 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
protected static boolean isE4000Tuner( UsbDevice device,
|
||||
boolean controlI2CRepeater ) throws UsbClaimException
|
||||
{
|
||||
Log.debug( "RTL2832 - testing for E4000 tuner" );
|
||||
|
||||
try
|
||||
{
|
||||
int value = readI2CRegister( device, E4K_I2C_ADDRESS,
|
||||
@@ -974,6 +988,7 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
boolean controlI2CRepeater )
|
||||
throws UsbClaimException
|
||||
{
|
||||
Log.debug( "RTL2832 - testing for F0013 tuner" );
|
||||
try
|
||||
{
|
||||
int value = readI2CRegister( device, FC0013_I2C_ADDRESS,
|
||||
@@ -1030,6 +1045,7 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
protected static boolean isR820TTuner( UsbDevice device,
|
||||
boolean controlI2CRepeater ) throws UsbClaimException
|
||||
{
|
||||
Log.debug( "RTL2832 - testing for R820T tuner" );
|
||||
try
|
||||
{
|
||||
int value = readI2CRegister( device, R820T_I2C_ADDRESS,
|
||||
|
||||
Reference in New Issue
Block a user