mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-15 01:57:39 -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:
@@ -31,6 +31,7 @@ import javax.swing.tree.TreePath;
|
|||||||
import map.IconManager;
|
import map.IconManager;
|
||||||
import playlist.PlaylistNode;
|
import playlist.PlaylistNode;
|
||||||
import source.config.SourceConfigTuner;
|
import source.config.SourceConfigTuner;
|
||||||
|
import source.recording.RecordingGroupNode;
|
||||||
import source.tuner.Tuner;
|
import source.tuner.Tuner;
|
||||||
import source.tuner.TunerGroupNode;
|
import source.tuner.TunerGroupNode;
|
||||||
import source.tuner.TunerNode;
|
import source.tuner.TunerNode;
|
||||||
@@ -61,8 +62,8 @@ public class ConfigurationControllerModel extends DefaultTreeModel
|
|||||||
|
|
||||||
|
|
||||||
private PlaylistNode mPlaylistNode;
|
private PlaylistNode mPlaylistNode;
|
||||||
|
|
||||||
private TunerGroupNode mTunerGroupNode;
|
private TunerGroupNode mTunerGroupNode;
|
||||||
|
private RecordingGroupNode mRecordingGroupNode;
|
||||||
|
|
||||||
private IconManager mIconManagerFrame;
|
private IconManager mIconManagerFrame;
|
||||||
|
|
||||||
@@ -114,17 +115,24 @@ public class ConfigurationControllerModel extends DefaultTreeModel
|
|||||||
public void init()
|
public void init()
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Add the root tuner group node
|
* Add the tuner group node
|
||||||
*/
|
*/
|
||||||
mTunerGroupNode = new TunerGroupNode();
|
mTunerGroupNode = new TunerGroupNode();
|
||||||
insertNodeInto( mTunerGroupNode, (MutableTreeNode)root, 0 );
|
insertNodeInto( mTunerGroupNode, (MutableTreeNode)root, 0 );
|
||||||
addTuners( mTunerGroupNode );
|
addTuners( mTunerGroupNode );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the recording group node
|
||||||
|
*/
|
||||||
|
mRecordingGroupNode = new RecordingGroupNode();
|
||||||
|
insertNodeInto( mRecordingGroupNode, (MutableTreeNode)root, 1 );
|
||||||
|
mRecordingGroupNode.loadRecordings();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add the playlist node
|
* Add the playlist node
|
||||||
*/
|
*/
|
||||||
mPlaylistNode = new PlaylistNode();
|
mPlaylistNode = new PlaylistNode();
|
||||||
insertNodeInto( mPlaylistNode, (MutableTreeNode)root, 1 );
|
insertNodeInto( mPlaylistNode, (MutableTreeNode)root, 2 );
|
||||||
mPlaylistNode.loadPlaylist();
|
mPlaylistNode.loadPlaylist();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import playlist.PlaylistManager;
|
|||||||
import record.RecorderManager;
|
import record.RecorderManager;
|
||||||
import settings.SettingsManager;
|
import settings.SettingsManager;
|
||||||
import source.SourceManager;
|
import source.SourceManager;
|
||||||
|
import source.recording.RecordingSourceManager;
|
||||||
import source.tuner.TunerManager;
|
import source.tuner.TunerManager;
|
||||||
import controller.channel.ChannelManager;
|
import controller.channel.ChannelManager;
|
||||||
import eventlog.EventLogManager;
|
import eventlog.EventLogManager;
|
||||||
@@ -35,6 +36,7 @@ public class ResourceManager
|
|||||||
private EventLogManager mEventLogManager;
|
private EventLogManager mEventLogManager;
|
||||||
private PlaylistManager mPlaylistManager;
|
private PlaylistManager mPlaylistManager;
|
||||||
private RecorderManager mRecorderManager;
|
private RecorderManager mRecorderManager;
|
||||||
|
private RecordingSourceManager mRecordingSourceManager;
|
||||||
private SettingsManager mSettingsManager;
|
private SettingsManager mSettingsManager;
|
||||||
private SourceManager mSourceManager;
|
private SourceManager mSourceManager;
|
||||||
private TunerManager mTunerManager;
|
private TunerManager mTunerManager;
|
||||||
@@ -66,6 +68,7 @@ public class ResourceManager
|
|||||||
*/
|
*/
|
||||||
mChannelManager = new ChannelManager( this );
|
mChannelManager = new ChannelManager( this );
|
||||||
mSourceManager = new SourceManager( this );
|
mSourceManager = new SourceManager( this );
|
||||||
|
mRecordingSourceManager = new RecordingSourceManager( this );
|
||||||
mTunerManager = new TunerManager( this );
|
mTunerManager = new TunerManager( this );
|
||||||
mController = new ConfigurationControllerModel( this );
|
mController = new ConfigurationControllerModel( this );
|
||||||
mMapService = new MapService( this );
|
mMapService = new MapService( this );
|
||||||
@@ -147,6 +150,16 @@ public class ResourceManager
|
|||||||
mSourceManager = sourceManager;
|
mSourceManager = sourceManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RecordingSourceManager getRecordingSourceManager()
|
||||||
|
{
|
||||||
|
return mRecordingSourceManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRecordingSourceManager( RecordingSourceManager manager )
|
||||||
|
{
|
||||||
|
mRecordingSourceManager = manager;
|
||||||
|
}
|
||||||
|
|
||||||
public ChannelManager getChannelManager()
|
public ChannelManager getChannelManager()
|
||||||
{
|
{
|
||||||
return mChannelManager;
|
return mChannelManager;
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import record.config.RecordConfiguration;
|
|||||||
import sample.Listener;
|
import sample.Listener;
|
||||||
import source.SourceType;
|
import source.SourceType;
|
||||||
import source.config.SourceConfigFactory;
|
import source.config.SourceConfigFactory;
|
||||||
|
import source.config.SourceConfigRecording;
|
||||||
import source.config.SourceConfigTuner;
|
import source.config.SourceConfigTuner;
|
||||||
import source.config.SourceConfiguration;
|
import source.config.SourceConfiguration;
|
||||||
import source.tuner.TunerChannel;
|
import source.tuner.TunerChannel;
|
||||||
@@ -344,6 +345,14 @@ public class Channel extends Configuration
|
|||||||
retVal = new TunerChannel( Type.LOCKED, config.getFrequency(),
|
retVal = new TunerChannel( Type.LOCKED, config.getFrequency(),
|
||||||
mDecodeConfiguration.getDecoderType().getChannelBandwidth() );
|
mDecodeConfiguration.getDecoderType().getChannelBandwidth() );
|
||||||
}
|
}
|
||||||
|
else if( mSourceConfiguration.getSourceType() == SourceType.RECORDING )
|
||||||
|
{
|
||||||
|
SourceConfigRecording config =
|
||||||
|
(SourceConfigRecording)mSourceConfiguration;
|
||||||
|
|
||||||
|
retVal = new TunerChannel( Type.LOCKED, config.getFrequency(),
|
||||||
|
mDecodeConfiguration.getDecoderType().getChannelBandwidth() );
|
||||||
|
}
|
||||||
|
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import source.FloatArraySource;
|
|||||||
import source.FloatSource;
|
import source.FloatSource;
|
||||||
import source.Source;
|
import source.Source;
|
||||||
import source.Source.SampleType;
|
import source.Source.SampleType;
|
||||||
|
import source.SourceException;
|
||||||
import source.config.SourceConfigMixer;
|
import source.config.SourceConfigMixer;
|
||||||
import source.tuner.Tuner;
|
import source.tuner.Tuner;
|
||||||
import source.tuner.TunerChannelSource;
|
import source.tuner.TunerChannelSource;
|
||||||
@@ -256,8 +257,18 @@ public class ProcessingChain implements Listener<Message>
|
|||||||
/* Get a new source if needed and start the sample processor thread */
|
/* Get a new source if needed and start the sample processor thread */
|
||||||
if( mChannel.getEnabled() && mResourceManager != null )
|
if( mChannel.getEnabled() && mResourceManager != null )
|
||||||
{
|
{
|
||||||
mSource = mResourceManager.getSourceManager()
|
try
|
||||||
.getSource( ProcessingChain.this );
|
{
|
||||||
|
mSource = mResourceManager.getSourceManager()
|
||||||
|
.getSource( ProcessingChain.this );
|
||||||
|
}
|
||||||
|
catch ( SourceException e )
|
||||||
|
{
|
||||||
|
Log.error( "Couldn't obtain source for processing chain [" +
|
||||||
|
toString() + "] - " + e.getLocalizedMessage() );
|
||||||
|
|
||||||
|
mSource = null;
|
||||||
|
}
|
||||||
|
|
||||||
if( mSource != null )
|
if( mSource != null )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -31,7 +31,8 @@ public enum DecoderType
|
|||||||
MDC1200( "MDC1200", "MDC1200", "images/fm", 12500 ),
|
MDC1200( "MDC1200", "MDC1200", "images/fm", 12500 ),
|
||||||
MPT1327( "MPT1327", "MPT1327", "images/mpt1327", 12500 ),
|
MPT1327( "MPT1327", "MPT1327", "images/mpt1327", 12500 ),
|
||||||
NBFM( "NBFM", "NBFM", "images/fm", 12500 ),
|
NBFM( "NBFM", "NBFM", "images/fm", 12500 ),
|
||||||
PASSPORT( "Passport", "Passport", "images/passport", 12500 );
|
PASSPORT( "Passport", "Passport", "images/passport", 12500 ),
|
||||||
|
P25( "P25", "P25", "images/p25", 12500 );
|
||||||
|
|
||||||
private String mDisplayString;
|
private String mDisplayString;
|
||||||
private String mShortDisplayString;
|
private String mShortDisplayString;
|
||||||
@@ -68,7 +69,8 @@ public enum DecoderType
|
|||||||
DecoderType.LTR_NET,
|
DecoderType.LTR_NET,
|
||||||
DecoderType.MDC1200,
|
DecoderType.MDC1200,
|
||||||
DecoderType.MPT1327,
|
DecoderType.MPT1327,
|
||||||
DecoderType.PASSPORT );
|
DecoderType.PASSPORT,
|
||||||
|
DecoderType.P25 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
144
src/decode/p25/P25Decoder.java
Normal file
144
src/decode/p25/P25Decoder.java
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* 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 decode.p25;
|
||||||
|
|
||||||
|
import instrument.Instrumentable;
|
||||||
|
import instrument.tap.Tap;
|
||||||
|
import instrument.tap.stream.FloatTap;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import source.Source.SampleType;
|
||||||
|
import alias.AliasList;
|
||||||
|
import decode.Decoder;
|
||||||
|
import decode.DecoderType;
|
||||||
|
import dsp.filter.DCRemovalFilter2;
|
||||||
|
import dsp.fsk.C4FMDecoder;
|
||||||
|
import dsp.nbfm.FilteringNBFMDemodulator;
|
||||||
|
|
||||||
|
public class P25Decoder extends Decoder implements Instrumentable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* This value determines how quickly the DC remove filter responds to
|
||||||
|
* changes in frequency.
|
||||||
|
*/
|
||||||
|
private static final double sDC_REMOVAL_RATIO = 0.000003;
|
||||||
|
|
||||||
|
private final String TAP_DEMOD_TO_DECODER = "Demodulated Audio <> C4FM Decoder";
|
||||||
|
|
||||||
|
private FilteringNBFMDemodulator mDemodulator;
|
||||||
|
private DCRemovalFilter2 mDCRemovalFilter;
|
||||||
|
private C4FMDecoder mC4FMDecoder;
|
||||||
|
private AliasList mAliasList;
|
||||||
|
|
||||||
|
private ArrayList<Tap> mTaps;
|
||||||
|
|
||||||
|
public P25Decoder( SampleType sampleType, AliasList aliasList )
|
||||||
|
{
|
||||||
|
super( sampleType );
|
||||||
|
|
||||||
|
mAliasList = aliasList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only setup a demod chain if we're receiving complex samples. If
|
||||||
|
* we're receiving demodulated samples, they'll be handled the same
|
||||||
|
* way as we handle the output of the demodulator.
|
||||||
|
*/
|
||||||
|
if( mSourceSampleType == SampleType.COMPLEX )
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The Decoder super class is both a Complex listener and a float
|
||||||
|
* listener. So, we add the demod to listen to the incoming
|
||||||
|
* quadrature samples, and we wire the output of the demod right
|
||||||
|
* back to this class, so we can receive the demodulated output
|
||||||
|
* to process
|
||||||
|
*/
|
||||||
|
mDemodulator = new FilteringNBFMDemodulator();
|
||||||
|
this.addComplexListener( mDemodulator );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the DC component that is present when we're mistuned
|
||||||
|
*/
|
||||||
|
mDCRemovalFilter = new DCRemovalFilter2( sDC_REMOVAL_RATIO );
|
||||||
|
mDemodulator.addListener( mDCRemovalFilter );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Route the demodulated, filtered samples back to this class to send
|
||||||
|
* to all registered listeners
|
||||||
|
*/
|
||||||
|
mDCRemovalFilter.setListener( this.getFloatReceiver() );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
mC4FMDecoder = new C4FMDecoder();
|
||||||
|
addFloatListener( mC4FMDecoder );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DecoderType getType()
|
||||||
|
{
|
||||||
|
return DecoderType.NBFM;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Tap> getTaps()
|
||||||
|
{
|
||||||
|
if( mTaps == null )
|
||||||
|
{
|
||||||
|
mTaps = new ArrayList<Tap>();
|
||||||
|
mTaps.add( new FloatTap( TAP_DEMOD_TO_DECODER, 0, 1.0f ) );
|
||||||
|
|
||||||
|
mTaps.addAll( mC4FMDecoder.getTaps() );
|
||||||
|
}
|
||||||
|
|
||||||
|
return mTaps;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addTap( Tap tap )
|
||||||
|
{
|
||||||
|
mC4FMDecoder.addTap( tap );
|
||||||
|
|
||||||
|
switch( tap.getName() )
|
||||||
|
{
|
||||||
|
case TAP_DEMOD_TO_DECODER:
|
||||||
|
FloatTap demodTap = (FloatTap)tap;
|
||||||
|
removeFloatListener( mC4FMDecoder );
|
||||||
|
addFloatListener( demodTap );
|
||||||
|
demodTap.setListener( mC4FMDecoder );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeTap( Tap tap )
|
||||||
|
{
|
||||||
|
mC4FMDecoder.removeTap( tap );
|
||||||
|
|
||||||
|
switch( tap.getName() )
|
||||||
|
{
|
||||||
|
case TAP_DEMOD_TO_DECODER:
|
||||||
|
FloatTap demodTap = (FloatTap)tap;
|
||||||
|
removeFloatListener( demodTap );
|
||||||
|
demodTap.removeListener( mC4FMDecoder );
|
||||||
|
addFloatListener( mC4FMDecoder );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
66
src/dsp/fsk/C4FMDecoder.java
Normal file
66
src/dsp/fsk/C4FMDecoder.java
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
package dsp.fsk;
|
||||||
|
|
||||||
|
import instrument.Instrumentable;
|
||||||
|
import instrument.tap.Tap;
|
||||||
|
import instrument.tap.stream.FloatTap;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import sample.Listener;
|
||||||
|
|
||||||
|
public class C4FMDecoder implements Listener<Float>, Instrumentable
|
||||||
|
{
|
||||||
|
private final String TAP_C4FM_INPUT = "C4FM Input";
|
||||||
|
private ArrayList<Tap> mTaps;
|
||||||
|
private FloatTap mInputTap;
|
||||||
|
|
||||||
|
public C4FMDecoder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Tap> getTaps()
|
||||||
|
{
|
||||||
|
if( mTaps == null )
|
||||||
|
{
|
||||||
|
mTaps = new ArrayList<Tap>();
|
||||||
|
|
||||||
|
FloatTap floatTap = new FloatTap( TAP_C4FM_INPUT, 0, 1.0f );
|
||||||
|
mTaps.add( floatTap );
|
||||||
|
}
|
||||||
|
|
||||||
|
return mTaps;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addTap( Tap tap )
|
||||||
|
{
|
||||||
|
switch( tap.getName() )
|
||||||
|
{
|
||||||
|
case TAP_C4FM_INPUT:
|
||||||
|
mInputTap = (FloatTap)tap;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeTap( Tap tap )
|
||||||
|
{
|
||||||
|
switch( tap.getName() )
|
||||||
|
{
|
||||||
|
case TAP_C4FM_INPUT:
|
||||||
|
mInputTap = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void receive( Float t )
|
||||||
|
{
|
||||||
|
if( mInputTap != null )
|
||||||
|
{
|
||||||
|
mInputTap.receive( t );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,9 +19,13 @@ package instrument.gui;
|
|||||||
|
|
||||||
import instrument.Instrumentable;
|
import instrument.Instrumentable;
|
||||||
import instrument.tap.Tap;
|
import instrument.tap.Tap;
|
||||||
|
import instrument.tap.TapViewPanel;
|
||||||
import instrument.tap.stream.BinaryTap;
|
import instrument.tap.stream.BinaryTap;
|
||||||
|
import instrument.tap.stream.BinaryTapViewPanel;
|
||||||
import instrument.tap.stream.FloatTap;
|
import instrument.tap.stream.FloatTap;
|
||||||
|
import instrument.tap.stream.FloatTapViewPanel;
|
||||||
import instrument.tap.stream.SymbolEventTap;
|
import instrument.tap.stream.SymbolEventTap;
|
||||||
|
import instrument.tap.stream.SymbolEventTapViewPanel;
|
||||||
|
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
@@ -51,7 +55,9 @@ import decode.Decoder;
|
|||||||
public class DecoderViewFrame extends JInternalFrame
|
public class DecoderViewFrame extends JInternalFrame
|
||||||
implements PositionListener, Listener<Message>
|
implements PositionListener, Listener<Message>
|
||||||
{
|
{
|
||||||
private Decoder mDecoder;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private Decoder mDecoder;
|
||||||
private WaveSource mWaveSource;
|
private WaveSource mWaveSource;
|
||||||
|
|
||||||
private HashMap<Tap,TapViewPanel> mPanelMap =
|
private HashMap<Tap,TapViewPanel> mPanelMap =
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ import decode.fleetsync2.Fleetsync2Decoder;
|
|||||||
import decode.ltrnet.LTRNetDecoder;
|
import decode.ltrnet.LTRNetDecoder;
|
||||||
import decode.mdc1200.MDCDecoder;
|
import decode.mdc1200.MDCDecoder;
|
||||||
import decode.mpt1327.MPT1327Decoder;
|
import decode.mpt1327.MPT1327Decoder;
|
||||||
|
import decode.p25.P25Decoder;
|
||||||
import decode.passport.PassportDecoder;
|
import decode.passport.PassportDecoder;
|
||||||
|
|
||||||
public class WaveSourceFrame extends JInternalFrame implements PositionListener
|
public class WaveSourceFrame extends JInternalFrame implements PositionListener
|
||||||
@@ -146,6 +147,10 @@ public class WaveSourceFrame extends JInternalFrame implements PositionListener
|
|||||||
break;
|
break;
|
||||||
case PASSPORT:
|
case PASSPORT:
|
||||||
decoder = new PassportDecoder( SampleType.FLOAT, null );
|
decoder = new PassportDecoder( SampleType.FLOAT, null );
|
||||||
|
break;
|
||||||
|
case P25:
|
||||||
|
decoder = new P25Decoder( SampleType.FLOAT, null );
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( decoder != null )
|
if( decoder != null )
|
||||||
|
|||||||
@@ -15,7 +15,9 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package instrument.gui;
|
package instrument.tap;
|
||||||
|
|
||||||
|
import instrument.gui.SampleModel;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
@@ -15,10 +15,11 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package instrument.gui;
|
package instrument.tap.stream;
|
||||||
|
|
||||||
|
import instrument.gui.SampleModel;
|
||||||
import instrument.tap.Tap;
|
import instrument.tap.Tap;
|
||||||
import instrument.tap.stream.BinaryTap;
|
import instrument.tap.TapViewPanel;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.FontMetrics;
|
import java.awt.FontMetrics;
|
||||||
128
src/instrument/tap/stream/FloatTapPhaseViewPanel.java
Normal file
128
src/instrument/tap/stream/FloatTapPhaseViewPanel.java
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* 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 instrument.tap.stream;
|
||||||
|
|
||||||
|
import instrument.gui.SampleModel;
|
||||||
|
import instrument.tap.Tap;
|
||||||
|
import instrument.tap.TapViewPanel;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.geom.Path2D;
|
||||||
|
import java.awt.geom.Point2D;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Observable;
|
||||||
|
|
||||||
|
import log.Log;
|
||||||
|
|
||||||
|
public class FloatTapPhaseViewPanel extends TapViewPanel
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private Tap mTap;
|
||||||
|
private List<Float> mSamples;
|
||||||
|
private int mSampleCount;
|
||||||
|
|
||||||
|
public FloatTapPhaseViewPanel( FloatTap tap )
|
||||||
|
{
|
||||||
|
super( new SampleModel<Float>(), tap.getName() );
|
||||||
|
|
||||||
|
mTap = tap;
|
||||||
|
mTap.addListener( getModel() );
|
||||||
|
|
||||||
|
mSampleCount = (int)( 2000 * tap.getSampleRateRatio() );
|
||||||
|
|
||||||
|
getModel().setSampleCount( mSampleCount );
|
||||||
|
getModel().setDelay( tap.getDelay() );
|
||||||
|
|
||||||
|
Log.info( "Float Tap Panel [" + tap.getName() + "] count: " +
|
||||||
|
getModel().getSampleCount() + " delay:" + getModel().getDelay() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update( Observable arg0, Object arg1 )
|
||||||
|
{
|
||||||
|
mSamples = (List<Float>)getModel().getSamples();
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void paintComponent( Graphics g )
|
||||||
|
{
|
||||||
|
super.paintComponent( g );
|
||||||
|
|
||||||
|
Graphics2D g2 = (Graphics2D)g;
|
||||||
|
|
||||||
|
int height = getHeight();
|
||||||
|
int width = getWidth();
|
||||||
|
|
||||||
|
g2.setColor( Color.DARK_GRAY );
|
||||||
|
|
||||||
|
float middle = (float)height / 2.0f;
|
||||||
|
|
||||||
|
g2.drawLine( 0, (int)middle, width, (int)middle );
|
||||||
|
|
||||||
|
if( mSamples != null &&
|
||||||
|
mSamples.size() > 0 )
|
||||||
|
{
|
||||||
|
g2.setColor( getForeground() );
|
||||||
|
|
||||||
|
g2.drawString( mLabel, 5 , 15 );
|
||||||
|
|
||||||
|
Path2D.Float polyline =
|
||||||
|
new Path2D.Float( Path2D.Float.WIND_EVEN_ODD, mSamples.size() );
|
||||||
|
|
||||||
|
/* Move to the first point */
|
||||||
|
Point2D.Float first = resolve( 0, mSamples.get( 0 ) );
|
||||||
|
polyline.moveTo( first.x, first.y );
|
||||||
|
|
||||||
|
for( int x = 1; x < mSamples.size(); x++ )
|
||||||
|
{
|
||||||
|
Point2D.Float point = resolve( x, mSamples.get( x ) );
|
||||||
|
|
||||||
|
polyline.lineTo( point.x, point.y );
|
||||||
|
}
|
||||||
|
|
||||||
|
g2.draw(polyline);
|
||||||
|
}
|
||||||
|
|
||||||
|
g2.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Point2D.Float resolve( int index, float value )
|
||||||
|
{
|
||||||
|
int middle = (int)( getHeight() / 2 );
|
||||||
|
|
||||||
|
double scaledValue = Math.asin( value );
|
||||||
|
|
||||||
|
float y = middle - (float)( middle * scaledValue * mVerticalZoom );
|
||||||
|
|
||||||
|
/* Clip y to zero as necessary */
|
||||||
|
y = ( y < 0 ) ? 0 : y;
|
||||||
|
|
||||||
|
/* Clip y to max height as necessary */
|
||||||
|
y = ( y > getHeight() ) ? getHeight() : y;
|
||||||
|
|
||||||
|
float indexWidth = (float)getWidth() / (float)mSampleCount;
|
||||||
|
|
||||||
|
float x = (float)index * indexWidth;
|
||||||
|
|
||||||
|
Point2D.Float point = new Point2D.Float( x, y );
|
||||||
|
|
||||||
|
return new Point2D.Float( x , y );
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,10 +15,11 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package instrument.gui;
|
package instrument.tap.stream;
|
||||||
|
|
||||||
|
import instrument.gui.SampleModel;
|
||||||
import instrument.tap.Tap;
|
import instrument.tap.Tap;
|
||||||
import instrument.tap.stream.FloatTap;
|
import instrument.tap.TapViewPanel;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
@@ -108,6 +109,7 @@ public class FloatTapViewPanel extends TapViewPanel
|
|||||||
|
|
||||||
float scaledValue = value / (float)Short.MAX_VALUE;
|
float scaledValue = value / (float)Short.MAX_VALUE;
|
||||||
|
|
||||||
|
Log.info( "Float value is:" + scaledValue );
|
||||||
float y = middle - ( middle * scaledValue * mVerticalZoom );
|
float y = middle - ( middle * scaledValue * mVerticalZoom );
|
||||||
|
|
||||||
/* Clip y to zero as necessary */
|
/* Clip y to zero as necessary */
|
||||||
@@ -15,9 +15,10 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package instrument.gui;
|
package instrument.tap.stream;
|
||||||
|
|
||||||
import instrument.tap.stream.SymbolEventTap;
|
import instrument.gui.SampleModel;
|
||||||
|
import instrument.tap.TapViewPanel;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.FontMetrics;
|
import java.awt.FontMetrics;
|
||||||
@@ -86,6 +86,32 @@ public class Log
|
|||||||
System.out.println( ( label == null ? "" : label + ": " ) + msg );
|
System.out.println( ( label == null ? "" : label + ": " ) + msg );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void log( String msg, String label, Throwable throwable )
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
if( msg != null )
|
||||||
|
{
|
||||||
|
sb.append( msg );
|
||||||
|
sb.append( "\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append( "---- STACK TRACE ----\n" );
|
||||||
|
sb.append( "\tERROR: " );
|
||||||
|
sb.append( throwable.getLocalizedMessage() + "\n" );
|
||||||
|
|
||||||
|
StackTraceElement[] stack = throwable.getStackTrace();
|
||||||
|
|
||||||
|
for( StackTraceElement element: stack )
|
||||||
|
{
|
||||||
|
sb.append( "\t" );
|
||||||
|
sb.append( element.toString() );
|
||||||
|
sb.append( "\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
log( sb.toString(), label );
|
||||||
|
}
|
||||||
|
|
||||||
public static void header( String name )
|
public static void header( String name )
|
||||||
{
|
{
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
@@ -138,11 +164,21 @@ public class Log
|
|||||||
log( msg, "ERROR" );
|
log( msg, "ERROR" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void error( String msg, Throwable throwable )
|
||||||
|
{
|
||||||
|
log( msg, "ERROR", throwable );
|
||||||
|
}
|
||||||
|
|
||||||
public static void debug( String msg )
|
public static void debug( String msg )
|
||||||
{
|
{
|
||||||
log( msg, "DEBUG" );
|
log( msg, "DEBUG" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void debug( String msg, Throwable throwable )
|
||||||
|
{
|
||||||
|
log( msg, "DEBUG", throwable );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes logging to the specified filename
|
* Initializes logging to the specified filename
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -26,10 +26,8 @@ import javax.xml.bind.annotation.XmlSeeAlso;
|
|||||||
|
|
||||||
import map.DefaultIcon;
|
import map.DefaultIcon;
|
||||||
import map.MapIcon;
|
import map.MapIcon;
|
||||||
|
|
||||||
import org.jdesktop.swingx.mapviewer.GeoPosition;
|
|
||||||
|
|
||||||
import settings.ColorSetting.ColorSettingName;
|
import settings.ColorSetting.ColorSettingName;
|
||||||
|
import source.recording.RecordingConfiguration;
|
||||||
import source.tuner.TunerConfiguration;
|
import source.tuner.TunerConfiguration;
|
||||||
import source.tuner.TunerConfigurationAssignment;
|
import source.tuner.TunerConfigurationAssignment;
|
||||||
import source.tuner.TunerType;
|
import source.tuner.TunerType;
|
||||||
@@ -50,6 +48,7 @@ import source.tuner.rtl.r820t.R820TTunerConfiguration;
|
|||||||
MapViewSetting.class,
|
MapViewSetting.class,
|
||||||
MapIcon.class,
|
MapIcon.class,
|
||||||
R820TTunerConfiguration.class,
|
R820TTunerConfiguration.class,
|
||||||
|
RecordingConfiguration.class,
|
||||||
Setting.class,
|
Setting.class,
|
||||||
TunerConfiguration.class,
|
TunerConfiguration.class,
|
||||||
TunerConfigurationAssignment.class} )
|
TunerConfigurationAssignment.class} )
|
||||||
@@ -65,10 +64,35 @@ public class Settings
|
|||||||
private ArrayList<TunerConfigurationAssignment> mConfigurationAssignments =
|
private ArrayList<TunerConfigurationAssignment> mConfigurationAssignments =
|
||||||
new ArrayList<TunerConfigurationAssignment>();
|
new ArrayList<TunerConfigurationAssignment>();
|
||||||
|
|
||||||
|
private ArrayList<RecordingConfiguration> mRecordingConfigurations =
|
||||||
|
new ArrayList<RecordingConfiguration>();
|
||||||
|
|
||||||
public Settings()
|
public Settings()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@XmlElement( name="recording_configuration" )
|
||||||
|
public ArrayList<RecordingConfiguration> getRecordingConfigurations()
|
||||||
|
{
|
||||||
|
return mRecordingConfigurations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRecordingConfigurations( ArrayList<RecordingConfiguration> configs )
|
||||||
|
{
|
||||||
|
mRecordingConfigurations = configs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addRecordingConfiguration( RecordingConfiguration config )
|
||||||
|
{
|
||||||
|
mRecordingConfigurations.add( config );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeRecordingConfiguration( RecordingConfiguration config )
|
||||||
|
{
|
||||||
|
mRecordingConfigurations.remove( config );
|
||||||
|
}
|
||||||
|
|
||||||
@XmlElement( name="tuner_configuration" )
|
@XmlElement( name="tuner_configuration" )
|
||||||
public ArrayList<TunerConfiguration> getTunerConfigurations()
|
public ArrayList<TunerConfiguration> getTunerConfigurations()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ import org.jdesktop.swingx.mapviewer.GeoPosition;
|
|||||||
|
|
||||||
import properties.SystemProperties;
|
import properties.SystemProperties;
|
||||||
import settings.ColorSetting.ColorSettingName;
|
import settings.ColorSetting.ColorSettingName;
|
||||||
|
import source.recording.RecordingConfiguration;
|
||||||
import source.tuner.TunerConfiguration;
|
import source.tuner.TunerConfiguration;
|
||||||
import source.tuner.TunerConfigurationAssignment;
|
import source.tuner.TunerConfigurationAssignment;
|
||||||
import source.tuner.TunerType;
|
import source.tuner.TunerType;
|
||||||
@@ -517,6 +518,23 @@ public class SettingsManager
|
|||||||
broadcastSettingChange( setting );
|
broadcastSettingChange( setting );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ArrayList<RecordingConfiguration> getRecordingConfigurations()
|
||||||
|
{
|
||||||
|
return mSettings.getRecordingConfigurations();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addRecordingConfiguration( RecordingConfiguration config )
|
||||||
|
{
|
||||||
|
mSettings.addRecordingConfiguration( config );
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeRecordingConfiguration( RecordingConfiguration config )
|
||||||
|
{
|
||||||
|
mSettings.removeRecordingConfiguration( config );
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
|
||||||
public ArrayList<TunerConfiguration> getTunerConfigurations( TunerType type )
|
public ArrayList<TunerConfiguration> getTunerConfigurations( TunerType type )
|
||||||
{
|
{
|
||||||
ArrayList<TunerConfiguration> configs = getSettings()
|
ArrayList<TunerConfiguration> configs = getSettings()
|
||||||
|
|||||||
@@ -20,14 +20,16 @@ package source;
|
|||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
|
|
||||||
import source.config.SourceConfiguration;
|
import source.config.SourceConfiguration;
|
||||||
|
import controller.ResourceManager;
|
||||||
|
|
||||||
public class EmptySourceEditor extends SourceEditor
|
public class EmptySourceEditor extends SourceEditor
|
||||||
{
|
{
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
public EmptySourceEditor( SourceConfiguration config )
|
public EmptySourceEditor( ResourceManager resourceManager,
|
||||||
|
SourceConfiguration config )
|
||||||
{
|
{
|
||||||
super( config );
|
super( resourceManager, config );
|
||||||
|
|
||||||
initGUI();
|
initGUI();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,8 @@ public class SourceComponentEditor extends AbstractChannelEditor
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Change to the new one
|
//Change to the new one
|
||||||
mEditor = SourceEditorFactory.getPanel( config );
|
mEditor = SourceEditorFactory.getPanel(
|
||||||
|
mChannelNode.getModel().getResourceManager(), config );
|
||||||
|
|
||||||
//Add it to the jpanel
|
//Add it to the jpanel
|
||||||
add( mEditor, "span 2" );
|
add( mEditor, "span 2" );
|
||||||
|
|||||||
@@ -19,15 +19,18 @@ package source;
|
|||||||
|
|
||||||
import source.config.SourceConfiguration;
|
import source.config.SourceConfiguration;
|
||||||
import controller.Editor;
|
import controller.Editor;
|
||||||
|
import controller.ResourceManager;
|
||||||
|
|
||||||
public abstract class SourceEditor extends Editor
|
public abstract class SourceEditor extends Editor
|
||||||
{
|
{
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
protected ResourceManager mResourceManager;
|
||||||
protected SourceConfiguration mConfig;
|
protected SourceConfiguration mConfig;
|
||||||
|
|
||||||
public SourceEditor( SourceConfiguration config )
|
public SourceEditor( ResourceManager resourceManager, SourceConfiguration config )
|
||||||
{
|
{
|
||||||
|
mResourceManager = resourceManager;
|
||||||
mConfig = config;
|
mConfig = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,4 +38,9 @@ public abstract class SourceEditor extends Editor
|
|||||||
{
|
{
|
||||||
return mConfig;
|
return mConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ResourceManager getResourceManager()
|
||||||
|
{
|
||||||
|
return mResourceManager;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,25 +19,31 @@ package source;
|
|||||||
|
|
||||||
import source.config.SourceConfiguration;
|
import source.config.SourceConfiguration;
|
||||||
import source.mixer.MixerEditor;
|
import source.mixer.MixerEditor;
|
||||||
|
import source.recording.RecordingEditor;
|
||||||
import source.tuner.TunerEditor;
|
import source.tuner.TunerEditor;
|
||||||
|
import controller.ResourceManager;
|
||||||
|
|
||||||
public class SourceEditorFactory
|
public class SourceEditorFactory
|
||||||
{
|
{
|
||||||
public static SourceEditor getPanel( SourceConfiguration config )
|
public static SourceEditor getPanel( ResourceManager resourceManager,
|
||||||
|
SourceConfiguration config )
|
||||||
{
|
{
|
||||||
SourceEditor configuredPanel;
|
SourceEditor configuredPanel;
|
||||||
|
|
||||||
switch( config.getSourceType() )
|
switch( config.getSourceType() )
|
||||||
{
|
{
|
||||||
case MIXER:
|
case MIXER:
|
||||||
configuredPanel = new MixerEditor( config );
|
configuredPanel = new MixerEditor( resourceManager, config );
|
||||||
break;
|
break;
|
||||||
case TUNER:
|
case TUNER:
|
||||||
configuredPanel = new TunerEditor( config );
|
configuredPanel = new TunerEditor( resourceManager, config );
|
||||||
|
break;
|
||||||
|
case RECORDING:
|
||||||
|
configuredPanel = new RecordingEditor( resourceManager, config );
|
||||||
break;
|
break;
|
||||||
case NONE:
|
case NONE:
|
||||||
default:
|
default:
|
||||||
configuredPanel = new EmptySourceEditor( config );
|
configuredPanel = new EmptySourceEditor( resourceManager, config );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public class SourceManager {
|
|||||||
mResourceManager = resourceManager;
|
mResourceManager = resourceManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Source getSource( ProcessingChain channel )
|
public Source getSource( ProcessingChain channel ) throws SourceException
|
||||||
{
|
{
|
||||||
Source retVal = null;
|
Source retVal = null;
|
||||||
|
|
||||||
@@ -55,6 +55,9 @@ public class SourceManager {
|
|||||||
case TUNER:
|
case TUNER:
|
||||||
retVal = mResourceManager.getTunerManager().getSource( channel );
|
retVal = mResourceManager.getTunerManager().getSource( channel );
|
||||||
break;
|
break;
|
||||||
|
case RECORDING:
|
||||||
|
retVal = mResourceManager.getRecordingSourceManager()
|
||||||
|
.getSource( channel );
|
||||||
case NONE:
|
case NONE:
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ public enum SourceType
|
|||||||
{
|
{
|
||||||
NONE( "No Source" ),
|
NONE( "No Source" ),
|
||||||
MIXER( "Mixer/Sound Card" ),
|
MIXER( "Mixer/Sound Card" ),
|
||||||
TUNER( "Tuner" );
|
TUNER( "Tuner" ),
|
||||||
// WAVE( "Wave File" );
|
RECORDING( "IQ Recording" );
|
||||||
|
|
||||||
private String mDisplayString;
|
private String mDisplayString;
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ public class SourceConfigFactory
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static SourceConfiguration
|
public static SourceConfiguration
|
||||||
getSourceConfiguration( SourceType source )
|
getSourceConfiguration( SourceType source )
|
||||||
{
|
{
|
||||||
SourceConfiguration retVal;
|
SourceConfiguration retVal;
|
||||||
|
|
||||||
@@ -39,6 +39,9 @@ public class SourceConfigFactory
|
|||||||
case TUNER:
|
case TUNER:
|
||||||
retVal = new SourceConfigTuner();
|
retVal = new SourceConfigTuner();
|
||||||
break;
|
break;
|
||||||
|
case RECORDING:
|
||||||
|
retVal = new SourceConfigRecording();
|
||||||
|
break;
|
||||||
case NONE:
|
case NONE:
|
||||||
default:
|
default:
|
||||||
retVal = new SourceConfigNone();
|
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.SourceEditor;
|
||||||
import source.config.SourceConfigMixer;
|
import source.config.SourceConfigMixer;
|
||||||
import source.config.SourceConfiguration;
|
import source.config.SourceConfiguration;
|
||||||
|
import controller.ResourceManager;
|
||||||
|
|
||||||
public class MixerEditor extends SourceEditor
|
public class MixerEditor extends SourceEditor
|
||||||
{
|
{
|
||||||
@@ -36,9 +37,10 @@ public class MixerEditor extends SourceEditor
|
|||||||
protected Mixer.Info mSelectedMixer = null;
|
protected Mixer.Info mSelectedMixer = null;
|
||||||
|
|
||||||
|
|
||||||
public MixerEditor( SourceConfiguration config )
|
public MixerEditor( ResourceManager resourceManager,
|
||||||
|
SourceConfiguration config )
|
||||||
{
|
{
|
||||||
super( config );
|
super( resourceManager, config );
|
||||||
|
|
||||||
initGUI();
|
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
|
* Tuner - provides tuner channel sources, representing a channel frequency
|
||||||
*/
|
*/
|
||||||
public abstract class Tuner implements FrequencyChangeBroadcaster,
|
public abstract class Tuner implements FrequencyChangeBroadcaster,
|
||||||
FrequencyChangeListener
|
FrequencyChangeListener,
|
||||||
|
TunerChannelProvider
|
||||||
{
|
{
|
||||||
private String mName;
|
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.SourceEditor;
|
||||||
import source.config.SourceConfigTuner;
|
import source.config.SourceConfigTuner;
|
||||||
import source.config.SourceConfiguration;
|
import source.config.SourceConfiguration;
|
||||||
|
import controller.ResourceManager;
|
||||||
|
|
||||||
public class TunerEditor extends SourceEditor
|
public class TunerEditor extends SourceEditor
|
||||||
{
|
{
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
private JFrequencyControl mFrequencyControl;
|
private JFrequencyControl mFrequencyControl;
|
||||||
|
|
||||||
public TunerEditor( SourceConfiguration config )
|
public TunerEditor( ResourceManager resourceManager,
|
||||||
|
SourceConfiguration config )
|
||||||
{
|
{
|
||||||
super( config );
|
super( resourceManager, config );
|
||||||
|
|
||||||
initGUI();
|
initGUI();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,15 +65,15 @@ public class TunerManager
|
|||||||
* Iterates current tuners to get a tuner channel source for the frequency
|
* Iterates current tuners to get a tuner channel source for the frequency
|
||||||
* specified in the channel config's source config object
|
* specified in the channel config's source config object
|
||||||
*/
|
*/
|
||||||
public Source getSource( ProcessingChain channel )
|
public Source getSource( ProcessingChain processingChain )
|
||||||
{
|
{
|
||||||
TunerChannelSource retVal = null;
|
TunerChannelSource retVal = null;
|
||||||
|
|
||||||
|
|
||||||
if( channel.getChannel().getSourceConfiguration()
|
if( processingChain.getChannel().getSourceConfiguration()
|
||||||
instanceof SourceConfigTuner )
|
instanceof SourceConfigTuner )
|
||||||
{
|
{
|
||||||
TunerChannel tunerChannel = channel.getChannel().getTunerChannel();
|
TunerChannel tunerChannel = processingChain.getChannel().getTunerChannel();
|
||||||
|
|
||||||
Iterator<Tuner> it = mTuners.iterator();
|
Iterator<Tuner> it = mTuners.iterator();
|
||||||
|
|
||||||
|
|||||||
@@ -368,16 +368,24 @@ public abstract class RTL2832TunerController extends TunerController
|
|||||||
|
|
||||||
if( claim( iface ) )
|
if( claim( iface ) )
|
||||||
{
|
{
|
||||||
|
Log.debug( "RTL2832 - usb interface claimed" );
|
||||||
|
|
||||||
/* Perform a dummy write to see if the device needs reset */
|
/* Perform a dummy write to see if the device needs reset */
|
||||||
writeRegister( device, Block.USB, Address.USB_SYSCTL.getAddress(), 0x09, 1 );
|
writeRegister( device, Block.USB, Address.USB_SYSCTL.getAddress(), 0x09, 1 );
|
||||||
|
|
||||||
|
Log.debug( "RTL2832 - initializing baseband" );
|
||||||
|
|
||||||
/* Initialize the baseband */
|
/* Initialize the baseband */
|
||||||
initBaseband( device );
|
initBaseband( device );
|
||||||
|
|
||||||
|
Log.debug( "RTL2832 - enabling I2C repeater" );
|
||||||
|
|
||||||
enableI2CRepeater( device, true );
|
enableI2CRepeater( device, true );
|
||||||
|
|
||||||
boolean controlI2CRepeater = false;
|
boolean controlI2CRepeater = false;
|
||||||
|
|
||||||
|
Log.debug( "RTL2832 - testing for tuner types" );
|
||||||
|
|
||||||
/* Test for each tuner type until we find the correct one */
|
/* Test for each tuner type until we find the correct one */
|
||||||
if( isE4000Tuner( device, controlI2CRepeater ) )
|
if( isE4000Tuner( device, controlI2CRepeater ) )
|
||||||
{
|
{
|
||||||
@@ -404,15 +412,19 @@ public abstract class RTL2832TunerController extends TunerController
|
|||||||
tunerClass = TunerType.FITIPOWER_FC0012;
|
tunerClass = TunerType.FITIPOWER_FC0012;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log.debug( "RTL2832 - disabling I2C repeater" );
|
||||||
|
|
||||||
enableI2CRepeater( device, false );
|
enableI2CRepeater( device, false );
|
||||||
|
|
||||||
|
Log.debug( "RTL2832 - releasing USB interface" );
|
||||||
|
|
||||||
iface.release();
|
iface.release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch( Exception e )
|
catch( Exception e )
|
||||||
{
|
{
|
||||||
Log.error( "RTL2832TunerController - error while determining "
|
Log.error( "RTL2832TunerController - error while determining "
|
||||||
+ "tuner type - " + e.getLocalizedMessage() );
|
+ "tuner type - ", e );
|
||||||
}
|
}
|
||||||
|
|
||||||
return tunerClass;
|
return tunerClass;
|
||||||
@@ -927,6 +939,8 @@ public abstract class RTL2832TunerController extends TunerController
|
|||||||
protected static boolean isE4000Tuner( UsbDevice device,
|
protected static boolean isE4000Tuner( UsbDevice device,
|
||||||
boolean controlI2CRepeater ) throws UsbClaimException
|
boolean controlI2CRepeater ) throws UsbClaimException
|
||||||
{
|
{
|
||||||
|
Log.debug( "RTL2832 - testing for E4000 tuner" );
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
int value = readI2CRegister( device, E4K_I2C_ADDRESS,
|
int value = readI2CRegister( device, E4K_I2C_ADDRESS,
|
||||||
@@ -974,6 +988,7 @@ public abstract class RTL2832TunerController extends TunerController
|
|||||||
boolean controlI2CRepeater )
|
boolean controlI2CRepeater )
|
||||||
throws UsbClaimException
|
throws UsbClaimException
|
||||||
{
|
{
|
||||||
|
Log.debug( "RTL2832 - testing for F0013 tuner" );
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
int value = readI2CRegister( device, FC0013_I2C_ADDRESS,
|
int value = readI2CRegister( device, FC0013_I2C_ADDRESS,
|
||||||
@@ -1030,6 +1045,7 @@ public abstract class RTL2832TunerController extends TunerController
|
|||||||
protected static boolean isR820TTuner( UsbDevice device,
|
protected static boolean isR820TTuner( UsbDevice device,
|
||||||
boolean controlI2CRepeater ) throws UsbClaimException
|
boolean controlI2CRepeater ) throws UsbClaimException
|
||||||
{
|
{
|
||||||
|
Log.debug( "RTL2832 - testing for R820T tuner" );
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
int value = readI2CRegister( device, R820T_I2C_ADDRESS,
|
int value = readI2CRegister( device, R820T_I2C_ADDRESS,
|
||||||
|
|||||||
Reference in New Issue
Block a user