diff --git a/.classpath b/.classpath index a630c18d..2217d1f1 100644 --- a/.classpath +++ b/.classpath @@ -25,5 +25,10 @@ + + + + + diff --git a/images/control_play.png b/images/control_play.png new file mode 100644 index 00000000..0846555d Binary files /dev/null and b/images/control_play.png differ diff --git a/images/control_stop.png b/images/control_stop.png new file mode 100644 index 00000000..893bb60e Binary files /dev/null and b/images/control_stop.png differ diff --git a/images/no_icon.png b/images/no_icon.png index 3b2b90c4..bab7cc9b 100644 Binary files a/images/no_icon.png and b/images/no_icon.png differ diff --git a/imports/tablefilter-swing-5.2.1.jar b/imports/tablefilter-swing-5.2.1.jar new file mode 100644 index 00000000..a7d26029 Binary files /dev/null and b/imports/tablefilter-swing-5.2.1.jar differ diff --git a/src/alias/AliasDirectoryNode.java b/src/alias/AliasDirectoryNode.java index a616b755..c44d32b9 100644 --- a/src/alias/AliasDirectoryNode.java +++ b/src/alias/AliasDirectoryNode.java @@ -23,15 +23,27 @@ import java.awt.event.ActionListener; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; +import playlist.PlaylistManager; +import settings.SettingsManager; import controller.ConfigurableNode; public class AliasDirectoryNode extends ConfigurableNode { private static final long serialVersionUID = 1L; + + private PlaylistManager mPlaylistManager; - public AliasDirectoryNode( AliasDirectory directory ) + private SettingsManager mSettingsManager; + + public AliasDirectoryNode( PlaylistManager playlistManager, + SettingsManager settingsManager, + AliasDirectory directory ) { - super( directory ); + super( playlistManager, directory ); + + mPlaylistManager = playlistManager; + + mSettingsManager = settingsManager; } public AliasDirectory getAliasDirectory() @@ -43,7 +55,7 @@ public class AliasDirectoryNode extends ConfigurableNode { for( AliasList list: getAliasDirectory().getAliasList() ) { - AliasListNode node = new AliasListNode( list ); + AliasListNode node = new AliasListNode( mPlaylistManager, mSettingsManager, list ); getModel().addNode( node, AliasDirectoryNode.this, getChildCount() ); @@ -72,7 +84,7 @@ public class AliasDirectoryNode extends ConfigurableNode getAliasDirectory().addAliasList( list ); - AliasListNode node = new AliasListNode( list ); + AliasListNode node = new AliasListNode( mPlaylistManager, mSettingsManager, list ); getModel().addNode( node, AliasDirectoryNode.this, diff --git a/src/alias/AliasEditor.java b/src/alias/AliasEditor.java index 77be321b..cb4f9682 100644 --- a/src/alias/AliasEditor.java +++ b/src/alias/AliasEditor.java @@ -19,6 +19,7 @@ package alias; import java.awt.Color; import java.awt.Dimension; +import java.awt.EventQueue; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -32,19 +33,19 @@ import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.tree.TreePath; +import map.IconManager; import map.MapIcon; import map.MapIconListCellRenderer; import net.miginfocom.swing.MigLayout; import settings.SettingsManager; import controller.ConfigurableNode; -import controller.ResourceManager; public class AliasEditor extends JPanel implements ActionListener { private static final long serialVersionUID = 1L; private AliasNode mAliasNode; - private ResourceManager mResourceManager; + private SettingsManager mSettingsManager; private JLabel mLabelName; private JTextField mTextAlias; @@ -54,10 +55,11 @@ public class AliasEditor extends JPanel implements ActionListener private JComboBox mComboMapIcon; private JButton mBtnIconManager; - public AliasEditor( AliasNode aliasNode, ResourceManager resourceManager ) + public AliasEditor( AliasNode aliasNode, + SettingsManager settingsManager ) { mAliasNode = aliasNode; - mResourceManager = resourceManager; + mSettingsManager = settingsManager; initGUI(); } @@ -98,8 +100,7 @@ public class AliasEditor extends JPanel implements ActionListener add( new JLabel( "Icon:" ) ); - mComboMapIcon = new JComboBox( - mResourceManager.getSettingsManager().getMapIcons() ); + mComboMapIcon = new JComboBox( mSettingsManager.getMapIcons() ); MapIconListCellRenderer renderer = new MapIconListCellRenderer(); renderer.setPreferredSize( new Dimension( 200, 30 ) ); @@ -112,8 +113,7 @@ public class AliasEditor extends JPanel implements ActionListener iconName = SettingsManager.DEFAULT_ICON; } - MapIcon savedIcon = mResourceManager.getSettingsManager() - .getMapIcon( iconName ); + MapIcon savedIcon = mSettingsManager.getMapIcon( iconName ); if( savedIcon != null ) { @@ -131,7 +131,17 @@ public class AliasEditor extends JPanel implements ActionListener @Override public void actionPerformed( ActionEvent arg0 ) { - mResourceManager.getController().showIconManager(); + final IconManager iconManager = + new IconManager( mSettingsManager, AliasEditor.this ); + + EventQueue.invokeLater( new Runnable() + { + @Override + public void run() + { + iconManager.setVisible( true ); + } + } ); } } ); add( mBtnIconManager, "span 2,wrap" ); @@ -194,7 +204,7 @@ public class AliasEditor extends JPanel implements ActionListener mButtonColor.setBackground( mAliasNode.getAlias().getMapColor() ); mButtonColor.setForeground( mAliasNode.getAlias().getMapColor() ); - MapIcon savedIcon = mResourceManager.getSettingsManager() + MapIcon savedIcon = mSettingsManager .getMapIcon( mAliasNode.getAlias().getIconName() ); mComboMapIcon.setSelectedItem( savedIcon ); diff --git a/src/alias/AliasIDNode.java b/src/alias/AliasIDNode.java index c861c56a..3852b44d 100644 --- a/src/alias/AliasIDNode.java +++ b/src/alias/AliasIDNode.java @@ -17,19 +17,20 @@ ******************************************************************************/ package alias; +import playlist.PlaylistManager; import controller.ConfigurableNode; public class AliasIDNode extends ConfigurableNode { private static final long serialVersionUID = 1L; - public AliasIDNode( AliasID id ) + public AliasIDNode( PlaylistManager playlistManager, AliasID id ) { - super( id ); + super( playlistManager, id ); } public void save() { - getModel().getResourceManager().getPlaylistManager().save(); + getPlaylistManager().save(); } } diff --git a/src/alias/AliasListNode.java b/src/alias/AliasListNode.java index 65632971..573708ce 100644 --- a/src/alias/AliasListNode.java +++ b/src/alias/AliasListNode.java @@ -26,15 +26,25 @@ import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JSeparator; +import playlist.PlaylistManager; +import settings.SettingsManager; import controller.ConfigurableNode; public class AliasListNode extends ConfigurableNode { private static final long serialVersionUID = 1L; + + private PlaylistManager mPlaylistManager; + private SettingsManager mSettingsManager; - public AliasListNode( AliasList list ) + public AliasListNode( PlaylistManager playlistManager, + SettingsManager settingsManager, + AliasList list ) { - super( list ); + super( playlistManager, list ); + + mPlaylistManager = playlistManager; + mSettingsManager = settingsManager; } @Override @@ -52,7 +62,7 @@ public class AliasListNode extends ConfigurableNode { for( Group group: getList().getGroup() ) { - GroupNode node = new GroupNode( group ); + GroupNode node = new GroupNode( mPlaylistManager, mSettingsManager, group ); getModel().addNode( node, AliasListNode.this, getChildCount() ); @@ -81,7 +91,7 @@ public class AliasListNode extends ConfigurableNode getList().addGroup( group ); - GroupNode node = new GroupNode( group ); + GroupNode node = new GroupNode( mPlaylistManager, mSettingsManager, group ); getModel().addNode( node, AliasListNode.this, diff --git a/src/alias/AliasNode.java b/src/alias/AliasNode.java index 43de7703..070e3b60 100644 --- a/src/alias/AliasNode.java +++ b/src/alias/AliasNode.java @@ -27,6 +27,8 @@ import javax.swing.JPanel; import javax.swing.JPopupMenu; import map.MapIcon; +import playlist.PlaylistManager; +import settings.SettingsManager; import alias.action.AliasAction; import alias.action.beep.BeepAction; import alias.action.beep.BeepActionNode; @@ -64,15 +66,22 @@ public class AliasNode extends ConfigurableNode { private static final long serialVersionUID = 1L; - public AliasNode( Alias alias ) + private SettingsManager mSettingsManager; + private PlaylistManager mPlaylistManager; + + public AliasNode( PlaylistManager playlistManager, + SettingsManager settingsManager, + Alias alias ) { - super( alias ); + super( playlistManager, alias ); + + mSettingsManager = settingsManager; } @Override public JPanel getEditor() { - return new AliasEditor( this, getModel().getResourceManager() ); + return new AliasEditor( this, mSettingsManager ); } public Alias getAlias() @@ -84,8 +93,7 @@ public class AliasNode extends ConfigurableNode { String icon = getAlias().getIconName(); - MapIcon mapIcon = getModel().getResourceManager() - .getSettingsManager().getMapIcon( icon ); + MapIcon mapIcon = mSettingsManager.getMapIcon( icon ); if( mapIcon != null ) { @@ -104,51 +112,51 @@ public class AliasNode extends ConfigurableNode switch( aliasID.getType() ) { case ESN: - getModel().addNode( new ESNNode( (Esn)aliasID ), + getModel().addNode( new ESNNode( mPlaylistManager, (Esn)aliasID ), AliasNode.this, getChildCount() ); break; case Fleetsync: - getModel().addNode( new FleetsyncIDNode( (FleetsyncID)aliasID ), + getModel().addNode( new FleetsyncIDNode( mPlaylistManager, (FleetsyncID)aliasID ), AliasNode.this, getChildCount() ); break; case LoJack: - getModel().addNode( new LoJackIDNode( (LoJackFunctionAndID)aliasID ), + getModel().addNode( new LoJackIDNode( mPlaylistManager, (LoJackFunctionAndID)aliasID ), AliasNode.this, getChildCount() ); break; case LTRNetUID: - getModel().addNode( new UniqueIDNode( (UniqueID)aliasID ), + getModel().addNode( new UniqueIDNode( mPlaylistManager, (UniqueID)aliasID ), AliasNode.this, getChildCount() ); break; case MDC1200: - getModel().addNode( new MDC1200IDNode( (MDC1200ID)aliasID ), + getModel().addNode( new MDC1200IDNode( mPlaylistManager, (MDC1200ID)aliasID ), AliasNode.this, getChildCount() ); break; case MIN: - getModel().addNode( new MINNode( (Min)aliasID ), + getModel().addNode( new MINNode( mPlaylistManager, (Min)aliasID ), AliasNode.this, getChildCount() ); break; case MPT1327: - getModel().addNode( new MPT1327IDNode( (MPT1327ID)aliasID ), + getModel().addNode( new MPT1327IDNode( mPlaylistManager, (MPT1327ID)aliasID ), AliasNode.this, getChildCount() ); break; case NonRecordable: - getModel().addNode( new NonRecordableNode( (NonRecordable)aliasID ), + getModel().addNode( new NonRecordableNode( mPlaylistManager, (NonRecordable)aliasID ), AliasNode.this, getChildCount() ); break; case Priority: - getModel().addNode( new PriorityNode( (Priority)aliasID ), + getModel().addNode( new PriorityNode( mPlaylistManager, (Priority)aliasID ), AliasNode.this, getChildCount() ); break; case Site: - getModel().addNode( new SiteIDNode( (SiteID)aliasID ), + getModel().addNode( new SiteIDNode( mPlaylistManager, (SiteID)aliasID ), AliasNode.this, getChildCount() ); break; case Status: - getModel().addNode( new StatusIDNode( (StatusID)aliasID ), + getModel().addNode( new StatusIDNode( mPlaylistManager, (StatusID)aliasID ), AliasNode.this, getChildCount() ); break; case Talkgroup: - getModel().addNode( new TalkgroupIDNode( (TalkgroupID)aliasID ), + getModel().addNode( new TalkgroupIDNode( mPlaylistManager, (TalkgroupID)aliasID ), AliasNode.this, getChildCount() ); break; default: @@ -161,17 +169,17 @@ public class AliasNode extends ConfigurableNode { if( action instanceof BeepAction ) { - getModel().addNode( new BeepActionNode( (BeepAction)action ), + getModel().addNode( new BeepActionNode( mPlaylistManager, (BeepAction)action ), AliasNode.this, getChildCount() ); } else if( action instanceof ClipAction ) { - getModel().addNode( new ClipActionNode( (ClipAction)action ), + getModel().addNode( new ClipActionNode( mPlaylistManager, (ClipAction)action ), AliasNode.this, getChildCount() ); } else if( action instanceof ScriptAction ) { - getModel().addNode( new ScriptActionNode( (ScriptAction)action ), + getModel().addNode( new ScriptActionNode( mPlaylistManager, (ScriptAction)action ), AliasNode.this, getChildCount() ); } } @@ -200,7 +208,7 @@ public class AliasNode extends ConfigurableNode getAlias().addAliasID( esn ); - ESNNode node = new ESNNode( esn ); + ESNNode node = new ESNNode( mPlaylistManager, esn ); getModel().addNode( node, AliasNode.this, @@ -221,7 +229,7 @@ public class AliasNode extends ConfigurableNode getAlias().addAliasID( fs ); - FleetsyncIDNode node = new FleetsyncIDNode( fs ); + FleetsyncIDNode node = new FleetsyncIDNode( mPlaylistManager, fs ); getModel().addNode( node, AliasNode.this, @@ -242,7 +250,7 @@ public class AliasNode extends ConfigurableNode getAlias().addAliasID( lj ); - LoJackIDNode node = new LoJackIDNode( lj ); + LoJackIDNode node = new LoJackIDNode( mPlaylistManager, lj ); getModel().addNode( node, AliasNode.this, @@ -263,7 +271,7 @@ public class AliasNode extends ConfigurableNode getAlias().addAliasID( mdc ); - MDC1200IDNode node = new MDC1200IDNode( mdc ); + MDC1200IDNode node = new MDC1200IDNode( mPlaylistManager, mdc ); getModel().addNode( node, AliasNode.this, @@ -284,7 +292,7 @@ public class AliasNode extends ConfigurableNode getAlias().addAliasID( min ); - MINNode node = new MINNode( min ); + MINNode node = new MINNode( mPlaylistManager, min ); getModel().addNode( node, AliasNode.this, @@ -305,7 +313,7 @@ public class AliasNode extends ConfigurableNode getAlias().addAliasID( mpt ); - MPT1327IDNode node = new MPT1327IDNode( mpt ); + MPT1327IDNode node = new MPT1327IDNode( mPlaylistManager, mpt ); getModel().addNode( node, AliasNode.this, @@ -326,7 +334,7 @@ public class AliasNode extends ConfigurableNode getAlias().addAliasID( siteID ); - SiteIDNode node = new SiteIDNode( siteID ); + SiteIDNode node = new SiteIDNode( mPlaylistManager, siteID ); getModel().addNode( node, AliasNode.this, @@ -347,7 +355,7 @@ public class AliasNode extends ConfigurableNode getAlias().addAliasID( statusID ); - StatusIDNode node = new StatusIDNode( statusID ); + StatusIDNode node = new StatusIDNode( mPlaylistManager, statusID ); getModel().addNode( node, AliasNode.this, @@ -369,7 +377,7 @@ public class AliasNode extends ConfigurableNode getAlias().addAliasID( tg ); - TalkgroupIDNode node = new TalkgroupIDNode( tg ); + TalkgroupIDNode node = new TalkgroupIDNode( mPlaylistManager, tg ); getModel().addNode( node, AliasNode.this, @@ -390,7 +398,7 @@ public class AliasNode extends ConfigurableNode getAlias().addAliasID( uid ); - UniqueIDNode node = new UniqueIDNode( uid ); + UniqueIDNode node = new UniqueIDNode( mPlaylistManager, uid ); getModel().addNode( node, AliasNode.this, @@ -416,7 +424,7 @@ public class AliasNode extends ConfigurableNode getAlias().addAliasAction( clipAction ); - ClipActionNode node = new ClipActionNode( clipAction ); + ClipActionNode node = new ClipActionNode( mPlaylistManager, clipAction ); getModel().addNode( node, AliasNode.this, @@ -439,7 +447,7 @@ public class AliasNode extends ConfigurableNode getAlias().addAliasAction( beepAction ); - BeepActionNode node = new BeepActionNode( beepAction ); + BeepActionNode node = new BeepActionNode( mPlaylistManager, beepAction ); getModel().addNode( node, AliasNode.this, @@ -462,7 +470,7 @@ public class AliasNode extends ConfigurableNode getAlias().addAliasAction( scriptAction ); - ScriptActionNode node = new ScriptActionNode( scriptAction ); + ScriptActionNode node = new ScriptActionNode( mPlaylistManager, scriptAction ); getModel().addNode( node, AliasNode.this, @@ -491,7 +499,7 @@ public class AliasNode extends ConfigurableNode getAlias().addAliasID( non ); - NonRecordableNode node = new NonRecordableNode( non ); + NonRecordableNode node = new NonRecordableNode( mPlaylistManager, non ); getModel().addNode( node, AliasNode.this, @@ -518,7 +526,7 @@ public class AliasNode extends ConfigurableNode getAlias().addAliasID( priority ); - PriorityNode node = new PriorityNode( priority ); + PriorityNode node = new PriorityNode( mPlaylistManager, priority ); getModel().addNode( node, AliasNode.this, diff --git a/src/alias/GroupNode.java b/src/alias/GroupNode.java index ac0ca894..f8d52904 100644 --- a/src/alias/GroupNode.java +++ b/src/alias/GroupNode.java @@ -26,15 +26,24 @@ import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JSeparator; +import playlist.PlaylistManager; +import settings.SettingsManager; import controller.ConfigurableNode; public class GroupNode extends ConfigurableNode { private static final long serialVersionUID = 1L; + + private PlaylistManager mPlaylistManager; + private SettingsManager mSettingsManager; - public GroupNode( Group group ) + public GroupNode( PlaylistManager playlistManager, + SettingsManager settingsManager, + Group group ) { - super( group ); + super( playlistManager, group ); + + mSettingsManager = settingsManager; } @Override @@ -52,7 +61,7 @@ public class GroupNode extends ConfigurableNode { for( Alias alias: getGroup().getAlias() ) { - AliasNode node = new AliasNode( alias ); + AliasNode node = new AliasNode( mPlaylistManager, mSettingsManager, alias ); getModel().addNode( node, GroupNode.this, getChildCount() ); @@ -81,7 +90,7 @@ public class GroupNode extends ConfigurableNode getGroup().addAlias( alias ); - AliasNode node = new AliasNode( alias ); + AliasNode node = new AliasNode( mPlaylistManager, mSettingsManager, alias ); getModel().addNode( node, GroupNode.this, diff --git a/src/alias/action/AliasActionNode.java b/src/alias/action/AliasActionNode.java index 79ee2484..173ecf07 100644 --- a/src/alias/action/AliasActionNode.java +++ b/src/alias/action/AliasActionNode.java @@ -17,20 +17,25 @@ ******************************************************************************/ package alias.action; +import playlist.PlaylistManager; import controller.ConfigurableNode; public class AliasActionNode extends ConfigurableNode { private static final long serialVersionUID = 1L; + + private PlaylistManager mPlaylistManager; - public AliasActionNode( AliasAction action ) + public AliasActionNode( PlaylistManager playlistManager, AliasAction action ) { - super( action ); + super( playlistManager, action ); + + mPlaylistManager = playlistManager; } public void save() { - getModel().getResourceManager().getPlaylistManager().save(); + mPlaylistManager.save(); } public String getIconPath() diff --git a/src/alias/action/beep/BeepActionNode.java b/src/alias/action/beep/BeepActionNode.java index 817e3949..ba5fccdf 100644 --- a/src/alias/action/beep/BeepActionNode.java +++ b/src/alias/action/beep/BeepActionNode.java @@ -25,6 +25,7 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; +import playlist.PlaylistManager; import alias.AliasNode; import alias.action.AliasActionNode; @@ -32,9 +33,9 @@ public class BeepActionNode extends AliasActionNode { private static final long serialVersionUID = 1L; - public BeepActionNode( BeepAction beepAction ) + public BeepActionNode( PlaylistManager playlistManager, BeepAction beepAction ) { - super( beepAction ); + super( playlistManager, beepAction ); } @Override diff --git a/src/alias/action/clip/ClipActionNode.java b/src/alias/action/clip/ClipActionNode.java index e3255cd0..15f7005b 100644 --- a/src/alias/action/clip/ClipActionNode.java +++ b/src/alias/action/clip/ClipActionNode.java @@ -25,6 +25,7 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; +import playlist.PlaylistManager; import alias.AliasNode; import alias.action.AliasActionNode; @@ -32,9 +33,9 @@ public class ClipActionNode extends AliasActionNode { private static final long serialVersionUID = 1L; - public ClipActionNode( ClipAction clipAction ) + public ClipActionNode( PlaylistManager playlistManager, ClipAction clipAction ) { - super( clipAction ); + super( playlistManager, clipAction ); } @Override diff --git a/src/alias/action/script/ScriptActionNode.java b/src/alias/action/script/ScriptActionNode.java index b0385e3f..cbe25b45 100644 --- a/src/alias/action/script/ScriptActionNode.java +++ b/src/alias/action/script/ScriptActionNode.java @@ -25,6 +25,7 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; +import playlist.PlaylistManager; import alias.AliasNode; import alias.action.AliasActionNode; @@ -32,9 +33,9 @@ public class ScriptActionNode extends AliasActionNode { private static final long serialVersionUID = 1L; - public ScriptActionNode( ScriptAction scriptAction ) + public ScriptActionNode( PlaylistManager playlistManager, ScriptAction scriptAction ) { - super( scriptAction ); + super( playlistManager, scriptAction ); } @Override diff --git a/src/alias/id/esn/ESNNode.java b/src/alias/id/esn/ESNNode.java index 1b6234d0..ecdd33e8 100644 --- a/src/alias/id/esn/ESNNode.java +++ b/src/alias/id/esn/ESNNode.java @@ -25,6 +25,7 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; +import playlist.PlaylistManager; import alias.AliasIDNode; import alias.AliasNode; @@ -32,9 +33,9 @@ public class ESNNode extends AliasIDNode { private static final long serialVersionUID = 1L; - public ESNNode( Esn esn ) + public ESNNode( PlaylistManager playlistManager, Esn esn ) { - super( esn ); + super( playlistManager, esn ); } @Override diff --git a/src/alias/id/fleetsync/FleetsyncIDNode.java b/src/alias/id/fleetsync/FleetsyncIDNode.java index 9a16c1d9..4d0e09f1 100644 --- a/src/alias/id/fleetsync/FleetsyncIDNode.java +++ b/src/alias/id/fleetsync/FleetsyncIDNode.java @@ -25,6 +25,7 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; +import playlist.PlaylistManager; import alias.AliasIDNode; import alias.AliasNode; @@ -32,9 +33,9 @@ public class FleetsyncIDNode extends AliasIDNode { private static final long serialVersionUID = 1L; - public FleetsyncIDNode( FleetsyncID id ) + public FleetsyncIDNode( PlaylistManager playlistManager, FleetsyncID id ) { - super( id ); + super( playlistManager, id ); } @Override diff --git a/src/alias/id/fleetsync/StatusIDNode.java b/src/alias/id/fleetsync/StatusIDNode.java index 621626fb..49aaeb83 100644 --- a/src/alias/id/fleetsync/StatusIDNode.java +++ b/src/alias/id/fleetsync/StatusIDNode.java @@ -25,6 +25,7 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; +import playlist.PlaylistManager; import alias.AliasIDNode; import alias.AliasNode; @@ -32,9 +33,9 @@ public class StatusIDNode extends AliasIDNode { private static final long serialVersionUID = 1L; - public StatusIDNode( StatusID id ) + public StatusIDNode( PlaylistManager playlistManager, StatusID id ) { - super( id ); + super( playlistManager, id ); } @Override diff --git a/src/alias/id/lojack/LoJackIDNode.java b/src/alias/id/lojack/LoJackIDNode.java index 3b4f3ed0..fcda77bd 100644 --- a/src/alias/id/lojack/LoJackIDNode.java +++ b/src/alias/id/lojack/LoJackIDNode.java @@ -25,6 +25,7 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; +import playlist.PlaylistManager; import alias.AliasIDNode; import alias.AliasNode; @@ -32,9 +33,9 @@ public class LoJackIDNode extends AliasIDNode { private static final long serialVersionUID = 1L; - public LoJackIDNode( LoJackFunctionAndID id ) + public LoJackIDNode( PlaylistManager playlistManager, LoJackFunctionAndID id ) { - super( id ); + super( playlistManager,id ); } @Override diff --git a/src/alias/id/mdc/MDC1200IDNode.java b/src/alias/id/mdc/MDC1200IDNode.java index 5a5a837b..9c315a49 100644 --- a/src/alias/id/mdc/MDC1200IDNode.java +++ b/src/alias/id/mdc/MDC1200IDNode.java @@ -25,6 +25,7 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; +import playlist.PlaylistManager; import alias.AliasIDNode; import alias.AliasNode; @@ -32,9 +33,9 @@ public class MDC1200IDNode extends AliasIDNode { private static final long serialVersionUID = 1L; - public MDC1200IDNode( MDC1200ID id ) + public MDC1200IDNode( PlaylistManager playlistManager, MDC1200ID id ) { - super( id ); + super( playlistManager, id ); } @Override diff --git a/src/alias/id/mobileID/MINNode.java b/src/alias/id/mobileID/MINNode.java index cf832f91..be0b7e83 100644 --- a/src/alias/id/mobileID/MINNode.java +++ b/src/alias/id/mobileID/MINNode.java @@ -25,6 +25,7 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; +import playlist.PlaylistManager; import alias.AliasIDNode; import alias.AliasNode; @@ -32,9 +33,9 @@ public class MINNode extends AliasIDNode { private static final long serialVersionUID = 1L; - public MINNode( Min min ) + public MINNode( PlaylistManager playlistManager, Min min ) { - super( min ); + super( playlistManager, min ); } @Override diff --git a/src/alias/id/mpt1327/MPT1327IDNode.java b/src/alias/id/mpt1327/MPT1327IDNode.java index ab591365..a5937cee 100644 --- a/src/alias/id/mpt1327/MPT1327IDNode.java +++ b/src/alias/id/mpt1327/MPT1327IDNode.java @@ -25,6 +25,7 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; +import playlist.PlaylistManager; import alias.AliasIDNode; import alias.AliasNode; @@ -32,9 +33,9 @@ public class MPT1327IDNode extends AliasIDNode { private static final long serialVersionUID = 1L; - public MPT1327IDNode( MPT1327ID id ) + public MPT1327IDNode( PlaylistManager playlistManager, MPT1327ID id ) { - super( id ); + super( playlistManager, id ); } @Override diff --git a/src/alias/id/siteID/SiteIDNode.java b/src/alias/id/siteID/SiteIDNode.java index 26569699..e9e2a4b4 100644 --- a/src/alias/id/siteID/SiteIDNode.java +++ b/src/alias/id/siteID/SiteIDNode.java @@ -25,6 +25,7 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; +import playlist.PlaylistManager; import alias.AliasIDNode; import alias.AliasNode; @@ -32,9 +33,9 @@ public class SiteIDNode extends AliasIDNode { private static final long serialVersionUID = 1L; - public SiteIDNode( SiteID id ) + public SiteIDNode( PlaylistManager playlistManager, SiteID id ) { - super( id ); + super( playlistManager, id ); } @Override diff --git a/src/alias/id/talkgroup/TalkgroupIDNode.java b/src/alias/id/talkgroup/TalkgroupIDNode.java index 0a8e7e0a..261adc75 100644 --- a/src/alias/id/talkgroup/TalkgroupIDNode.java +++ b/src/alias/id/talkgroup/TalkgroupIDNode.java @@ -25,6 +25,7 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; +import playlist.PlaylistManager; import alias.AliasIDNode; import alias.AliasNode; @@ -32,9 +33,9 @@ public class TalkgroupIDNode extends AliasIDNode { private static final long serialVersionUID = 1L; - public TalkgroupIDNode( TalkgroupID id ) + public TalkgroupIDNode( PlaylistManager playlistManager, TalkgroupID id ) { - super( id ); + super( playlistManager,id ); } @Override diff --git a/src/alias/id/uniqueID/UniqueIDNode.java b/src/alias/id/uniqueID/UniqueIDNode.java index 5c850f15..ebb92f4f 100644 --- a/src/alias/id/uniqueID/UniqueIDNode.java +++ b/src/alias/id/uniqueID/UniqueIDNode.java @@ -25,6 +25,7 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; +import playlist.PlaylistManager; import alias.AliasIDNode; import alias.AliasNode; @@ -32,9 +33,9 @@ public class UniqueIDNode extends AliasIDNode { private static final long serialVersionUID = 1L; - public UniqueIDNode( UniqueID id ) + public UniqueIDNode( PlaylistManager playlistManager, UniqueID id ) { - super( id ); + super( playlistManager, id ); } @Override diff --git a/src/alias/priority/PriorityNode.java b/src/alias/priority/PriorityNode.java index 178860fe..707ae0f7 100644 --- a/src/alias/priority/PriorityNode.java +++ b/src/alias/priority/PriorityNode.java @@ -25,6 +25,7 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; +import playlist.PlaylistManager; import alias.AliasIDNode; import alias.AliasNode; @@ -32,9 +33,9 @@ public class PriorityNode extends AliasIDNode { private static final long serialVersionUID = 1L; - public PriorityNode( Priority priority ) + public PriorityNode( PlaylistManager playlistManager, Priority priority ) { - super( priority ); + super( playlistManager, priority ); } @Override diff --git a/src/alias/record/NonRecordableNode.java b/src/alias/record/NonRecordableNode.java index eb8ba572..082238df 100644 --- a/src/alias/record/NonRecordableNode.java +++ b/src/alias/record/NonRecordableNode.java @@ -25,6 +25,7 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; +import playlist.PlaylistManager; import alias.AliasID; import alias.AliasIDNode; import alias.AliasNode; @@ -33,9 +34,9 @@ public class NonRecordableNode extends AliasIDNode { private static final long serialVersionUID = 1L; - public NonRecordableNode( NonRecordable id ) + public NonRecordableNode( PlaylistManager playlistManager, NonRecordable id ) { - super( id ); + super( playlistManager, id ); } @Override diff --git a/src/audio/AudioModule.java b/src/audio/AudioModule.java index 7e28b70d..1f87f38d 100644 --- a/src/audio/AudioModule.java +++ b/src/audio/AudioModule.java @@ -8,7 +8,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import sample.Listener; -import sample.real.IRealBufferListener; +import sample.real.IFilteredRealBufferListener; import sample.real.RealBuffer; import audio.metadata.AudioMetadata; import audio.metadata.IMetadataListener; @@ -18,7 +18,6 @@ import audio.squelch.SquelchState; import controller.channel.ChannelEvent; import controller.channel.IChannelEventListener; import dsp.filter.Filters; -import dsp.filter.dc.DCRemovalFilter_RB; import dsp.filter.fir.real.RealFIRFilter_R_R; /** @@ -32,49 +31,31 @@ import dsp.filter.fir.real.RealFIRFilter_R_R; public class AudioModule extends Module implements IAudioPacketProvider, IChannelEventListener, IMetadataListener, - IRealBufferListener, + IFilteredRealBufferListener, ISquelchStateListener, Listener { protected static final Logger mLog = LoggerFactory.getLogger( AudioModule.class ); - /* Determines responsiveness of DC filter to frequency changes */ - private static final float DC_REMOVAL_RATIO = 0.000003f; - /* Provides a unique identifier for this audio module instance to use as a * source identifier for all audio packets */ private static int UNIQUE_ID = 0; private int mSourceID; private AudioMetadata mAudioMetadata; - private ChannelEventListener mChannelEventListener = new ChannelEventListener(); - private SquelchStateListener mSquelchStateListener = new SquelchStateListener(); private SquelchState mSquelchState = SquelchState.SQUELCH; - - private RealFIRFilter_R_R mAudioFilter = new RealFIRFilter_R_R( - Filters.FIR_BANDPASS_AUDIO_48KHZ.getCoefficients(), 2.0f ); - - private DCRemovalFilter_RB mDCRemovalFilter; - private Listener mAudioPacketListener; + +//TODO: remove this -- is being replaced by the DemodulatedAudioFilterModule + private RealFIRFilter_R_R mAudioFilter = new RealFIRFilter_R_R( + Filters.FIR_BANDPASS_AUDIO_48KHZ.getCoefficients(), 2.0f ); - private boolean mRemoveDC = false; - - public AudioModule( boolean record, boolean removeDC ) + public AudioModule( boolean record ) { mSourceID = ++UNIQUE_ID; - mAudioMetadata = new AudioMetadata( mSourceID, record ); - - mRemoveDC = removeDC; - - if( mRemoveDC ) - { - mDCRemovalFilter = new DCRemovalFilter_RB( DC_REMOVAL_RATIO ); - mDCRemovalFilter.setListener( this ); - } } @Override @@ -132,13 +113,8 @@ public class AudioModule extends Module implements IAudioPacketProvider, } @Override - public Listener getRealBufferListener() + public Listener getFilteredRealBufferListener() { - if( mRemoveDC ) - { - return mDCRemovalFilter; - } - return this; } diff --git a/src/audio/AudioPanel.java b/src/audio/AudioPanel.java index 0d008f01..3e6ba613 100644 --- a/src/audio/AudioPanel.java +++ b/src/audio/AudioPanel.java @@ -27,6 +27,7 @@ import org.slf4j.LoggerFactory; import sample.Listener; import settings.SettingsManager; +import source.SourceManager; import source.mixer.MixerChannelConfiguration; import source.mixer.MixerManager; import audio.output.AudioOutput; @@ -43,14 +44,18 @@ public class AudioPanel extends JPanel implements Listener new ImageIcon( "images/audio_unmuted.png" ), 38 ); private SettingsManager mSettingsManager; + private SourceManager mSourceManager; private IAudioController mController; private JButton mMuteButton; private AudioChannelsPanel mAudioChannelsPanel; - public AudioPanel( SettingsManager settingsManager, IAudioController controller ) + public AudioPanel( SettingsManager settingsManager, + SourceManager sourceManager, + IAudioController controller ) { mSettingsManager = settingsManager; + mSourceManager = sourceManager; mController = controller; mController.addControllerListener( this ); @@ -148,7 +153,7 @@ public class AudioPanel extends JPanel implements Listener JMenu outputMenu = new JMenu( "Audio Output" ); MixerChannelConfiguration[] mixerConfigurations = - MixerManager.getInstance().getOutputMixers(); + mSourceManager.getMixerManager().getOutputMixers(); for( MixerChannelConfiguration mixerConfig: mixerConfigurations ) { diff --git a/src/buffer/BufferOverflowException.java b/src/buffer/BufferOverflowException.java deleted file mode 100644 index 4b6e1a57..00000000 --- a/src/buffer/BufferOverflowException.java +++ /dev/null @@ -1,33 +0,0 @@ -/******************************************************************************* - * 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 - ******************************************************************************/ -package buffer; - -public class BufferOverflowException extends Exception -{ - private static final long serialVersionUID = 1L; - - public BufferOverflowException( String text ) - { - super( text ); - } - - public BufferOverflowException( String text, Throwable exc ) - { - super( text, exc ); - } -} diff --git a/src/buffer/BufferOverflowListener.java b/src/buffer/BufferOverflowListener.java deleted file mode 100644 index 2f8acb03..00000000 --- a/src/buffer/BufferOverflowListener.java +++ /dev/null @@ -1,23 +0,0 @@ -/******************************************************************************* - * 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 - ******************************************************************************/ -package buffer; - -public interface BufferOverflowListener -{ - public void overflow( Object source, String message ); -} diff --git a/src/buffer/ByteArrayDelayBuffer.java b/src/buffer/ByteArrayDelayBuffer.java deleted file mode 100644 index fc60703a..00000000 --- a/src/buffer/ByteArrayDelayBuffer.java +++ /dev/null @@ -1,60 +0,0 @@ -/******************************************************************************* - * 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 - ******************************************************************************/ -package buffer; - -public class ByteArrayDelayBuffer -{ - private int mBufferSize; - private byte[][] mBuffer = null; - private int mBufferPointer = 0; - - /** - * Implements a delay buffer for byte arrays. As a new byte[] is placed - * into the buffer, the oldest byte[] is returned - * @param bufferSize - number of byte arrays to buffer - */ - public ByteArrayDelayBuffer( int bufferSize ) - { - mBufferSize = bufferSize; - } - - /** - * Inserts new bytes into the buffer - * - * @return - oldest byte[] from the buffer, or null if the buffer is not - * yet full - */ - public byte[] get( byte[] bytes ) - { - if( mBuffer == null ) - { - mBuffer = new byte[ mBufferSize ][ bytes.length ]; - } - - byte[] returnBytes = mBuffer[ mBufferPointer ]; - - mBuffer[ mBufferPointer++ ] = bytes; - - if( mBufferPointer >= mBufferSize ) - { - mBufferPointer = 0; - } - - return returnBytes; - } -} diff --git a/src/buffer/ByteArrayListener.java b/src/buffer/ByteArrayListener.java deleted file mode 100644 index 021b8e2a..00000000 --- a/src/buffer/ByteArrayListener.java +++ /dev/null @@ -1,23 +0,0 @@ -/******************************************************************************* - * 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 - ******************************************************************************/ -package buffer; - -public interface ByteArrayListener -{ - public void receive( byte[] data ); -} diff --git a/src/buffer/ByteBufferListener.java b/src/buffer/ByteBufferListener.java deleted file mode 100644 index 7df629a0..00000000 --- a/src/buffer/ByteBufferListener.java +++ /dev/null @@ -1,25 +0,0 @@ -/******************************************************************************* - * 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 - ******************************************************************************/ -package buffer; - -import java.nio.ByteBuffer; - -public interface ByteBufferListener -{ - public void receive( ByteBuffer buffer ); -} diff --git a/src/buffer/ByteBufferProvider.java b/src/buffer/ByteBufferProvider.java deleted file mode 100644 index f85962c3..00000000 --- a/src/buffer/ByteBufferProvider.java +++ /dev/null @@ -1,33 +0,0 @@ -/******************************************************************************* - * 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 - ******************************************************************************/ -package buffer; - - - -public interface ByteBufferProvider -{ - /** - * Adds a sample listener to receive samples - */ - public void addByteBufferListener( ByteBufferListener listener ); - - /** - * Removes the sample listener, if it is currently registered as a listener - */ - public void removeByteBufferListener( ByteBufferListener listener ); -} diff --git a/src/buffer/ComplexByteBuffer.java b/src/buffer/ComplexByteBuffer.java deleted file mode 100644 index 1abb25dc..00000000 --- a/src/buffer/ComplexByteBuffer.java +++ /dev/null @@ -1,91 +0,0 @@ -/******************************************************************************* - * 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 - ******************************************************************************/ -package buffer; - -import java.nio.ByteBuffer; -import java.util.Enumeration; - -import sample.complex.Complex; - -/** - * Provides a complex sample enumeration wrapper around a byte array containing - * interleaved byte-length I & Q sample values in the range of 0 - 255, converting - * those samples into complex samples with value range of -128 to 0 to 127. - */ -public class ComplexByteBuffer implements Enumeration -{ - private static float[] mValues; - - /** - * Creates a lookup table that converts the 8-bit valued range from 0 - 255 - * into scaled float values of -128 to 0 to 127 - */ - static - { - mValues = new float[ 256 ]; - - float scale = (float)( 1.0f / 127.0f ); - - for( int x = 0; x < 256; x++ ) - { - mValues[ x ] = (float)( x - 128 ) * scale; - } - } - - private ByteBuffer mBytes; -// private byte[] mBytes; -// private int mPointer; - - public ComplexByteBuffer( byte[] bytes ) - { - mBytes = ByteBuffer.wrap( bytes ); -// mBytes = bytes; -// mPointer = 0; - } - - public byte[] toArray() - { -// return mBytes; - return mBytes.array(); - } - - /** - * Indicates if there are more complex samples remaining. - */ - @Override - public boolean hasMoreElements() - { -// return mPointer < mBytes.length; - return mBytes.hasRemaining(); - } - - /** - * Returns the next complex sample. - * - * Note: does not check for buffer overrun. Use the hasMoreElements() - * method to ensure you do not read past the end of the buffer. - */ - @Override - public Complex nextElement() - { -// return new ComplexSample( mValues[ ( mBytes[ mPointer++ ] & 0xFF ) ], -// mValues[ ( mBytes[ mPointer++ ] & 0xFF ) ] ); - return new Complex( mValues[ ( mBytes.get() & 0xFF ) ], - mValues[ ( mBytes.get() & 0xFF ) ] ); - } -} diff --git a/src/buffer/ComplexSampleBufferAssembler.java b/src/buffer/ComplexSampleBufferAssembler.java deleted file mode 100644 index 935696f1..00000000 --- a/src/buffer/ComplexSampleBufferAssembler.java +++ /dev/null @@ -1,73 +0,0 @@ -/******************************************************************************* - * 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 - ******************************************************************************/ -package buffer; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.Arrays; - -import sample.complex.Complex; - -public class ComplexSampleBufferAssembler -{ - private ByteBuffer mByteBuffer; - private int mSizeInBytes; - - public ComplexSampleBufferAssembler( int size ) - { - mSizeInBytes = size * 4; - - //Allocate a byte buffer with 4 bytes per sample (ie 2 x 16-bit samples) - mByteBuffer = ByteBuffer.allocate( mSizeInBytes ); - mByteBuffer.order( ByteOrder.LITTLE_ENDIAN ); - } - - /** - * Load the sample's bytes, left then right, little endian, into the - * backing byte array - */ - public void put( Complex sample ) - { - mByteBuffer.putShort( (short)( sample.left() * Short.MAX_VALUE ) ); - mByteBuffer.putShort( (short)( sample.right() * Short.MAX_VALUE ) ); - } - - /** - * Indicates if there is room for more samples in the buffer, or if it is full - */ - public boolean hasRemaining() - { - return mByteBuffer.hasRemaining(); - } - - /** - * Returns a copy of the byte array backing this buffer - */ - public ByteBuffer get() - { - return ByteBuffer.wrap( Arrays.copyOf( mByteBuffer.array(), mSizeInBytes ) ); - } - - /** - * Clear the bytes from the underlying buffer and reset the pointer to 0. - */ - public void clear() - { - mByteBuffer.clear(); - } -} diff --git a/src/buffer/DelayBuffer.java b/src/buffer/DelayBuffer.java deleted file mode 100644 index 001058db..00000000 --- a/src/buffer/DelayBuffer.java +++ /dev/null @@ -1,67 +0,0 @@ -/******************************************************************************* - * 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 - ******************************************************************************/ -package buffer; - -import sample.Listener; - -/** - * Delay Buffer - implements a circular delay buffer backed by an object array - */ -public class DelayBuffer implements Listener -{ - private Object[] mBuffer; - private int mBufferPointer = 0; - private Listener mListener; - - public DelayBuffer( int length ) - { - mBuffer = new Object[ length ]; - } - - @Override - @SuppressWarnings( "unchecked" ) - public void receive( T value ) - { - Object delayed = mBuffer[ mBufferPointer ]; - - mBuffer[ mBufferPointer ] = value; - - mBufferPointer++; - - /* Wrap the buffer pointer around to 0 when necessary */ - if( mBufferPointer >= mBuffer.length ) - { - mBufferPointer = 0; - } - - if( mListener != null && delayed != null ) - { - mListener.receive( (T)delayed ); - } - } - - public void setListener( Listener listener ) - { - mListener = listener; - } - - public void removeListener( Listener listener ) - { - mListener = null; - } -} diff --git a/src/buffer/FloatArrayCircularAveragingBuffer.java b/src/buffer/FloatArrayCircularAveragingBuffer.java deleted file mode 100644 index 5003d789..00000000 --- a/src/buffer/FloatArrayCircularAveragingBuffer.java +++ /dev/null @@ -1,97 +0,0 @@ -/******************************************************************************* - * 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 - ******************************************************************************/ -package buffer; - -import java.util.ArrayList; -import java.util.Arrays; - -public class FloatArrayCircularAveragingBuffer -{ - private ArrayList mBuffer; - private int mBufferPointer; - private int mBufferSize; - private float[] mAverage; - - public FloatArrayCircularAveragingBuffer( int bufferSize ) - { - mBufferSize = bufferSize; - mBuffer = new ArrayList(); - } - - /** - * Replaces the oldest float array element in the buffer with this new - * float array element, and then returns the average of the buffer contents - * with the newElement values included in the average array - */ - public float[] get( float[] newElement ) - { - /** - * If we've never setup the average array, or the newElements length is - * different than what we've been processing, reset the buffer & averages - */ - if( mAverage == null || mAverage.length != newElement.length ) - { - reset( newElement.length ); - } - - float[] oldElement = mBuffer.get( mBufferPointer ); - - for( int x = 0; x < newElement.length; x++ ) - { - /** - * Change the current average value in each array element by the - * difference of the new element minus the old element, divided - * by the buffer size ... average it - */ - mAverage[ x ] += - ( ( newElement[ x ] - oldElement[ x ] ) / mBufferSize ); - } - - mBuffer.set( mBufferPointer, newElement ); - - mBufferPointer++; - - if( mBufferPointer >= mBufferSize ) - { - mBufferPointer = 0; - } - - return mAverage; - } - - /** - * Clears buffer and average and fills buffer with zero-valued float arrays - */ - private void reset( int arrayLength ) - { - mAverage = new float[ arrayLength ]; - Arrays.fill( mAverage, 0.0f ); - - mBuffer.clear(); - mBufferPointer = 0; - - float[] emptyArray = new float[ arrayLength ]; - Arrays.fill( emptyArray, 0.0f ); - - for( int x = 0; x < mBufferSize; x++ ) - { - mBuffer.add( emptyArray ); - } - } - -} diff --git a/src/buffer/FloatBufferAssembler.java b/src/buffer/FloatBufferAssembler.java deleted file mode 100644 index 651a1794..00000000 --- a/src/buffer/FloatBufferAssembler.java +++ /dev/null @@ -1,70 +0,0 @@ -/******************************************************************************* - * 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 - ******************************************************************************/ -package buffer; - -import java.util.Arrays; - -import sample.Listener; - - -/** - * Assembles single samples into sample blocks (ie arrays) for broadcast to - * registered SampleBlockListeners - */ -public class FloatBufferAssembler implements Listener -{ - private Float[] mFloatBuffer; - private int mBufferSize; - private int mBufferPointer = 0; - private Listener mListener; - - public FloatBufferAssembler( int bufferSize ) - { - mBufferSize = bufferSize; - mFloatBuffer = new Float[ mBufferSize ]; - } - - /** - * Stores received samples in the sample block and manages the storage - * pointer. Sends sample blocks when full. - */ - @Override - public void receive( Float sample ) - { - mFloatBuffer[ mBufferPointer++ ] = sample; - - if( mBufferPointer == mBufferSize ) - { - if( mListener != null ) - { - mListener.receive( Arrays.copyOf( mFloatBuffer, mBufferSize ) ); - } - - mBufferPointer = 0; - } - } - - /** - * Adds a new sampleblock listener to receive sample blocks as they are - * assembled from the sample stream - */ - public void setListener( Listener listener ) - { - mListener = listener; - } -} diff --git a/src/buffer/FloatCircularAveragingBuffer.java b/src/buffer/FloatCircularAveragingBuffer.java deleted file mode 100644 index 6a05ea61..00000000 --- a/src/buffer/FloatCircularAveragingBuffer.java +++ /dev/null @@ -1,110 +0,0 @@ -/******************************************************************************* - * 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 - ******************************************************************************/ -package buffer; - -import java.util.Arrays; - -/** - * Circular sample buffer - allocates a buffer and stores samples in a circular - * fashion, overwriting older samples with newly arrived samples. Initially - * fills buffer with 0-valued samples - * - * Produces no output. Obtain the average buffer value on-demand via the - * getAverage() method - */ -public class FloatCircularAveragingBuffer -{ - private float[] mBuffer; - private int mBufferPointer = 0; - private int mSampleCountForAveraging; - private int mCurrentSampleCount = 0; - private float mAverage = 0.0f; - - public FloatCircularAveragingBuffer( int size, int sampleCountForAveraging ) - { - mBuffer = new float[ size ]; - mSampleCountForAveraging = sampleCountForAveraging; - Arrays.fill( mBuffer, 0.0f ); - } - - /** - * Convenience wrapper to throw away to put the new sample and throwaway - * the oldest sample - */ - public void put( float newestSample ) - { - get( newestSample ); - } - - /** - * Loads the newest sample into the buffer and returns the oldest sample - */ - public float get( float newestSample ) - { - float oldestSample = mBuffer[ mBufferPointer ]; - - mBuffer[ mBufferPointer ] = newestSample; - - mBufferPointer++; - - if( mBufferPointer >= mBuffer.length ) - { - mBufferPointer = 0; - } - - mCurrentSampleCount++; - - if( mCurrentSampleCount >= mSampleCountForAveraging ) - { - calculateAverage(); - - mCurrentSampleCount = 0; - } - - return oldestSample; - } - - /** - * Calculates the average of the maximum and minimum values present in - * the buffer - */ - private void calculateAverage() - { - float min = mBuffer[ 0 ]; - float max = mBuffer[ 0 ]; - - for( int x = 0; x < mBuffer.length; x++ ) - { - if( mBuffer[ x ] < min ) - { - min = mBuffer[ x ]; - } - if( mBuffer[ x ] > max ) - { - max = mBuffer[ x ]; - } - } - - mAverage = (float)( ( min + max ) / 2.0f ); - } - - public float getAverage() - { - return mAverage; - } -} diff --git a/src/buffer/FloatCircularAveragingBuffer2.java b/src/buffer/FloatCircularAveragingBuffer2.java deleted file mode 100644 index da27d207..00000000 --- a/src/buffer/FloatCircularAveragingBuffer2.java +++ /dev/null @@ -1,68 +0,0 @@ -/******************************************************************************* - * 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 - ******************************************************************************/ -package buffer; - -import java.util.Arrays; - -/** - * Circular sample buffer - stores samples in a circular buffer - * overwriting older samples with newly arrived samples. Initially - * fills buffer with 0-valued samples - * - * Continuously calculates the average of the samples in the buffer, with the - * average available from the average() method. - */ -public class FloatCircularAveragingBuffer2 -{ - private float[] mBuffer; - private int mBufferPointer = 0; - private float mAverage = 0.0f; - - public FloatCircularAveragingBuffer2( int size ) - { - mBuffer = new float[ size ]; - Arrays.fill( mBuffer, 0.0f ); - } - - /** - * Loads the newest sample into the buffer and returns the oldest sample - */ - public float get( float newestSample ) - { - float oldestSample = mBuffer[ mBufferPointer ]; - - mBuffer[ mBufferPointer ] = newestSample; - - mBufferPointer++; - - if( mBufferPointer >= mBuffer.length ) - { - mBufferPointer = 0; - } - - mAverage = mAverage - ( oldestSample / mBuffer.length ) + - ( newestSample / mBuffer.length ); - - return oldestSample; - } - - public float average() - { - return mAverage; - } -} diff --git a/src/buffer/FloatSampleBuffer.java b/src/buffer/FloatSampleBuffer.java deleted file mode 100644 index bca43189..00000000 --- a/src/buffer/FloatSampleBuffer.java +++ /dev/null @@ -1,66 +0,0 @@ -/******************************************************************************* - * 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 - ******************************************************************************/ -package buffer; - -import java.nio.ByteBuffer; - - -public class FloatSampleBuffer -{ - private static final long serialVersionUID = 1L; - - private int mSize; - private float[] mBuffer; - private int mBufferPointer = 0; - - public FloatSampleBuffer( int size ) - { - super(); - mBuffer = new float[ size ]; - } - - public void put( float sample ) - { - if( !isFull() ) - { - mBuffer[ mBufferPointer++ ] = sample; - } - } - - public void reset() - { - mBufferPointer = 0; - } - - public boolean isFull() - { - return mBufferPointer >= mBuffer.length; - } - - public byte[] getBytes() - { - ByteBuffer bb = ByteBuffer.allocate( mBuffer.length * 2 ); - - for( int x = 0; x < mBuffer.length; x++ ) - { - bb.putShort( ((Float)mBuffer[ x ]).shortValue() ); - } - - return bb.array(); - } -} diff --git a/src/buffer/FloatSampleBufferAssembler.java b/src/buffer/FloatSampleBufferAssembler.java deleted file mode 100644 index de4d53c2..00000000 --- a/src/buffer/FloatSampleBufferAssembler.java +++ /dev/null @@ -1,72 +0,0 @@ -/******************************************************************************* - * 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 - ******************************************************************************/ -package buffer; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -public class FloatSampleBufferAssembler -{ - private ByteBuffer mByteBuffer; - private int mSizeInBytes; - - public FloatSampleBufferAssembler( int size ) - { - mSizeInBytes = size * 2; - - //Allocate a byte buffer with 2 bytes per sample (ie 1 x 16-bit sample) - mByteBuffer = ByteBuffer.allocate( mSizeInBytes ); - mByteBuffer.order( ByteOrder.LITTLE_ENDIAN ); - } - - /** - * Load the sample's bytes, left then right, little endian, into the - * backing byte array - */ - public void put( float sample ) - { - mByteBuffer.putShort( (short)( sample * 32768 ) ); - } - - /** - * Indicates if there is room for more samples in the buffer, or if it is full - */ - public boolean hasRemaining() - { - return mByteBuffer.hasRemaining(); - } - - /** - * Returns a copy of the byte array backing this buffer - */ - public ByteBuffer get() - { - return mByteBuffer; -// return ByteBuffer.wrap( Arrays.copyOf( mByteBuffer.array(), mSizeInBytes ) ); - } - - /** - * Clear the bytes from the underlying buffer and reset the pointer to 0. - */ - public void reset() - { -// mByteBuffer.clear(); - mByteBuffer = ByteBuffer.allocate( mSizeInBytes ); - mByteBuffer.order( ByteOrder.LITTLE_ENDIAN ); - } -} diff --git a/src/buffer/FloatTappedCircularBuffer.java b/src/buffer/FloatTappedCircularBuffer.java deleted file mode 100644 index 5d0c3e7f..00000000 --- a/src/buffer/FloatTappedCircularBuffer.java +++ /dev/null @@ -1,86 +0,0 @@ -/******************************************************************************* - * 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 - ******************************************************************************/ -package buffer; - - -/** - * Implements a FIFO circular buffer for floats that provides access - * to each sample by index number, where index 0 is the newest/latest - * complex sample and index (length - 1) is the oldest sample in the buffer. - */ -public class FloatTappedCircularBuffer -{ - private Float[] mBuffer; - private int mBufferPointer = 0; - - public FloatTappedCircularBuffer( int length ) - { - mBuffer = new Float[ length ]; - - //Pre-load the buffer with 0-valued samples - for( int x = 0; x < length; x++ ) - { - mBuffer[ x ] = Float.valueOf( 0.0f ); - } - } - - /** - * Adds the sample to the buffer and removes the oldest sample - * @param sample - */ - public void add( Float sample ) - { - mBuffer[ mBufferPointer++ ] = sample; - - //Reset the buffer pointer once it points past the end of the buffer - if( mBufferPointer >= mBuffer.length ) - { - mBufferPointer = 0; - } - } - - /** - * Retrieves a sample currently in the buffer by index position. - * - * Index 0 is the newest/latest sample in the buffer and index (length - 1) - * is the oldest. - * - * Note: the buffer is preloaded with complex samples of 0,0 value. - * - * @param index where 0 is the newest/latest sample and length-1 is the oldest - * @return complex sample from the buffer. - * @throws ArrayIndexOutOfBoundsException if you attempt to access a sample - * outside of the buffer size - */ - public Float get( int index ) - { - /* Since the samples are stored in a forward fashion, we have to access - * the samples in reverse to comply with the access contract, where - * index 0 is the newest and index (length -1) is the oldest, all - * relative to the current buffer pointer */ - - int pointer = mBuffer.length - 1 + mBufferPointer - index; - - if( pointer >= mBuffer.length ) - { - pointer -= mBuffer.length; - } - - return mBuffer[ pointer ]; - } -} diff --git a/src/buffer/FloatToByteBufferAssembler.java b/src/buffer/FloatToByteBufferAssembler.java deleted file mode 100644 index 5f24ffce..00000000 --- a/src/buffer/FloatToByteBufferAssembler.java +++ /dev/null @@ -1,69 +0,0 @@ -/******************************************************************************* - * 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 - ******************************************************************************/ -package buffer; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -import sample.Broadcaster; -import sample.Listener; - -public class FloatToByteBufferAssembler implements Listener -{ - private Broadcaster mBroadcaster = new Broadcaster(); - - private int mBufferSize = 0; - private ByteBuffer mBuffer; - - public FloatToByteBufferAssembler( int bufferSize ) - { - mBufferSize = bufferSize; - resetBuffer(); - } - - public void addByteBufferListener( Listener listener ) - { - mBroadcaster.addListener( listener ); - } - - public void removeByteBufferListener( Listener listener ) - { - mBroadcaster.removeListener( listener ); - } - - private void resetBuffer() - { - mBuffer = ByteBuffer.allocate( mBufferSize ); - mBuffer.order( ByteOrder.BIG_ENDIAN ); - } - - @Override - public void receive( Float sample ) - { - mBuffer.putShort( Float.valueOf( sample ).shortValue() ); - - if( mBuffer.position() >= mBufferSize ) - { - //Buffer is full ... send it - mBroadcaster.receive( mBuffer ); - - //Reset the buffer - resetBuffer(); - } - } -} diff --git a/src/buffer/StereoByteBuffer.java b/src/buffer/StereoByteBuffer.java deleted file mode 100644 index 6e4e6db4..00000000 --- a/src/buffer/StereoByteBuffer.java +++ /dev/null @@ -1,59 +0,0 @@ -/******************************************************************************* - * 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 - ******************************************************************************/ -package buffer; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.Enumeration; - -import sample.complex.Complex; -import source.mixer.MixerChannel; - -public class StereoByteBuffer implements Enumeration -{ - private ByteBuffer mByteBuffer; - - public StereoByteBuffer( byte[] bytes, int frames ) - { - mByteBuffer = ByteBuffer.wrap( bytes ); - mByteBuffer.order( ByteOrder.LITTLE_ENDIAN ); - } - - public byte[] array() - { - return mByteBuffer.array(); - } - - public ByteBuffer getChannel( MixerChannel channel ) - { - return StereoToMonoByteBufferConverter.getChannel( mByteBuffer, channel ); - } - - @Override - public boolean hasMoreElements() - { - return mByteBuffer.hasRemaining(); - } - - @Override - public Complex nextElement() - { - return new Complex( (float)mByteBuffer.getShort(), - (float)mByteBuffer.getShort() ); - } -} diff --git a/src/buffer/StereoByteBufferListener.java b/src/buffer/StereoByteBufferListener.java deleted file mode 100644 index 641305c1..00000000 --- a/src/buffer/StereoByteBufferListener.java +++ /dev/null @@ -1,24 +0,0 @@ -/******************************************************************************* - * 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 - ******************************************************************************/ -package buffer; - - -public interface StereoByteBufferListener -{ - public void receive( StereoByteBuffer buffer ); -} diff --git a/src/buffer/StereoByteBufferProvider.java b/src/buffer/StereoByteBufferProvider.java deleted file mode 100644 index 76f91930..00000000 --- a/src/buffer/StereoByteBufferProvider.java +++ /dev/null @@ -1,32 +0,0 @@ -/******************************************************************************* - * 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 - ******************************************************************************/ -package buffer; - - -public interface StereoByteBufferProvider -{ - /** - * Adds a sample listener to receive samples - */ - public void addStereoByteBufferListener( StereoByteBufferListener listener ); - - /** - * Removes the sample listener, if it is currently registered as a listener - */ - public void removeStereoByteBufferListener( StereoByteBufferListener listener ); -} diff --git a/src/buffer/StereoToMonoByteBufferConverter.java b/src/buffer/StereoToMonoByteBufferConverter.java deleted file mode 100644 index 55e43aca..00000000 --- a/src/buffer/StereoToMonoByteBufferConverter.java +++ /dev/null @@ -1,58 +0,0 @@ -/******************************************************************************* - * 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 - ******************************************************************************/ -package buffer; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -import source.mixer.MixerChannel; - -public class StereoToMonoByteBufferConverter -{ - public static ByteBuffer getChannel( ByteBuffer buffer, MixerChannel channel ) - { - byte[] channelBuffer = new byte[ buffer.capacity() / 2 ]; - - - int channelBufferPointer = 0; - - if( channel == MixerChannel.RIGHT ) - { - //throw away the first two bytes - buffer.get(); - buffer.get(); - } - - while( channelBufferPointer < channelBuffer.length ) - { - if( buffer.hasRemaining() ) - { - channelBuffer[ channelBufferPointer++ ] = buffer.get(); - channelBuffer[ channelBufferPointer++ ] = buffer.get(); - } - - if( buffer.hasRemaining() ) - { - buffer.get(); - buffer.get(); - } - } - - return ByteBuffer.wrap( channelBuffer ).order( ByteOrder.LITTLE_ENDIAN ); - } -} diff --git a/src/controller/ConfigurableNode.java b/src/controller/ConfigurableNode.java index f9a6e3be..77da7453 100644 --- a/src/controller/ConfigurableNode.java +++ b/src/controller/ConfigurableNode.java @@ -17,14 +17,24 @@ ******************************************************************************/ package controller; +import playlist.PlaylistManager; public abstract class ConfigurableNode extends BaseNode { private static final long serialVersionUID = 1L; + + private PlaylistManager mPlaylistManager; - public ConfigurableNode( Object object ) + public ConfigurableNode( PlaylistManager playlistManager, Object object ) { super( object ); + + mPlaylistManager = playlistManager; + } + + protected PlaylistManager getPlaylistManager() + { + return mPlaylistManager; } /** @@ -32,7 +42,7 @@ public abstract class ConfigurableNode extends BaseNode */ public void save() { - getModel().getResourceManager().getPlaylistManager().save(); + mPlaylistManager.save(); BaseNode parent = (BaseNode)getParent(); diff --git a/src/controller/ConfigurationControllerModel.java b/src/controller/ConfigurationControllerModel.java index 8bbd48c3..692ee7ee 100644 --- a/src/controller/ConfigurationControllerModel.java +++ b/src/controller/ConfigurationControllerModel.java @@ -28,9 +28,14 @@ import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.MutableTreeNode; import javax.swing.tree.TreePath; -import map.IconManager; import module.decode.DecoderType; + +import playlist.PlaylistManager; import playlist.PlaylistNode; + +import settings.SettingsManager; +import source.SourceManager; +import source.recording.RecordingGroupNode; import source.tuner.Tuner; import source.tuner.TunerGroupNode; import source.tuner.TunerNode; @@ -39,14 +44,14 @@ import controller.channel.Channel; import controller.channel.ChannelModel; import controller.channel.ChannelNode; +import controller.channel.ChannelProcessingManager; + public class ConfigurationControllerModel extends DefaultTreeModel { private static final long serialVersionUID = 1L; private JTree mTree; - private ResourceManager mResourceManager; - private ArrayList mTunerSelectionListeners = new ArrayList(); @@ -54,7 +59,11 @@ public class ConfigurationControllerModel extends DefaultTreeModel private TunerGroupNode mTunerGroupNode; // private RecordingGroupNode mRecordingGroupNode; - private IconManager mIconManagerFrame; + private ChannelModel mChannelModel; + private ChannelProcessingManager mChannelProcessingManager; + private PlaylistManager mPlaylistManager; + private SettingsManager mSettingsManager; + private SourceManager mSourceManager; private ChannelModel mChannelModel; /** @@ -63,14 +72,21 @@ public class ConfigurationControllerModel extends DefaultTreeModel * design perspective, the model and the control are necessarily merged to * work well with the JTree as the system view. */ - public ConfigurationControllerModel( ChannelModel channelModel, - ResourceManager resourceManager ) + public ConfigurationControllerModel( ChannelModel channelModel, + ChannelProcessingManager channelProcessingManager, + PlaylistManager playlistManager, + SettingsManager settingsManager, + SourceManager sourceManager ) { super( new BaseNode( null ) ); mChannelModel = channelModel; - - mResourceManager = resourceManager; + + mChannelModel = channelModel; + mChannelProcessingManager = channelProcessingManager; + mPlaylistManager = playlistManager; + mSettingsManager = settingsManager; + mSourceManager = sourceManager; /** * Give the root node a reference to this model, so that all nodes can @@ -84,23 +100,6 @@ public class ConfigurationControllerModel extends DefaultTreeModel return mTree; } - public void showIconManager() - { - if( mIconManagerFrame == null ) - { - mIconManagerFrame = new IconManager( mResourceManager, mTree ); - - mResourceManager.getSettingsManager().addListener( mIconManagerFrame ); - } - - if( !mIconManagerFrame.isVisible() ) - { - mIconManagerFrame.setVisible( true ); - } - - mIconManagerFrame.toFront(); - } - /** * init() gets invoked manually/externally, after all of the references * are established in the constructor @@ -124,7 +123,8 @@ public class ConfigurationControllerModel extends DefaultTreeModel /** * Add the playlist node */ - mPlaylistNode = new PlaylistNode(); + mPlaylistNode = new PlaylistNode( mChannelModel, mChannelProcessingManager, + mPlaylistManager, mSettingsManager, mSourceManager ); insertNodeInto( mPlaylistNode, (MutableTreeNode)root, 1 ); mPlaylistNode.loadPlaylist(); } @@ -137,11 +137,6 @@ public class ConfigurationControllerModel extends DefaultTreeModel } } - public ResourceManager getResourceManager() - { - return mResourceManager; - } - public void setTree( JTree tree ) { mTree = tree; @@ -149,11 +144,13 @@ public class ConfigurationControllerModel extends DefaultTreeModel private void addTuners( TunerGroupNode parent ) { - List tuners = mResourceManager.getTunerManager().getTuners(); + List tuners = mSourceManager.getTunerManager().getTuners(); for( Tuner tuner: tuners ) { - TunerNode child = new TunerNode( mChannelModel, tuner ); + TunerNode child = new TunerNode( mChannelModel, + mChannelProcessingManager, mPlaylistManager, mSettingsManager, + tuner ); insertNodeInto( child, parent, parent.getChildCount() ); diff --git a/src/controller/ControllerPanel.java b/src/controller/ControllerPanel.java index 64b40a6d..e8612478 100644 --- a/src/controller/ControllerPanel.java +++ b/src/controller/ControllerPanel.java @@ -33,8 +33,10 @@ import module.decode.event.CallEventPanel; import module.decode.event.MessageActivityPanel; import module.decode.state.ChannelList; import net.miginfocom.swing.MigLayout; +import playlist.PlaylistEditor; import playlist.PlaylistManager; import settings.SettingsManager; +import source.SourceManager; import spectrum.ChannelSpectrumPanel; import audio.AudioManager; import audio.AudioPanel; @@ -53,15 +55,16 @@ public class ControllerPanel extends JPanel private CallEventPanel mCallEventPanel; - private MessageActivityPanel mMessageActivityPanel = - new MessageActivityPanel(); + private MessageActivityPanel mMessageActivityPanel; private ChannelSpectrumPanel mChannelSpectrumPanel; - private JideTabbedPane mTabbedPane; + private PlaylistEditor mPlaylistEditor; + + private JideTabbedPane mTabbedPane; protected ConfigurationTreePanel mSystemControlViewPanel; - protected ConfigurationEditor mConfigurationEditor; + protected OldConfigurationEditor mConfigurationEditor; protected JideSplitPane mSystemControlSplitPane; protected JTable mChannelActivityTable = new JTable(); @@ -78,20 +81,30 @@ public class ControllerPanel extends JPanel ChannelProcessingManager channelProcessingManager, MapService mapService, PlaylistManager playlistManager, - SettingsManager settingsManager ) + SettingsManager settingsManager, + SourceManager sourceManager ) { mChannelModel = channelModel; mController = controller; mSettingsManager = settingsManager; - mAudioPanel = new AudioPanel( mSettingsManager, audioManager ); + mAudioPanel = new AudioPanel( mSettingsManager, sourceManager, audioManager ); - mMapPanel = new MapPanel( mapService, mSettingsManager, channelProcessingManager ); + mMapPanel = new MapPanel( mapService, mSettingsManager ); - mCallEventPanel = new CallEventPanel( mSettingsManager ); - - mChannelStateList = new ChannelList( playlistManager, mSettingsManager ); + mMessageActivityPanel = new MessageActivityPanel( channelProcessingManager ); + + mCallEventPanel = new CallEventPanel( mSettingsManager, + channelProcessingManager ); + mChannelSpectrumPanel = new ChannelSpectrumPanel( mSettingsManager, + channelProcessingManager ); + + mChannelStateList = new ChannelList( channelModel, channelProcessingManager, + playlistManager, mSettingsManager ); + + mPlaylistEditor = new PlaylistEditor( channelModel, playlistManager, sourceManager ); + init(); } @@ -102,7 +115,7 @@ public class ControllerPanel extends JPanel "[grow,fill]") ); //System Configuration View and Editor - mConfigurationEditor = new ConfigurationEditor(); + mConfigurationEditor = new OldConfigurationEditor(); mSystemControlViewPanel = new ConfigurationTreePanel( mController ); mSystemControlViewPanel.addTreeSelectionListener( mConfigurationEditor ); @@ -112,8 +125,6 @@ public class ControllerPanel extends JPanel mSystemControlSplitPane.add( mSystemControlViewPanel ); mSystemControlSplitPane.add( mConfigurationEditor ); - mChannelSpectrumPanel = new ChannelSpectrumPanel( mSettingsManager ); - //Tabbed View - configuration, calls, messages, map mTabbedPane = new JideTabbedPane(); mTabbedPane.setFont( this.getFont() ); @@ -122,10 +133,8 @@ public class ControllerPanel extends JPanel mTabbedPane.addTab( "Channel Spectrum", mChannelSpectrumPanel ); mTabbedPane.addTab( "Events", mCallEventPanel ); mTabbedPane.addTab( "Messages", mMessageActivityPanel ); - - JTable channelsTable = new JTable( mChannelModel ); - JScrollPane channelsScroller = new JScrollPane( channelsTable ); - mTabbedPane.addTab( "Channels", channelsScroller ); + + mTabbedPane.addTab( "Playlist", mPlaylistEditor ); /** * Change listener to enable/disable the channel spectrum display diff --git a/src/controller/ConfigurationEditor.java b/src/controller/OldConfigurationEditor.java similarity index 95% rename from src/controller/ConfigurationEditor.java rename to src/controller/OldConfigurationEditor.java index 84a99a30..29d504ee 100644 --- a/src/controller/ConfigurationEditor.java +++ b/src/controller/OldConfigurationEditor.java @@ -26,7 +26,7 @@ import javax.swing.JTree; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; -public class ConfigurationEditor extends JPanel +public class OldConfigurationEditor extends JPanel implements TreeSelectionListener { private static final long serialVersionUID = 1L; @@ -34,7 +34,7 @@ public class ConfigurationEditor extends JPanel /** * Host for configuration editor display panels */ - public ConfigurationEditor() + public OldConfigurationEditor() { init(); } diff --git a/src/controller/ResourceManager.java b/src/controller/ResourceManager.java deleted file mode 100644 index a71de851..00000000 --- a/src/controller/ResourceManager.java +++ /dev/null @@ -1,177 +0,0 @@ -/******************************************************************************* - * 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 - ******************************************************************************/ -package controller; - -import map.MapService; -import module.log.EventLogManager; -import playlist.PlaylistManager; -import record.RecorderManager; -import settings.SettingsManager; -import source.SourceManager; -import source.recording.RecordingSourceManager; -import source.tuner.TunerManager; -import audio.AudioManager; -import controller.channel.ChannelModel; - -/** - * Manager for system wide resources - */ -public class ResourceManager -{ - private AudioManager mAudioManager; - private EventLogManager mEventLogManager; - private PlaylistManager mPlaylistManager; - private RecorderManager mRecorderManager; - private RecordingSourceManager mRecordingSourceManager; - private SettingsManager mSettingsManager; - private SourceManager mSourceManager; - private TunerManager mTunerManager; - private ConfigurationControllerModel mController; - private MapService mMapService; - private ThreadPoolManager mThreadPoolManager; - - public ResourceManager( PlaylistManager playlistManager, - ThreadPoolManager threadPoolManager, - ChannelModel channelModel ) - { - this( threadPoolManager, - new SettingsManager(), - playlistManager, - new EventLogManager(), - channelModel ); - } - - public ResourceManager( ThreadPoolManager threadPoolManager, - SettingsManager settingsManager, - PlaylistManager playlistManager, - EventLogManager eventLogManager, - ChannelModel channelModel ) - { - mThreadPoolManager = threadPoolManager; - mSettingsManager = settingsManager; - mPlaylistManager = playlistManager; - mEventLogManager = eventLogManager; - - /** - * ChannelManager requires a reference to the ResourceManager so that - * channel processing chains can access system wide resources - */ - mAudioManager = new AudioManager( mThreadPoolManager ); - mRecorderManager = new RecorderManager( mThreadPoolManager ); - mSourceManager = new SourceManager( this ); - mRecordingSourceManager = new RecordingSourceManager( this ); - mTunerManager = new TunerManager( this ); - mController = new ConfigurationControllerModel( channelModel, this ); - mMapService = new MapService( this ); - } - - public AudioManager getAudioManager() - { - return mAudioManager; - } - - public void setAudioManager( AudioManager audioManager ) - { - mAudioManager = audioManager; - } - - public ConfigurationControllerModel getController() - { - return mController; - } - - public ThreadPoolManager getThreadPoolManager() - { - return mThreadPoolManager; - } - - public void setController( ConfigurationControllerModel controller ) - { - mController = controller; - } - - public TunerManager getTunerManager() - { - return mTunerManager; - } - - public MapService getMapService() - { - return mMapService; - } - - public SettingsManager getSettingsManager() - { - return mSettingsManager; - } - - public void setSettingsManager( SettingsManager manager ) - { - mSettingsManager = manager; - } - - public PlaylistManager getPlaylistManager() - { - return mPlaylistManager; - } - - public void setPlaylistManager( PlaylistManager aliasManager ) - { - mPlaylistManager = aliasManager; - } - - public EventLogManager getEventLogManager() - { - return mEventLogManager; - } - - public void setEventLogManager( EventLogManager eventLogManager ) - { - mEventLogManager = eventLogManager; - } - - public RecorderManager getRecorderManager() - { - return mRecorderManager; - } - - public void setRecorderManager( RecorderManager recorderManager ) - { - mRecorderManager = recorderManager; - } - - public SourceManager getSourceManager() - { - return mSourceManager; - } - - public void setSourceManager( SourceManager sourceManager ) - { - mSourceManager = sourceManager; - } - - public RecordingSourceManager getRecordingSourceManager() - { - return mRecordingSourceManager; - } - - public void setRecordingSourceManager( RecordingSourceManager manager ) - { - mRecordingSourceManager = manager; - } -} diff --git a/src/controller/channel/AbstractChannelEditor.java b/src/controller/channel/AbstractChannelEditor.java index 41c3b4aa..2ef02f60 100644 --- a/src/controller/channel/AbstractChannelEditor.java +++ b/src/controller/channel/AbstractChannelEditor.java @@ -17,23 +17,22 @@ ******************************************************************************/ package controller.channel; -import controller.Editor; -public abstract class AbstractChannelEditor extends Editor +public abstract class AbstractChannelEditor extends ChannelConfigurationEditor { private static final long serialVersionUID = 1L; - protected ChannelNode mChannelNode; + protected Channel mChannel; - public AbstractChannelEditor( ChannelNode channel ) + public AbstractChannelEditor( Channel channel ) { super(); - mChannelNode = channel; + mChannel = channel; } - public ChannelNode getChannelNode() + public Channel getChannel() { - return mChannelNode; + return mChannel; } public abstract void save(); diff --git a/src/controller/channel/Channel.java b/src/controller/channel/Channel.java index 3da95791..b7d290a8 100644 --- a/src/controller/channel/Channel.java +++ b/src/controller/channel/Channel.java @@ -1,6 +1,6 @@ /******************************************************************************* * SDR Trunk - * Copyright (C) 2014 Dennis Sheirer + * Copyright (C) 2014-2016 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 @@ -17,35 +17,21 @@ ******************************************************************************/ package controller.channel; -import java.util.List; - import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlSeeAlso; import javax.xml.bind.annotation.XmlTransient; -import message.Message; -import module.Module; -import module.ProcessingChain; -import module.decode.DecoderFactory; import module.decode.config.AuxDecodeConfiguration; import module.decode.config.DecodeConfigFactory; import module.decode.config.DecodeConfiguration; -import module.decode.event.CallEventModel; -import module.decode.event.MessageActivityModel; -import module.decode.state.ChannelState; -import module.log.MessageEventLogger; import module.log.config.EventLogConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import record.RecorderManager; -import record.RecorderType; import record.config.RecordConfiguration; -import source.Source; -import source.SourceException; import source.SourceType; import source.config.SourceConfigFactory; import source.config.SourceConfigRecording; @@ -53,27 +39,25 @@ import source.config.SourceConfigTuner; import source.config.SourceConfiguration; import source.tuner.TunerChannel; import source.tuner.TunerChannel.Type; -import alias.AliasList; -import audio.metadata.Metadata; -import audio.metadata.MetadataType; -import controller.ResourceManager; + +import source.tuner.frequency.FrequencyChangeEvent; +import source.tuner.frequency.FrequencyChangeEvent.Event; +import source.tuner.frequency.IFrequencyChangeProcessor; import controller.config.Configuration; -import filter.FilterSet; @XmlSeeAlso( { Configuration.class } ) @XmlRootElement( name = "channel" ) -public class Channel extends Configuration +public class Channel extends Configuration implements IFrequencyChangeProcessor { private final static Logger mLog = LoggerFactory.getLogger( Channel.class ); - private static final boolean DISABLED = false; - - public enum ChannelType - { - STANDARD, - TRAFFIC - }; + // Standard channels are persisted and traffic channels are temporary + public enum ChannelType { STANDARD, TRAFFIC }; + + // Static unique channel identifier tracking + private static int UNIQUE_ID = 0; + private DecodeConfiguration mDecodeConfiguration = DecodeConfigFactory.getDefaultDecodeConfiguration(); private AuxDecodeConfiguration mAuxDecodeConfiguration = @@ -84,134 +68,67 @@ public class Channel extends Configuration new EventLogConfiguration(); private RecordConfiguration mRecordConfiguration = new RecordConfiguration(); - private ResourceManager mResourceManager; private String mAliasListName; - private String mSystem; - private String mSite; - private String mName; + private String mSystem = "System"; + private String mSite = "Site"; + private String mName = "Channel"; + private boolean mEnabled; private boolean mSelected; - private ChannelType mChannelType; - private ChannelState mChannelState; - private CallEventModel mCallEventModel; - private MessageActivityModel mMessageActivityModel; - private MessageEventLogger mEventLogger; - private ProcessingChain mProcessingChain; + private TunerChannel mTunerChannel = null; - private long mTrafficChannelTimeout = - DecodeConfiguration.DEFAULT_CALL_TIMEOUT_SECONDS; + private ChannelType mChannelType = ChannelType.STANDARD; + + private int mChannelID; + private int mChannelFrequencyCorrection = 0; /** - * Constructs a new standard channel with a default name of "New Channel" - */ - public Channel() - { - this( "New Channel", ChannelType.STANDARD ); - } - - /** - * Constructs a new standard channel with the specified channel name - */ - public Channel( String channelName ) - { - this( channelName, ChannelType.STANDARD ); - } - - /** - * Constructs a new channel with the specified channel name and type. + * Channel represents a complete set of configurations needed to setup and + * manage a processing chain and/or manage as a set of business objects that + * can be displayed in graphical components. * * @param channelName * @param channelType */ public Channel( String channelName, ChannelType channelType ) { - mName = channelName; + this( channelName ); mChannelType = channelType; } - + /** - * Indicates if the channel has Automatic or Direct Frequency Control + * Constructs a new standard channel with the specified channel name */ - public boolean hasFrequencyControl() + public Channel( String channelName ) { - return mProcessingChain != null && - mProcessingChain.hasFrequencyCorrectionControl(); - } - - public long getFrequencyCorrection() - { - if( hasFrequencyControl() ) - { - return mProcessingChain.getFrequencyCorrectionControl().getErrorCorrection(); - } - - return 0; + this(); + mName = channelName; } /** - * Sets the channel state traffic channel call end timer to the specified - * value. - */ - public void setTrafficChannelTimeout( long milliseconds ) - { - mTrafficChannelTimeout = milliseconds; - - if( mChannelState != null ) - { - mChannelState.setTrafficChannelTimeout( milliseconds ); - } - } - - /** - * Sets the resource manager responsible for this channel and registers - * the channel manager as a listener to this channel. Fires channel add - * channel event to the newly added channel manager channel listener. - * - * Note: resource manager instance is applied after object construction - * since we construct the channel objects from the xml playlist + * Constructs a new standard channel with a default name of "Channel" */ //TODO: remove this - public void setResourceManager( ResourceManager resourceManager ) + public Channel() { - mResourceManager = resourceManager; - - /* If we're enabled, fire enable changed event to get processing started */ - if( mEnabled ) - { - enableChanged(); - } + mChannelID = UNIQUE_ID++; } //TODO: remove this - @XmlTransient - public ResourceManager getResourceManager() - { - return mResourceManager; - } - /** - * Returns the processing chain for this channel. If the processing chain - * is not currently constructed and running, this method will return null. + * Unique identifier for this channel. Value is transient (not persisted). */ @XmlTransient - public ProcessingChain getProcessingChain() + public int getChannelID() { - return mProcessingChain; + return mChannelID; } /** - * Indicates if this channel has a processing chain constructed and it - * is processing. - */ - public boolean isProcessing() - { - return mProcessingChain != null && mProcessingChain.processing(); - } - - /** - * Indicates if this channel has been selected for audio output + * Indicates if this channel has been selected for prioritized audio output + * and display of processing chain products */ @XmlTransient public boolean isSelected() @@ -224,100 +141,12 @@ public class Channel extends Configuration mSelected = selected; } - @XmlTransient - public CallEventModel getCallEventModel() - { - return mCallEventModel; - } - - /** - * Returns the MessageEventLogger for this processing chain - */ - @XmlTransient - public MessageEventLogger getEventLogger() - { - return mEventLogger; - } - - /** - * Sets the MessageEventLogger for this processing chain - */ - public void setEventLogger( MessageEventLogger eventLogger ) - { - mEventLogger = eventLogger; - } - - @XmlTransient - public MessageActivityModel getMessageActivityModel() - { - return mMessageActivityModel; - } - - @XmlTransient - public ChannelState getChannelState() - { - return mChannelState; - } - @XmlTransient public ChannelType getChannelType() { return mChannelType; } - - /** - * Orderly shutdown method when this channel is going to be deleted. - */ - public void dispose() - { - setEnabled( DISABLED ); - } - - /** - * Returns a full channel name containing the system, site and channel name. - */ - public String getChannelDisplayName() - { - StringBuilder sb = new StringBuilder(); - - sb.append( ( mSystem == null ? "-" : mSystem ) ); - sb.append( ( mSite == null ? "-" : mSite ) ); - sb.append( mName ); - - return sb.toString(); - } - - /** - * Returns the tuner channel requirement for this channel when the source - * configuration specifies a tuner and frequency as the source for this - * channel. - * - * If the source configuration is anything else, this method returns null. - */ - public TunerChannel getTunerChannel() - { - TunerChannel retVal = null; - - if( mSourceConfiguration.getSourceType() == SourceType.TUNER ) - { - SourceConfigTuner config = (SourceConfigTuner)mSourceConfiguration; - - retVal = new TunerChannel( Type.LOCKED, config.getFrequency(), - 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; - } - /** * Returns the owning system for this channel. */ @@ -343,50 +172,78 @@ public class Channel extends Configuration @XmlAttribute( name = "site" ) public String getSite() { - return mSite; + return mSite; } public void setSite( String site ) { mSite = site; } - + public boolean hasSite() { return mSite != null; } + /** + * Returns the name of this channel. + */ + @XmlAttribute( name = "name" ) + public String getName() + { + return mName; + } + + /** + * Sets the name of this channel. + */ + public void setName( String name ) + { + mName = name; + } + /** - * Default display string for this channel -- the channel name. + * Default display string for this channel: SYSTEM_SITE_NAME */ public String toString() { - return mName; + StringBuilder sb = new StringBuilder(); + sb.append( hasSystem() ? getSystem() : "SYSTEM" ); + sb.append( "_" ); + sb.append( hasSite() ? getSite() : "SITE" ); + sb.append( "_" ); + sb.append( getName() ); + + return sb.toString(); } /** * Indicates if this channel is enabled for processing. */ - @XmlAttribute + @XmlAttribute( name = "enabled" ) public boolean getEnabled() { return mEnabled; } /** - * Enables/disables this channel for processing. Automatically starts or - * stops channel processing in response to this change. + * Indicates if this channel will automatically start processing on + * application startup or if this channel is currently processing after + * application startup. + * + * Note: this method is package private and is intended to be managed + * by a co-package central processing manager + * + * @see controller.ChannelProcessingManager */ - public void setEnabled( boolean enabled ) + void setEnabled( boolean enabled ) { mEnabled = enabled; - - enableChanged(); } /** * Returns the alias list that is used by this channel for looking up alias - * values for the various identifiers produced by the decoder. + * values for the various identifiers produced by the decoder(s). */ @XmlElement( name = "alias_list_name" ) public String getAliasListName() @@ -404,7 +261,7 @@ public class Channel extends Configuration } /** - * Gets the decoder configuration used by this channel + * Gets the primary decoder configuration used by this channel */ @XmlElement( name = "decode_configuration" ) public DecodeConfiguration getDecodeConfiguration() @@ -413,7 +270,7 @@ public class Channel extends Configuration } /** - * Sets the decoder configuration used by this channel + * Sets the primary decoder configuration used by this channel */ public void setDecodeConfiguration( DecodeConfiguration config ) { @@ -421,7 +278,8 @@ public class Channel extends Configuration } /** - * Gets the aux decoder configuration used by this channel + * Gets the aux decoder configuration used by this channel. Aux decoders + * operate on demodulated audio */ @XmlElement( name = "aux_decode_configuration" ) public AuxDecodeConfiguration getAuxDecodeConfiguration() @@ -438,7 +296,8 @@ public class Channel extends Configuration } /** - * Returns the source configuration for this channel. + * Returns the source configuration for this channel. A channel source + * identifies where the processing chain will get source sample data from. */ @XmlElement( name = "source_configuration" ) public SourceConfiguration getSourceConfiguration() @@ -452,6 +311,10 @@ public class Channel extends Configuration public void setSourceConfiguration( SourceConfiguration config ) { mSourceConfiguration = config; + + //Clear the tune channel object so that it can be recreated if the + //source configuration changes + mTunerChannel = null; } /** @@ -489,252 +352,41 @@ public class Channel extends Configuration } /** - * Returns the name of this channel. - */ - @XmlAttribute - public String getName() - { - return mName; - } - - /** - * Sets the name of this channel. - */ - public void setName( String name ) - { - mName = name; - } - - /** - * Responds to changes in the enabled setting by starting the processing - * change if the channel is now enabled, or stopping the procesing chain - * if it was already started. - */ - private void enableChanged() - { - if( mEnabled ) - { - start(); - } - else - { - stop(); - } - } - - /** - * Starts the channel processing chain. - */ - private void start() - { - if( mEnabled && mResourceManager != null ) - { - setupChannelState(); - - try - { - setup(); - - mProcessingChain.start(); - } - catch( SourceException se ) - { - //Do nothing, we couldn't get a source for the channel - } - } - } - - private void setupChannelState() - { - if( mChannelState == null ) - { - mChannelState = new ChannelState( mResourceManager - .getThreadPoolManager(), mChannelType ); - - mChannelState.setTrafficChannelTimeout( mTrafficChannelTimeout ); - } - } - - /** - * Sets up the channel and prepares to start processing. Sets up the - * processing chain and requests a source. + * Convenience method to construct a tuner channel object representing a + * tuner or recording source frequency and bandwidth that can be used by + * application components for graphically representing this channel. * - * @throws SourceException - if no source is available or if there is an - * error obtaining a source + * If the source configuration is not a tuner or recording, this method + * returns null. */ - public void setup() throws SourceException - { - setupProcessingChain(); - setupSource(); - } + @XmlTransient + public TunerChannel getTunerChannel() + { + if( mTunerChannel == null ) + { + if( mSourceConfiguration.getSourceType() == SourceType.TUNER ) + { + SourceConfigTuner config = (SourceConfigTuner)mSourceConfiguration; + + mTunerChannel = new TunerChannel( Type.LOCKED, config.getFrequency(), + mDecodeConfiguration.getDecoderType().getChannelBandwidth() ); + } + else if( mSourceConfiguration.getSourceType() == SourceType.RECORDING ) + { + SourceConfigRecording config = + (SourceConfigRecording)mSourceConfiguration; + + mTunerChannel = new TunerChannel( Type.LOCKED, config.getFrequency(), + mDecodeConfiguration.getDecoderType().getChannelBandwidth() ); + } + } + + return mTunerChannel; + } /** - * Setup recording options. Adds RecorderManager as a audio packet listener - * to receive and record decoded audio. - */ - private void setupRecording() - { - List recorders = mRecordConfiguration.getRecorders(); - - if( !recorders.isEmpty() ) - { - if( recorders.contains( RecorderType.AUDIO ) ) - { - mProcessingChain.addAudioPacketListener( - mResourceManager.getRecorderManager() ); - } - - /* Add baseband recorder */ - if( ( recorders.contains( RecorderType.BASEBAND ) && - mChannelType == ChannelType.STANDARD ) ) - { - mProcessingChain.addModule( RecorderManager.getBasebandRecorder( - mResourceManager.getThreadPoolManager(), getChannelName() ) ); - } - - /* Add traffic channel baseband recorder */ - if( recorders.contains( RecorderType.TRAFFIC_BASEBAND ) && - mChannelType == ChannelType.TRAFFIC ) - { - mProcessingChain.addModule( RecorderManager.getBasebandRecorder( - mResourceManager.getThreadPoolManager(), getChannelName() ) ); - } - } - } - - private String getChannelName() - { - StringBuilder sb = new StringBuilder(); - sb.append( mSystem ); - sb.append( "_" ); - sb.append( mSite ); - sb.append( "_" ); - sb.append( mName ); - - return sb.toString(); - } - - private void setupLogging() - { - if( mProcessingChain != null ) - { - String channelName = getChannelName(); - - List loggers = mResourceManager.getEventLogManager() - .getLoggers( mEventLogConfiguration, channelName ); - - if( !loggers.isEmpty() ) - { - mProcessingChain.addModules( loggers ); - } - } - } - - private void setupProcessingChain() - { - if( mProcessingChain == null ) - { - mProcessingChain = new ProcessingChain(); - - /* Get the optional alias list for the decode modules to use */ - AliasList aliasList = mResourceManager.getPlaylistManager() - .getPlayist().getAliasDirectory().getAliasList( mAliasListName ); - - /* Add the channel state as a module */ - mProcessingChain.addModule( mChannelState ); - - /* Processing Modules */ - List modules = DecoderFactory.getModules( mChannelType, - mResourceManager, mDecodeConfiguration, mRecordConfiguration, - mAuxDecodeConfiguration, aliasList, mSystem, - mSite, mName ); - - mProcessingChain.addModules( modules ); - - /* Get message filters for the set of processing modules */ - FilterSet messageFilter = DecoderFactory.getMessageFilters( modules ); - - /* Setup the message activity model and add message listeners */ - mMessageActivityModel = new MessageActivityModel( messageFilter ); - mProcessingChain.addMessageListener( mMessageActivityModel ); - - /* Add audio manager as listener for audio packets */ - mProcessingChain.addAudioPacketListener( - mResourceManager.getAudioManager() ); - - /* Create the call event model to receive call events */ - mCallEventModel = new CallEventModel(); - mProcessingChain.addCallEventListener( mCallEventModel ); - - setupLogging(); - - setupRecording(); - - /* Inject channel metadata that will be inserted into audio packets - * for the recorder manager and streaming */ - mProcessingChain.broadcast( - new Metadata( MetadataType.SYSTEM, mSystem ) ); - mProcessingChain.broadcast( - new Metadata( MetadataType.SITE_ID, mSite ) ); - mProcessingChain.broadcast( - new Metadata( MetadataType.CHANNEL_NAME, mName ) ); - } - } - - /** - * Attempts to obtain a source and apply it to the processing chain. - * - * @throws SourceException - if the processing chain is not setup or if - * there is an error produced while obtaining the source - */ - private void setupSource() throws SourceException - { - if( mProcessingChain != null ) - { - Source source = mResourceManager.getSourceManager() - .getSource( getSourceConfiguration(), getDecodeConfiguration() - .getDecoderType().getChannelBandwidth() ); - - if( source != null ) - { - mProcessingChain.setSource( source ); - } - else - { - throw new SourceException( "Couldn't obtain tuner channel source" ); - } - } - else - { - throw new SourceException( "Cannot obtain source for a null " - + "processing chain - setup the processing chain first" ); - } - } - - /** - * Stops the channel processing chain - */ - private void stop() - { - if( !mEnabled && mProcessingChain != null ) - { - fireChannelEvent( Event.CHANNEL_PROCESSING_STOPPED ); - - mProcessingChain.stop(); - - if( mChannelType == ChannelType.STANDARD ) - { - mProcessingChain.dispose(); - mProcessingChain = null; - } - - mSelected = false; - } - } - - /** - * Indicates if any part of this channel is contained within the - * minimum and maximum frequency values. + * Convenience method to indicate if any part of this channel is contained + * within the minimum and maximum frequency values. */ public boolean isWithin( long minimum, long maximum ) { diff --git a/src/controller/Editor.java b/src/controller/channel/ChannelConfigurationEditor.java similarity index 58% rename from src/controller/Editor.java rename to src/controller/channel/ChannelConfigurationEditor.java index 56411ce1..7b3e1427 100644 --- a/src/controller/Editor.java +++ b/src/controller/channel/ChannelConfigurationEditor.java @@ -1,6 +1,7 @@ /******************************************************************************* + * SDR Trunk - * Copyright (C) 2014 Dennis Sheirer + * Copyright (C) 2014-2016 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 @@ -15,37 +16,29 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see ******************************************************************************/ -package controller; +package controller.channel; import javax.swing.JPanel; -import net.miginfocom.swing.MigLayout; -import controller.channel.ChannelValidationException; - -public abstract class Editor extends JPanel +public abstract class ChannelConfigurationEditor extends JPanel { private static final long serialVersionUID = 1L; - public Editor() - { - setLayout( new MigLayout() ); - } + /** + * Sets or resets the configuration editor components + */ + public abstract void setConfiguration( Channel channel ); + /** + * Saves the contents of the editor components to the configuration + */ public abstract void save(); - public abstract void reset(); - /** - * Override this method to allow the editor to inspect the argument for - * valid configuration + * Validates the contents of the editor components prior to saving the + * content to the configuration. * - * @param editor - any editor - * - * @throws ChannelValidationException if the configuration is not compatible - * with this editor's configuration. Supplies a validation text value for - * display to the user + * @throws ConfigurationValidationException if the content is invalid */ - public void validate( Editor editor ) throws ChannelValidationException - { - } + public abstract void validateConfiguration() throws ConfigurationValidationException; } diff --git a/src/controller/channel/ChannelEditor.java b/src/controller/channel/ChannelEditor.java index c9935088..a76902d7 100644 --- a/src/controller/channel/ChannelEditor.java +++ b/src/controller/channel/ChannelEditor.java @@ -19,21 +19,17 @@ package controller.channel; import java.awt.Color; -import java.awt.ComponentOrientation; +import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.util.Collections; -import java.util.List; -import javax.swing.DefaultComboBoxModel; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JOptionPane; +import javax.swing.JPanel; import javax.swing.JTextField; -import javax.swing.tree.DefaultTreeModel; -import javax.swing.tree.TreePath; import module.decode.AuxDecodeComponentEditor; import module.decode.DecodeComponentEditor; @@ -46,20 +42,21 @@ import org.slf4j.LoggerFactory; import playlist.PlaylistManager; import record.RecordComponentEditor; import source.SourceComponentEditor; +import source.SourceManager; import alias.AliasList; import com.jidesoft.swing.JideTabbedPane; -import controller.Editor; +import controller.channel.ChannelEvent.Event; -public class ChannelEditor extends Editor implements ActionListener +public class ChannelEditor extends JPanel + implements ActionListener, ChannelEventListener { + private static final long serialVersionUID = 1L; + private final static Logger mLog = LoggerFactory.getLogger( ChannelEditor.class ); - private static final long serialVersionUID = 1L; - private DefaultTreeModel mTreeModel; - private ChannelNode mChannelNode; - + private ChannelConfigurationEditor mNameConfigurationEditor; private DecodeComponentEditor mDecodeEditor; private AuxDecodeComponentEditor mAuxDecodeEditor; private EventLogComponentEditor mEventLogEditor; @@ -70,18 +67,33 @@ public class ChannelEditor extends Editor implements ActionListener private JCheckBox mChannelEnabled = new JCheckBox(); private JComboBox mComboAliasLists; + private Channel mChannel; + private ChannelModel mChannelModel; private PlaylistManager mPlaylistManager; + private SourceManager mSourceManager; - public ChannelEditor( ChannelNode channel, PlaylistManager playlistManager ) + public ChannelEditor( ChannelModel channelModel, + PlaylistManager playlistManager, + SourceManager sourceManager ) { super(); - mChannelNode = channel; - + mChannelModel = channelModel; mPlaylistManager = playlistManager; + mSourceManager = sourceManager; + + mNameConfigurationEditor = new NameConfigurationEditor( + mChannelModel, mPlaylistManager ); initGUI(); } + + public void setChannel( Channel channel ) + { + mNameConfigurationEditor.setConfiguration( channel ); + + mChannel = channel; + } private void initGUI() { @@ -89,65 +101,29 @@ public class ChannelEditor extends Editor implements ActionListener add( new JLabel( "Channel Configuration" ), "span, align center" ); - add( new JLabel( "Enabled:" ) ); + add( new JLabel( "Enabled:" ), "wrap" ); - mChannelEnabled.setSelected( - mChannelNode.getChannel().getEnabled() ); - mChannelEnabled.setComponentOrientation( ComponentOrientation.RIGHT_TO_LEFT ); - add( mChannelEnabled ); - - add( new JLabel( "Name:" ) ); - - mChannelName = new JTextField( mChannelNode.getChannel().getName() ); - add( mChannelName, "growx,push" ); - - /** - * ComboBox: Alias Lists - */ - add( new JLabel( "Alias List:" ) ); - - mComboAliasLists = new JComboBox(); - - List lists = mChannelNode.getModel().getResourceManager() - .getPlaylistManager().getPlayist().getAliasDirectory().getAliasList(); - - Collections.sort( lists ); - - mComboAliasLists.setModel( new DefaultComboBoxModel( - lists.toArray( new AliasList[ lists.size() ] ) ) ); - - String aliasListName = - mChannelNode.getChannel().getAliasListName(); - - if( aliasListName != null ) - { - AliasList selected = mChannelNode.getModel().getResourceManager() - .getPlaylistManager().getPlayist().getAliasDirectory() - .getAliasList( aliasListName ); - - mComboAliasLists.setSelectedItem( selected ); - } - - add( mComboAliasLists, "growx,push" ); + add( mNameConfigurationEditor ); JideTabbedPane tabs = new JideTabbedPane(); tabs.setFont( this.getFont() ); tabs.setForeground( Color.BLACK ); - mSourceEditor = new SourceComponentEditor( mChannelNode ); - tabs.addTab( "Source", mSourceEditor ); - - mDecodeEditor = new DecodeComponentEditor( mChannelNode, mPlaylistManager ); - tabs.addTab( "Decoder", mDecodeEditor ); - - mAuxDecodeEditor = new AuxDecodeComponentEditor( mChannelNode ); - tabs.addTab( "Aux", mAuxDecodeEditor ); - - mEventLogEditor = new EventLogComponentEditor( mChannelNode ); - tabs.addTab( "Event Log", mEventLogEditor ); - - mRecordEditor = new RecordComponentEditor( mChannelNode ); - tabs.addTab( "Record", mRecordEditor ); + tabs.addTab( "Name/Alias", mNameConfigurationEditor ); +// mSourceEditor = new SourceComponentEditor( mSourceManager, mChannel ); +// tabs.addTab( "Source", mSourceEditor ); +// +// mDecodeEditor = new DecodeComponentEditor( mPlaylistManager, mChannel ); +// tabs.addTab( "Decoder", mDecodeEditor ); +// +// mAuxDecodeEditor = new AuxDecodeComponentEditor( mChannel ); +// tabs.addTab( "Aux", mAuxDecodeEditor ); +// +// mEventLogEditor = new EventLogComponentEditor( mChannel ); +// tabs.addTab( "Event Log", mEventLogEditor ); +// +// mRecordEditor = new RecordComponentEditor( mChannel ); +// tabs.addTab( "Record", mRecordEditor ); add( tabs, "span,grow,push" ); @@ -159,6 +135,12 @@ public class ChannelEditor extends Editor implements ActionListener btnReset.addActionListener( ChannelEditor.this ); add( btnReset, "growx,push" ); } + + @Override + public void channelChanged( ChannelEvent event ) + { + + } @Override public void actionPerformed( ActionEvent e ) @@ -171,109 +153,105 @@ public class ChannelEditor extends Editor implements ActionListener } else if( command.contentEquals( "Reset" ) ) { - reset(); - } - - if( mTreeModel != null ) - { - mTreeModel.nodeChanged( mChannelNode ); + setChannel( mChannel ); } } - @Override public void save() { try { - /** - * Validate the source configuration against the other component - * configuration editors - */ - validate( mSourceEditor.getSourceEditor() ); - - boolean expanded = mChannelNode.getModel().getTree() - .isExpanded( new TreePath( mChannelNode ) ); - - mSourceEditor.save(); - mDecodeEditor.save(); - mAuxDecodeEditor.save(); - mEventLogEditor.save(); - mRecordEditor.save(); - - mChannelNode.getChannel().setName( mChannelName.getText() ); - mChannelNode.getChannel().setEnabled( mChannelEnabled.isSelected() ); - - AliasList selected = mComboAliasLists.getItemAt( - mComboAliasLists.getSelectedIndex() ); - if( selected != null ) - { - mChannelNode.getChannel().setAliasListName( selected.getName() ); - } - - - mChannelNode.save(); - mChannelNode.show(); - - if( expanded ) - { - mChannelNode.getModel().getTree().expandPath( new TreePath( mChannelNode ) ); - } + //Validate each of the configuration editors to check for errors + mNameConfigurationEditor.validateConfiguration(); +// /** +// * Validate the source configuration against the other component +// * configuration editors +// */ +// validate( mSourceEditor.getSourceEditor() ); +// +// mSourceEditor.save(); +// mDecodeEditor.save(); +// mAuxDecodeEditor.save(); +// mEventLogEditor.save(); +// mRecordEditor.save(); +// +// mChannel.setName( mChannelName.getText() ); +// mChannel.setEnabled( mChannelEnabled.isSelected() ); +// +// AliasList selected = mComboAliasLists.getItemAt( +// mComboAliasLists.getSelectedIndex() ); +// if( selected != null ) +// { +// mChannel.setAliasListName( selected.getName() ); +// } } - catch ( ChannelValidationException validationException ) + catch ( ConfigurationValidationException validationException ) { /* ChannelValidationException can be thrown by any of the component * editors. Show the validation error text in a popup menu to the - * user */ + * user and set the focus on the error component */ JOptionPane.showMessageDialog( ChannelEditor.this, validationException.getMessage(), "Channel Configuration Error", JOptionPane.ERROR_MESSAGE ); + + Component component = validationException.getComponent(); + + if( component != null ) + { + component.requestFocus(); + } + + return; } - } - @Override - public void reset() - { - mChannelName.setText( - mChannelNode.getChannel().getName() ); - mChannelName.requestFocus(); - mChannelName.requestFocusInWindow(); + //Save the contents of each editor to the channel configuration + mNameConfigurationEditor.save(); - mChannelEnabled.setSelected( - mChannelNode.getChannel().getEnabled() ); - mChannelEnabled.requestFocus(); - mChannelEnabled.requestFocusInWindow(); - - String aliasListName = - mChannelNode.getChannel().getAliasListName(); - - if( aliasListName != null ) - { - AliasList selected = mChannelNode.getModel().getResourceManager() - .getPlaylistManager().getPlayist().getAliasDirectory() - .getAliasList( aliasListName ); - - mComboAliasLists.setSelectedItem( selected ); - } - - - mSourceEditor.reset(); - mDecodeEditor.reset(); - mAuxDecodeEditor.reset(); - mEventLogEditor.reset(); - mRecordEditor.reset(); + //Broadcast a channel configuration change event + mChannelModel.broadcast( new ChannelEvent( mChannel, + Event.NOTIFICATION_CONFIGURATION_CHANGE ) ); } - /** - * Validate the specified editor against each of the component editors - */ - @Override - public void validate( Editor editor ) throws ChannelValidationException - { - mSourceEditor.validate( editor ); - mDecodeEditor.validate( editor ); - mAuxDecodeEditor.validate( editor ); - mEventLogEditor.validate( editor ); - mRecordEditor.validate( editor ); - } +// @Override +// public void reset() +// { +// mChannelName.setText( mChannel.getName() ); +// mChannelName.requestFocus(); +// mChannelName.requestFocusInWindow(); +// +// mChannelEnabled.setSelected( mChannel.getEnabled() ); +// mChannelEnabled.requestFocus(); +// mChannelEnabled.requestFocusInWindow(); +// +// String aliasListName = mChannel.getAliasListName(); +// +// if( aliasListName != null ) +// { +// AliasList selected = mPlaylistManager.getPlayist().getAliasDirectory() +// .getAliasList( aliasListName ); +// +// mComboAliasLists.setSelectedItem( selected ); +// } +// +// +// mSourceEditor.reset(); +// mDecodeEditor.reset(); +// mAuxDecodeEditor.reset(); +// mEventLogEditor.reset(); +// mRecordEditor.reset(); +// } + +// /** +// * Validate the specified editor against each of the component editors +// */ +// @Override +// public void validate( ChannelConfigurationEditor editor ) throws ConfigurationValidationException +// { +// mSourceEditor.validate( editor ); +// mDecodeEditor.validate( editor ); +// mAuxDecodeEditor.validate( editor ); +// mEventLogEditor.validate( editor ); +// mRecordEditor.validate( editor ); +// } } diff --git a/src/controller/channel/ChannelEvent.java b/src/controller/channel/ChannelEvent.java index 93bb94fc..a4166a2d 100644 --- a/src/controller/channel/ChannelEvent.java +++ b/src/controller/channel/ChannelEvent.java @@ -64,6 +64,8 @@ public class ChannelEvent NOTIFICATION_SELECTION_CHANGE, //Channel's channel-state has been reset NOTIFICATION_STATE_RESET, + //Request to delete the channel + REQUEST_DELETE, //Request to deselect the channel REQUEST_DESELECT, //Request to disable a channel - response will be a PROCESSING_STOP_NOTIFICATION diff --git a/src/controller/channel/ChannelModel.java b/src/controller/channel/ChannelModel.java new file mode 100644 index 00000000..1f0d6821 --- /dev/null +++ b/src/controller/channel/ChannelModel.java @@ -0,0 +1,346 @@ +/******************************************************************************* + * SDR Trunk + * Copyright (C) 2015 Dennis Sheirer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + ******************************************************************************/ +package controller.channel; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +import javax.swing.event.TableModelEvent; +import javax.swing.event.TableModelListener; +import javax.swing.table.TableModel; + +import module.decode.DecoderType; +import controller.channel.Channel.ChannelType; +import controller.channel.ChannelEvent.Event; + +/** + * Channel Model + */ +public class ChannelModel implements IChannelEventBroadcaster, TableModel +{ + private ChannelSelectionManager mChannelSelectionManager; + private List mChannels = new ArrayList<>(); + private List mTrafficChannels = new ArrayList<>(); + private List mListeners = new CopyOnWriteArrayList<>(); + private List mTableModelListeners = new CopyOnWriteArrayList<>(); + + public ChannelModel() + { + mChannelSelectionManager = new ChannelSelectionManager( this ); + addListener( mChannelSelectionManager ); + } + + /** + * Unmodifiable list of non-traffic channels currently in the model + */ + public List getChannels() + { + return Collections.unmodifiableList( mChannels ); + } + + /** + * Returns a list of unique system values from across the channel set + */ + public List getSystems() + { + List systems = new ArrayList<>(); + + for( Channel channel: mChannels ) + { + if( channel.hasSystem() && !systems.contains( channel.getSystem() ) ) + { + systems.add( channel.getSystem() ); + } + } + + Collections.sort( systems ); + + return systems; + } + + /** + * Returns a list of unique site values for all channels that have a matching + * system value + */ + public List getSites( String system ) + { + List sites = new ArrayList<>(); + + if( system != null ) + { + for( Channel channel: mChannels ) + { + if( channel.hasSystem() && + system.equals( channel.getSystem() ) && + channel.hasSite() && + !sites.contains( channel.getSite() ) ) + { + sites.add( channel.getSite() ); + } + } + } + + Collections.sort( sites ); + + return sites; + } + + /** + * Broadcasts the channel event to all registered listeners + */ + @Override + public void broadcast( ChannelEvent event ) + { + for( ChannelEventListener listener: mListeners ) + { + listener.channelChanged( event ); + } + + if( event.getChannel().getChannelType() == ChannelType.STANDARD ) + { + switch( event.getEvent() ) + { + case NOTIFICATION_CONFIGURATION_CHANGE: + case NOTIFICATION_PROCESSING_START: + case NOTIFICATION_PROCESSING_STOP: + case NOTIFICATION_SELECTION_CHANGE: + int index = mChannels.indexOf( event.getChannel() ); + broadcast( new TableModelEvent( this, index ) ); + break; + default: + break; + } + } + + if( event.getEvent() == Event.REQUEST_DELETE ) + { + removeChannel( event.getChannel() ); + } + } + + /** + * Bulk loading of channel list. Each channel is added and a channel add + * event is broadcast. + */ + public void addChannels( List channels ) + { + for( Channel channel: channels ) + { + addChannel( channel ); + } + } + + /** + * Adds the channel to the model and broadcasts a channel add event + */ + public void addChannel( Channel channel ) + { + switch( channel.getChannelType() ) + { + case STANDARD: + mChannels.add( channel ); + + int index = mChannels.size() - 1; + + broadcast( new TableModelEvent( this, index, index, + TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT ) ); + break; + case TRAFFIC: + mTrafficChannels.add( channel ); + break; + default: + break; + } + + broadcast( new ChannelEvent( channel, Event.NOTIFICATION_ADD ) ); + } + + /** + * Removes the channel from the model and broadcasts a channel remove event + */ + public void removeChannel( Channel channel ) + { + switch( channel.getChannelType() ) + { + case STANDARD: + int index = mChannels.indexOf( channel ); + + mChannels.remove( channel ); + + if( index >= 0 ) + { + broadcast( new TableModelEvent( this, index, index, + TableModelEvent.ALL_COLUMNS, TableModelEvent.DELETE ) ); + } + break; + case TRAFFIC: + mTrafficChannels.remove( channel ); + break; + default: + break; + } + + broadcast( new ChannelEvent( channel, Event.NOTIFICATION_DELETE ) ); + } + + /** + * Returns a list of channels that fall within the frequency range + * + * @param start frequency of the range + * @param stop frequency of the range + * + * @return list of channels or an empty list if none fall within the range + */ + public List getChannelsInFrequencyRange( long start, long stop ) + { + List channels = new ArrayList<>(); + + for( Channel channel: mChannels ) + { + if( channel.isWithin( start, stop ) ) + { + channels.add( channel ); + } + } + + for( Channel channel: mTrafficChannels ) + { + if( channel.isWithin( start, stop ) ) + { + channels.add( channel ); + } + } + + return channels; + } + + public void addListener( ChannelEventListener listener ) + { + mListeners.add( listener ); + } + + public void removeListener( ChannelEventListener listener ) + { + mListeners.remove( listener ); + } + + //Table Model Interface Methods - standard channels only + @Override + public int getRowCount() + { + return mChannels.size(); + } + + @Override + public int getColumnCount() + { + return 6; + } + + @Override + public String getColumnName( int columnIndex ) + { + switch( columnIndex ) + { + case 0: + return "System"; + case 1: + return "Site"; + case 2: + return "Name"; + case 3: + return "Alias List"; + case 4: + return "Source"; + case 5: + return "Decoder"; + } + + return null; + } + + @Override + public Class getColumnClass( int columnIndex ) + { + return String.class; + } + + @Override + public boolean isCellEditable( int rowIndex, int columnIndex ) + { + return false; + } + + @Override + public Object getValueAt( int rowIndex, int columnIndex ) + { + Channel channel = mChannels.get( rowIndex ); + + switch( columnIndex ) + { + case 0: + return channel.getSystem(); + case 1: + return channel.getSite(); + case 2: + return channel.getName(); + case 3: + return channel.getAliasListName(); + case 4: + return channel.getSourceConfiguration().getDescription(); + case 5: + return channel.getDecodeConfiguration() + .getDecoderType().getShortDisplayString(); + } + + return null; + } + + @Override + public void setValueAt( Object aValue, int rowIndex, int columnIndex ) + { + throw new IllegalArgumentException( "Not yet implemented" ); + } + + private void broadcast( TableModelEvent event ) + { + for( TableModelListener listener: mTableModelListeners ) + { + listener.tableChanged( event ); + } + } + + @Override + public void addTableModelListener( TableModelListener listener ) + { + mTableModelListeners.add( listener ); + } + + @Override + public void removeTableModelListener( TableModelListener listener ) + { + mTableModelListeners.remove( listener ); + } + + public void createChannel( DecoderType decoderType, long frequency ) + { + throw new UnsupportedOperationException( "Not yet implemented" ); + } +} diff --git a/src/controller/channel/ChannelNode.java b/src/controller/channel/ChannelNode.java index acaa0222..ca8e5b37 100644 --- a/src/controller/channel/ChannelNode.java +++ b/src/controller/channel/ChannelNode.java @@ -27,6 +27,8 @@ import javax.swing.JPopupMenu; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import playlist.PlaylistManager; +import source.SourceManager; import source.tuner.TunerChannel; import controller.ConfigurableNode; import controller.site.SiteNode; @@ -43,10 +45,22 @@ public class ChannelNode extends ConfigurableNode implements ChannelEventListene private final static Logger mLog = LoggerFactory.getLogger( ChannelNode.class ); private static DecimalFormat sFORMAT = new DecimalFormat( "0.0000" ); + + private ChannelModel mChannelModel; + private ChannelProcessingManager mChannelProcessingManager; + private SourceManager mSourceManager; - public ChannelNode( Channel channel ) + public ChannelNode( Channel channel, + ChannelModel channelModel, + ChannelProcessingManager channelProcessingManager, + PlaylistManager playlistManager, + SourceManager sourceManager ) { - super( channel ); + super( playlistManager, channel ); + + mChannelModel = channelModel; + mChannelProcessingManager = channelProcessingManager; + mSourceManager = sourceManager; } public void init() @@ -69,9 +83,6 @@ public class ChannelNode extends ConfigurableNode implements ChannelEventListene /* Add this node as listener to receive changes from underlying channel */ // getChannel().addListener( this ); - /* Add the resource manager to the channel so that the channel - * can provide channel change events to all system resources */ - getChannel().setResourceManager( getModel().getResourceManager() ); } /** @@ -109,7 +120,7 @@ public class ChannelNode extends ConfigurableNode implements ChannelEventListene { if( getChannel().getEnabled() ) { - if( getChannel().isProcessing() ) + if( getChannel().getEnabled() ) { return Color.GREEN; } @@ -125,9 +136,7 @@ public class ChannelNode extends ConfigurableNode implements ChannelEventListene @Override public JPanel getEditor() { - return new ChannelEditor( this, - getChannel().getResourceManager() == null ? null : - getChannel().getResourceManager().getPlaylistManager() ); + return new OldChannelEditor( getChannel(), mChannelModel, getPlaylistManager(), mSourceManager ); } public Channel getChannel() @@ -158,9 +167,9 @@ public class ChannelNode extends ConfigurableNode implements ChannelEventListene { JPopupMenu popupMenu = new JPopupMenu(); - JMenu channelMenu = ChannelUtils.getContextMenu( - getModel().getResourceManager().getPlaylistManager(), - getChannel(), getModel().getTree() ); + JMenu channelMenu = ChannelUtils.getContextMenu( mChannelModel, + mChannelProcessingManager, getPlaylistManager(), getChannel(), + getModel().getTree() ); if( channelMenu != null ) { diff --git a/src/controller/channel/ChannelProcessingManager.java b/src/controller/channel/ChannelProcessingManager.java new file mode 100644 index 00000000..9bdb727e --- /dev/null +++ b/src/controller/channel/ChannelProcessingManager.java @@ -0,0 +1,301 @@ +/******************************************************************************* + * SDR Trunk + * Copyright (C) 2014-2016 Dennis Sheirer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + ******************************************************************************/ + +package controller.channel; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; + +import message.Message; +import module.Module; +import module.ProcessingChain; +import module.decode.DecoderFactory; +import module.decode.event.MessageActivityModel; +import module.log.EventLogManager; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import playlist.PlaylistManager; +import record.RecorderManager; +import record.RecorderType; +import sample.Listener; +import source.Source; +import source.SourceException; +import source.SourceManager; +import audio.AudioPacket; +import audio.metadata.Metadata; +import audio.metadata.MetadataType; +import controller.ThreadPoolManager; +import controller.channel.Channel.ChannelType; +import controller.channel.ChannelEvent.Event; +import filter.FilterSet; + +public class ChannelProcessingManager implements ChannelEventListener +{ + private final static Logger mLog = LoggerFactory.getLogger( ChannelProcessingManager.class ); + + private Map mProcessingChains = new HashMap<>(); + + private List> mAudioPacketListeners = new CopyOnWriteArrayList<>(); + private List> mMessageListeners = new CopyOnWriteArrayList<>(); + + private ChannelModel mChannelModel; + private EventLogManager mEventLogManager; + private PlaylistManager mPlaylistManager; + private RecorderManager mRecorderManager; + private SourceManager mSourceManager; + private ThreadPoolManager mThreadPoolManager; + + public ChannelProcessingManager( ChannelModel channelModel, + EventLogManager eventLogManager, + PlaylistManager playlistManager, + RecorderManager recorderManager, + SourceManager sourceManager, + ThreadPoolManager threadPoolManager ) + { + mChannelModel = channelModel; + mEventLogManager = eventLogManager; + mPlaylistManager = playlistManager; + mRecorderManager = recorderManager; + mSourceManager = sourceManager; + mThreadPoolManager = threadPoolManager; + + mChannelModel.addListener( this ); + } + + /** + * Indicates if a processing chain is constructed for the channel and that + * the processing chain is currently processing. + */ + public boolean isProcessing( Channel channel ) + { + if( mProcessingChains.containsKey( channel.getChannelID() ) ) + { + return mProcessingChains.get( channel.getChannelID() ).isProcessing(); + } + + return false; + } + + /** + * Returns the current processing chain associated with the channel, or + * null if a processing chain is not currently setup for the channel + */ + public ProcessingChain getProcessingChain( Channel channel ) + { + return mProcessingChains.get( channel.getChannelID() ); + } + + @Override + public void channelChanged( ChannelEvent event ) + { + Channel channel = event.getChannel(); + + switch( event.getEvent() ) + { + case REQUEST_ENABLE: + if( !mProcessingChains.containsKey( channel.getChannelID() ) || + !mProcessingChains.get( channel.getChannelID() ).isProcessing() ) + { + startProcessing( channel ); + } + break; + case REQUEST_DISABLE: + if( channel.getEnabled() ) + { + switch( channel.getChannelType() ) + { + case STANDARD: + stopProcessing( channel, true ); + break; + case TRAFFIC: + //Don't remove traffic channel processing chains + //until explicitly deleted, so that we can reuse them + stopProcessing( channel, false ); + default: + break; + } + } + case NOTIFICATION_DELETE: + if( channel.getEnabled() ) + { + stopProcessing( channel, true ); + } + break; + default: + break; + } + } + + private void startProcessing( Channel channel ) + { + ProcessingChain processingChain = mProcessingChains.get( channel.getChannelID() ); + + //If we're already processing, ignore the request + if( processingChain != null && processingChain.isProcessing() ) + { + return; + } + + //Ensure that we can get a source before we construct a new processing chain + Source source = null; + + try + { + source = mSourceManager.getSource( channel.getSourceConfiguration(), + channel.getDecodeConfiguration().getDecoderType().getChannelBandwidth() ); + } + catch( SourceException se ) + { + mLog.debug( "Error obtaining source for channel [" + channel.getName() + "]", se ); + } + + if( source == null ) + { + channel.setEnabled( false ); + + mChannelModel.broadcast( + new ChannelEvent( channel, Event.NOTIFICATION_ENABLE_REJECTED ) ); + + return; + } + + if( processingChain == null ) + { + processingChain = new ProcessingChain( mThreadPoolManager, + channel.getChannelType() ); + + /* Register global listeners */ + for( Listener listener: mAudioPacketListeners ) + { + processingChain.addAudioPacketListener( listener ); + } + + for( Listener listener: mMessageListeners ) + { + processingChain.addMessageListener( listener ); + } + + /* Processing Modules */ + List modules = DecoderFactory.getModules( mChannelModel, + this, mPlaylistManager, channel ); + processingChain.addModules( modules ); + + /* Setup message activity model with filtering */ + FilterSet messageFilter = DecoderFactory.getMessageFilters( modules ); + MessageActivityModel messageModel = new MessageActivityModel( messageFilter ); + processingChain.setMessageActivityModel( messageModel ); + + /* Setup event logging */ + List loggers = mEventLogManager.getLoggers( + channel.getEventLogConfiguration(), channel.getName() ); + + if( !loggers.isEmpty() ) + { + processingChain.addModules( loggers ); + } + + /* Setup recorders */ + List recorders = channel.getRecordConfiguration().getRecorders(); + + if( !recorders.isEmpty() ) + { + if( recorders.contains( RecorderType.AUDIO ) ) + { + processingChain.addAudioPacketListener( mRecorderManager ); + } + + /* Add baseband recorder */ + if( ( recorders.contains( RecorderType.BASEBAND ) && + channel.getChannelType() == ChannelType.STANDARD ) ) + { + processingChain.addModule( mRecorderManager.getBasebandRecorder( + channel.toString() ) ); + } + + /* Add traffic channel baseband recorder */ + if( recorders.contains( RecorderType.TRAFFIC_BASEBAND ) && + channel.getChannelType() == ChannelType.TRAFFIC ) + { + processingChain.addModule( mRecorderManager + .getBasebandRecorder( channel.toString() ) ); + } + } + + /* Inject channel metadata that will be inserted into audio packets + * for the recorder manager and streaming */ + processingChain.broadcast( + new Metadata( MetadataType.SYSTEM, channel.getSystem() ) ); + processingChain.broadcast( + new Metadata( MetadataType.SITE_ID, channel.getSite() ) ); + processingChain.broadcast( + new Metadata( MetadataType.CHANNEL_NAME, channel.getName() ) ); + } + + processingChain.setSource( source ); + processingChain.start(); + + channel.setEnabled( true ); + + mChannelModel.broadcast( + new ChannelEvent( channel, Event.NOTIFICATION_PROCESSING_START ) ); + } + + private void stopProcessing( Channel channel, boolean remove ) + { + mChannelModel.broadcast( + new ChannelEvent( channel, Event.NOTIFICATION_PROCESSING_STOP ) ); + } + + /** + * Adds a message listener that will be added to all channels to receive + * any messages. + */ + public void addAudioPacketListener( Listener listener ) + { + mAudioPacketListeners.add( listener ); + } + + /** + * Removes a message listener. + */ + public void removeAudioPacketListener( Listener listener ) + { + mAudioPacketListeners.remove( listener ); + } + + /** + * Adds a message listener that will be added to all channels to receive + * any messages. + */ + public void addMessageListener( Listener listener ) + { + mMessageListeners.add( listener ); + } + + /** + * Removes a message listener. + */ + public void removeMessageListener( Listener listener ) + { + mMessageListeners.remove( listener ); + } +} diff --git a/src/controller/channel/ChannelSelectionManager.java b/src/controller/channel/ChannelSelectionManager.java new file mode 100644 index 00000000..65ac9b91 --- /dev/null +++ b/src/controller/channel/ChannelSelectionManager.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * SDR Trunk + * Copyright (C) 2015 Dennis Sheirer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + ******************************************************************************/ +package controller.channel; + +import controller.channel.ChannelEvent.Event; + +public class ChannelSelectionManager implements ChannelEventListener +{ + private IChannelEventBroadcaster mChannelEventBroadcaster; + private Channel mSelectedChannel = null; + + /** + * Manages channel selection state to ensure that only one channel is ever + * in a selected state. + */ + public ChannelSelectionManager( IChannelEventBroadcaster broadcaster ) + { + mChannelEventBroadcaster = broadcaster; + } + + @Override + public void channelChanged( ChannelEvent event ) + { + switch( event.getEvent() ) + { + case REQUEST_SELECT: + if( mSelectedChannel != null ) + { + mSelectedChannel.setSelected( false ); + mChannelEventBroadcaster.broadcast( new ChannelEvent( mSelectedChannel, + Event.NOTIFICATION_SELECTION_CHANGE ) ); + mSelectedChannel = null; + } + + mSelectedChannel = event.getChannel(); + mSelectedChannel.setSelected( true ); + mChannelEventBroadcaster.broadcast( new ChannelEvent( event.getChannel(), + Event.NOTIFICATION_SELECTION_CHANGE ) ); + break; + case NOTIFICATION_PROCESSING_STOP: + case REQUEST_DESELECT: + if( mSelectedChannel != null && + mSelectedChannel == event.getChannel() ) + { + mSelectedChannel.setSelected( false ); + mSelectedChannel = null; + mChannelEventBroadcaster.broadcast( new ChannelEvent( event.getChannel(), + Event.NOTIFICATION_SELECTION_CHANGE ) ); + } + break; + default: + break; + } + } + +} diff --git a/src/controller/channel/ChannelUtils.java b/src/controller/channel/ChannelUtils.java index f4fd2bf1..9a716ea3 100644 --- a/src/controller/channel/ChannelUtils.java +++ b/src/controller/channel/ChannelUtils.java @@ -9,10 +9,11 @@ import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JSeparator; +import controller.channel.ChannelEvent.Event; +import module.ProcessingChain; import module.decode.event.ActivitySummaryFrame; import module.decode.state.DecoderState; import playlist.PlaylistManager; -import controller.channel.ChannelEvent.Event; public class ChannelUtils { @@ -23,7 +24,9 @@ public class ChannelUtils /** * Creates a context menu for the channel argument */ - public static JMenu getContextMenu( final PlaylistManager playlistManager, + public static JMenu getContextMenu( final ChannelModel channelModel, + final ChannelProcessingManager channelProcessingManager, + final PlaylistManager playlistManager, final Channel channel, final Component anchor ) { @@ -39,12 +42,8 @@ public class ChannelUtils @Override public void actionPerformed( ActionEvent e ) { - channel.setEnabled( DISABLED ); - - if( playlistManager != null ) - { - playlistManager.save(); - } + channelModel.broadcast( + new ChannelEvent( channel, Event.REQUEST_DISABLE ) ); } } ); @@ -62,10 +61,14 @@ public class ChannelUtils { StringBuilder sb = new StringBuilder(); - for( DecoderState decoderState: channel - .getProcessingChain().getDecoderStates() ) + ProcessingChain chain = channelProcessingManager.getProcessingChain( channel ); + + if( chain != null ) { - sb.append( decoderState.getActivitySummary() ); + for( DecoderState decoderState: chain.getDecoderStates() ) + { + sb.append( decoderState.getActivitySummary() ); + } } new ActivitySummaryFrame( sb.toString(), anchor ); @@ -82,12 +85,8 @@ public class ChannelUtils @Override public void actionPerformed( ActionEvent e ) { - channel.setEnabled( ENABLED ); - - if( playlistManager != null ) - { - playlistManager.save(); - } + channelModel.broadcast( + new ChannelEvent( channel, Event.REQUEST_ENABLE ) ); } } ); @@ -108,16 +107,8 @@ public class ChannelUtils if( response == JOptionPane.YES_OPTION ) { - /* Disable the channel */ - channel.setEnabled( DISABLED ); - - /* Broadcast channel deleted event */ -// channel.fireChannelEvent( Event.NOTIFICATION_DELETE ); - - if( playlistManager != null ) - { - playlistManager.save(); - } + channelModel.broadcast( + new ChannelEvent( channel, Event.REQUEST_DELETE ) ); } } } ); diff --git a/src/controller/channel/ChannelValidationException.java b/src/controller/channel/ChannelValidationException.java deleted file mode 100644 index 53422a11..00000000 --- a/src/controller/channel/ChannelValidationException.java +++ /dev/null @@ -1,11 +0,0 @@ -package controller.channel; - -public class ChannelValidationException extends Exception -{ - private static final long serialVersionUID = 1L; - - public ChannelValidationException( String validationMessage ) - { - super( validationMessage ); - } -} diff --git a/src/controller/channel/ConfigurationValidationException.java b/src/controller/channel/ConfigurationValidationException.java new file mode 100644 index 00000000..a61862c5 --- /dev/null +++ b/src/controller/channel/ConfigurationValidationException.java @@ -0,0 +1,23 @@ +package controller.channel; + +import java.awt.Component; + +public class ConfigurationValidationException extends Exception +{ + private static final long serialVersionUID = 1L; + + private Component mComponent; + + public ConfigurationValidationException( Component component, + String validationMessage ) + { + super( validationMessage ); + + mComponent = component; + } + + public Component getComponent() + { + return mComponent; + } +} diff --git a/src/buffer/ComplexByteBufferListener.java b/src/controller/channel/IChannelEventBroadcaster.java similarity index 77% rename from src/buffer/ComplexByteBufferListener.java rename to src/controller/channel/IChannelEventBroadcaster.java index efdb3a1a..ef7c89fd 100644 --- a/src/buffer/ComplexByteBufferListener.java +++ b/src/controller/channel/IChannelEventBroadcaster.java @@ -1,6 +1,6 @@ /******************************************************************************* * SDR Trunk - * Copyright (C) 2014 Dennis Sheirer + * Copyright (C) 2016 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 @@ -15,9 +15,15 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see ******************************************************************************/ -package buffer; +package controller.channel; -public interface ComplexByteBufferListener +/** + * Provides channel event broadcasting capability. + */ +public interface IChannelEventBroadcaster { - public void receive( ComplexByteBuffer buffer ); + /** + * Broadcasts the channel event + */ + public void broadcast( ChannelEvent event ); } diff --git a/src/controller/channel/NameConfigurationEditor.java b/src/controller/channel/NameConfigurationEditor.java new file mode 100644 index 00000000..c7c171ec --- /dev/null +++ b/src/controller/channel/NameConfigurationEditor.java @@ -0,0 +1,221 @@ +package controller.channel; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Collections; +import java.util.List; + +import javax.swing.ComboBoxModel; +import javax.swing.DefaultComboBoxModel; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JTextField; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import net.miginfocom.swing.MigLayout; +import playlist.PlaylistManager; +import alias.AliasList; + +public class NameConfigurationEditor extends ChannelConfigurationEditor +{ + private static final long serialVersionUID = 1L; + + private final static Logger mLog = LoggerFactory.getLogger( NameConfigurationEditor.class ); + + private static ComboBoxModel EMPTY_MODEL = new DefaultComboBoxModel<>(); + + private ChannelModel mChannelModel; + private PlaylistManager mPlaylistManager; + + private JTextField mChannelName = new JTextField( "Please select a channel to edit" ); + private JComboBox mSystemNameCombo = new JComboBox<>( EMPTY_MODEL ); + private JComboBox mSiteNameCombo = new JComboBox<>( EMPTY_MODEL ); + private JComboBox mAliasListCombo; + + private Channel mChannel; + + public NameConfigurationEditor( ChannelModel model, + PlaylistManager playlistManager ) + { + mChannelModel = model; + mPlaylistManager = playlistManager; + + setLayout( new MigLayout( "fill,wrap 2", "[right][]", "[][][][grow]" ) ); + + add( new JLabel( "Name:" ) ); + add( mChannelName, "growx" ); + + mSystemNameCombo.setEditable( true ); + mSystemNameCombo.addActionListener( new ActionListener() + { + @Override + public void actionPerformed( ActionEvent e ) + { + Object selected = mSystemNameCombo.getSelectedItem(); + + if( selected != null ) + { + String system = (String)selected; + + List sites = mChannelModel.getSites( system ); + + if( !sites.contains( mChannel.getSite() ) ) + { + sites.add( mChannel.getSite() ); + } + + if( sites.isEmpty() ) + { + mSiteNameCombo.setModel( EMPTY_MODEL ); + } + else + { + mSiteNameCombo.setModel( new DefaultComboBoxModel( + sites.toArray( new String[ sites.size() ] ) ) );; + } + + mSiteNameCombo.setSelectedItem( mChannel.getSite() ); + } + } + } ); + + add( new JLabel( "System:" ) ); + add( mSystemNameCombo, "growx" ); + + mSiteNameCombo.setEditable( true ); + + add( new JLabel( "Site:" ) ); + add( mSiteNameCombo, "growx" ); + + /** + * ComboBox: Alias Lists + */ + add( new JLabel( "Alias List:" ) ); + + mAliasListCombo = new JComboBox(); + + List lists = mPlaylistManager.getPlayist() + .getAliasDirectory().getAliasList(); + + Collections.sort( lists ); + + mAliasListCombo.setModel( new DefaultComboBoxModel( + lists.toArray( new AliasList[ lists.size() ] ) ) ); + + add( mAliasListCombo, "growx" ); + + add( new JLabel() ); + + final JButton aliasListButton = new JButton( "New Alias List ..." ); + + aliasListButton.addActionListener( new ActionListener() + { + @Override + public void actionPerformed( ActionEvent e ) + { + String name = JOptionPane.showInputDialog( aliasListButton, + "Please enter an Alias List name:" ); + + if( name != null && !name.isEmpty() ) + { + AliasList aliasList = new AliasList( name ); + + mPlaylistManager.getPlayist().getAliasDirectory() + .addAliasList( aliasList ); + + mPlaylistManager.save(); + + List lists = mPlaylistManager.getPlayist() + .getAliasDirectory().getAliasList(); + + Collections.sort( lists ); + + mAliasListCombo.setModel( new DefaultComboBoxModel( + lists.toArray( new AliasList[ lists.size() ] ) ) ); + + mAliasListCombo.setSelectedItem( aliasList ); + } + } + } ); + + add( aliasListButton, "growx" ); + } + + @Override + public void save() + { + if( mChannel != null ) + { + mChannel.setName( mChannelName.getText() ); + + Object system = mSystemNameCombo.getSelectedItem(); + mChannel.setSystem( ( system == null ? null : (String)system ) ); + + Object site = mSiteNameCombo.getSelectedItem(); + mChannel.setSystem( ( site == null ? null : (String)site ) ); + } + } + + @Override + public void validateConfiguration() throws ConfigurationValidationException + { + //System and site can be null, but we must (should?) have a channel name + String name = mChannelName.getText(); + + if( name == null || name.isEmpty() ) + { + throw new ConfigurationValidationException( + mChannelName, "Channel name cannot be empty" ); + } + } + + @Override + public void setConfiguration( Channel channel ) + { + mChannel = channel; + + mChannelName.setText( channel.getName() ); + + List systems = mChannelModel.getSystems(); + + if( systems.isEmpty() ) + { + mSystemNameCombo.setModel( EMPTY_MODEL ); + } + else + { + mSystemNameCombo.setModel( new DefaultComboBoxModel( + systems.toArray( new String[ systems.size() ] ) ) );; + } + + mSystemNameCombo.setSelectedItem( channel.getSystem() ); + + List sites = mChannelModel.getSites( channel.getSystem() ); + + if( sites.isEmpty() ) + { + mSiteNameCombo.setModel( EMPTY_MODEL ); + } + else + { + mSiteNameCombo.setModel( new DefaultComboBoxModel( + sites.toArray( new String[ sites.size() ] ) ) );; + } + + mSiteNameCombo.setSelectedItem( channel.getSite() ); + + String aliasListName = mChannel.getAliasListName(); + + if( aliasListName != null ) + { + AliasList selected = mPlaylistManager.getPlayist().getAliasDirectory() + .getAliasList( aliasListName ); + + mAliasListCombo.setSelectedItem( selected ); + } + } +} diff --git a/src/controller/channel/OldChannelEditor.java b/src/controller/channel/OldChannelEditor.java new file mode 100644 index 00000000..f4f317f8 --- /dev/null +++ b/src/controller/channel/OldChannelEditor.java @@ -0,0 +1,260 @@ +/******************************************************************************* + * 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 + ******************************************************************************/ +package controller.channel; + + +import java.awt.Color; +import java.awt.ComponentOrientation; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Collections; +import java.util.List; + +import javax.swing.DefaultComboBoxModel; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JTextField; + +import module.decode.AuxDecodeComponentEditor; +import module.decode.DecodeComponentEditor; +import module.log.EventLogComponentEditor; +import net.miginfocom.swing.MigLayout; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import playlist.PlaylistManager; +import record.RecordComponentEditor; +import source.SourceComponentEditor; +import source.SourceManager; +import alias.AliasList; + +import com.jidesoft.swing.JideTabbedPane; + +public class OldChannelEditor extends ChannelConfigurationEditor implements ActionListener +{ + private final static Logger mLog = LoggerFactory.getLogger( OldChannelEditor.class ); + + private static final long serialVersionUID = 1L; + + private DecodeComponentEditor mDecodeEditor; + private AuxDecodeComponentEditor mAuxDecodeEditor; + private EventLogComponentEditor mEventLogEditor; + private RecordComponentEditor mRecordEditor; + private SourceComponentEditor mSourceEditor; + + private JTextField mChannelName; + private JCheckBox mChannelEnabled = new JCheckBox(); + private JComboBox mComboAliasLists; + + private Channel mChannel; + private ChannelModel mChannelModel; + private PlaylistManager mPlaylistManager; + private SourceManager mSourceManager; + + public OldChannelEditor( Channel channel, + ChannelModel channelModel, + PlaylistManager playlistManager, + SourceManager sourceManager ) + { + super(); + + mChannel = channel; + mChannelModel = channelModel; + mPlaylistManager = playlistManager; + mSourceManager = sourceManager; + + initGUI(); + } + + private void initGUI() + { + setLayout( new MigLayout( "fill,wrap 2", "[right,grow][grow]", "[][][][][grow][]" ) ); + + add( new JLabel( "Channel Configuration" ), "span, align center" ); + + add( new JLabel( "Enabled:" ) ); + + mChannelEnabled.setSelected( mChannel.getEnabled() ); + mChannelEnabled.setComponentOrientation( ComponentOrientation.RIGHT_TO_LEFT ); + add( mChannelEnabled ); + + add( new JLabel( "Name:" ) ); + + mChannelName = new JTextField( mChannel.getName() ); + add( mChannelName, "growx,push" ); + + /** + * ComboBox: Alias Lists + */ + add( new JLabel( "Alias List:" ) ); + + mComboAliasLists = new JComboBox(); + + List lists = mPlaylistManager.getPlayist() + .getAliasDirectory().getAliasList(); + + Collections.sort( lists ); + + mComboAliasLists.setModel( new DefaultComboBoxModel( + lists.toArray( new AliasList[ lists.size() ] ) ) ); + + String aliasListName = mChannel.getAliasListName(); + + if( aliasListName != null ) + { + AliasList selected = mPlaylistManager.getPlayist().getAliasDirectory() + .getAliasList( aliasListName ); + + mComboAliasLists.setSelectedItem( selected ); + } + + add( mComboAliasLists, "growx,push" ); + + JideTabbedPane tabs = new JideTabbedPane(); + tabs.setFont( this.getFont() ); + tabs.setForeground( Color.BLACK ); + + mSourceEditor = new SourceComponentEditor( mSourceManager, mChannel ); + tabs.addTab( "Source", mSourceEditor ); + + mDecodeEditor = new DecodeComponentEditor( mPlaylistManager, mChannel ); + tabs.addTab( "Decoder", mDecodeEditor ); + + mAuxDecodeEditor = new AuxDecodeComponentEditor( mChannel ); + tabs.addTab( "Aux", mAuxDecodeEditor ); + + mEventLogEditor = new EventLogComponentEditor( mChannel ); + tabs.addTab( "Event Log", mEventLogEditor ); + + mRecordEditor = new RecordComponentEditor( mChannel ); + tabs.addTab( "Record", mRecordEditor ); + + add( tabs, "span,grow,push" ); + + JButton btnSave = new JButton( "Save" ); + btnSave.addActionListener( OldChannelEditor.this ); + add( btnSave, "growx,push" ); + + JButton btnReset = new JButton( "Reset" ); + btnReset.addActionListener( OldChannelEditor.this ); + add( btnReset, "growx,push" ); + } + + @Override + public void actionPerformed( ActionEvent e ) + { + String command = e.getActionCommand(); + + if( command.contentEquals( "Save" ) ) + { + save(); + } + else if( command.contentEquals( "Reset" ) ) + { +// reset(); + } + } + + @Override + public void save() + { +// try +// { +// /** +// * Validate the source configuration against the other component +// * configuration editors +// */ +// validate( mSourceEditor.getSourceEditor() ); +// +// mSourceEditor.save(); +// mDecodeEditor.save(); +// mAuxDecodeEditor.save(); +// mEventLogEditor.save(); +// mRecordEditor.save(); +// +// mChannel.setName( mChannelName.getText() ); +// mChannel.setEnabled( mChannelEnabled.isSelected() ); +// +// AliasList selected = mComboAliasLists.getItemAt( +// mComboAliasLists.getSelectedIndex() ); +// if( selected != null ) +// { +// mChannel.setAliasListName( selected.getName() ); +// } +// } +// catch ( ConfigurationValidationException validationException ) +// { +// /* ChannelValidationException can be thrown by any of the component +// * editors. Show the validation error text in a popup menu to the +// * user */ +// JOptionPane.showMessageDialog( OldChannelEditor.this, +// validationException.getMessage(), +// "Channel Configuration Error", +// JOptionPane.ERROR_MESSAGE ); +// } + } + +// @Override +// public void reset() +// { +// mChannelName.setText( mChannel.getName() ); +// mChannelName.requestFocus(); +// mChannelName.requestFocusInWindow(); +// +// mChannelEnabled.setSelected( mChannel.getEnabled() ); +// mChannelEnabled.requestFocus(); +// mChannelEnabled.requestFocusInWindow(); +// +// String aliasListName = mChannel.getAliasListName(); +// +// if( aliasListName != null ) +// { +// AliasList selected = mPlaylistManager.getPlayist().getAliasDirectory() +// .getAliasList( aliasListName ); +// +// mComboAliasLists.setSelectedItem( selected ); +// } +// +// +// mSourceEditor.reset(); +// mDecodeEditor.reset(); +// mAuxDecodeEditor.reset(); +// mEventLogEditor.reset(); +// mRecordEditor.reset(); +// } + + @Override + public void setConfiguration( Channel channel ) + { + + } + + @Override + public void validateConfiguration() throws ConfigurationValidationException + { + mSourceEditor.validate(); + mDecodeEditor.validate(); + mAuxDecodeEditor.validate(); + mEventLogEditor.validate(); + mRecordEditor.validate(); + } + +} diff --git a/src/controller/channel/map/ChannelMapListNode.java b/src/controller/channel/map/ChannelMapListNode.java index 208e22a4..9259bba3 100644 --- a/src/controller/channel/map/ChannelMapListNode.java +++ b/src/controller/channel/map/ChannelMapListNode.java @@ -23,15 +23,16 @@ import java.awt.event.ActionListener; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; +import playlist.PlaylistManager; import controller.ConfigurableNode; public class ChannelMapListNode extends ConfigurableNode { private static final long serialVersionUID = 1L; - public ChannelMapListNode( ChannelMapList list ) + public ChannelMapListNode( PlaylistManager playlistManager, ChannelMapList list ) { - super( list ); + super( playlistManager, list ); } public ChannelMapList getChannelMapList() @@ -43,7 +44,7 @@ public class ChannelMapListNode extends ConfigurableNode { for( ChannelMap channelMap: getChannelMapList().getChannelMap() ) { - ChannelMapNode node = new ChannelMapNode( channelMap ); + ChannelMapNode node = new ChannelMapNode( getPlaylistManager(), channelMap ); getModel().addNode( node, ChannelMapListNode.this, getChildCount() ); @@ -72,7 +73,7 @@ public class ChannelMapListNode extends ConfigurableNode getChannelMapList().addChannelMap( channelMap ); - getModel().addNode( new ChannelMapNode( channelMap ), + getModel().addNode( new ChannelMapNode( getPlaylistManager(), channelMap ), ChannelMapListNode.this, ChannelMapListNode.this.getChildCount() ); diff --git a/src/controller/channel/map/ChannelMapNode.java b/src/controller/channel/map/ChannelMapNode.java index 7a0712e0..ef6c6bfe 100644 --- a/src/controller/channel/map/ChannelMapNode.java +++ b/src/controller/channel/map/ChannelMapNode.java @@ -25,15 +25,16 @@ import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JPopupMenu; +import playlist.PlaylistManager; import controller.ConfigurableNode; public class ChannelMapNode extends ConfigurableNode { private static final long serialVersionUID = 1L; - public ChannelMapNode( ChannelMap ChannelMap ) + public ChannelMapNode( PlaylistManager playlistManager, ChannelMap ChannelMap ) { - super( ChannelMap ); + super( playlistManager, ChannelMap ); } public void init() diff --git a/src/controller/site/SiteNode.java b/src/controller/site/SiteNode.java index b1184ab3..65ad140f 100644 --- a/src/controller/site/SiteNode.java +++ b/src/controller/site/SiteNode.java @@ -29,26 +29,43 @@ import javax.swing.JPopupMenu; import javax.swing.JSeparator; import javax.swing.tree.DefaultMutableTreeNode; +import playlist.PlaylistManager; +import source.SourceManager; import controller.ConfigurableNode; import controller.channel.Channel; +import controller.channel.ChannelModel; import controller.channel.ChannelNode; +import controller.channel.ChannelProcessingManager; import controller.system.System; import controller.system.SystemNode; public class SiteNode extends ConfigurableNode { private static final long serialVersionUID = 1L; + + private ChannelModel mChannelModel; + private ChannelProcessingManager mChannelProcessingManager; + private SourceManager mSourceManager; - public SiteNode( Site site ) + public SiteNode( Site site, + ChannelModel channelModel, + ChannelProcessingManager channelProcessingManager, + PlaylistManager playlistManager, + SourceManager sourceManager ) { - super( site ); + super( playlistManager, site ); + + mChannelModel = channelModel; + mChannelProcessingManager = channelProcessingManager; + mSourceManager = sourceManager; } public void init() { for( Channel channel: getSite().getChannel() ) { - ChannelNode node = new ChannelNode( channel ); + ChannelNode node = new ChannelNode( channel, mChannelModel, + mChannelProcessingManager, getPlaylistManager(), mSourceManager ); getModel().insertNodeInto( node, SiteNode.this, getChildCount() ); @@ -130,7 +147,8 @@ public class SiteNode extends ConfigurableNode getSite().addChannel( channel ); - ChannelNode node = new ChannelNode( channel ); + ChannelNode node = new ChannelNode( channel, mChannelModel, + mChannelProcessingManager, getPlaylistManager(), mSourceManager ); getModel().addNode( node, SiteNode.this, @@ -139,11 +157,6 @@ public class SiteNode extends ConfigurableNode sort(); save(); node.show(); - - /* Give channel reference to the resource manager and the - * channel will register the listeners and send a channel - * add event */ - channel.setResourceManager( getModel().getResourceManager() ); } } ); diff --git a/src/controller/system/SystemListNode.java b/src/controller/system/SystemListNode.java index 4629133d..d0e5b3a9 100644 --- a/src/controller/system/SystemListNode.java +++ b/src/controller/system/SystemListNode.java @@ -23,15 +23,31 @@ import java.awt.event.ActionListener; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; +import playlist.PlaylistManager; +import source.SourceManager; import controller.ConfigurableNode; +import controller.channel.ChannelModel; +import controller.channel.ChannelProcessingManager; public class SystemListNode extends ConfigurableNode { private static final long serialVersionUID = 1L; - public SystemListNode( SystemList list ) + private ChannelModel mChannelModel; + private ChannelProcessingManager mChannelProcessingManager; + private SourceManager mSourceManager; + + public SystemListNode( SystemList list, + ChannelModel channelModel, + ChannelProcessingManager channelProcessingManager, + PlaylistManager playlistManager, + SourceManager sourceManager ) { - super( list ); + super( playlistManager, list ); + + mChannelModel = channelModel; + mChannelProcessingManager = channelProcessingManager; + mSourceManager = sourceManager; } public SystemList getSystemList() @@ -43,7 +59,8 @@ public class SystemListNode extends ConfigurableNode { for( System system: getSystemList().getSystem() ) { - SystemNode node = new SystemNode( system ); + SystemNode node = new SystemNode( system, mChannelModel, + mChannelProcessingManager, getPlaylistManager(), mSourceManager ); getModel().addNode( node, SystemListNode.this, getChildCount() ); @@ -72,9 +89,9 @@ public class SystemListNode extends ConfigurableNode getSystemList().addSystem( system ); - getModel().addNode( new SystemNode( system ), - SystemListNode.this, - SystemListNode.this.getChildCount() ); + getModel().addNode( new SystemNode( system, mChannelModel, + mChannelProcessingManager, getPlaylistManager(), mSourceManager ), + SystemListNode.this, SystemListNode.this.getChildCount() ); } } ); diff --git a/src/controller/system/SystemNode.java b/src/controller/system/SystemNode.java index a9c4e3b9..39f28214 100644 --- a/src/controller/system/SystemNode.java +++ b/src/controller/system/SystemNode.java @@ -29,7 +29,11 @@ import javax.swing.JPopupMenu; import javax.swing.JSeparator; import javax.swing.tree.DefaultMutableTreeNode; +import playlist.PlaylistManager; +import source.SourceManager; import controller.ConfigurableNode; +import controller.channel.ChannelModel; +import controller.channel.ChannelProcessingManager; import controller.site.Site; import controller.site.SiteNode; @@ -37,16 +41,29 @@ public class SystemNode extends ConfigurableNode { private static final long serialVersionUID = 1L; - public SystemNode( System system ) + private ChannelModel mChannelModel; + private ChannelProcessingManager mChannelProcessingManager; + private SourceManager mSourceManager; + + public SystemNode( System system, + ChannelModel channelModel, + ChannelProcessingManager channelProcessingManager, + PlaylistManager playlistManager, + SourceManager sourceManager ) { - super( system ); + super( playlistManager, system ); + + mChannelModel = channelModel; + mChannelProcessingManager = channelProcessingManager; + mSourceManager = sourceManager; } public void init() { for( Site site: getSystem().getSite() ) { - SiteNode node = new SiteNode( site ); + SiteNode node = new SiteNode( site, mChannelModel, + mChannelProcessingManager, getPlaylistManager(), mSourceManager ); getModel().insertNodeInto( node, SystemNode.this, getChildCount() ); @@ -133,7 +150,8 @@ public class SystemNode extends ConfigurableNode Site site = new Site(); getSystem().addSite( site ); - SiteNode node = new SiteNode( site ); + SiteNode node = new SiteNode( site, mChannelModel, + mChannelProcessingManager, getPlaylistManager(), mSourceManager ); getModel().addNode( node, SystemNode.this, diff --git a/src/dsp/filter/dc/DCRemovalFilter_RealBuffer.java b/src/dsp/filter/dc/DCRemovalFilter_RealBuffer.java new file mode 100644 index 00000000..308b4ed7 --- /dev/null +++ b/src/dsp/filter/dc/DCRemovalFilter_RealBuffer.java @@ -0,0 +1,60 @@ +package dsp.filter.dc; + +import sample.Listener; +import sample.real.RealBuffer; + +public class DCRemovalFilter_RealBuffer implements Listener +{ + private Listener mListener; + /** + * Removes DC bias present across the samples in the buffer by calculating + * the mean DC component and subtracting that component from each of the + * samples. + */ + public DCRemovalFilter_RealBuffer() + { + } + + public void dispose() + { + mListener = null; + } + + public RealBuffer filter( RealBuffer buffer ) + { + double accumulator = 0.0d; + + for( float sample: buffer.getSamples() ) + { + accumulator += sample; + } + + float mean = (float)( accumulator / (double)buffer.getSamples().length ); + + for( float sample: buffer.getSamples() ) + { + sample -= mean; + } + + return buffer; + } + + @Override + public void receive( RealBuffer buffer ) + { + if( mListener != null ) + { + mListener.receive( filter( buffer ) ); + } + } + + public void setListener( Listener listener ) + { + mListener = listener; + } + + public void removeListener() + { + mListener = null; + } +} diff --git a/src/dsp/psk/LSMDemodulator.java b/src/dsp/psk/LSMDemodulator.java index dd44a5a1..d3b40479 100644 --- a/src/dsp/psk/LSMDemodulator.java +++ b/src/dsp/psk/LSMDemodulator.java @@ -46,7 +46,7 @@ import org.slf4j.LoggerFactory; import sample.Listener; import sample.complex.Complex; import sample.complex.ComplexSampleListener; -import source.tuner.frequency.FrequencyChangeListener; +import source.tuner.frequency.IFrequencyChangeListener; import buffer.FloatAveragingBuffer; import dsp.filter.interpolator.RealInterpolator; import dsp.symbol.Dibit; @@ -79,7 +79,7 @@ public class LSMDemodulator implements Instrumentable, ComplexSampleListener private CostasLoop mCostasLoop = new CostasLoop(); - private FrequencyChangeListener mFrequencyChangeListener; + private IFrequencyChangeListener mFrequencyChangeListener; private EyeDiagramDataTap mEyeDiagramDataTap; @@ -153,12 +153,12 @@ public class LSMDemodulator implements Instrumentable, ComplexSampleListener } } - public void addListener( FrequencyChangeListener listener ) + public void addListener( IFrequencyChangeListener listener ) { mFrequencyChangeListener = listener; } - public void removeListener( FrequencyChangeListener listener ) + public void removeListener( IFrequencyChangeListener listener ) { mFrequencyChangeListener = null; } diff --git a/src/dsp/psk/LSMDemodulator2.java b/src/dsp/psk/LSMDemodulator2.java index 1df263f1..819af376 100644 --- a/src/dsp/psk/LSMDemodulator2.java +++ b/src/dsp/psk/LSMDemodulator2.java @@ -48,7 +48,7 @@ import sample.Listener; import sample.Provider; import sample.complex.Complex; import sample.complex.ComplexSampleListener; -import source.tuner.frequency.FrequencyChangeListener; +import source.tuner.frequency.IFrequencyChangeListener; import buffer.FloatAveragingBuffer; import dsp.filter.interpolator.RealInterpolator; import dsp.symbol.Dibit; @@ -84,7 +84,7 @@ public class LSMDemodulator2 implements Instrumentable, ComplexSampleListener, private CostasLoop mCostasLoop = new CostasLoop(); - private FrequencyChangeListener mFrequencyChangeListener; + private IFrequencyChangeListener mFrequencyChangeListener; private EyeDiagramDataTap mEyeDiagramDataTap; @@ -143,12 +143,12 @@ public class LSMDemodulator2 implements Instrumentable, ComplexSampleListener, } } - public void addListener( FrequencyChangeListener listener ) + public void addListener( IFrequencyChangeListener listener ) { mFrequencyChangeListener = listener; } - public void removeListener( FrequencyChangeListener listener ) + public void removeListener( IFrequencyChangeListener listener ) { mFrequencyChangeListener = null; } diff --git a/src/gui/SDRTrunk.java b/src/gui/SDRTrunk.java index 79345b07..6de05d02 100644 --- a/src/gui/SDRTrunk.java +++ b/src/gui/SDRTrunk.java @@ -43,7 +43,9 @@ import javax.swing.JOptionPane; import javax.swing.JSeparator; import javax.swing.KeyStroke; +import map.IconManager; import map.MapService; +import module.log.EventLogManager; import net.miginfocom.swing.MigLayout; import org.slf4j.Logger; @@ -51,7 +53,9 @@ import org.slf4j.LoggerFactory; import playlist.PlaylistManager; import properties.SystemProperties; +import record.RecorderManager; import settings.SettingsManager; +import source.SourceManager; import source.tuner.Tuner; import source.tuner.TunerSelectionListener; import spectrum.SpectralDisplayPanel; @@ -63,7 +67,6 @@ import com.jidesoft.swing.JideSplitPane; import controller.ConfigurationControllerModel; import controller.ControllerPanel; -import controller.ResourceManager; import controller.ThreadPoolManager; import controller.ThreadPoolManager.ThreadType; import controller.channel.ChannelEventListener; @@ -76,6 +79,7 @@ public class SDRTrunk private final static Logger mLog = LoggerFactory.getLogger( SDRTrunk.class ); private ControllerPanel mControllerPanel; + private SettingsManager mSettingsManager; private SpectralDisplayPanel mSpectralPanel; private JFrame mMainGui = new JFrame(); @@ -107,49 +111,54 @@ public class SDRTrunk //Log current properties setting SystemProperties.getInstance().logCurrentSettings(); + + mSettingsManager = new SettingsManager(); + + ThreadPoolManager threadPoolManager = new ThreadPoolManager(); + + SourceManager sourceManager = new SourceManager( mSettingsManager, threadPoolManager ); ChannelModel channelModel = new ChannelModel(); + PlaylistManager playlistManager = new PlaylistManager( channelModel ); + + RecorderManager recorderManager = new RecorderManager( threadPoolManager ); + + EventLogManager eventLogManager = new EventLogManager(); + ChannelProcessingManager channelProcessingManager = - new ChannelProcessingManager( channelModel ); + new ChannelProcessingManager( channelModel, eventLogManager, + playlistManager, recorderManager, sourceManager, threadPoolManager ); channelModel.addListener( channelProcessingManager ); - ThreadPoolManager threadPoolManager = new ThreadPoolManager(); + channelProcessingManager.addAudioPacketListener( recorderManager ); AliasActionManager aliasActionManager = new AliasActionManager( threadPoolManager ); - channelProcessingManager.addListener( aliasActionManager ); + channelProcessingManager.addMessageListener( aliasActionManager ); + + AudioManager audioManager = new AudioManager( threadPoolManager ); + channelProcessingManager.addAudioPacketListener( audioManager ); + + MapService mapService = new MapService( mSettingsManager ); + channelProcessingManager.addMessageListener( mapService ); ChannelSelectionManager channelSelectionManager = new ChannelSelectionManager( channelModel ); channelModel.addListener( channelSelectionManager ); - - /** - * Construct the resource manager now, so that it can use the system - * properties that were just loaded - */ - //TODO: get rid of resource manager ... below is start of breaking out - //the encapsulated pieces from the resource manager - PlaylistManager playlistManager = new PlaylistManager( channelModel ); - ResourceManager resource = - new ResourceManager( playlistManager, threadPoolManager, channelModel ); - - AudioManager audio = resource.getAudioManager(); - ConfigurationControllerModel configurationControllerModel = resource.getController(); - MapService map = resource.getMapService(); - SettingsManager settings = resource.getSettingsManager(); + //Initialize the playlist manager to load the saved playlist + playlistManager.init(); - mControllerPanel = - new ControllerPanel( audio, - configurationControllerModel, - channelModel, - channelProcessingManager, - map, - playlistManager, - settings ); + ConfigurationControllerModel configurationControllerModel = + new ConfigurationControllerModel( channelModel, channelProcessingManager, + playlistManager, mSettingsManager, sourceManager ); - mSpectralPanel = new SpectralDisplayPanel( channelModel, - configurationControllerModel, playlistManager, settings ); + mControllerPanel = new ControllerPanel( audioManager, configurationControllerModel, + channelModel, channelProcessingManager, mapService, playlistManager, + mSettingsManager, sourceManager ); + + mSpectralPanel = new SpectralDisplayPanel( configurationControllerModel, + channelModel, channelProcessingManager, playlistManager, mSettingsManager ); mTitle = getTitle(); @@ -162,7 +171,7 @@ public class SDRTrunk { Runnable cml = new ChannelMemoryLogger(); channelModel.addListener( (ChannelEventListener)cml ); - resource.getThreadPoolManager().scheduleFixedRate( + threadPoolManager.scheduleFixedRate( ThreadType.DECODER, cml, 5, TimeUnit.SECONDS ); } @@ -277,7 +286,16 @@ public class SDRTrunk @Override public void actionPerformed( ActionEvent arg0 ) { - mControllerPanel.getController().showIconManager(); + final IconManager iconManager = new IconManager( mSettingsManager, mMainGui ); + + EventQueue.invokeLater( new Runnable() + { + @Override + public void run() + { + iconManager.setVisible( true ); + } + } ); } } ); fileMenu.add( settingsMenu ); diff --git a/src/gui/control/JFrequencyControl.java b/src/gui/control/JFrequencyControl.java index a413e11f..95b88249 100644 --- a/src/gui/control/JFrequencyControl.java +++ b/src/gui/control/JFrequencyControl.java @@ -33,6 +33,7 @@ import java.text.ParseException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import javax.swing.JLabel; import javax.swing.JPanel; @@ -44,17 +45,17 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import source.tuner.frequency.FrequencyChangeEvent; -import source.tuner.frequency.FrequencyChangeListener; import source.tuner.frequency.FrequencyChangeEvent.Event; +import source.tuner.frequency.IFrequencyChangeListener; +import source.tuner.frequency.IFrequencyChangeProcessor; -public class JFrequencyControl extends JPanel implements FrequencyChangeListener +public class JFrequencyControl extends JPanel implements IFrequencyChangeProcessor { private static final long serialVersionUID = 1L; private final static Logger mLog = LoggerFactory.getLogger( JFrequencyControl.class ); - private ArrayList mListeners = - new ArrayList(); + private List mProcessors = new ArrayList<>(); private Color mHighlightColor = Color.YELLOW; @@ -136,7 +137,7 @@ public class JFrequencyControl extends JPanel implements FrequencyChangeListener @Override public void frequencyChanged( FrequencyChangeEvent event ) { - if( event.getEvent() == Event.FREQUENCY_CHANGE_NOTIFICATION ) + if( event.getEvent() == Event.NOTIFICATION_FREQUENCY_CHANGE ) { setFrequency( event.getValue().longValue(), false ); } @@ -177,10 +178,10 @@ public class JFrequencyControl extends JPanel implements FrequencyChangeListener { updateFrequency(); - Iterator it = mListeners.iterator(); + Iterator it = mProcessors.iterator(); FrequencyChangeEvent event = - new FrequencyChangeEvent( Event.FREQUENCY_CHANGE_NOTIFICATION, mFrequency ); + new FrequencyChangeEvent( Event.NOTIFICATION_FREQUENCY_CHANGE, mFrequency ); while( it.hasNext() ) { @@ -188,14 +189,14 @@ public class JFrequencyControl extends JPanel implements FrequencyChangeListener } } - public void addListener( FrequencyChangeListener listener ) + public void addListener( IFrequencyChangeProcessor processor ) { - mListeners.add( listener ); + mProcessors.add( processor ); } - public void removeListener( FrequencyChangeListener listener ) + public void removeListener( IFrequencyChangeProcessor processor ) { - mListeners.remove( listener ); + mProcessors.remove( processor ); } public class Digit extends JTextField diff --git a/src/instrument/InstrumentableProcessingChain.java b/src/instrument/InstrumentableProcessingChain.java index 3efef0ae..94181b18 100644 --- a/src/instrument/InstrumentableProcessingChain.java +++ b/src/instrument/InstrumentableProcessingChain.java @@ -9,11 +9,13 @@ import java.util.List; import module.Module; import module.ProcessingChain; import source.Source; +import controller.channel.Channel.ChannelType; public class InstrumentableProcessingChain extends ProcessingChain implements Instrumentable { public InstrumentableProcessingChain() { + super( ChannelType.STANDARD ); } public void setSource( Source source ) throws IllegalStateException diff --git a/src/instrument/gui/DecoderSelectionFrame.java b/src/instrument/gui/DecoderSelectionFrame.java index b2b6a32d..998191b1 100644 --- a/src/instrument/gui/DecoderSelectionFrame.java +++ b/src/instrument/gui/DecoderSelectionFrame.java @@ -13,8 +13,6 @@ import module.decode.config.DecodeConfiguration; import net.miginfocom.swing.MigLayout; import playlist.PlaylistManager; import source.IControllableFileSource; -import controller.ResourceManager; -import controller.ThreadPoolManager; import controller.channel.ChannelModel; public class DecoderSelectionFrame extends JInternalFrame @@ -22,7 +20,7 @@ public class DecoderSelectionFrame extends JInternalFrame private static final long serialVersionUID = 1L; private DecodeComponentEditor mDecodeEditor = new DecodeComponentEditor( null ); - private ResourceManager mResourceManager; + private PlaylistManager mPlaylistManager; private IControllableFileSource mSource; private JDesktopPane mDesktop; @@ -31,9 +29,7 @@ public class DecoderSelectionFrame extends JInternalFrame IControllableFileSource source ) { ChannelModel channelModel = new ChannelModel(); - - mResourceManager = new ResourceManager( new PlaylistManager( channelModel ), - new ThreadPoolManager(), channelModel ); + mPlaylistManager = new PlaylistManager( channelModel ); mDesktop = desktop; mSource = source; @@ -78,12 +74,7 @@ public class DecoderSelectionFrame extends JInternalFrame if( config != null ) { DecoderViewFrame decoderFrame = new DecoderViewFrame( - mResourceManager, - config, - null, - null, - null, - mSource ); + mPlaylistManager, null, mSource ); decoderFrame.setVisible( true ); diff --git a/src/instrument/gui/DecoderViewFrame.java b/src/instrument/gui/DecoderViewFrame.java index 9cdfe1c5..a2afb439 100644 --- a/src/instrument/gui/DecoderViewFrame.java +++ b/src/instrument/gui/DecoderViewFrame.java @@ -57,22 +57,20 @@ import javax.swing.JSeparator; import message.Message; import module.Module; import module.decode.DecoderFactory; -import module.decode.config.AuxDecodeConfiguration; import module.decode.config.DecodeConfiguration; import net.miginfocom.swing.MigLayout; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import record.config.RecordConfiguration; +import playlist.PlaylistManager; import sample.Listener; import source.IControllableFileSource; import source.Source; -import alias.AliasList; -import controller.ResourceManager; -import controller.channel.Channel.ChannelType; -import controller.site.Site; -import controller.system.System; +import controller.ThreadPoolManager; +import controller.channel.Channel; +import controller.channel.ChannelModel; +import controller.channel.ChannelProcessingManager; public class DecoderViewFrame extends JInternalFrame implements Listener @@ -88,29 +86,23 @@ public class DecoderViewFrame extends JInternalFrame private HashMap mPanelMap = new HashMap(); - public DecoderViewFrame( ResourceManager resourceManager, - DecodeConfiguration decodeConfig, - RecordConfiguration recordConfig, - AuxDecodeConfiguration auxConfig, - AliasList aliasList, + public DecoderViewFrame( PlaylistManager playlistManager, + Channel channel, IControllableFileSource source ) { mSource = source; - mDecodeConfig = decodeConfig; + mDecodeConfig = channel.getDecodeConfiguration(); mProcessingChain = new InstrumentableProcessingChain(); + + ChannelModel channelModel = new ChannelModel(); + ChannelProcessingManager channelProcessingManager = + new ChannelProcessingManager( channelModel, null, + playlistManager, null, null, new ThreadPoolManager() ); - List modules = DecoderFactory - .getModules( ChannelType.STANDARD, - resourceManager, - decodeConfig, - recordConfig, - auxConfig, - aliasList, - "Instrumented", - "Instrumented", - "Channel Name" ); + List modules = DecoderFactory.getModules( channelModel, + channelProcessingManager, playlistManager, channel ); mProcessingChain.addModules( modules ); diff --git a/src/map/IconManager.java b/src/map/IconManager.java index 220ca034..9cc07f3b 100644 --- a/src/map/IconManager.java +++ b/src/map/IconManager.java @@ -50,7 +50,7 @@ import org.slf4j.LoggerFactory; import settings.Setting; import settings.SettingChangeListener; -import controller.ResourceManager; +import settings.SettingsManager; public class IconManager extends JFrame implements ActionListener, SettingChangeListener @@ -62,8 +62,6 @@ public class IconManager extends JFrame private final static Logger mLog = LoggerFactory.getLogger( IconManager.class ); - private ResourceManager mResourceManager; - private static final String sMSG_NEW = "Type a name for the new icon, " + "select the file, and click Save,\nor Cancel to reset"; private static final String sMSG_EDIT = "Change the name for the selected \n" @@ -81,9 +79,11 @@ public class IconManager extends JFrame private JFileChooser mFileChooser; private Mode mMode = Mode.NORMAL; - public IconManager( ResourceManager resourceManager, Component displayOver ) + private SettingsManager mSettingsManager; + + public IconManager( SettingsManager settingsManager, Component displayOver ) { - mResourceManager = resourceManager; + mSettingsManager = settingsManager; init( displayOver ); } @@ -128,7 +128,7 @@ public class IconManager extends JFrame /** * MapIcon list */ - MapIcon[] icons = mResourceManager.getSettingsManager().getMapIcons(); + MapIcon[] icons = mSettingsManager.getMapIcons(); Arrays.sort( icons ); mIconList = new JList( icons ); @@ -176,8 +176,7 @@ public class IconManager extends JFrame @Override public void actionPerformed( ActionEvent e ) { - mResourceManager.getSettingsManager() - .setDefaultIcon( icon ); + mSettingsManager.setDefaultIcon( icon ); refreshList(); } @@ -193,8 +192,7 @@ public class IconManager extends JFrame @Override public void actionPerformed( ActionEvent arg0 ) { - mResourceManager.getSettingsManager() - .deleteMapIcon( icon ); + mSettingsManager.deleteMapIcon( icon ); } } ); @@ -350,7 +348,7 @@ public class IconManager extends JFrame private void refreshList() { - MapIcon[] icons = mResourceManager.getSettingsManager().getMapIcons(); + MapIcon[] icons = mSettingsManager.getMapIcons(); Arrays.sort( icons ); @@ -371,8 +369,7 @@ public class IconManager extends JFrame { if( path != null && !path.isEmpty() ) { - mResourceManager.getSettingsManager() - .addMapIcon( new MapIcon( name, path, true ) ); + mSettingsManager.addMapIcon( new MapIcon( name, path, true ) ); } else { @@ -400,8 +397,7 @@ public class IconManager extends JFrame { selected.setName( name ); selected.setPath( path ); - mResourceManager.getSettingsManager() - .updatMapIcon( selected, name, path ); + mSettingsManager.updatMapIcon( selected, name, path ); } else { diff --git a/src/map/MapPanel.java b/src/map/MapPanel.java index e9b66045..4a61b33f 100644 --- a/src/map/MapPanel.java +++ b/src/map/MapPanel.java @@ -46,17 +46,12 @@ public class MapPanel extends JPanel implements PlottableUpdateListener private JXMapViewer mMapViewer = new JXMapViewer(); private PlottableEntityPainter mMapPainter; - public MapPanel( MapService mapService, - SettingsManager settingsManager, - ChannelProcessingManager channelProcessingManager ) + public MapPanel( MapService mapService, SettingsManager settingsManager ) { mSettingsManager = settingsManager; mMapService = mapService; mMapPainter = new PlottableEntityPainter( mSettingsManager ); - /* Add Map Service as message listener to receive all messages */ - channelProcessingManager.addListener( (Listener)mMapService ); - init(); } diff --git a/src/map/MapService.java b/src/map/MapService.java index 0b6c9f87..0c251277 100644 --- a/src/map/MapService.java +++ b/src/map/MapService.java @@ -30,7 +30,6 @@ import sample.Listener; import settings.SettingsManager; import alias.Alias; import controller.NamingThreadFactory; -import controller.ResourceManager; public class MapService implements Listener { @@ -49,11 +48,11 @@ public class MapService implements Listener private HashMap mEntities = new HashMap(); - private ResourceManager mResourceManager; + private SettingsManager mSettingsManager; - public MapService( ResourceManager resourceManager ) + public MapService( SettingsManager resourceManager ) { - mResourceManager = resourceManager; + mSettingsManager = resourceManager; // scheduler.scheduleAtFixedRate( new CullThread(), 5, 5, TimeUnit.MINUTES ); } @@ -111,8 +110,7 @@ public class MapService implements Listener iconName = SettingsManager.DEFAULT_ICON; } - icon = mResourceManager.getSettingsManager() - .getMapIcon( iconName ); + icon = mSettingsManager.getMapIcon( iconName ); } if( color == null ) diff --git a/src/module/ProcessingChain.java b/src/module/ProcessingChain.java index c8e3da4f..68c94256 100644 --- a/src/module/ProcessingChain.java +++ b/src/module/ProcessingChain.java @@ -1,6 +1,6 @@ /******************************************************************************* * SDR Trunk - * Copyright (C) 2015 Dennis Sheirer + * Copyright (C) 2015-2016 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 @@ -26,8 +26,11 @@ import message.IMessageListener; import message.IMessageProvider; import message.Message; import module.decode.event.CallEvent; +import module.decode.event.CallEventModel; import module.decode.event.ICallEventListener; import module.decode.event.ICallEventProvider; +import module.decode.event.MessageActivityModel; +import module.decode.state.ChannelState; import module.decode.state.DecoderState; import module.decode.state.DecoderStateEvent; import module.decode.state.DecoderStateEvent.Event; @@ -42,16 +45,19 @@ import sample.Broadcaster; import sample.Listener; import sample.complex.ComplexBuffer; import sample.complex.IComplexBufferListener; -import sample.real.IRealBufferListener; -import sample.real.IRealBufferProvider; +import sample.real.IFilteredRealBufferListener; +import sample.real.IFilteredRealBufferProvider; +import sample.real.IUnFilteredRealBufferListener; +import sample.real.IUnFilteredRealBufferProvider; import sample.real.RealBuffer; import source.ComplexSource; import source.RealSource; import source.Source; import source.SourceException; import source.tuner.TunerChannelSource; -import source.tuner.frequency.FrequencyCorrectionControl; -import source.tuner.frequency.IFrequencyCorrectionController; +import source.tuner.frequency.FrequencyChangeEvent; +import source.tuner.frequency.IFrequencyChangeListener; +import source.tuner.frequency.IFrequencyChangeProvider; import audio.AudioPacket; import audio.IAudioPacketListener; import audio.IAudioPacketProvider; @@ -62,6 +68,7 @@ import audio.squelch.ISquelchStateListener; import audio.squelch.ISquelchStateProvider; import audio.squelch.SquelchState; import controller.ThreadPoolManager; +import controller.channel.Channel.ChannelType; import controller.channel.ChannelEvent; import controller.channel.IChannelEventListener; import controller.channel.IChannelEventProvider; @@ -95,8 +102,10 @@ public class ProcessingChain implements IChannelEventListener private Broadcaster mChannelEventBroadcaster = new Broadcaster<>(); private Broadcaster mComplexBufferBroadcaster = new Broadcaster<>(); private Broadcaster mDecoderStateEventBroadcaster = new Broadcaster<>(); + private Broadcaster mFrequencyChangeEventBroadcaster = new Broadcaster<>(); private Broadcaster mMessageBroadcaster = new Broadcaster<>(); - private Broadcaster mRealBufferBroadcaster = new Broadcaster<>(); + private Broadcaster mFilteredRealBufferBroadcaster = new Broadcaster<>(); + private Broadcaster mUnFilteredRealBufferBroadcaster = new Broadcaster<>(); private Broadcaster mSquelchStateBroadcaster = new Broadcaster<>(); // private ThreadPoolManager mThreadPoolManager; @@ -104,12 +113,50 @@ public class ProcessingChain implements IChannelEventListener protected Source mSource; private List mModules = new ArrayList<>(); - private IFrequencyCorrectionController mFrequencyCorrectionController; + private CallEventModel mCallEventModel; + private ChannelState mChannelState; + private MessageActivityModel mMessageActivityModel; - public ProcessingChain() + public ProcessingChain( ChannelType channelType ) { + this( new ThreadPoolManager(), channelType ); } + + public ProcessingChain( ThreadPoolManager threadManager, + ChannelType channelType ) + { + mThreadPoolManager = threadManager; + + mChannelState = new ChannelState( mThreadPoolManager, channelType ); + addModule( mChannelState ); + + mCallEventModel = new CallEventModel(); + addCallEventListener( mCallEventModel ); + } + + public MessageActivityModel getMessageActivityModel() + { + return mMessageActivityModel; + } + + public CallEventModel getCallEventModel() + { + return mCallEventModel; + } + + public ChannelState getChannelState() + { + return mChannelState; + } + + public void setMessageActivityModel( MessageActivityModel model ) + { + mMessageActivityModel = model; + + addMessageListener( mMessageActivityModel ); + } + public void dispose() { stop(); @@ -121,14 +168,16 @@ public class ProcessingChain implements IChannelEventListener mModules.clear(); - mFrequencyCorrectionController = null; + + mThreadPoolManager = null; + mBufferProcessingTask = null; mAudioPacketBroadcaster.dispose(); mCallEventBroadcaster.dispose(); mChannelEventBroadcaster.dispose(); mComplexBufferBroadcaster.dispose(); mMessageBroadcaster.dispose(); - mRealBufferBroadcaster.dispose(); + mFilteredRealBufferBroadcaster.dispose(); mSquelchStateBroadcaster.dispose(); } @@ -147,7 +196,7 @@ public class ProcessingChain implements IChannelEventListener * Indicates if this processing chain is currently receiving samples from * a source and sending those samples to the decoders. */ - public boolean processing() + public boolean isProcessing() { return mRunning.get(); } @@ -160,28 +209,6 @@ public class ProcessingChain implements IChannelEventListener return mSource != null; } - /** - * Indicates if one of the modules provides frequency error control. - */ - public boolean hasFrequencyCorrectionControl() - { - return mFrequencyCorrectionController != null && - mFrequencyCorrectionController.hasFrequencyCorrectionControl(); - } - - /** - * Frequency correction controller. Can be null. - */ - public FrequencyCorrectionControl getFrequencyCorrectionControl() - { - if( mFrequencyCorrectionController != null ) - { - return mFrequencyCorrectionController.getFrequencyCorrectionControl(); - } - - return null; - } - /** * Applies a sample source to this processing chain. Processing won't * start until the start() method is invoked. @@ -194,7 +221,7 @@ public class ProcessingChain implements IChannelEventListener */ public void setSource( Source source ) throws IllegalStateException { - if( processing() ) + if( isProcessing() ) { throw new IllegalStateException( "Processing chain is currently " + "processing. Invoke stop() on the processing chain before " @@ -202,23 +229,6 @@ public class ProcessingChain implements IChannelEventListener } mSource = source; - - /* Establish two-way communication between the tuner channel source and - * the decoder for fine tuning frequency error correction feedback from - * the decoder. The tuner channel source will also notify the frequency - * controller during frequency changes to allow the controller to reset - * frequency error tracking */ - if( mSource != null && - mSource instanceof TunerChannelSource && - hasFrequencyCorrectionControl() ) - { - TunerChannelSource channel = (TunerChannelSource)mSource; - - FrequencyCorrectionControl control = getFrequencyCorrectionControl(); - - channel.setFrequencyChangeListener( control ); - control.setFrequencyChangeListener( channel ); - } } /** @@ -247,24 +257,45 @@ public class ProcessingChain implements IChannelEventListener return decoderStates; } + /** + * Adds the list of modules to this processing chain + */ + public void addModules( List modules ) + { + for( Module module: modules ) + { + addModule( module ); + } + } + /** * Adds a module to the processing chain. Each module is tested for the * interfaces that it supports and is registered or receives a listener * to consume or produce the supported interface data type. All elements - * that are produced by any component are automatically routed to all other - * components that support the corresponding listener interface. + * and events that are produced by any module are automatically routed to + * all other components that support the corresponding listener interface. * * At least one module should consume complex samples and either produce * decoded messages and/or audio, or produce decoded real sample buffers * for all other modules to consume. * - * @param module - processing module, demodulator or decoder + * @param module - processing module, demodulator, decoder, source, state + * machine, etc. */ public void addModule( Module module ) { mModules.add( module ); + + registerListeners( module ); + registerProviders( module ); + } - /* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Listeners <<<<<<<<<<<<<<<<<<<<<<<<<<< */ + /** + * Registers the module as a listener to each of the broadcasters that + * provide the data interface(s) supported by the module. + */ + private void registerListeners( Module module ) + { if( module instanceof IAudioPacketListener ) { mAudioPacketBroadcaster.addListener( @@ -295,6 +326,12 @@ public class ProcessingChain implements IChannelEventListener ((IDecoderStateEventListener)module).getDecoderStateListener() ); } + if( module instanceof IFrequencyChangeListener ) + { + mFrequencyChangeEventBroadcaster.addListener( + ((IFrequencyChangeListener)module).getFrequencyChangeListener()); + } + if( module instanceof IMessageListener ) { mMessageBroadcaster.addListener( @@ -307,10 +344,10 @@ public class ProcessingChain implements IChannelEventListener ((IMetadataListener)module).getMetadataListener() ); } - if( module instanceof IRealBufferListener ) + if( module instanceof IFilteredRealBufferListener ) { - mRealBufferBroadcaster.addListener( - ((IRealBufferListener)module).getRealBufferListener() ); + mFilteredRealBufferBroadcaster.addListener( + ((IFilteredRealBufferListener)module).getFilteredRealBufferListener() ); } if( module instanceof ISquelchStateListener ) @@ -318,8 +355,20 @@ public class ProcessingChain implements IChannelEventListener mSquelchStateBroadcaster.addListener( ((ISquelchStateListener)module).getSquelchStateListener() ); } - - /* >>>>>>>>>>>>>>>>>>> Providers <<<<<<<<<<<<<<<<<<<<<<<<< */ + + if( module instanceof IUnFilteredRealBufferListener ) + { + mFilteredRealBufferBroadcaster.addListener( + ((IUnFilteredRealBufferListener)module).getUnFilteredRealBufferListener() ); + } + } + + /** + * Registers the broadcaster(s) as listeners to the module for each + * provider interface that is supported by the module. + */ + private void registerProviders( Module module ) + { if( module instanceof IAudioPacketProvider ) { ((IAudioPacketProvider)module).setAudioPacketListener( @@ -342,12 +391,13 @@ public class ProcessingChain implements IChannelEventListener ((IDecoderStateEventProvider)module).setDecoderStateListener( mDecoderStateEventBroadcaster ); } - - if( module instanceof IFrequencyCorrectionController ) - { - mFrequencyCorrectionController = (IFrequencyCorrectionController)module; - } + if( module instanceof IFrequencyChangeProvider ) + { + ((IFrequencyChangeProvider)module).setFrequencyChangeListener( + mFrequencyChangeEventBroadcaster ); + } + if( module instanceof IMessageProvider ) { ((IMessageProvider)module).addMessageListener( mMessageBroadcaster ); @@ -359,9 +409,10 @@ public class ProcessingChain implements IChannelEventListener mMetadataBroadcaster ); } - if( module instanceof IRealBufferProvider ) + if( module instanceof IFilteredRealBufferProvider ) { - ((IRealBufferProvider)module).setRealBufferListener( mRealBufferBroadcaster ); + ((IFilteredRealBufferProvider)module) + .setFilteredRealBufferListener( mFilteredRealBufferBroadcaster ); } if( module instanceof ISquelchStateProvider ) @@ -369,19 +420,13 @@ public class ProcessingChain implements IChannelEventListener ((ISquelchStateProvider)module).setSquelchStateListener( mSquelchStateBroadcaster ); } - } - - /** - * Adds the list of modules to this processing chain - */ - public void addModules( List modules ) - { - for( Module module: modules ) + + if( module instanceof IUnFilteredRealBufferProvider ) { - addModule( module ); + ((IUnFilteredRealBufferProvider)module) + .setUnFilteredRealBufferListener( mUnFilteredRealBufferBroadcaster ); } } - /** * Starts processing if the chain has a valid source. Invocations on an @@ -421,7 +466,7 @@ public class ProcessingChain implements IChannelEventListener ((ComplexSource)mSource).setListener( mComplexBufferBroadcaster ); break; case REAL: - ((RealSource)mSource).setListener( mRealBufferBroadcaster ); + ((RealSource)mSource).setListener( mFilteredRealBufferBroadcaster ); break; default: throw new IllegalArgumentException( "Unrecognized source " @@ -448,7 +493,7 @@ public class ProcessingChain implements IChannelEventListener } else { - mLog.debug( "Source is null on start()" ); + mLog.error( "Source is null on start()" ); } } } @@ -469,7 +514,7 @@ public class ProcessingChain implements IChannelEventListener ((ComplexSource)mSource).removeListener( mComplexBufferBroadcaster ); break; case REAL: - ((RealSource)mSource).removeListener( mRealBufferBroadcaster ); + ((RealSource)mSource).removeListener( mFilteredRealBufferBroadcaster ); break; default: throw new IllegalArgumentException( "Unrecognized source " @@ -585,12 +630,12 @@ public class ProcessingChain implements IChannelEventListener public void addRealBufferListener( Listener listener ) { - mRealBufferBroadcaster.addListener( listener ); + mFilteredRealBufferBroadcaster.addListener( listener ); } public void removeRealBufferListener( Listener listener ) { - mRealBufferBroadcaster.removeListener( listener ); + mFilteredRealBufferBroadcaster.removeListener( listener ); } @Override diff --git a/src/module/decode/AuxDecodeComponentEditor.java b/src/module/decode/AuxDecodeComponentEditor.java index dd55ee59..8e3dc8cb 100644 --- a/src/module/decode/AuxDecodeComponentEditor.java +++ b/src/module/decode/AuxDecodeComponentEditor.java @@ -1,6 +1,6 @@ /******************************************************************************* * SDR Trunk - * Copyright (C) 2014 Dennis Sheirer + * Copyright (C) 2014-2016 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 @@ -26,7 +26,8 @@ import javax.swing.SwingUtilities; import module.decode.config.AuxDecodeConfiguration; import controller.channel.AbstractChannelEditor; -import controller.channel.ChannelNode; +import controller.channel.Channel; +import controller.channel.ConfigurationValidationException; public class AuxDecodeComponentEditor extends AbstractChannelEditor { @@ -35,9 +36,9 @@ public class AuxDecodeComponentEditor extends AbstractChannelEditor private HashMap mControls = new HashMap(); - public AuxDecodeComponentEditor( ChannelNode channelNode ) + public AuxDecodeComponentEditor( Channel channel ) { - super( channelNode ); + super( channel ); List decoders = DecoderType.getAuxDecoders(); @@ -60,7 +61,7 @@ public class AuxDecodeComponentEditor extends AbstractChannelEditor public AuxDecodeConfiguration getConfig() { - return getChannelNode().getChannel().getAuxDecodeConfiguration(); + return getChannel().getAuxDecodeConfiguration(); } @Override @@ -107,4 +108,18 @@ public class AuxDecodeComponentEditor extends AbstractChannelEditor mDecoderType = decoder; } } + + @Override + public void setConfiguration( Channel channel ) + { + // TODO Auto-generated method stub + + } + + @Override + public void validateConfiguration() throws ConfigurationValidationException + { + // TODO Auto-generated method stub + + } } diff --git a/src/module/decode/DecodeComponentEditor.java b/src/module/decode/DecodeComponentEditor.java index bec8de84..bdc48706 100644 --- a/src/module/decode/DecodeComponentEditor.java +++ b/src/module/decode/DecodeComponentEditor.java @@ -1,6 +1,7 @@ /******************************************************************************* + * SDR Trunk - * Copyright (C) 2014 Dennis Sheirer + * Copyright (C) 2014-2016 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 @@ -17,7 +18,6 @@ ******************************************************************************/ package module.decode; - import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -30,11 +30,10 @@ import module.decode.config.DecodeConfigFactory; import module.decode.config.DecodeConfiguration; import net.miginfocom.swing.MigLayout; import playlist.PlaylistManager; -import controller.Editor; import controller.channel.AbstractChannelEditor; import controller.channel.Channel; -import controller.channel.ChannelNode; -import controller.channel.ChannelValidationException; +import controller.channel.ChannelConfigurationEditor; +import controller.channel.ConfigurationValidationException; public class DecodeComponentEditor extends AbstractChannelEditor { @@ -48,13 +47,12 @@ public class DecodeComponentEditor extends AbstractChannelEditor public DecodeComponentEditor( PlaylistManager playlistManager ) { - this( new ChannelNode( new Channel() ), playlistManager ); + this( playlistManager, new Channel() ); } - public DecodeComponentEditor( ChannelNode channelNode, - PlaylistManager playlistMangager ) + public DecodeComponentEditor( PlaylistManager playlistMangager, Channel channel ) { - super( channelNode ); + super( channel ); mPlaylistManager = playlistMangager; @@ -87,17 +85,13 @@ public class DecodeComponentEditor extends AbstractChannelEditor { DecodeConfiguration config; - if( mChannelNode.getChannel() - .getDecodeConfiguration().getDecoderType() == - selected ) + if( mChannel.getDecodeConfiguration().getDecoderType() == selected ) { - config = mChannelNode.getChannel() - .getDecodeConfiguration(); + config = mChannel.getDecodeConfiguration(); } else { - config = DecodeConfigFactory - .getDecodeConfiguration( selected ); + config = DecodeConfigFactory.getDecodeConfiguration( selected ); } //Remove the existing one @@ -108,7 +102,7 @@ public class DecodeComponentEditor extends AbstractChannelEditor //Change to the new one mEditor = DecoderFactory.getEditorPanel( config, - mChannelNode, mPlaylistManager ); + mChannel, mPlaylistManager ); add( mEditor, "span 2,center" ); @@ -125,8 +119,7 @@ public class DecodeComponentEditor extends AbstractChannelEditor public void reset() { - final DecoderType decoder = mChannelNode.getChannel() - .getDecodeConfiguration().getDecoderType(); + final DecoderType decoder = mChannel.getDecodeConfiguration().getDecoderType(); SwingUtilities.invokeLater(new Runnable() { @@ -155,18 +148,31 @@ public class DecodeComponentEditor extends AbstractChannelEditor } //The component that calls save will invoke the change broadcast - mChannelNode.getChannel() - .setDecodeConfiguration( mEditor.getConfig() ); + mChannel.setDecodeConfiguration( mEditor.getConfig() ); } - /** - * Validates the editor against the current decode editor - */ +// /** +// * Validates the editor against the current decode editor +// */ +// @Override +// public void validate( ChannelConfigurationEditor editor ) throws ConfigurationValidationException +// { +// super.validate( editor ); +// +// mEditor.validate( editor ); +// } + @Override - public void validate( Editor editor ) throws ChannelValidationException + public void setConfiguration( Channel channel ) { - super.validate( editor ); + // TODO Auto-generated method stub + + } + + @Override + public void validateConfiguration() throws ConfigurationValidationException + { + // TODO Auto-generated method stub - mEditor.validate( editor ); } } diff --git a/src/module/decode/DecodeEditor.java b/src/module/decode/DecodeEditor.java index dcebf156..cddc6082 100644 --- a/src/module/decode/DecodeEditor.java +++ b/src/module/decode/DecodeEditor.java @@ -31,9 +31,11 @@ import javax.swing.event.ChangeListener; import module.decode.config.DecodeConfiguration; import net.miginfocom.swing.MigLayout; -import controller.Editor; +import controller.channel.Channel; +import controller.channel.ChannelConfigurationEditor; +import controller.channel.ConfigurationValidationException; -public class DecodeEditor extends Editor +public class DecodeEditor extends ChannelConfigurationEditor { private static final long serialVersionUID = 1L; @@ -110,7 +112,16 @@ public class DecodeEditor extends Editor } @Override - public void reset() - { - } + public void setConfiguration( Channel channel ) + { + // TODO Auto-generated method stub + + } + + @Override + public void validateConfiguration() throws ConfigurationValidationException + { + // TODO Auto-generated method stub + + } } diff --git a/src/module/decode/DecoderFactory.java b/src/module/decode/DecoderFactory.java index 2acc06b1..109c0017 100644 --- a/src/module/decode/DecoderFactory.java +++ b/src/module/decode/DecoderFactory.java @@ -63,10 +63,10 @@ import module.decode.nbfm.NBFMDecoder; import module.decode.nbfm.NBFMDecoderPanel; import module.decode.nbfm.NBFMEditor; import module.decode.p25.DecodeConfigP25Phase1; +import module.decode.p25.P25DecodeEditor; import module.decode.p25.P25Decoder.Modulation; import module.decode.p25.P25DecoderPanel; import module.decode.p25.P25DecoderState; -import module.decode.p25.P25DecodeEditor; import module.decode.p25.P25_C4FMDecoder; import module.decode.p25.P25_LSMDecoder; import module.decode.p25.audio.P25AudioModule; @@ -84,6 +84,7 @@ import module.decode.tait.Tait1200Decoder; import module.decode.tait.Tait1200DecoderPanel; import module.decode.tait.Tait1200DecoderState; import module.demodulate.am.AMDemodulatorModule; +import module.demodulate.audio.DemodulatedAudioFilterModule; import module.demodulate.fm.FMDemodulatorModule; import org.slf4j.Logger; @@ -97,12 +98,11 @@ import settings.SettingsManager; import util.TimeStamp; import alias.AliasList; import audio.AudioModule; -import controller.ResourceManager; +import controller.channel.Channel; import controller.channel.Channel.ChannelType; -import controller.channel.ChannelNode; +import controller.channel.ChannelModel; +import controller.channel.ChannelProcessingManager; import controller.channel.map.ChannelMap; -import controller.site.Site; -import controller.system.System; import filter.AllPassFilter; import filter.FilterSet; import filter.IFilter; @@ -120,72 +120,46 @@ public class DecoderFactory * Returns a list of one primary decoder and any auxiliary decoders, as * specified in the configurations. * - * @param channelType - standard or traffic channel type - * @param resourceManager - * @param decodeConfig - primary decoder configuration - * @param recordConfig - recording configuration used by traffic channel manager - * @param auxConfig - auxiliary decoder(s) configuration - * @param optional alias list - (null is ok) - * * @return list of configured decoders */ - public static List getModules( ChannelType channelType, - ResourceManager resourceManager, - DecodeConfiguration decodeConfig, - RecordConfiguration recordConfig, - AuxDecodeConfiguration auxConfig, - AliasList aliasList, - String system, - String site, - String channelName ) + public static List getModules( ChannelModel channelModel, + ChannelProcessingManager channelProcessingManager, + PlaylistManager playlistManager, + Channel channel ) { - List modules = getPrimaryModules( channelType, decodeConfig, - recordConfig, aliasList, system, site, channelName, resourceManager ); - modules.addAll( getAuxiliaryDecoders( auxConfig, aliasList ) ); + /* Get the optional alias list for the decode modules to use */ + AliasList aliasList = playlistManager.getPlayist() + .getAliasDirectory().getAliasList( channel.getAliasListName() ); + + List modules = getPrimaryModules( channelModel, channelProcessingManager, + playlistManager, aliasList, channel ); + + modules.addAll( getAuxiliaryDecoders( channel.getAuxDecodeConfiguration(), aliasList ) ); return modules; } - public static FMDemodulatorModule getFMDemodulator( - DecodeConfiguration config, int pass, int stop, boolean removeDC ) - { - if( config.isAFCEnabled() ) - { - return new FMDemodulatorModule( pass, stop, - config.getAFCMaximumCorrection(), removeDC ); - } - else - { - return new FMDemodulatorModule( pass, stop, - NO_FREQUENCY_CORRECTION, removeDC ); - } - } - /** * Constructs a primary decoder as specified in the decode configuration - * - * @param channelType - traffic or standard decode channel - * @param decodeConfig - primary decoder configuration - * @param recordConfig - recording options - * @param aliasList - optional alias list - * @param resourceManager - shared resource manager - * @return configured decoder or null */ - public static List getPrimaryModules( ChannelType channelType, - DecodeConfiguration decodeConfig, - RecordConfiguration recordConfig, + public static List getPrimaryModules( ChannelModel channelModel, + ChannelProcessingManager channelProcessingManager, + PlaylistManager playlistManager, AliasList aliasList, - String system, - String site, - String channelName, - ResourceManager resourceManager ) + Channel channel ) { List modules = new ArrayList(); + ChannelType channelType = channel.getChannelType(); + /* Baseband low-pass filter pass and stop frequencies */ - int pass = decodeConfig.getDecoderType().getChannelBandwidth() / 2; - int stop = pass + 1250; + DecodeConfiguration decodeConfig = channel.getDecodeConfiguration(); + + int iqPass = decodeConfig.getDecoderType().getChannelBandwidth() / 2; + int iqStop = iqPass + 1250; + + RecordConfiguration recordConfig = channel.getRecordConfiguration(); boolean recordAudio = recordConfig == null ? false : recordConfig.getRecorders().contains( RecorderType.AUDIO ); @@ -193,41 +167,44 @@ public class DecoderFactory switch( decodeConfig.getDecoderType() ) { case AM: - modules.add( new AMDemodulatorModule() ); modules.add( new AMDecoder( decodeConfig ) ); - modules.add( new AlwaysUnsquelchedDecoderState( DecoderType.AM, channelName ) ); - modules.add( new AudioModule( recordAudio, REMOVE_DC ) ); + modules.add( new AlwaysUnsquelchedDecoderState( DecoderType.AM, channel.getName() ) ); + modules.add( new AMDemodulatorModule() ); + modules.add( new DemodulatedAudioFilterModule( 4000, 6000 )); + modules.add( new AudioModule( recordAudio ) ); break; case NBFM: - modules.add( new AudioModule( recordAudio, NO_REMOVE_DC ) ); modules.add( new NBFMDecoder( decodeConfig ) ); - modules.add( new AlwaysUnsquelchedDecoderState( DecoderType.NBFM, channelName ) ); - modules.add( getFMDemodulator( decodeConfig, pass, stop, REMOVE_DC ) ); + modules.add( new AlwaysUnsquelchedDecoderState( DecoderType.NBFM, channel.getName() ) ); + modules.add( new FMDemodulatorModule( iqPass, iqStop ) ); + modules.add( new DemodulatedAudioFilterModule( 4000, 6000 )); + modules.add( new AudioModule( recordAudio ) ); break; case LTR_STANDARD: - modules.add( new AudioModule( recordAudio, REMOVE_DC ) ); MessageDirection direction = ((DecodeConfigLTRStandard)decodeConfig).getMessageDirection(); modules.add( new LTRStandardDecoder( aliasList, direction ) ); modules.add( new LTRStandardDecoderState( aliasList ) ); - modules.add( getFMDemodulator( decodeConfig, pass, stop, NO_REMOVE_DC ) ); + modules.add( new FMDemodulatorModule( iqPass, iqStop ) ); + modules.add( new DemodulatedAudioFilterModule( 4000, 6000 )); + modules.add( new AudioModule( recordAudio ) ); break; case LTR_NET: - modules.add( new AudioModule( recordAudio, REMOVE_DC ) ); modules.add( new LTRNetDecoder( (DecodeConfigLTRNet)decodeConfig, aliasList ) ); modules.add( new LTRNetDecoderState( aliasList ) ); - modules.add( getFMDemodulator( decodeConfig, pass, stop, NO_REMOVE_DC ) ); + modules.add( new FMDemodulatorModule( iqPass, iqStop ) ); + modules.add( new DemodulatedAudioFilterModule( 4000, 6000 )); + modules.add( new AudioModule( recordAudio ) ); break; case MPT1327: DecodeConfigMPT1327 mptConfig = (DecodeConfigMPT1327)decodeConfig; - modules.add( new AudioModule( recordAudio, NO_REMOVE_DC ) ); - - ChannelMap channelMap = resourceManager.getPlaylistManager().getPlayist() + ChannelMap channelMap = playlistManager.getPlayist() .getChannelMapList().getChannelMap( mptConfig.getChannelMapName() ); Sync sync = mptConfig.getSync(); modules.add( new MPT1327Decoder( aliasList, sync ) ); + modules.add( new MPT1327DecoderState( aliasList, channelMap, channelType, mptConfig.getCallTimeout() * 1000 ) ); @@ -235,30 +212,34 @@ public class DecoderFactory { long timeout = mptConfig.getCallTimeout() * 1000; //convert to milliseconds - modules.add( new TrafficChannelManager( resourceManager, - decodeConfig, recordConfig, system, site, - ( aliasList != null ? aliasList.getName() : null ), timeout, + modules.add( new TrafficChannelManager( channelModel, channelProcessingManager, + decodeConfig, recordConfig, channel.getSystem(), + channel.getSite(), ( aliasList != null ? aliasList.getName() : null ), timeout, mptConfig.getTrafficChannelPoolSize() ) ); } - modules.add( getFMDemodulator( decodeConfig, pass, stop, REMOVE_DC ) ); + modules.add( new FMDemodulatorModule( iqPass, iqStop ) ); + modules.add( new DemodulatedAudioFilterModule( 4000, 6000 )); + modules.add( new AudioModule( recordAudio ) ); break; case PASSPORT: - modules.add( new AudioModule( recordAudio, REMOVE_DC ) ); modules.add( new PassportDecoder( decodeConfig, aliasList ) ); modules.add( new PassportDecoderState( aliasList ) ); - modules.add( getFMDemodulator( decodeConfig, pass, stop, NO_REMOVE_DC ) ); + modules.add( new FMDemodulatorModule( iqPass, iqStop ) ); + modules.add( new DemodulatedAudioFilterModule( 4000, 6000 )); + modules.add( new AudioModule( recordAudio ) ); break; case P25_PHASE1: DecodeConfigP25Phase1 p25Config = (DecodeConfigP25Phase1)decodeConfig; Modulation modulation = p25Config.getModulation(); + switch( modulation ) { case C4FM: - modules.add( getFMDemodulator( decodeConfig, 6750, 7500, NO_REMOVE_DC ) ); - modules.add( new P25_C4FMDecoder( aliasList ) ); + modules.add( new FMDemodulatorModule( 6750, 7500 ) ); + modules.add( new P25_C4FMDecoder( aliasList, decodeConfig.getAFCMaximumCorrection() ) ); modules.add( new P25DecoderState( aliasList, channelType, Modulation.C4FM, p25Config.getIgnoreDataCalls() ) ); break; @@ -277,8 +258,9 @@ public class DecoderFactory //Set call timeout to 3 seconds for P25 traffic channels long timeout = 3000; - modules.add( new TrafficChannelManager( resourceManager, - decodeConfig, recordConfig, system, site, + modules.add( new TrafficChannelManager( channelModel, + channelProcessingManager, decodeConfig, + recordConfig, channel.getSystem(), channel.getSite(), ( aliasList != null ? aliasList.getName() : null ), timeout, p25Config.getTrafficChannelPoolSize() ) ); } @@ -449,7 +431,7 @@ public class DecoderFactory } public static DecodeEditor getEditorPanel( DecodeConfiguration config, - ChannelNode channelNode, PlaylistManager playlistManager ) + Channel channel, PlaylistManager playlistManager ) { DecodeEditor configuredPanel; @@ -466,7 +448,7 @@ public class DecoderFactory break; case MPT1327: configuredPanel = new MPT1327ConfigEditor( config, - channelNode, playlistManager ); + channel, playlistManager ); break; case PASSPORT: configuredPanel = new PassportEditor( config ); diff --git a/src/module/decode/event/CallEventPanel.java b/src/module/decode/event/CallEventPanel.java index c9ac7ac0..48d8ce34 100644 --- a/src/module/decode/event/CallEventPanel.java +++ b/src/module/decode/event/CallEventPanel.java @@ -23,12 +23,14 @@ import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; +import module.ProcessingChain; import net.miginfocom.swing.MigLayout; import settings.SettingsManager; import controller.channel.Channel; import controller.channel.ChannelEvent; import controller.channel.ChannelEvent.Event; import controller.channel.ChannelEventListener; +import controller.channel.ChannelProcessingManager; public class CallEventPanel extends JPanel implements ChannelEventListener { @@ -37,9 +39,13 @@ public class CallEventPanel extends JPanel implements ChannelEventListener private JScrollPane mEmptyScroller; private Channel mDisplayedChannel; private CallEventAliasCellRenderer mRenderer; + private ChannelProcessingManager mChannelProcessingManager; - public CallEventPanel( SettingsManager settingsManager ) + public CallEventPanel( SettingsManager settingsManager, + ChannelProcessingManager channelProcessingManager ) { + mChannelProcessingManager = channelProcessingManager; + setLayout( new MigLayout("insets 0 0 0 0 ", "[grow,fill]", "[grow,fill]") ); JTable table = new JTable( new CallEventModel() ); @@ -69,34 +75,43 @@ public class CallEventPanel extends JPanel implements ChannelEventListener ( mDisplayedChannel != null && mDisplayedChannel != event.getChannel() ) ) { - EventQueue.invokeLater( new Runnable() - { - @Override - public void run() - { - removeAll(); - - JTable table = new JTable( - event.getChannel().getCallEventModel() ); - - table.setAutoCreateRowSorter( true ); - table.setAutoResizeMode( JTable.AUTO_RESIZE_LAST_COLUMN ); - - table.getColumnModel().getColumn( CallEventModel.FROM_ALIAS ) - .setCellRenderer( mRenderer ); - - table.getColumnModel().getColumn( CallEventModel.TO_ALIAS ) - .setCellRenderer( mRenderer ); - - add( new JScrollPane( table ) ); - - mDisplayedChannel = event.getChannel(); - - revalidate(); - repaint(); - } - } ); + ProcessingChain chain = mChannelProcessingManager + .getProcessingChain( event.getChannel() ); + if( chain != null ) + { + final CallEventModel model = chain.getCallEventModel(); + + if( model != null ) + { + EventQueue.invokeLater( new Runnable() + { + @Override + public void run() + { + removeAll(); + + JTable table = new JTable( model ); + + table.setAutoCreateRowSorter( true ); + table.setAutoResizeMode( JTable.AUTO_RESIZE_LAST_COLUMN ); + + table.getColumnModel().getColumn( CallEventModel.FROM_ALIAS ) + .setCellRenderer( mRenderer ); + + table.getColumnModel().getColumn( CallEventModel.TO_ALIAS ) + .setCellRenderer( mRenderer ); + + add( new JScrollPane( table ) ); + + mDisplayedChannel = event.getChannel(); + + revalidate(); + repaint(); + } + } ); + } + } } } else if( event.getEvent() == Event.NOTIFICATION_PROCESSING_STOP || diff --git a/src/module/decode/event/MessageActivityPanel.java b/src/module/decode/event/MessageActivityPanel.java index 9f84d619..6cc4ac71 100644 --- a/src/module/decode/event/MessageActivityPanel.java +++ b/src/module/decode/event/MessageActivityPanel.java @@ -36,6 +36,7 @@ import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import message.Message; +import module.ProcessingChain; import net.miginfocom.swing.MigLayout; import org.slf4j.Logger; @@ -48,6 +49,7 @@ import controller.channel.Channel; import controller.channel.ChannelEvent; import controller.channel.ChannelEvent.Event; import controller.channel.ChannelEventListener; +import controller.channel.ChannelProcessingManager; import filter.FilterEditorPanel; import filter.FilterSet; @@ -63,16 +65,21 @@ public class MessageActivityPanel extends JPanel implements ChannelEventListener private JTable mMessageTable; private Channel mDisplayedChannel; + private MessageActivityModel mDisplayedModel = EMPTY_MODEL; private MessageManagementPanel mManagementPanel = new MessageManagementPanel(); + + private ChannelProcessingManager mChannelProcessingManager; - public MessageActivityPanel() + public MessageActivityPanel( ChannelProcessingManager channelProcessingManager ) { + mChannelProcessingManager = channelProcessingManager; + setLayout( new MigLayout("insets 0 0 0 0", "[][grow,fill]", "[]0[grow,fill]") ); add( mManagementPanel, "span,growx" ); - mMessageTable = new JTable( EMPTY_MODEL ); + mMessageTable = new JTable( mDisplayedModel ); add( new JScrollPane( mMessageTable ), "span,grow" ); } @@ -91,7 +98,19 @@ public class MessageActivityPanel extends JPanel implements ChannelEventListener { mDisplayedChannel = event.getChannel(); - mMessageTable.setModel( event.getChannel().getMessageActivityModel() ); + ProcessingChain chain = mChannelProcessingManager + .getProcessingChain( mDisplayedChannel ); + + if( chain != null ) + { + mDisplayedModel = chain.getMessageActivityModel(); + } + else + { + mDisplayedModel = EMPTY_MODEL; + } + + mMessageTable.setModel( mDisplayedModel ); if( mDisplayedChannel != null ) { @@ -195,10 +214,9 @@ public class MessageActivityPanel extends JPanel implements ChannelEventListener public void mouseReleased( MouseEvent arg0 ) {} } ); - if( mDisplayedChannel != null ) + if( mDisplayedModel != null ) { - slider.setValue( mDisplayedChannel.getMessageActivityModel() - .getMaxMessageCount() ); + slider.setValue( mDisplayedModel.getMaxMessageCount() ); } else { @@ -210,10 +228,9 @@ public class MessageActivityPanel extends JPanel implements ChannelEventListener @Override public void stateChanged( ChangeEvent arg0 ) { - if( mDisplayedChannel != null ) + if( mDisplayedModel != null ) { - mDisplayedChannel.getMessageActivityModel() - .setMaxMessageCount( slider.getValue() ); + mDisplayedModel.setMaxMessageCount( slider.getValue() ); } } }); @@ -228,9 +245,9 @@ public class MessageActivityPanel extends JPanel implements ChannelEventListener @Override public void actionPerformed( ActionEvent e ) { - if( mDisplayedChannel != null ) + if( mDisplayedModel != null ) { - mDisplayedChannel.getMessageActivityModel().clear(); + mDisplayedModel.clear(); } } } ); @@ -258,50 +275,52 @@ public class MessageActivityPanel extends JPanel implements ChannelEventListener } else { - final JFrame editor = new JFrame(); - - editor.setTitle( "Message Filter Editor" ); - editor.setSize( 600, 400 ); - editor.setLocationRelativeTo( MessageFilterButton.this ); - editor.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE ); - editor.setLayout( new MigLayout( "", "[grow,fill]", - "[grow,fill][][]" ) ); - - @SuppressWarnings( "unchecked" ) - FilterSet filter = (FilterSet) - mDisplayedChannel.getMessageActivityModel() - .getMessageFilter(); - - FilterEditorPanel panel = - new FilterEditorPanel( filter ); - - JScrollPane scroller = new JScrollPane( panel ); - scroller.setViewportView( panel ); - - editor.add( scroller, "wrap" ); - - editor.add( new JLabel( "Right-click to select/deselect " - + "all nodes" ), "wrap" ); - - JButton close = new JButton( "Close" ); - close.addActionListener( new ActionListener() + if( mDisplayedModel != null ) { - @Override - public void actionPerformed( ActionEvent e ) - { - editor.dispose(); - } - } ); - - editor.add( close ); + final JFrame editor = new JFrame(); + + editor.setTitle( "Message Filter Editor" ); + editor.setSize( 600, 400 ); + editor.setLocationRelativeTo( MessageFilterButton.this ); + editor.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE ); + editor.setLayout( new MigLayout( "", "[grow,fill]", + "[grow,fill][][]" ) ); - EventQueue.invokeLater( new Runnable() - { - public void run() - { - editor.setVisible( true ); - } - } ); + @SuppressWarnings( "unchecked" ) + FilterSet filter = (FilterSet) + mDisplayedModel.getMessageFilter(); + + FilterEditorPanel panel = + new FilterEditorPanel( filter ); + + JScrollPane scroller = new JScrollPane( panel ); + scroller.setViewportView( panel ); + + editor.add( scroller, "wrap" ); + + editor.add( new JLabel( "Right-click to select/deselect " + + "all nodes" ), "wrap" ); + + JButton close = new JButton( "Close" ); + close.addActionListener( new ActionListener() + { + @Override + public void actionPerformed( ActionEvent e ) + { + editor.dispose(); + } + } ); + + editor.add( close ); + + EventQueue.invokeLater( new Runnable() + { + public void run() + { + editor.setVisible( true ); + } + } ); + } } } } ); diff --git a/src/module/decode/fleetsync2/Fleetsync2Decoder.java b/src/module/decode/fleetsync2/Fleetsync2Decoder.java index 1425983a..f8092472 100644 --- a/src/module/decode/fleetsync2/Fleetsync2Decoder.java +++ b/src/module/decode/fleetsync2/Fleetsync2Decoder.java @@ -29,7 +29,7 @@ import java.util.List; import module.decode.Decoder; import module.decode.DecoderType; import sample.Listener; -import sample.real.IRealBufferListener; +import sample.real.IFilteredRealBufferListener; import sample.real.RealBuffer; import alias.AliasList; import bits.MessageFramer; @@ -44,7 +44,7 @@ import dsp.fsk.FSK2Decoder.Output; * Fleetsync II Decoder - 1200 baud 2FSK decoder that can process 48k sample rate * floating point samples and output fully framed Fleetsync II messages */ -public class Fleetsync2Decoder extends Decoder implements IRealBufferListener, +public class Fleetsync2Decoder extends Decoder implements IFilteredRealBufferListener, Instrumentable { /* Decimated sample rate ( 48,000 / 2 = 24,000 ) feeding the decoder */ @@ -169,7 +169,7 @@ public class Fleetsync2Decoder extends Decoder implements IRealBufferListener, } @Override - public Listener getRealBufferListener() + public Listener getFilteredRealBufferListener() { return mDecimationFilter; } diff --git a/src/module/decode/lj1200/LJ1200Decoder.java b/src/module/decode/lj1200/LJ1200Decoder.java index 57297d57..1e20eeda 100644 --- a/src/module/decode/lj1200/LJ1200Decoder.java +++ b/src/module/decode/lj1200/LJ1200Decoder.java @@ -31,7 +31,7 @@ import module.decode.Decoder; import module.decode.DecoderType; import sample.Broadcaster; import sample.Listener; -import sample.real.IRealBufferListener; +import sample.real.IFilteredRealBufferListener; import sample.real.RealBuffer; import sample.real.RealSampleListener; import alias.AliasList; @@ -46,7 +46,7 @@ import dsp.fsk.FSK2Decoder.Output; /** * LJ1200 - 1200 baud 2FSK decoder */ -public class LJ1200Decoder extends Decoder implements IRealBufferListener, +public class LJ1200Decoder extends Decoder implements IFilteredRealBufferListener, Instrumentable { /* Decimated sample rate ( 48,000 / 2 = 24,000 ) feeding the decoder */ @@ -187,7 +187,7 @@ public class LJ1200Decoder extends Decoder implements IRealBufferListener, } @Override - public Listener getRealBufferListener() + public Listener getFilteredRealBufferListener() { return mDecimationFilter; } diff --git a/src/module/decode/ltrnet/LTRNetDecoder.java b/src/module/decode/ltrnet/LTRNetDecoder.java index 095dffe4..f5c1d3ca 100644 --- a/src/module/decode/ltrnet/LTRNetDecoder.java +++ b/src/module/decode/ltrnet/LTRNetDecoder.java @@ -28,14 +28,15 @@ import message.MessageDirection; import module.decode.Decoder; import module.decode.DecoderType; import sample.Listener; -import sample.real.IRealBufferListener; +import sample.real.IUnFilteredRealBufferListener; import sample.real.RealBuffer; import alias.AliasList; import bits.MessageFramer; import bits.SyncPattern; import dsp.fsk.LTRFSKDecoder; -public class LTRNetDecoder extends Decoder implements IRealBufferListener, Instrumentable +public class LTRNetDecoder extends Decoder + implements IUnFilteredRealBufferListener, Instrumentable { public static final int LTR_STANDARD_MESSAGE_LENGTH = 40; private LTRFSKDecoder mLTRFSKDecoder; @@ -44,6 +45,10 @@ public class LTRNetDecoder extends Decoder implements IRealBufferListener, Instr private List mAvailableTaps; + /** + * LTR-Net Decoder. Decodes unfiltered (e.g. demodulated but with no DC or + * audio filtering) samples and produces LTR-Net messages. + */ public LTRNetDecoder( DecodeConfigLTRNet config, AliasList aliasList ) { mLTRFSKDecoder = new LTRFSKDecoder(); @@ -79,7 +84,7 @@ public class LTRNetDecoder extends Decoder implements IRealBufferListener, Instr } @Override - public Listener getRealBufferListener() + public Listener getUnFilteredRealBufferListener() { return mLTRFSKDecoder; } diff --git a/src/module/decode/ltrstandard/LTRStandardDecoder.java b/src/module/decode/ltrstandard/LTRStandardDecoder.java index a39d659c..228d68f5 100644 --- a/src/module/decode/ltrstandard/LTRStandardDecoder.java +++ b/src/module/decode/ltrstandard/LTRStandardDecoder.java @@ -21,14 +21,14 @@ import message.MessageDirection; import module.decode.Decoder; import module.decode.DecoderType; import sample.Listener; -import sample.real.IRealBufferListener; +import sample.real.IUnFilteredRealBufferListener; import sample.real.RealBuffer; import alias.AliasList; import bits.MessageFramer; import bits.SyncPattern; import dsp.fsk.LTRFSKDecoder; -public class LTRStandardDecoder extends Decoder implements IRealBufferListener +public class LTRStandardDecoder extends Decoder implements IUnFilteredRealBufferListener { public static final int LTR_STANDARD_MESSAGE_LENGTH = 40; @@ -36,6 +36,10 @@ public class LTRStandardDecoder extends Decoder implements IRealBufferListener private MessageFramer mLTRMessageFramer; private LTRStandardMessageProcessor mLTRMessageProcessor; + /** + * LTR Decoder. Decodes unfiltered (e.g. demodulated but with no DC or + * audio filtering) samples and produces LTR Standard messages. + */ public LTRStandardDecoder( AliasList aliasList, MessageDirection direction ) { @@ -68,7 +72,7 @@ public class LTRStandardDecoder extends Decoder implements IRealBufferListener } @Override - public Listener getRealBufferListener() + public Listener getUnFilteredRealBufferListener() { return mLTRFSKDecoder; } diff --git a/src/module/decode/mdc1200/MDCDecoder.java b/src/module/decode/mdc1200/MDCDecoder.java index 86289146..7e973af2 100644 --- a/src/module/decode/mdc1200/MDCDecoder.java +++ b/src/module/decode/mdc1200/MDCDecoder.java @@ -30,7 +30,7 @@ import java.util.List; import module.decode.Decoder; import module.decode.DecoderType; import sample.Listener; -import sample.real.IRealBufferListener; +import sample.real.IFilteredRealBufferListener; import sample.real.RealBuffer; import alias.AliasList; import bits.MessageFramer; @@ -46,7 +46,7 @@ import dsp.fsk.FSK2Decoder.Output; * MDC1200 Decoder - 1200 baud 2FSK decoder that can process 48k sample rate * complex or floating point samples and output fully framed MDC1200 messages */ -public class MDCDecoder extends Decoder implements IRealBufferListener, +public class MDCDecoder extends Decoder implements IFilteredRealBufferListener, Instrumentable { /* Decimated sample rate ( 48,000 / 2 = 24,000 ) feeding the decoder */ @@ -197,7 +197,7 @@ public class MDCDecoder extends Decoder implements IRealBufferListener, } @Override - public Listener getRealBufferListener() + public Listener getFilteredRealBufferListener() { return mDecimationFilter; } diff --git a/src/module/decode/mpt1327/MPT1327ConfigEditor.java b/src/module/decode/mpt1327/MPT1327ConfigEditor.java index 01c2af35..fa036c96 100644 --- a/src/module/decode/mpt1327/MPT1327ConfigEditor.java +++ b/src/module/decode/mpt1327/MPT1327ConfigEditor.java @@ -31,7 +31,7 @@ import module.decode.DecodeEditor; import module.decode.config.DecodeConfiguration; import module.decode.mpt1327.MPT1327Decoder.Sync; import playlist.PlaylistManager; -import controller.channel.ChannelNode; +import controller.channel.Channel; import controller.channel.map.ChannelMap; public class MPT1327ConfigEditor extends DecodeEditor @@ -44,16 +44,16 @@ public class MPT1327ConfigEditor extends DecodeEditor private JSlider mCallTimeout; private JLabel mTrafficChannelPoolSizeLabel; private JSlider mTrafficChannelPoolSize; - private ChannelNode mChannelNode; + private Channel mChannel; private PlaylistManager mPlaylistManager; public MPT1327ConfigEditor( DecodeConfiguration config, - ChannelNode channelNode, + Channel channel, PlaylistManager playlistManager ) { super( config ); - mChannelNode = channelNode; + mChannel = channel; mPlaylistManager = playlistManager; initGUI(); @@ -140,7 +140,7 @@ public class MPT1327ConfigEditor extends DecodeEditor add( mTrafficChannelPoolSizeLabel ); add( mTrafficChannelPoolSize, "wrap,grow" ); - reset(); +// reset(); } @Override @@ -167,36 +167,35 @@ public class MPT1327ConfigEditor extends DecodeEditor config.setTrafficChannelPoolSize( mTrafficChannelPoolSize.getValue() ); } - @Override - public void reset() - { - DecodeConfigMPT1327 config = (DecodeConfigMPT1327)mConfig; - - String name = config.getChannelMapName(); - - ChannelMap selected = null; - - if( name != null ) - { - for( ChannelMap map: mChannelNode.getModel().getResourceManager() - .getPlaylistManager().getPlayist().getChannelMapList() - .getChannelMap() ) - { - if( map.getName().equalsIgnoreCase( name ) ) - { - selected = map; - } - } - } - - mComboChannelMaps.setSelectedItem( selected ); - mComboChannelMaps.requestFocus(); - mComboChannelMaps.requestFocusInWindow(); - - mComboSync.setSelectedItem( config.getSync() ); - - mCallTimeout.setValue( config.getCallTimeout() ); - - mTrafficChannelPoolSize.setValue( config.getTrafficChannelPoolSize() ); - } +// @Override +// public void reset() +// { +// DecodeConfigMPT1327 config = (DecodeConfigMPT1327)mConfig; +// +// String name = config.getChannelMapName(); +// +// ChannelMap selected = null; +// +// if( name != null ) +// { +// for( ChannelMap map: mPlaylistManager.getPlayist().getChannelMapList() +// .getChannelMap() ) +// { +// if( map.getName().equalsIgnoreCase( name ) ) +// { +// selected = map; +// } +// } +// } +// +// mComboChannelMaps.setSelectedItem( selected ); +// mComboChannelMaps.requestFocus(); +// mComboChannelMaps.requestFocusInWindow(); +// +// mComboSync.setSelectedItem( config.getSync() ); +// +// mCallTimeout.setValue( config.getCallTimeout() ); +// +// mTrafficChannelPoolSize.setValue( config.getTrafficChannelPoolSize() ); +// } } diff --git a/src/module/decode/mpt1327/MPT1327Decoder.java b/src/module/decode/mpt1327/MPT1327Decoder.java index 679da857..799fd5a0 100644 --- a/src/module/decode/mpt1327/MPT1327Decoder.java +++ b/src/module/decode/mpt1327/MPT1327Decoder.java @@ -35,7 +35,7 @@ import org.slf4j.LoggerFactory; import sample.Broadcaster; import sample.Listener; -import sample.real.IRealBufferListener; +import sample.real.IFilteredRealBufferListener; import sample.real.RealBuffer; import alias.AliasList; import bits.MessageFramer; @@ -55,7 +55,7 @@ import dsp.fsk.FSK2Decoder.Output; * traffic messages. */ public class MPT1327Decoder extends Decoder - implements IRealBufferListener, Instrumentable + implements IFilteredRealBufferListener, Instrumentable { private final static Logger mLog = LoggerFactory.getLogger( MPT1327Decoder.class ); @@ -146,7 +146,7 @@ public class MPT1327Decoder extends Decoder } @Override - public Listener getRealBufferListener() + public Listener getFilteredRealBufferListener() { return mDecimationFilter; } diff --git a/src/module/decode/p25/C4FMSymbolFilter.java b/src/module/decode/p25/C4FMSymbolFilter.java index 0c88b18a..651f2c60 100644 --- a/src/module/decode/p25/C4FMSymbolFilter.java +++ b/src/module/decode/p25/C4FMSymbolFilter.java @@ -16,12 +16,13 @@ import sample.Listener; import sample.real.RealBuffer; import sample.real.RealSampleListener; import sample.real.RealSampleProvider; -import source.tuner.frequency.FrequencyCorrectionControl; -import source.tuner.frequency.FrequencyCorrectionControl.FrequencyCorrectionResetListener; +import source.tuner.frequency.FrequencyChangeEvent; +import source.tuner.frequency.FrequencyChangeEvent.Event; +import source.tuner.frequency.IFrequencyChangeListener; import dsp.gain.DirectGainControl; -public class C4FMSymbolFilter implements FrequencyCorrectionResetListener, - Listener, +public class C4FMSymbolFilter implements Listener, + IFrequencyChangeListener, RealSampleProvider, Instrumentable { @@ -201,15 +202,17 @@ public class C4FMSymbolFilter implements FrequencyCorrectionResetListener, private float mHistory[] = new float[ NUMBER_FILTER_TAPS ]; private int mHistoryLast = 0; - private boolean mResetFrequencyTracker = false; - private RealSampleListener mListener; private DirectGainControl mGainController = new DirectGainControl( 15.0f, 0.1f, 35.0f, 0.3f ); - private FrequencyCorrectionControl mFrequencyCorrectionControl; private int mFrequencyAdjustmentRequested = 0; + private int mFrequencyCorrection = 0; + private int mFrequencyCorrectionMaximum = 3000; + private boolean mResetFrequencyTracker = false; + private FrequencyCorrectionProcessor mFrequencyCorrectionProcessor; + private Listener mFrequencyChangeListener; /** * C4FM Symbol Filter @@ -224,18 +227,15 @@ public class C4FMSymbolFilter implements FrequencyCorrectionResetListener, * setting for this filter is 15.4 and that yields a symbol spread that * is centered on 2.0, ranging 1.92 to 2.08. */ - public C4FMSymbolFilter( FrequencyCorrectionControl frequencyControl ) + public C4FMSymbolFilter( int frequencyCorrectionMaximum ) { - mFrequencyCorrectionControl = frequencyControl; - - /* Register for reset events, so we can reset internal frequency tracking */ - mFrequencyCorrectionControl.setListener( this ); + mFrequencyCorrectionMaximum = frequencyCorrectionMaximum; } public void dispose() { mGainController = null; - mFrequencyCorrectionControl = null; +// mFrequencyCorrectionControl = null; mListener = null; } @@ -253,13 +253,21 @@ public class C4FMSymbolFilter implements FrequencyCorrectionResetListener, * the internal frequency correction tracker */ if( mFrequencyAdjustmentRequested != 0 ) { - mFrequencyCorrectionControl.adjust( mFrequencyAdjustmentRequested ); + int correction = mFrequencyCorrection + mFrequencyAdjustmentRequested; + + if( correction > mFrequencyCorrectionMaximum ) + { + correction = mFrequencyCorrectionMaximum; + } + else if( correction < -mFrequencyCorrectionMaximum ) + { + correction = -mFrequencyCorrectionMaximum; + } + + broadcast( new FrequencyChangeEvent( + Event.REQUEST_CHANNEL_FREQUENCY_CORRECTION_CHANGE, correction ) ); mFrequencyAdjustmentRequested = 0; - - //Reset internal frequency tracking - mCoarseFrequencyCorrection = 0.0f; - mFineFrequencyCorrection = 0.0f; } } @@ -272,7 +280,8 @@ public class C4FMSymbolFilter implements FrequencyCorrectionResetListener, mCoarseFrequencyCorrection = 0.0f; mFineFrequencyCorrection = 0.0f; - mFrequencyCorrectionControl.setFrequencyCorrection( 0 ); + broadcast( new FrequencyChangeEvent( + Event.REQUEST_CHANNEL_FREQUENCY_CORRECTION_CHANGE, 0 )); mResetFrequencyTracker = false; } @@ -397,17 +406,6 @@ public class C4FMSymbolFilter implements FrequencyCorrectionResetListener, } } - /** - * Listener interface for frequency correction reset events. We reset the - * coarse and fine frequency control values when the tuner channel source - * has changed frequency (PPM) or sample rate - */ - @Override - public void resetFrequencyCorrection() - { - mResetFrequencyTracker = true; - } - @Override public void setListener( RealSampleListener listener ) { @@ -459,4 +457,56 @@ public class C4FMSymbolFilter implements FrequencyCorrectionResetListener, mSymbolSpreadTap = null; } } + + public void broadcast( FrequencyChangeEvent event ) + { + if( mFrequencyChangeListener != null ) + { + mFrequencyChangeListener.receive( event ); + } + } + + public void setFrequencyChangeListener( Listener listener ) + { + mFrequencyChangeListener = listener; + } + + @Override + public Listener getFrequencyChangeListener() + { + if( mFrequencyCorrectionProcessor == null ) + { + mFrequencyCorrectionProcessor = new FrequencyCorrectionProcessor(); + } + + return mFrequencyCorrectionProcessor; + } + + /** + * Receives notifications that the channel frequency correction has been + * applied and updates internal tracking value. + */ + public class FrequencyCorrectionProcessor implements Listener + { + @Override + public void receive( FrequencyChangeEvent event ) + { + switch( event.getEvent() ) + { + case NOTIFICATION_CHANNEL_FREQUENCY_CORRECTION_CHANGE: + mFrequencyCorrection = event.getValue().intValue(); + + //Reset internal frequency tracking + mCoarseFrequencyCorrection = 0.0f; + mFineFrequencyCorrection = 0.0f; + break; + case NOTIFICATION_FREQUENCY_CORRECTION_CHANGE: + case NOTIFICATION_SAMPLE_RATE_CHANGE: + mResetFrequencyTracker = true; + break; + default: + break; + } + } + } } diff --git a/src/module/decode/p25/P25DecodeEditor.java b/src/module/decode/p25/P25DecodeEditor.java index e3c7052d..c87d1e7c 100644 --- a/src/module/decode/p25/P25DecodeEditor.java +++ b/src/module/decode/p25/P25DecodeEditor.java @@ -34,8 +34,8 @@ import org.slf4j.LoggerFactory; import source.SourceEditor; import source.tuner.TunerEditor; -import controller.Editor; -import controller.channel.ChannelValidationException; +import controller.channel.ChannelConfigurationEditor; +import controller.channel.ConfigurationValidationException; public class P25DecodeEditor extends DecodeEditor { @@ -101,29 +101,29 @@ public class P25DecodeEditor extends DecodeEditor add( new JLabel( "Ignore Data Calls" ) ); add( mIgnoreDataCalls, "wrap,grow" ); - reset(); +// reset(); } - /** - * Enforce source=tuner for CQPSK modulation - */ - @Override - public void validate( Editor editor ) throws ChannelValidationException - { - if( editor instanceof SourceEditor && - ((DecodeConfigP25Phase1)mConfig).getModulation() == Modulation.CQPSK ) - { - if( !( editor instanceof TunerEditor ) ) - { - throw new ChannelValidationException( - "

LSM Simulcast

" - + "

P25 LSM Simulcast decoder can only be used with " - + "a tuner source. Please change the Source to use a tuner" - + " or change the P25 Decoder to C4FM modulation" ); - - } - } - } +// /** +// * Enforce source=tuner for CQPSK modulation +// */ +// @Override +// public void validate( ChannelConfigurationEditor editor ) throws ConfigurationValidationException +// { +// if( editor instanceof SourceEditor && +// ((DecodeConfigP25Phase1)mConfig).getModulation() == Modulation.CQPSK ) +// { +// if( !( editor instanceof TunerEditor ) ) +// { +// throw new ConfigurationValidationException( +// "

LSM Simulcast

" +// + "

P25 LSM Simulcast decoder can only be used with " +// + "a tuner source. Please change the Source to use a tuner" +// + " or change the P25 Decoder to C4FM modulation" ); +// +// } +// } +// } @Override public void save() @@ -135,13 +135,13 @@ public class P25DecodeEditor extends DecodeEditor config.setTrafficChannelPoolSize( mTrafficChannelPoolSize.getValue() ); } - @Override - public void reset() - { - DecodeConfigP25Phase1 config = (DecodeConfigP25Phase1)mConfig; - - mComboModulation.setSelectedItem( config.getModulation() ); - mIgnoreDataCalls.setSelected( config.getIgnoreDataCalls() ); - mTrafficChannelPoolSize.setValue( config.getTrafficChannelPoolSize() ); - } +// @Override +// public void reset() +// { +// DecodeConfigP25Phase1 config = (DecodeConfigP25Phase1)mConfig; +// +// mComboModulation.setSelectedItem( config.getModulation() ); +// mIgnoreDataCalls.setSelected( config.getIgnoreDataCalls() ); +// mTrafficChannelPoolSize.setValue( config.getTrafficChannelPoolSize() ); +// } } diff --git a/src/module/decode/p25/P25Decoder.java b/src/module/decode/p25/P25Decoder.java index 674b00b9..ca46e81b 100644 --- a/src/module/decode/p25/P25Decoder.java +++ b/src/module/decode/p25/P25Decoder.java @@ -3,11 +3,9 @@ package module.decode.p25; import instrument.Instrumentable; import module.decode.Decoder; import module.decode.DecoderType; -import source.tuner.frequency.IFrequencyCorrectionController; import alias.AliasList; -public abstract class P25Decoder extends Decoder - implements IFrequencyCorrectionController, Instrumentable +public abstract class P25Decoder extends Decoder implements Instrumentable { private P25MessageProcessor mMessageProcessor; diff --git a/src/module/decode/p25/P25_C4FMDecoder.java b/src/module/decode/p25/P25_C4FMDecoder.java index c4fabf0a..3bae443d 100644 --- a/src/module/decode/p25/P25_C4FMDecoder.java +++ b/src/module/decode/p25/P25_C4FMDecoder.java @@ -24,22 +24,24 @@ import instrument.tap.stream.FloatBufferTap; import instrument.tap.stream.FloatTap; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import sample.Listener; -import sample.real.IRealBufferListener; +import sample.real.IFilteredRealBufferListener; import sample.real.RealBuffer; -import source.tuner.frequency.FrequencyCorrectionControl; +import source.tuner.frequency.FrequencyChangeEvent; +import source.tuner.frequency.IFrequencyChangeListener; +import source.tuner.frequency.IFrequencyChangeProvider; import alias.AliasList; import dsp.filter.FilterFactory; import dsp.filter.Window.WindowType; import dsp.filter.fir.real.RealFIRFilter_RB_RB; -public class P25_C4FMDecoder extends P25Decoder implements IRealBufferListener +public class P25_C4FMDecoder extends P25Decoder + implements IFrequencyChangeListener, IFrequencyChangeProvider,IFilteredRealBufferListener { private final static Logger mLog = LoggerFactory.getLogger( P25_C4FMDecoder.class ); @@ -48,11 +50,8 @@ public class P25_C4FMDecoder extends P25Decoder implements IRealBufferListener private static final String INSTRUMENT_C4FM_SYMBOL_FILTER_OUTPUT = "Tap Point: Symbol Filter Output"; private static final String INSTRUMENT_C4FM_SLICER_OUTPUT = "Tap Point: C4FM Slicer Output"; - private final static int MAXIMUM_FREQUENCY_CORRECTION = 3000; //Hertz, +/- - private List mAvailableTaps; private RealFIRFilter_RB_RB mC4FMPreFilter; - private FrequencyCorrectionControl mFrequencyCorrectionControl; private C4FMSymbolFilter mSymbolFilter; private C4FMSlicer mC4FMSlicer; private P25MessageFramer mMessageFramer; @@ -70,23 +69,18 @@ public class P25_C4FMDecoder extends P25Decoder implements IRealBufferListener * infrastructure and subscriber identities that will be included in each * decoded message */ - public P25_C4FMDecoder( AliasList aliasList ) + public P25_C4FMDecoder( AliasList aliasList, int frequencyCorrectionMaximum ) { super( aliasList ); /* Filter demodulated sample buffers */ float[] filter = FilterFactory.getLowPass( 48000, 2500, 4000, 80, WindowType.HANNING, true ); - mLog.debug( "Demod Filter tap count:" + filter.length + " coefficients:" + Arrays.toString( filter ) ); +// mLog.debug( "Demod Filter tap count:" + filter.length + " coefficients:" + Arrays.toString( filter ) ); mC4FMPreFilter = new RealFIRFilter_RB_RB( filter, 1.0f ); - /* Issue tuned frequency correction commands, remotely controlled by the - * downstream symbol filter */ - mFrequencyCorrectionControl = new FrequencyCorrectionControl( - MAXIMUM_FREQUENCY_CORRECTION ); - /* Shape gain and frequency offsets to optimize sample stream */ - mSymbolFilter = new C4FMSymbolFilter( mFrequencyCorrectionControl ); + mSymbolFilter = new C4FMSymbolFilter( frequencyCorrectionMaximum ); mC4FMPreFilter.setListener( mSymbolFilter ); /* Convert samples to symbols */ @@ -109,9 +103,6 @@ public class P25_C4FMDecoder extends P25Decoder implements IRealBufferListener mC4FMPreFilter.dispose(); mC4FMPreFilter = null; - mFrequencyCorrectionControl.dispose(); - mFrequencyCorrectionControl = null; - mSymbolFilter.dispose(); mSymbolFilter = null; @@ -128,19 +119,7 @@ public class P25_C4FMDecoder extends P25Decoder implements IRealBufferListener } @Override - public boolean hasFrequencyCorrectionControl() - { - return mFrequencyCorrectionControl != null; - } - - @Override - public FrequencyCorrectionControl getFrequencyCorrectionControl() - { - return mFrequencyCorrectionControl; - } - - @Override - public Listener getRealBufferListener() + public Listener getFilteredRealBufferListener() { return mC4FMPreFilter; } @@ -262,4 +241,33 @@ public class P25_C4FMDecoder extends P25Decoder implements IRealBufferListener // TODO Auto-generated method stub } + + @Override + public void setFrequencyChangeListener( Listener listener ) + { + if( mSymbolFilter != null ) + { + mSymbolFilter.setFrequencyChangeListener( listener ); + } + } + + @Override + public void removeFrequencyChangeListener() + { + if( mSymbolFilter != null ) + { + mSymbolFilter.setFrequencyChangeListener( null ); + } + } + + @Override + public Listener getFrequencyChangeListener() + { + if( mSymbolFilter != null ) + { + return mSymbolFilter.getFrequencyChangeListener(); + } + + return null; + } } diff --git a/src/module/decode/p25/P25_LSMDecoder.java b/src/module/decode/p25/P25_LSMDecoder.java index 21555ae9..0e72cba4 100644 --- a/src/module/decode/p25/P25_LSMDecoder.java +++ b/src/module/decode/p25/P25_LSMDecoder.java @@ -34,7 +34,6 @@ import sample.Listener; import sample.complex.ComplexBuffer; import sample.complex.ComplexBufferToStreamConverter; import sample.complex.IComplexBufferListener; -import source.tuner.frequency.FrequencyCorrectionControl; import alias.AliasList; import dsp.filter.FilterFactory; import dsp.filter.Window.WindowType; @@ -119,18 +118,6 @@ public class P25_LSMDecoder extends P25Decoder implements IComplexBufferListener return Modulation.CQPSK; } - @Override - public boolean hasFrequencyCorrectionControl() - { - return false; - } - - @Override - public FrequencyCorrectionControl getFrequencyCorrectionControl() - { - return null; - } - /** * Provides a list of instrumentation taps for monitoring internal processing */ diff --git a/src/module/decode/passport/PassportDecoder.java b/src/module/decode/passport/PassportDecoder.java index b6d46a2b..e125541d 100644 --- a/src/module/decode/passport/PassportDecoder.java +++ b/src/module/decode/passport/PassportDecoder.java @@ -28,7 +28,7 @@ import module.decode.Decoder; import module.decode.DecoderType; import module.decode.config.DecodeConfiguration; import sample.Listener; -import sample.real.IRealBufferListener; +import sample.real.IUnFilteredRealBufferListener; import sample.real.RealBuffer; import alias.AliasList; import bits.MessageFramer; @@ -36,7 +36,7 @@ import bits.SyncPattern; import dsp.fsk.LTRFSKDecoder; public class PassportDecoder extends Decoder - implements IRealBufferListener, Instrumentable + implements IUnFilteredRealBufferListener, Instrumentable { public static final int PASSPORT_MESSAGE_LENGTH = 68; public static final int PASSPORT_SYNC_LENGTH = 9; @@ -47,8 +47,11 @@ public class PassportDecoder extends Decoder private List mAvailableTaps; - public PassportDecoder( DecodeConfiguration config, - AliasList aliasList ) + /** + * Passport Decoder. Decodes unfiltered (e.g. demodulated but with no DC or + * audio filtering) samples and produces Passport messages. + */ + public PassportDecoder( DecodeConfiguration config, AliasList aliasList ) { mPassportFSKDecoder = new LTRFSKDecoder(); @@ -64,7 +67,7 @@ public class PassportDecoder extends Decoder } @Override - public Listener getRealBufferListener() + public Listener getUnFilteredRealBufferListener() { return mPassportFSKDecoder; } diff --git a/src/module/decode/state/ChannelCollectionPanel.java b/src/module/decode/state/ChannelCollectionPanel.java index 685511d1..eae3db84 100644 --- a/src/module/decode/state/ChannelCollectionPanel.java +++ b/src/module/decode/state/ChannelCollectionPanel.java @@ -16,6 +16,8 @@ import org.slf4j.LoggerFactory; import playlist.PlaylistManager; import settings.SettingsManager; import controller.channel.Channel; +import controller.channel.ChannelModel; +import controller.channel.ChannelProcessingManager; /** * Channel Collection assembles a primary channel panel and any related decoder @@ -28,15 +30,21 @@ public class ChannelCollectionPanel extends JPanel private final static Logger mLog = LoggerFactory.getLogger( ChannelCollectionPanel.class ); + private ChannelModel mChannelModel; + private ChannelProcessingManager mChannelProcessingManager; private PlaylistManager mPlaylistManager; private SettingsManager mSettingsManager; private List mChannelPanels = new ArrayList(); - public ChannelCollectionPanel( PlaylistManager playlistManager, + public ChannelCollectionPanel( ChannelModel channelModel, + ChannelProcessingManager channelProcessingManager, + PlaylistManager playlistManager, SettingsManager settingsManager, Channel channel ) { + mChannelModel = channelModel; + mChannelProcessingManager = channelProcessingManager; mPlaylistManager = playlistManager; mSettingsManager = settingsManager; @@ -49,8 +57,8 @@ public class ChannelCollectionPanel extends JPanel setOpaque( false ); - ChannelStatePanel csp = new ChannelStatePanel( mPlaylistManager, - mSettingsManager, channel ); + ChannelStatePanel csp = new ChannelStatePanel( mChannelModel, + mChannelProcessingManager, mPlaylistManager, mSettingsManager, channel ); mChannelPanels.add( csp ); diff --git a/src/module/decode/state/ChannelList.java b/src/module/decode/state/ChannelList.java index aff58241..5cd8f9b8 100644 --- a/src/module/decode/state/ChannelList.java +++ b/src/module/decode/state/ChannelList.java @@ -43,6 +43,8 @@ import settings.SettingsManager; import controller.channel.Channel; import controller.channel.ChannelEvent; import controller.channel.ChannelEventListener; +import controller.channel.ChannelModel; +import controller.channel.ChannelProcessingManager; /** * Gui wrapper for the list of currently processing primary channels @@ -56,12 +58,18 @@ public class ChannelList extends JPanel implements ChannelEventListener private HashMap mDisplayedPanels = new HashMap(); + private ChannelModel mChannelModel; + private ChannelProcessingManager mChannelProcessingManager; private PlaylistManager mPlaylistManager; private SettingsManager mSettingsManager; - public ChannelList( PlaylistManager playlistManager, + public ChannelList( ChannelModel channelModel, + ChannelProcessingManager channelProcessingManager, + PlaylistManager playlistManager, SettingsManager settingsManager ) { + mChannelModel = channelModel; + mChannelProcessingManager = channelProcessingManager; mPlaylistManager = playlistManager; mSettingsManager = settingsManager; @@ -96,8 +104,8 @@ public class ChannelList extends JPanel implements ChannelEventListener { if( !mDisplayedPanels.containsKey( channel ) ) { - ChannelCollectionPanel panel = new ChannelCollectionPanel( - mPlaylistManager, mSettingsManager, channel ); + ChannelCollectionPanel panel = new ChannelCollectionPanel( mChannelModel, + mChannelProcessingManager, mPlaylistManager, mSettingsManager, channel ); add( panel, "wrap" ); diff --git a/src/module/decode/state/ChannelStatePanel.java b/src/module/decode/state/ChannelStatePanel.java index 0559da06..4e626964 100644 --- a/src/module/decode/state/ChannelStatePanel.java +++ b/src/module/decode/state/ChannelStatePanel.java @@ -14,6 +14,7 @@ import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JPanel; +import module.ProcessingChain; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,6 +32,11 @@ import settings.Setting; import settings.SettingChangeListener; import settings.SettingsManager; +import controller.channel.Channel; +import controller.channel.ChannelModel; +import controller.channel.ChannelProcessingManager; +import controller.channel.ChannelUtils; + public class ChannelStatePanel extends JPanel implements Listener, SettingChangeListener { @@ -38,10 +44,6 @@ public class ChannelStatePanel extends JPanel private final static Logger mLog = LoggerFactory.getLogger( ChannelStatePanel.class ); - private static final boolean ENABLED = true; - private static final boolean DISABLED = false; - private static final boolean BROADCAST_CHANGE = true; - private Font mFontDetails = new Font( Font.MONOSPACED, Font.PLAIN, 12 ); private Font mFontDecoder = new Font( Font.MONOSPACED, Font.PLAIN, 12 ); @@ -75,7 +77,10 @@ public class ChannelStatePanel extends JPanel protected SettingsManager mSettingsManager; private Channel mChannel; + private ChannelState mChannelState; private List mDecoderPanels = new ArrayList<>(); + private ChannelModel mChannelModel; + private ChannelProcessingManager mChannelProcessingManager; /** * Gui component to a channel state. Provides System, Site and channel @@ -83,21 +88,31 @@ public class ChannelStatePanel extends JPanel * * Updates color background according to current channel state. */ - public ChannelStatePanel( PlaylistManager playlistManager, + public ChannelStatePanel( ChannelModel channelModel, + ChannelProcessingManager channelProcessingManager, + PlaylistManager playlistManager, SettingsManager settingsManager, Channel channel ) { + mChannelModel = channelModel; + mChannelProcessingManager = channelProcessingManager; mPlaylistManager = playlistManager; mSettingsManager = settingsManager; mSettingsManager.addListener( this ); mChannel = channel; - mChannel.getChannelState().setChangedAttributeListener( this ); + + ProcessingChain processingChain = + channelProcessingManager.getProcessingChain( mChannel ); + + mChannelState = processingChain.getChannelState(); + + mChannelState.setChangedAttributeListener( this ); init(); - for( DecoderState decoderState: getChannel().getProcessingChain().getDecoderStates() ) + for( DecoderState decoderState: processingChain.getDecoderStates() ) { DecoderPanel panel = DecoderFactory.getDecoderPanel( mSettingsManager, decoderState ); mDecoderPanels.add( panel ); @@ -126,8 +141,7 @@ public class ChannelStatePanel extends JPanel mChannelLabel.setForeground( mColorLabelDetails ); add( mChannelLabel, "wrap" ); - mStateLabel = new JLabel( mChannel.getChannelState().getState() - .getDisplayValue() ); + mStateLabel = new JLabel( mChannelState.getState().getDisplayValue() ); mStateLabel.setFont( mFontDecoder ); mStateLabel.setForeground( mColorLabelDecoder ); add( mStateLabel ); @@ -161,8 +175,6 @@ public class ChannelStatePanel extends JPanel mOptionsLabel.setFont( mFontDetails ); mOptionsLabel.setForeground( mColorLabelAuxDecoder ); add( mOptionsLabel, "wrap" ); - -// add( new JSeparator( JSeparator.HORIZONTAL ), "span,growx" ); } public Channel getChannel() @@ -177,7 +189,8 @@ public class ChannelStatePanel extends JPanel mSettingsManager.removeListener( this ); mSettingsManager = null; - mChannel.getChannelState().removeChangedAttributeListener(); + mChannelState.removeChangedAttributeListener(); + mChannelState = null; mChannel = null; for( DecoderPanel panel: mDecoderPanels ) @@ -192,8 +205,6 @@ public class ChannelStatePanel extends JPanel @Override public void receive( final ChangedAttribute changedAttribute ) { - final ChannelState state = mChannel.getChannelState(); - EventQueue.invokeLater( new Runnable() { @Override @@ -202,9 +213,9 @@ public class ChannelStatePanel extends JPanel switch( changedAttribute ) { case CHANNEL_STATE: - if( state.getState() != null ) + if( mChannelState.getState() != null ) { - mStateLabel.setText( state.getState().getDisplayValue() ); + mStateLabel.setText( mChannelState.getState().getDisplayValue() ); } break; case SOURCE: @@ -214,7 +225,7 @@ public class ChannelStatePanel extends JPanel case CHANNEL_NAME: case SITE_NAME: case SYSTEM_NAME: - mChannelLabel.setText( mChannel.getChannelDisplayName() ); + mChannelLabel.setText( mChannel.toString() ); break; default: break; @@ -419,7 +430,7 @@ public class ChannelStatePanel extends JPanel public JMenu getContextMenu() { - return ChannelUtils.getContextMenu( mPlaylistManager, mChannel, - ChannelStatePanel.this ); + return ChannelUtils.getContextMenu( mChannelModel, mChannelProcessingManager, + mPlaylistManager, mChannel, ChannelStatePanel.this ); } } diff --git a/src/module/decode/state/TrafficChannelManager.java b/src/module/decode/state/TrafficChannelManager.java index 18d90d74..ec64ab84 100644 --- a/src/module/decode/state/TrafficChannelManager.java +++ b/src/module/decode/state/TrafficChannelManager.java @@ -6,6 +6,7 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import module.Module; +import module.ProcessingChain; import module.decode.config.DecodeConfiguration; import module.decode.event.CallEvent; import module.decode.event.CallEvent.CallEventType; @@ -21,11 +22,12 @@ import source.tuner.TunerChannel; import source.tuner.TunerChannel.Type; import alias.Alias; import alias.priority.Priority; -import controller.ResourceManager; import controller.channel.Channel; import controller.channel.Channel.ChannelType; -import controller.site.Site; -import controller.system.System; +import controller.channel.ChannelEvent; +import controller.channel.ChannelEvent.Event; +import controller.channel.ChannelModel; +import controller.channel.ChannelProcessingManager; public class TrafficChannelManager extends Module implements ICallEventProvider, IDecoderStateEventListener @@ -40,15 +42,14 @@ public class TrafficChannelManager extends Module private DecoderStateEventListener mEventListener = new DecoderStateEventListener(); private Listener mCallEventListener; + private ChannelModel mChannelModel; + private ChannelProcessingManager mChannelProcessingManager; private DecodeConfiguration mDecodeConfiguration; private RecordConfiguration mRecordConfiguration; - private ResourceManager mResourceManager; private String mSystem; private String mSite; private String mAliasListName; - private long mTrafficChannelTimeout; private CallEvent mPreviousDoNotMonitorCallEvent; - private boolean mShuttingDown = false; /** * Monitors call events and allocates traffic decoder channels in response @@ -68,7 +69,8 @@ public class TrafficChannelManager extends Module * @param trafficChannelPoolSize - maximum number of allocated traffic channels * in the pool */ - public TrafficChannelManager( ResourceManager resourceManager, + public TrafficChannelManager( ChannelModel channelModel, + ChannelProcessingManager channelProcessingManager, DecodeConfiguration decodeConfiguration, RecordConfiguration recordConfiguration, String system, @@ -77,13 +79,14 @@ public class TrafficChannelManager extends Module long trafficChannelTimeout, int trafficChannelPoolSize ) { - mResourceManager = resourceManager; + mChannelModel = channelModel; + mChannelProcessingManager = channelProcessingManager; mDecodeConfiguration = decodeConfiguration; mRecordConfiguration = recordConfiguration; mSystem = system; mSite = site; mAliasListName = aliasListName; - mTrafficChannelTimeout = trafficChannelTimeout; +// mTrafficChannelTimeout = trafficChannelTimeout; mTrafficChannelPoolMaximumSize = trafficChannelPoolSize; } @@ -91,7 +94,6 @@ public class TrafficChannelManager extends Module public void dispose() { mCallEventListener = null; - mResourceManager = null; mDecodeConfiguration = null; mPreviousDoNotMonitorCallEvent = null; } @@ -115,7 +117,7 @@ public class TrafficChannelManager extends Module { for( Channel configuredChannel: mTrafficChannelPool ) { - if( !configuredChannel.isProcessing() ) + if( !configuredChannel.getEnabled() ) { channel = configuredChannel; break; @@ -130,12 +132,10 @@ public class TrafficChannelManager extends Module channel.setRecordConfiguration( mRecordConfiguration ); - channel.setResourceManager( mResourceManager ); - - channel.setTrafficChannelTimeout( mTrafficChannelTimeout ); - channel.setAliasListName( mAliasListName ); + mChannelModel.addChannel( channel ); + mTrafficChannelPool.add( channel ); } @@ -143,26 +143,15 @@ public class TrafficChannelManager extends Module if( channel != null ) { channel.setSourceConfiguration( new SourceConfigTuner( tunerChannel ) ); - channel.setSystem( mSystem ); channel.setSite( mSite ); channel.setName( channelNumber ); - channel.setEnabled( true ); + mChannelModel.broadcast( new ChannelEvent( channel, + Event.NOTIFICATION_CONFIGURATION_CHANGE ) ); - /* Check the channel obtained a source and is currently processing */ - if( channel.isProcessing() ) - { - mTrafficChannelsInUse.put( channelNumber, channel ); - } - else - { - channel.setEnabled( false ); - - channel.setSystem( mSystem ); - channel.setSite( mSite ); - channel.setName( "Traffic" ); - } + mChannelModel.broadcast( new ChannelEvent( channel, + Event.REQUEST_ENABLE ) ); } } @@ -210,26 +199,29 @@ public class TrafficChannelManager extends Module if( channel != null ) { - if( channel.isProcessing() ) + if( channel.getEnabled() ) { - callEvent.setDetails( "TRAFFIC CHANNEL ALLOCATED" ); - - ChannelState state = channel.getChannelState(); - - /* Register as a listener to be notified when the call - * is completed */ - state.configureAsTrafficChannel( - new TrafficChannelStatusListener( this, - callEvent.getChannel() ), event ); - - /* Set state to call so that audio squelch state is correct */ - state.setState( State.CALL ); + ProcessingChain chain = mChannelProcessingManager + .getProcessingChain( channel ); + + if( chain != null ) + { + ChannelState state = chain.getChannelState(); + + /* Register as a listener to be notified when the call + * is completed */ + state.configureAsTrafficChannel( + new TrafficChannelStatusListener( this, + callEvent.getChannel() ), event ); + + /* Set state to call so that audio squelch state is correct */ + state.setState( State.CALL ); + } } else { callEvent.setCallEventType( CallEventType.CALL_DETECT ); - callEvent.setDetails( "CHANNEL PROCESSING ERROR" ); - } + } } else { @@ -390,15 +382,13 @@ public class TrafficChannelManager extends Module { synchronized( mTrafficChannelsInUse ) { - if( channelNumber != null && - mTrafficChannelsInUse.containsKey( channelNumber ) ) + if( channelNumber != null && mTrafficChannelsInUse.containsKey( channelNumber ) ) { Channel channel = mTrafficChannelsInUse.get( channelNumber ); - + + mChannelModel.broadcast( new ChannelEvent( channel, Event.REQUEST_DISABLE ) ); + mTrafficChannelsInUse.remove( channelNumber ); - - /* Disable the channel and broadcast a notification */ - channel.setEnabled( false ); } } } diff --git a/src/module/decode/tait/Tait1200Decoder.java b/src/module/decode/tait/Tait1200Decoder.java index 83ccf2aa..8f21e80d 100644 --- a/src/module/decode/tait/Tait1200Decoder.java +++ b/src/module/decode/tait/Tait1200Decoder.java @@ -31,7 +31,7 @@ import module.decode.Decoder; import module.decode.DecoderType; import sample.Broadcaster; import sample.Listener; -import sample.real.IRealBufferListener; +import sample.real.IFilteredRealBufferListener; import sample.real.RealBuffer; import alias.AliasList; import bits.MessageFramer; @@ -45,7 +45,7 @@ import dsp.fsk.FSK2Decoder.Output; /** * TAIT 1200 - 1200 baud 2FSK decoder */ -public class Tait1200Decoder extends Decoder implements IRealBufferListener, +public class Tait1200Decoder extends Decoder implements IFilteredRealBufferListener, Instrumentable { /* Decimated sample rate ( 48,000 / 2 = 24,000 ) feeding the decoder */ @@ -179,7 +179,7 @@ public class Tait1200Decoder extends Decoder implements IRealBufferListener, } @Override - public Listener getRealBufferListener() + public Listener getFilteredRealBufferListener() { return mDecimationFilter; } diff --git a/src/module/demodulate/am/AMDemodulatorModule.java b/src/module/demodulate/am/AMDemodulatorModule.java index 716c6677..8e311102 100644 --- a/src/module/demodulate/am/AMDemodulatorModule.java +++ b/src/module/demodulate/am/AMDemodulatorModule.java @@ -21,7 +21,7 @@ import module.Module; import sample.Listener; import sample.complex.ComplexBuffer; import sample.complex.IComplexBufferListener; -import sample.real.IRealBufferProvider; +import sample.real.IFilteredRealBufferProvider; import sample.real.RealBuffer; import dsp.am.AMDemodulator_CB; import dsp.filter.FilterFactory; @@ -31,7 +31,7 @@ import dsp.filter.fir.real.RealFIRFilter_RB_RB; import dsp.gain.AutomaticGainControl_RB; public class AMDemodulatorModule extends Module - implements IComplexBufferListener, IRealBufferProvider + implements IComplexBufferListener, IFilteredRealBufferProvider { private static final int SAMPLE_RATE = 48000; @@ -99,13 +99,13 @@ public class AMDemodulatorModule extends Module } @Override - public void setRealBufferListener( Listener listener ) + public void setFilteredRealBufferListener( Listener listener ) { mAGC.setListener( listener ); } @Override - public void removeRealBufferListener() + public void removeFilteredRealBufferListener() { mAGC.removeListener(); } diff --git a/src/module/demodulate/audio/DemodulatedAudioFilterModule.java b/src/module/demodulate/audio/DemodulatedAudioFilterModule.java new file mode 100644 index 00000000..c6535268 --- /dev/null +++ b/src/module/demodulate/audio/DemodulatedAudioFilterModule.java @@ -0,0 +1,101 @@ +/******************************************************************************* + * SDR Trunk + * Copyright (C) 2014-2016 Dennis Sheirer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + ******************************************************************************/ +package module.demodulate.audio; + +import module.Module; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import sample.Listener; +import sample.real.IFilteredRealBufferProvider; +import sample.real.IUnFilteredRealBufferListener; +import sample.real.RealBuffer; +import dsp.filter.FilterFactory; +import dsp.filter.Window.WindowType; +import dsp.filter.dc.DCRemovalFilter_RealBuffer; +import dsp.filter.fir.real.RealFIRFilter_RB_RB; + +public class DemodulatedAudioFilterModule extends Module + implements IUnFilteredRealBufferListener, IFilteredRealBufferProvider +{ + private final static Logger mLog = LoggerFactory.getLogger( DemodulatedAudioFilterModule.class ); + + private DCRemovalFilter_RealBuffer mDCFilter = new DCRemovalFilter_RealBuffer(); + private RealFIRFilter_RB_RB mBandPassFilter; + /** + * Filters demodulated audio and removes any DC component from the buffer + * + * @param pass - audio pass band pass frequency + * @param stop - audio pass band stop frequency + */ + public DemodulatedAudioFilterModule( int pass, int stop ) + { + assert( stop > pass ); + +//TODO: change this to a band pass filter + mBandPassFilter = new RealFIRFilter_RB_RB( + FilterFactory.getLowPass( 48000, pass, stop, 60, + WindowType.HANNING, true ), 1.0f ); + + mDCFilter.setListener( mBandPassFilter ); + } + + @Override + public void dispose() + { + mBandPassFilter.dispose(); + mBandPassFilter = null; + + mDCFilter.dispose(); + mDCFilter = null; + } + + @Override + public void reset() + { + } + + @Override + public void setFilteredRealBufferListener( Listener listener ) + { + mBandPassFilter.setListener( listener ); + } + + @Override + public void removeFilteredRealBufferListener() + { + mBandPassFilter.removeListener(); + } + + @Override + public void start() + { + } + + @Override + public void stop() + { + } + + @Override + public Listener getUnFilteredRealBufferListener() + { + return mDCFilter; + } +} diff --git a/src/module/demodulate/fm/FMDemodulatorModule.java b/src/module/demodulate/fm/FMDemodulatorModule.java index 2d2afe16..da39a197 100644 --- a/src/module/demodulate/fm/FMDemodulatorModule.java +++ b/src/module/demodulate/fm/FMDemodulatorModule.java @@ -1,6 +1,6 @@ /******************************************************************************* * SDR Trunk - * Copyright (C) 2014,2015 Dennis Sheirer + * Copyright (C) 2014-2016 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 @@ -22,43 +22,27 @@ import module.Module; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import sample.Broadcaster; import sample.Listener; import sample.complex.ComplexBuffer; import sample.complex.IComplexBufferListener; -import sample.real.IRealBufferProvider; +import sample.real.IUnFilteredRealBufferProvider; import sample.real.RealBuffer; -import source.tuner.frequency.AutomaticFrequencyControl_RB; -import source.tuner.frequency.FrequencyCorrectionControl; -import source.tuner.frequency.IFrequencyCorrectionController; import dsp.filter.FilterFactory; import dsp.filter.Window.WindowType; -import dsp.filter.dc.DCRemovalFilter_RB; import dsp.filter.fir.complex.ComplexFIRFilter_CB_CB; import dsp.fm.FMDemodulator_CB; -public class FMDemodulatorModule extends Module implements IComplexBufferListener, - IFrequencyCorrectionController, IRealBufferProvider +public class FMDemodulatorModule extends Module + implements IComplexBufferListener, IUnFilteredRealBufferProvider { - private final static Logger mLog = LoggerFactory.getLogger( FMDemodulatorModule.class ); - - /* Determines responsiveness of DC filter to frequency changes */ - private static final float DC_REMOVAL_RATIO = 0.000003f; - private static final int SAMPLE_RATE = 48000; private ComplexFIRFilter_CB_CB mIQFilter; private FMDemodulator_CB mDemodulator; - private Broadcaster mUnfilteredBufferBroadcaster = new Broadcaster(); - private DCRemovalFilter_RB mDCRemovalFilter; - private AutomaticFrequencyControl_RB mAutomaticFrequencyControl; - private boolean mRemoveDC = true; - - private Listener mListener; /** - * FM Demodulator with integrated DC removal and automatic frequency - * correction control. + * FM Demodulator with I/Q filter. Demodulated output is unfiltered and + * may contain a DC component. * * @param pass - pass frequency for IQ filtering prior to demodulation. This * frequency should be half of the signal bandwidth since the filter will @@ -66,56 +50,16 @@ public class FMDemodulatorModule extends Module implements IComplexBufferListene * combined pass bandwidth will be twice this value. * * @param stop - stop frequency for IQ filtering prior to demodulation. - * - * @param maxFrequencyCorrection - defines the maximum frequency +/- that - * the correction controller can adjust from the center tuned frequency. - * Set this value to 0 for no frequency correction control. */ - public FMDemodulatorModule( int pass, int stop, int maxFrequencyCorrection ) - { - this( pass, stop, maxFrequencyCorrection, true ); - } - - public FMDemodulatorModule( int pass, int stop, int maxFrequencyCorrection, boolean removeDC ) + public FMDemodulatorModule( int pass, int stop ) { assert( stop > pass ); - mRemoveDC = removeDC; - mIQFilter = new ComplexFIRFilter_CB_CB( FilterFactory.getLowPass( SAMPLE_RATE, pass, stop, 60, WindowType.HAMMING, true ), 1.0f ); mDemodulator = new FMDemodulator_CB( 1.0f ); mIQFilter.setListener( mDemodulator ); - - mUnfilteredBufferBroadcaster = new Broadcaster(); - mDemodulator.setListener( mUnfilteredBufferBroadcaster ); - - if( maxFrequencyCorrection > 0 ) - { - /* Frequency correction requires unfiltered samples in order to detect - * the DC component present in a mistuned FM demodulated sample stream */ - mAutomaticFrequencyControl = new AutomaticFrequencyControl_RB( maxFrequencyCorrection ); - mUnfilteredBufferBroadcaster.addListener( mAutomaticFrequencyControl ); - } - - if( mRemoveDC ) - { - mDCRemovalFilter = new DCRemovalFilter_RB( DC_REMOVAL_RATIO ); - mUnfilteredBufferBroadcaster.addListener( mDCRemovalFilter ); - } - } - - @Override - public boolean hasFrequencyCorrectionControl() - { - return mAutomaticFrequencyControl != null; - } - - @Override - public FrequencyCorrectionControl getFrequencyCorrectionControl() - { - return mAutomaticFrequencyControl; } @Override @@ -132,68 +76,24 @@ public class FMDemodulatorModule extends Module implements IComplexBufferListene mDemodulator.dispose(); mDemodulator = null; - - if( mDCRemovalFilter != null ) - { - mDCRemovalFilter.dispose(); - } - mDCRemovalFilter = null; - - if( mAutomaticFrequencyControl != null ) - { - mAutomaticFrequencyControl.dispose(); - mAutomaticFrequencyControl = null; - } - - if( mUnfilteredBufferBroadcaster != null ) - { - mUnfilteredBufferBroadcaster.dispose(); - mUnfilteredBufferBroadcaster = null; - } } @Override public void reset() { mDemodulator.reset(); - - if( mDCRemovalFilter != null ) - { - mDCRemovalFilter.reset(); - } - - if( mAutomaticFrequencyControl != null ) - { - mAutomaticFrequencyControl.reset(); - } } @Override - public void setRealBufferListener( Listener listener ) + public void setUnFilteredRealBufferListener( Listener listener ) { - mListener = listener; - - if( mRemoveDC ) - { - mDCRemovalFilter.setListener( listener ); - } - else - { - mUnfilteredBufferBroadcaster.addListener( listener ); - } + mDemodulator.setListener( listener ); } @Override - public void removeRealBufferListener() + public void removeUnFilteredRealBufferListener() { - if( mRemoveDC ) - { - mDCRemovalFilter.removeListener(); - } - else - { - mUnfilteredBufferBroadcaster.removeListener( mListener ); - } + mDemodulator.removeListener(); } @Override diff --git a/src/module/log/EventLogComponentEditor.java b/src/module/log/EventLogComponentEditor.java index e8fefbee..2a9e081a 100644 --- a/src/module/log/EventLogComponentEditor.java +++ b/src/module/log/EventLogComponentEditor.java @@ -1,6 +1,6 @@ /******************************************************************************* * SDR Trunk - * Copyright (C) 2014 Dennis Sheirer + * Copyright (C) 2014-2016 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 @@ -24,7 +24,8 @@ import javax.swing.SwingUtilities; import module.log.config.EventLogConfiguration; import controller.channel.AbstractChannelEditor; -import controller.channel.ChannelNode; +import controller.channel.Channel; +import controller.channel.ConfigurationValidationException; public class EventLogComponentEditor extends AbstractChannelEditor { @@ -34,9 +35,9 @@ public class EventLogComponentEditor extends AbstractChannelEditor private JCheckBox mDecodedLogger = new JCheckBox( "Decoded Messages" ); private JCheckBox mCallEventLogger = new JCheckBox( "Call Events" ); - public EventLogComponentEditor( ChannelNode channelNode ) + public EventLogComponentEditor( Channel channel ) { - super( channelNode ); + super( channel ); add( mBinaryLogger, "span" ); add( mDecodedLogger, "span" ); @@ -53,7 +54,7 @@ public class EventLogComponentEditor extends AbstractChannelEditor { SwingUtilities.invokeLater(new Runnable() { - final List mLoggers = mChannelNode.getChannel() + final List mLoggers = mChannel .getEventLogConfiguration().getLoggers(); @Override @@ -75,8 +76,7 @@ public class EventLogComponentEditor extends AbstractChannelEditor @Override public void save() { - EventLogConfiguration config = mChannelNode.getChannel() - .getEventLogConfiguration(); + EventLogConfiguration config = mChannel.getEventLogConfiguration(); config.clear(); @@ -94,4 +94,18 @@ public class EventLogComponentEditor extends AbstractChannelEditor config.addLogger( EventLogType.CALL_EVENT ); } } + + @Override + public void setConfiguration( Channel channel ) + { + // TODO Auto-generated method stub + + } + + @Override + public void validateConfiguration() throws ConfigurationValidationException + { + // TODO Auto-generated method stub + + } } diff --git a/src/playlist/PlaylistEditor.java b/src/playlist/PlaylistEditor.java new file mode 100644 index 00000000..5d5d92a2 --- /dev/null +++ b/src/playlist/PlaylistEditor.java @@ -0,0 +1,88 @@ +package playlist; + +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.ListSelectionModel; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; + +import net.coderazzi.filters.gui.AutoChoices; +import net.coderazzi.filters.gui.TableFilterHeader; +import net.miginfocom.swing.MigLayout; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import source.SourceManager; + +import com.jidesoft.swing.JideSplitPane; + +import controller.channel.Channel; +import controller.channel.ChannelEditor; +import controller.channel.ChannelModel; + +public class PlaylistEditor extends JPanel implements ListSelectionListener +{ + private static final long serialVersionUID = 1L; + private final static Logger mLog = LoggerFactory.getLogger( PlaylistEditor.class ); + + private ChannelModel mChannelModel; + private JTable mChannelTable; + private ChannelEditor mEditor; + + public PlaylistEditor( ChannelModel channelModel, + PlaylistManager playlistManager, + SourceManager sourceManager ) + { + mChannelModel = channelModel; + + mEditor = new ChannelEditor( channelModel, playlistManager, sourceManager ); + + init(); + } + + private void init() + { + setLayout( new MigLayout( "insets 0 0 0 0", + "[grow,fill]", + "[grow,fill]") ); + + //System Configuration View and Editor + mChannelTable = new JTable( mChannelModel ); + mChannelTable.setSelectionMode( ListSelectionModel.SINGLE_SELECTION ); + mChannelTable.getSelectionModel().addListSelectionListener( this ); + mChannelTable.setAutoCreateRowSorter( true ); + + TableFilterHeader channelHeaderFilter = new TableFilterHeader( mChannelTable ); + channelHeaderFilter.setAutoChoices( AutoChoices.ENABLED ); + + JScrollPane channelScroller = new JScrollPane( mChannelTable ); + + JideSplitPane splitPane = new JideSplitPane( JideSplitPane.HORIZONTAL_SPLIT ); + splitPane.setDividerSize( 5 ); + splitPane.add( channelScroller ); + splitPane.add( mEditor ); + + add( splitPane ); + } + + @Override + public void valueChanged( ListSelectionEvent event ) + { + //This limits event firing to only when selection is complete + if( !event.getValueIsAdjusting() ) + { + int index = mChannelTable.convertRowIndexToModel( mChannelTable.getSelectedRow() ); + + mLog.debug( "Index:" + index ); + + Channel channel = mChannelModel.getChannels().get( index ); + + if( channel != null ) + { + mEditor.setChannel( channel ); + } + } + } +} diff --git a/src/playlist/PlaylistManager.java b/src/playlist/PlaylistManager.java index f23f7075..9d43c496 100644 --- a/src/playlist/PlaylistManager.java +++ b/src/playlist/PlaylistManager.java @@ -52,7 +52,6 @@ public class PlaylistManager public PlaylistManager( ChannelModel channelModel ) { mChannelModel = channelModel; - init(); } public Playlist getPlayist() @@ -73,7 +72,7 @@ public class PlaylistManager * Loads playlist from the current playlist file, or the default playlist file, * as specified in the current SDRTRunk system settings */ - private void init() + public void init() { SystemProperties props = SystemProperties.getInstance(); @@ -163,6 +162,75 @@ public class PlaylistManager } } + private void createBackupPlaylist() + { + SystemProperties props = SystemProperties.getInstance(); + + Path playlistPath = props.getApplicationFolder( "playlist" ); + + String playlistDefault = props.get( "playlist.defaultfilename", + "playlist.xml" ); + + String playlistCurrent = props.get( "playlist.currentfilename", + playlistDefault ); + + Path current = playlistPath.resolve( playlistCurrent ); + + if( Files.exists( current ) ) + { + int revision = 1; + + String playlistBackup = playlistCurrent.replace( ".xml", "_backup_" + revision + ".xml" ); + + Path filePath = playlistPath.resolve( playlistBackup ); + + while( Files.exists( filePath ) ) + { + revision++; + + playlistBackup = playlistCurrent.replace( ".xml", "_backup_" + revision + ".xml" ); + + filePath = playlistPath.resolve( playlistBackup ); + + if( revision > 10 ) + { + mLog.error( "Couldn't create playlist backup - maximum revisions exceeded" ); + return; + } + } + + File outputFile = new File( filePath.toString() ); + + try + { + if( !outputFile.exists() ) + { + outputFile.createNewFile(); + } + } + catch( Exception e ) + { + mLog.error( "PlaylistManager - couldn't create file to save " + + "playlist backup [" + filePath.toString() + "]" ); + } + + try( OutputStream out = new FileOutputStream( outputFile ) ) + { + Files.copy( current, out ); + + mLog.info( "Playlist backed up to:" + filePath ); + } + catch( IOException ioe ) + { + mLog.error( "Error copying playlist to backup file [" + filePath + "]" ); + } + } + else + { + mLog.error( "Couldn't create backup playlist - original playlist does not exist" ); + } + } + /** * Erases current playlist and loads playlist from the playlistPath filename, * if it exists. @@ -238,6 +306,8 @@ public class PlaylistManager { mLog.info( "Legacy playlist format detected - converting ..." ); + createBackupPlaylist(); + //Playlist version 1 to version 2 format conversion. In order to keep //backwards compatibility, transfer all of the System-Site-Channel //objects over to the new channel list format diff --git a/src/playlist/PlaylistNode.java b/src/playlist/PlaylistNode.java index 93fdc2a8..5d8e5302 100644 --- a/src/playlist/PlaylistNode.java +++ b/src/playlist/PlaylistNode.java @@ -19,10 +19,14 @@ package playlist; import javax.swing.JPanel; +import settings.SettingsManager; +import source.SourceManager; import alias.AliasDirectory; import alias.AliasDirectoryNode; import controller.BaseNode; import controller.EmptyEditor; +import controller.channel.ChannelModel; +import controller.channel.ChannelProcessingManager; import controller.channel.map.ChannelMapList; import controller.channel.map.ChannelMapListNode; import controller.system.SystemList; @@ -35,11 +39,27 @@ public class PlaylistNode extends BaseNode private ChannelMapListNode mChannelMapListNode; private SystemListNode mSystemListNode; - public PlaylistNode() - { + private ChannelModel mChannelModel; + private ChannelProcessingManager mChannelProcessingManager; + private PlaylistManager mPlaylistManager; + private SettingsManager mSettingsManager; + private SourceManager mSourceManager; + + public PlaylistNode( ChannelModel channelModel, + ChannelProcessingManager channelProcessingManager, + PlaylistManager playlistManager, + SettingsManager settingsManager, + SourceManager sourceManager ) + { super( null ); - } - + + mChannelModel = channelModel; + mChannelProcessingManager = channelProcessingManager; + mPlaylistManager = playlistManager; + mSettingsManager = settingsManager; + mSourceManager = sourceManager; + } + private void init() { /** @@ -58,7 +78,8 @@ public class PlaylistNode extends BaseNode getPlaylist().setAliasDirectory( directory ); } - mAliasDirectoryNode = new AliasDirectoryNode( directory ); + mAliasDirectoryNode = new AliasDirectoryNode( mPlaylistManager, + mSettingsManager, directory ); getModel().insertNodeInto( mAliasDirectoryNode, this, 0 ); @@ -74,7 +95,7 @@ public class PlaylistNode extends BaseNode channelMapList = new ChannelMapList(); } - mChannelMapListNode = new ChannelMapListNode( channelMapList ); + mChannelMapListNode = new ChannelMapListNode( mPlaylistManager, channelMapList ); getModel().insertNodeInto( mChannelMapListNode, this, 1 ); @@ -91,7 +112,8 @@ public class PlaylistNode extends BaseNode getPlaylist().setSystemList( list ); } - mSystemListNode = new SystemListNode( list ); + mSystemListNode = new SystemListNode( list, mChannelModel, + mChannelProcessingManager, mPlaylistManager, mSourceManager ); getModel().insertNodeInto( mSystemListNode, this, 2 ); @@ -112,8 +134,7 @@ public class PlaylistNode extends BaseNode public void loadPlaylist() { - Playlist playlist = - getModel().getResourceManager().getPlaylistManager().getPlayist(); + Playlist playlist = mPlaylistManager.getPlayist(); setUserObject( playlist ); diff --git a/src/record/RecordComponentEditor.java b/src/record/RecordComponentEditor.java index 435a6ccb..7c23a360 100644 --- a/src/record/RecordComponentEditor.java +++ b/src/record/RecordComponentEditor.java @@ -1,6 +1,6 @@ /******************************************************************************* * SDR Trunk - * Copyright (C) 2014 Dennis Sheirer + * Copyright (C) 2014-2016 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 @@ -22,7 +22,8 @@ import javax.swing.JCheckBox; import record.config.RecordConfiguration; import controller.channel.AbstractChannelEditor; -import controller.channel.ChannelNode; +import controller.channel.Channel; +import controller.channel.ConfigurationValidationException; public class RecordComponentEditor extends AbstractChannelEditor { @@ -32,9 +33,9 @@ public class RecordComponentEditor extends AbstractChannelEditor private JCheckBox mBasebandRecorder = new JCheckBox( "Baseband I/Q" ); private JCheckBox mTrafficBasebandRecorder = new JCheckBox( "Traffic Channel Baseband I/Q" ); - public RecordComponentEditor( ChannelNode channelNode ) + public RecordComponentEditor( Channel channel ) { - super( channelNode ); + super( channel ); add( mAudioRecorder, "span" ); add( mBasebandRecorder, "span" ); @@ -46,8 +47,7 @@ public class RecordComponentEditor extends AbstractChannelEditor @Override public void save() { - RecordConfiguration config = - getChannelNode().getChannel().getRecordConfiguration(); + RecordConfiguration config = getChannel().getRecordConfiguration(); config.clearRecorders(); @@ -76,8 +76,7 @@ public class RecordComponentEditor extends AbstractChannelEditor @Override public void run() { - RecordConfiguration config = - getChannelNode().getChannel().getRecordConfiguration(); + RecordConfiguration config = getChannel().getRecordConfiguration(); mAudioRecorder.setSelected( config.getRecorders() .contains( RecorderType.AUDIO ) ); @@ -90,4 +89,18 @@ public class RecordComponentEditor extends AbstractChannelEditor } }); } + + @Override + public void setConfiguration( Channel channel ) + { + // TODO Auto-generated method stub + + } + + @Override + public void validateConfiguration() throws ConfigurationValidationException + { + // TODO Auto-generated method stub + + } } diff --git a/src/record/RecordEditor.java b/src/record/RecordEditor.java index 6d25832e..9913bf9e 100644 --- a/src/record/RecordEditor.java +++ b/src/record/RecordEditor.java @@ -18,9 +18,11 @@ package record; import record.config.RecordConfiguration; -import controller.Editor; +import controller.channel.Channel; +import controller.channel.ChannelConfigurationEditor; +import controller.channel.ConfigurationValidationException; -public class RecordEditor extends Editor +public class RecordEditor extends ChannelConfigurationEditor { private static final long serialVersionUID = 1L; @@ -42,7 +44,16 @@ public class RecordEditor extends Editor } @Override - public void reset() - { - } + public void setConfiguration( Channel channel ) + { + // TODO Auto-generated method stub + + } + + @Override + public void validateConfiguration() throws ConfigurationValidationException + { + // TODO Auto-generated method stub + + } } diff --git a/src/record/RecorderManager.java b/src/record/RecorderManager.java index 949ac241..b4bf4aad 100644 --- a/src/record/RecorderManager.java +++ b/src/record/RecorderManager.java @@ -1,6 +1,6 @@ /******************************************************************************* * SDR Trunk - * Copyright (C) 2014,2015 Dennis Sheirer + * Copyright (C) 2014-2016 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 @@ -20,7 +20,6 @@ package record; import java.io.File; import java.util.HashMap; import java.util.Map; -import java.util.concurrent.TimeUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -33,7 +32,6 @@ import audio.AudioPacket; import audio.metadata.Metadata; import audio.metadata.MetadataType; import controller.ThreadPoolManager; -import controller.ThreadPoolManager.ThreadType; public class RecorderManager implements Listener { @@ -170,8 +168,7 @@ public class RecorderManager implements Listener /** * Constructs a baseband recorder for use in a processing chain. */ - public static ComplexBufferWaveRecorder getBasebandRecorder( - ThreadPoolManager threadPoolManager, String channelName ) + public ComplexBufferWaveRecorder getBasebandRecorder( String channelName ) { StringBuilder sb = new StringBuilder(); sb.append( SystemProperties.getInstance() @@ -180,7 +177,7 @@ public class RecorderManager implements Listener sb.append( channelName ); sb.append( "_baseband" ); - return new ComplexBufferWaveRecorder( threadPoolManager, + return new ComplexBufferWaveRecorder( mThreadPoolManager, AUDIO_SAMPLE_RATE, sb.toString() ); } } diff --git a/src/record/wave/RealBufferWaveRecorder.java b/src/record/wave/RealBufferWaveRecorder.java index 49b0f3b6..0ad0d4f7 100644 --- a/src/record/wave/RealBufferWaveRecorder.java +++ b/src/record/wave/RealBufferWaveRecorder.java @@ -34,7 +34,7 @@ import org.slf4j.LoggerFactory; import sample.ConversionUtils; import sample.Listener; -import sample.real.IRealBufferListener; +import sample.real.IFilteredRealBufferListener; import sample.real.RealBuffer; import util.TimeStamp; import controller.ThreadPoolManager; @@ -44,7 +44,7 @@ import controller.ThreadPoolManager.ThreadType; * WAVE audio recorder module for recording real sample buffers to a wave file */ public class RealBufferWaveRecorder extends Module - implements IRealBufferListener, Listener + implements IFilteredRealBufferListener, Listener { private final static Logger mLog = LoggerFactory.getLogger( RealBufferWaveRecorder.class ); @@ -151,7 +151,7 @@ public class RealBufferWaveRecorder extends Module } @Override - public Listener getRealBufferListener() + public Listener getFilteredRealBufferListener() { return this; } diff --git a/src/sample/real/IFilteredRealBufferListener.java b/src/sample/real/IFilteredRealBufferListener.java new file mode 100644 index 00000000..06928fda --- /dev/null +++ b/src/sample/real/IFilteredRealBufferListener.java @@ -0,0 +1,8 @@ +package sample.real; + +import sample.Listener; + +public interface IFilteredRealBufferListener +{ + public Listener getFilteredRealBufferListener(); +} diff --git a/src/sample/real/IFilteredRealBufferProvider.java b/src/sample/real/IFilteredRealBufferProvider.java new file mode 100644 index 00000000..e600d368 --- /dev/null +++ b/src/sample/real/IFilteredRealBufferProvider.java @@ -0,0 +1,9 @@ +package sample.real; + +import sample.Listener; + +public interface IFilteredRealBufferProvider +{ + public void setFilteredRealBufferListener( Listener listener ); + public void removeFilteredRealBufferListener(); +} diff --git a/src/sample/real/IRealBufferListener.java b/src/sample/real/IRealBufferListener.java deleted file mode 100644 index 6ef33052..00000000 --- a/src/sample/real/IRealBufferListener.java +++ /dev/null @@ -1,8 +0,0 @@ -package sample.real; - -import sample.Listener; - -public interface IRealBufferListener -{ - public Listener getRealBufferListener(); -} diff --git a/src/sample/real/IRealBufferProvider.java b/src/sample/real/IRealBufferProvider.java deleted file mode 100644 index 0b11debd..00000000 --- a/src/sample/real/IRealBufferProvider.java +++ /dev/null @@ -1,9 +0,0 @@ -package sample.real; - -import sample.Listener; - -public interface IRealBufferProvider -{ - public void setRealBufferListener( Listener listener ); - public void removeRealBufferListener(); -} diff --git a/src/sample/real/IUnFilteredRealBufferListener.java b/src/sample/real/IUnFilteredRealBufferListener.java new file mode 100644 index 00000000..bce0f168 --- /dev/null +++ b/src/sample/real/IUnFilteredRealBufferListener.java @@ -0,0 +1,8 @@ +package sample.real; + +import sample.Listener; + +public interface IUnFilteredRealBufferListener +{ + public Listener getUnFilteredRealBufferListener(); +} diff --git a/src/sample/real/IUnFilteredRealBufferProvider.java b/src/sample/real/IUnFilteredRealBufferProvider.java new file mode 100644 index 00000000..764a5aeb --- /dev/null +++ b/src/sample/real/IUnFilteredRealBufferProvider.java @@ -0,0 +1,9 @@ +package sample.real; + +import sample.Listener; + +public interface IUnFilteredRealBufferProvider +{ + public void setUnFilteredRealBufferListener( Listener listener ); + public void removeUnFilteredRealBufferListener(); +} diff --git a/src/settings/SettingsManager.java b/src/settings/SettingsManager.java index ddcc4fa9..df430aa6 100644 --- a/src/settings/SettingsManager.java +++ b/src/settings/SettingsManager.java @@ -386,6 +386,12 @@ public class SettingsManager } MapIcon mapIcon = mIcons.get( name ); + + if( mapIcon == null ) + { + mapIcon = new MapIcon( name, name ); + mIcons.put( name, mapIcon ); + } if( mapIcon != null ) { @@ -399,7 +405,7 @@ public class SettingsManager } else { - mResizedIcons.put( mergedName, mapIcon.getImageIcon() ); + return mapIcon.getImageIcon(); } } diff --git a/src/source/ComplexSource.java b/src/source/ComplexSource.java index eeb4084e..e7e1939c 100644 --- a/src/source/ComplexSource.java +++ b/src/source/ComplexSource.java @@ -6,8 +6,8 @@ import sample.complex.ComplexBuffer; public abstract class ComplexSource extends Source implements Provider { - public ComplexSource( String name ) + public ComplexSource() { - super( name, SampleType.COMPLEX ); + super( SampleType.COMPLEX ); } } diff --git a/src/source/EmptySourceEditor.java b/src/source/EmptySourceEditor.java index ad1c1669..04af856d 100644 --- a/src/source/EmptySourceEditor.java +++ b/src/source/EmptySourceEditor.java @@ -19,14 +19,15 @@ package source; import javax.swing.JLabel; +import controller.channel.Channel; +import controller.channel.ConfigurationValidationException; import source.config.SourceConfiguration; -import controller.ResourceManager; public class EmptySourceEditor extends SourceEditor { private static final long serialVersionUID = 1L; - public EmptySourceEditor( ResourceManager resourceManager, + public EmptySourceEditor( SourceManager resourceManager, SourceConfiguration config ) { super( resourceManager, config ); @@ -43,4 +44,18 @@ public class EmptySourceEditor extends SourceEditor JLabel selectLabel = new JLabel( "Please select a source" ); add( selectLabel ); } + + @Override + public void setConfiguration( Channel channel ) + { + // TODO Auto-generated method stub + + } + + @Override + public void validateConfiguration() throws ConfigurationValidationException + { + // TODO Auto-generated method stub + + } } diff --git a/src/source/FloatSource.java b/src/source/FloatSource.java deleted file mode 100644 index c8161a9c..00000000 --- a/src/source/FloatSource.java +++ /dev/null @@ -1,12 +0,0 @@ -package source; - -import sample.Provider; -import sample.SampleType; - -public abstract class FloatSource extends Source implements Provider -{ - public FloatSource( String name ) - { - super( name, SampleType.REAL ); - } -} diff --git a/src/source/RealSource.java b/src/source/RealSource.java index 6b09ccd5..b512bfbc 100644 --- a/src/source/RealSource.java +++ b/src/source/RealSource.java @@ -7,8 +7,8 @@ import sample.real.RealBuffer; public abstract class RealSource extends Source implements Provider { - public RealSource( String name ) + public RealSource() { - super( name, SampleType.REAL ); + super( SampleType.REAL ); } } diff --git a/src/source/Source.java b/src/source/Source.java index 064cc6ce..217def00 100644 --- a/src/source/Source.java +++ b/src/source/Source.java @@ -17,27 +17,21 @@ ******************************************************************************/ package source; +import module.Module; import sample.SampleType; /** * Abstract class to define the minimum functionality of a sample data provider. */ -public abstract class Source +public abstract class Source extends Module { - protected String mName; protected SampleType mSampleType; - public Source( String name, SampleType sampleType ) + public Source( SampleType sampleType ) { - mName = name; mSampleType = sampleType; } - public String getName() - { - return mName; - } - public abstract int getSampleRate() throws SourceException; public abstract long getFrequency() throws SourceException; diff --git a/src/source/SourceComponentEditor.java b/src/source/SourceComponentEditor.java index c4d4e4a2..b4f3673a 100644 --- a/src/source/SourceComponentEditor.java +++ b/src/source/SourceComponentEditor.java @@ -1,6 +1,6 @@ /******************************************************************************* * SDR Trunk - * Copyright (C) 2014 Dennis Sheirer + * Copyright (C) 2014-2016 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 @@ -29,7 +29,8 @@ import net.miginfocom.swing.MigLayout; import source.config.SourceConfigFactory; import source.config.SourceConfiguration; import controller.channel.AbstractChannelEditor; -import controller.channel.ChannelNode; +import controller.channel.Channel; +import controller.channel.ConfigurationValidationException; public class SourceComponentEditor extends AbstractChannelEditor { @@ -37,10 +38,13 @@ public class SourceComponentEditor extends AbstractChannelEditor private JComboBox mComboSources; private SourceEditor mEditor; + private SourceManager mSourceManager; - public SourceComponentEditor( ChannelNode channelNode ) + public SourceComponentEditor( SourceManager sourceManager, Channel channel ) { - super( channelNode ); + super( channel ); + + mSourceManager = sourceManager; setLayout( new MigLayout( "fill,wrap 2", "[right,grow][grow]", "[][][grow]" ) ); @@ -57,11 +61,9 @@ public class SourceComponentEditor extends AbstractChannelEditor { SourceConfiguration config; - if( selected == mChannelNode.getChannel() - .getSourceConfiguration().getSourceType() ) + if( selected == mChannel.getSourceConfiguration().getSourceType() ) { - config = mChannelNode.getChannel() - .getSourceConfiguration(); + config = mChannel.getSourceConfiguration(); } else { @@ -76,8 +78,7 @@ public class SourceComponentEditor extends AbstractChannelEditor } //Change to the new one - mEditor = SourceEditorFactory.getPanel( - mChannelNode.getModel().getResourceManager(), config ); + mEditor = mSourceManager.getPanel( config ); //Add it to the jpanel add( mEditor, "span 2" ); @@ -105,10 +106,10 @@ public class SourceComponentEditor extends AbstractChannelEditor { @Override - public void run() { + public void run() + { mComboSources.setSelectedItem( - mChannelNode.getChannel() - .getSourceConfiguration().getSourceType() ); + mChannel.getSourceConfiguration().getSourceType() ); mComboSources.requestFocus(); @@ -123,7 +124,20 @@ public class SourceComponentEditor extends AbstractChannelEditor mEditor.save(); //Let the calling save method send the config change event - mChannelNode.getChannel() - .setSourceConfiguration( mEditor.getConfig() ); + mChannel.setSourceConfiguration( mEditor.getConfig() ); } + + @Override + public void setConfiguration( Channel channel ) + { + // TODO Auto-generated method stub + + } + + @Override + public void validateConfiguration() throws ConfigurationValidationException + { + // TODO Auto-generated method stub + + } } diff --git a/src/source/SourceEditor.java b/src/source/SourceEditor.java index dd5ad11e..1cb15a64 100644 --- a/src/source/SourceEditor.java +++ b/src/source/SourceEditor.java @@ -18,19 +18,18 @@ package source; import source.config.SourceConfiguration; -import controller.Editor; -import controller.ResourceManager; +import controller.channel.ChannelConfigurationEditor; -public abstract class SourceEditor extends Editor +public abstract class SourceEditor extends ChannelConfigurationEditor { private static final long serialVersionUID = 1L; - protected ResourceManager mResourceManager; + protected SourceManager mSourceManager; protected SourceConfiguration mConfig; - public SourceEditor( ResourceManager resourceManager, SourceConfiguration config ) + public SourceEditor( SourceManager sourceManager, SourceConfiguration config ) { - mResourceManager = resourceManager; + mSourceManager = sourceManager; mConfig = config; } @@ -38,9 +37,9 @@ public abstract class SourceEditor extends Editor { return mConfig; } - - public ResourceManager getResourceManager() + + protected SourceManager getSourceManager() { - return mResourceManager; + return mSourceManager; } } diff --git a/src/source/SourceEditorFactory.java b/src/source/SourceEditorFactory.java deleted file mode 100644 index b918f79f..00000000 --- a/src/source/SourceEditorFactory.java +++ /dev/null @@ -1,52 +0,0 @@ -/******************************************************************************* - * 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 - ******************************************************************************/ -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( ResourceManager resourceManager, - SourceConfiguration config ) - { - SourceEditor configuredPanel; - - switch( config.getSourceType() ) - { - case MIXER: - configuredPanel = new MixerEditor( resourceManager, config ); - break; - case TUNER: - configuredPanel = new TunerEditor( resourceManager, config ); - break; - case RECORDING: - configuredPanel = new RecordingEditor( resourceManager, config ); - break; - case NONE: - default: - configuredPanel = new EmptySourceEditor( resourceManager, config ); - break; - } - - return configuredPanel; - } -} diff --git a/src/source/SourceManager.java b/src/source/SourceManager.java index 8c783ab9..9fab09f4 100644 --- a/src/source/SourceManager.java +++ b/src/source/SourceManager.java @@ -17,27 +17,43 @@ ******************************************************************************/ package source; +import settings.SettingsManager; import source.config.SourceConfiguration; +import source.mixer.MixerEditor; import source.mixer.MixerManager; -import controller.ResourceManager; +import source.recording.RecordingEditor; +import source.recording.RecordingSourceManager; +import source.tuner.TunerEditor; +import source.tuner.TunerManager; +import controller.ThreadPoolManager; -public class SourceManager { - /** - * NOTE: each source will auto-start once a listener registers on it to - * receive samples and should auto-stop once a listener de-registers - * - * Each channel object will handle the starting and stopping of each channel - * processing chain. - * - * Source Manager will reach out to the MixerManager or the TunerManager - * to get source objects to pass off to the channel object, as requested. - */ - - private ResourceManager mResourceManager; +public class SourceManager +{ + private MixerManager mMixerManager; + private RecordingSourceManager mRecordingSourceManager; + private TunerManager mTunerManager; - public SourceManager( ResourceManager resourceManager ) + public SourceManager( SettingsManager settingsManager, + ThreadPoolManager threadPoolManager ) { - mResourceManager = resourceManager; + mMixerManager = new MixerManager(); + mRecordingSourceManager = new RecordingSourceManager( settingsManager, threadPoolManager ); + mTunerManager = new TunerManager( mMixerManager, settingsManager, threadPoolManager ); + } + + public MixerManager getMixerManager() + { + return mMixerManager; + } + + public RecordingSourceManager getRecordingSourceManager() + { + return mRecordingSourceManager; + } + + public TunerManager getTunerManager() + { + return mTunerManager; } public Source getSource( SourceConfiguration config, int bandwidth ) @@ -48,14 +64,13 @@ public class SourceManager { switch( config.getSourceType() ) { case MIXER: - retVal = MixerManager.getInstance().getSource( config ); + retVal = mMixerManager.getSource( config ); break; case TUNER: - retVal = mResourceManager.getTunerManager().getSource( config, bandwidth ); + retVal = mTunerManager.getSource( config, bandwidth ); break; case RECORDING: - retVal = mResourceManager.getRecordingSourceManager() - .getSource( config, bandwidth ); + retVal = mRecordingSourceManager.getSource( config, bandwidth ); case NONE: default: break; @@ -63,4 +78,28 @@ public class SourceManager { return retVal; } + + public SourceEditor getPanel( SourceConfiguration config ) + { + SourceEditor configuredPanel; + + switch( config.getSourceType() ) + { + case MIXER: + configuredPanel = new MixerEditor( this, config ); + break; + case TUNER: + configuredPanel = new TunerEditor( this, config ); + break; + case RECORDING: + configuredPanel = new RecordingEditor( this, config ); + break; + case NONE: + default: + configuredPanel = new EmptySourceEditor( this, config ); + break; + } + + return configuredPanel; + } } diff --git a/src/source/mixer/MixerEditor.java b/src/source/mixer/MixerEditor.java index 3782213b..075068b6 100644 --- a/src/source/mixer/MixerEditor.java +++ b/src/source/mixer/MixerEditor.java @@ -24,11 +24,13 @@ import javax.swing.DefaultComboBoxModel; import javax.swing.JComboBox; import javax.swing.JLabel; +import controller.channel.Channel; +import controller.channel.ConfigurationValidationException; import source.SourceEditor; +import source.SourceManager; import source.config.SourceConfigMixer; import source.config.SourceConfiguration; import source.mixer.MixerManager.InputMixerConfiguration; -import controller.ResourceManager; public class MixerEditor extends SourceEditor { @@ -38,10 +40,10 @@ public class MixerEditor extends SourceEditor protected Mixer.Info mSelectedMixer = null; - public MixerEditor( ResourceManager resourceManager, + public MixerEditor( SourceManager sourceManager, SourceConfiguration config ) { - super( resourceManager, config ); + super( sourceManager, config ); initGUI(); } @@ -105,7 +107,8 @@ public class MixerEditor extends SourceEditor @Override public void run() { - InputMixerConfiguration[] mixers = MixerManager.getInstance().getInputMixers(); + InputMixerConfiguration[] mixers = mSourceManager + .getMixerManager().getInputMixers(); mComboMixers.setModel( new DefaultComboBoxModel( mixers ) ); @@ -155,4 +158,18 @@ public class MixerEditor extends SourceEditor } }); } + + @Override + public void setConfiguration( Channel channel ) + { + // TODO Auto-generated method stub + + } + + @Override + public void validateConfiguration() throws ConfigurationValidationException + { + // TODO Auto-generated method stub + + } } diff --git a/src/source/mixer/MixerManager.java b/src/source/mixer/MixerManager.java index 298e760d..d7af001a 100644 --- a/src/source/mixer/MixerManager.java +++ b/src/source/mixer/MixerManager.java @@ -49,27 +49,15 @@ public class MixerManager private final static Logger mLog = LoggerFactory.getLogger( MixerManager.class ); - private static MixerManager sInstance = null; - private List mInputMixers = new ArrayList<>(); private List mOutputMixers = new ArrayList<>(); private HashMap mMixerTuners = new HashMap<>(); - private MixerManager() + public MixerManager() { loadMixers(); } - public static MixerManager getInstance() - { - if( sInstance == null ) - { - sInstance = new MixerManager(); - } - - return sInstance; - } - public RealMixerSource getSource( SourceConfiguration config ) { RealMixerSource retVal = null; @@ -108,7 +96,6 @@ public class MixerManager { return new RealMixerSource( dataLine, AudioFormats.PCM_SIGNED_48KHZ_16BITS_MONO, - mixerName, new ShortAdapter() ); } } @@ -137,7 +124,7 @@ public class MixerManager { return new RealMixerSource( dataLine, AudioFormats.PCM_SIGNED_48KHZ_16BITS_STEREO, - mixerName, new ChannelShortAdapter( + new ChannelShortAdapter( mixerConfig.getChannel() ) ); } } diff --git a/src/source/mixer/RealMixerSource.java b/src/source/mixer/RealMixerSource.java index 58b8d953..240e55bb 100644 --- a/src/source/mixer/RealMixerSource.java +++ b/src/source/mixer/RealMixerSource.java @@ -72,18 +72,30 @@ public class RealMixerSource extends RealSource * the left/right stereo channels are inverted. */ public RealMixerSource( TargetDataLine targetDataLine, - AudioFormat format, - String name, - ISampleAdapter sampleAdapter ) + AudioFormat format, + ISampleAdapter sampleAdapter ) { - super( name ); - mTargetDataLine = targetDataLine; mAudioFormat = format; mSampleAdapter = sampleAdapter; } - public void setListener( Listener listener ) + @Override + public void reset() + { + } + + @Override + public void start() + { + } + + @Override + public void stop() + { + } + + public void setListener( Listener listener ) { mSampleListeners.add( listener ); @@ -92,7 +104,7 @@ public class RealMixerSource extends RealSource { Thread thread = new Thread( mBufferReader ); thread.setDaemon( true ); - thread.setName( getName() + " Sample Reader" ); + thread.setName( "Sample Reader" ); thread.start(); } } diff --git a/src/source/recording/Recording.java b/src/source/recording/Recording.java index 90fad405..a3b1aba7 100644 --- a/src/source/recording/Recording.java +++ b/src/source/recording/Recording.java @@ -4,21 +4,20 @@ import java.io.File; import java.util.ArrayList; import java.util.concurrent.RejectedExecutionException; +import settings.SettingsManager; import source.SourceException; import source.tuner.TunerChannel; -import source.tuner.TunerChannelProvider; +import source.tuner.ITunerChannelProvider; import source.tuner.TunerChannelSource; import source.tuner.frequency.FrequencyChangeEvent; -import source.tuner.frequency.FrequencyChangeListener; import source.tuner.frequency.FrequencyChangeEvent.Event; -import controller.ResourceManager; +import source.tuner.frequency.IFrequencyChangeProcessor; import controller.ThreadPoolManager; public class Recording implements Comparable, - FrequencyChangeListener, - TunerChannelProvider + IFrequencyChangeProcessor, + ITunerChannelProvider { - private ResourceManager mResourceManager; private RecordingConfiguration mConfiguration; private ArrayList mTunerChannels = @@ -26,10 +25,12 @@ public class Recording implements Comparable, private long mCenterFrequency; - public Recording( ResourceManager resourceManager, + private SettingsManager mSettingsManager; + + public Recording( SettingsManager settingsManager, RecordingConfiguration configuration ) { - mResourceManager = resourceManager; + mSettingsManager = settingsManager; mConfiguration = configuration; mCenterFrequency = mConfiguration.getCenterFrequency(); } @@ -37,7 +38,7 @@ public class Recording implements Comparable, public void setAlias( String alias ) { mConfiguration.setAlias( alias ); - mResourceManager.getSettingsManager().save(); + mSettingsManager.save(); } public void setRecordingFile( File file ) throws SourceException @@ -50,7 +51,7 @@ public class Recording implements Comparable, } mConfiguration.setFilePath( file.getAbsolutePath() ); - mResourceManager.getSettingsManager().save(); + mSettingsManager.save(); } /** @@ -90,13 +91,13 @@ public class Recording implements Comparable, @Override public void frequencyChanged( FrequencyChangeEvent event ) { - if( event.getEvent() == Event.FREQUENCY_CHANGE_NOTIFICATION ) + if( event.getEvent() == Event.NOTIFICATION_FREQUENCY_CHANGE ) { long frequency = event.getValue().longValue(); mConfiguration.setCenterFrequency( frequency ); - mResourceManager.getSettingsManager().save(); + mSettingsManager.save(); mCenterFrequency = frequency; diff --git a/src/source/recording/RecordingEditor.java b/src/source/recording/RecordingEditor.java index aabec88f..a6be5cbe 100644 --- a/src/source/recording/RecordingEditor.java +++ b/src/source/recording/RecordingEditor.java @@ -26,11 +26,13 @@ import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.SwingUtilities; +import controller.channel.Channel; +import controller.channel.ConfigurationValidationException; import source.SourceEditor; +import source.SourceManager; import source.config.SourceConfigRecording; import source.config.SourceConfigTuner; import source.config.SourceConfiguration; -import controller.ResourceManager; public class RecordingEditor extends SourceEditor { @@ -38,10 +40,9 @@ public class RecordingEditor extends SourceEditor private JComboBox mComboRecordings; private JFrequencyControl mFrequencyControl; - public RecordingEditor( ResourceManager resourceManager, - SourceConfiguration config ) + public RecordingEditor( SourceManager sourceManager, SourceConfiguration config ) { - super( resourceManager, config ); + super( sourceManager, config ); initGUI(); } @@ -92,7 +93,7 @@ public class RecordingEditor extends SourceEditor @Override public void run() { - List recordings = getResourceManager() + List recordings = getSourceManager() .getRecordingSourceManager().getRecordings(); mComboRecordings.setModel( @@ -105,7 +106,7 @@ public class RecordingEditor extends SourceEditor if( recordingAlias != null ) { - Recording selected = mResourceManager + Recording selected = mSourceManager .getRecordingSourceManager() .getRecordingFromAlias( recordingAlias ); @@ -117,4 +118,18 @@ public class RecordingEditor extends SourceEditor } }); } + + @Override + public void setConfiguration( Channel channel ) + { + // TODO Auto-generated method stub + + } + + @Override + public void validateConfiguration() throws ConfigurationValidationException + { + // TODO Auto-generated method stub + + } } diff --git a/src/source/recording/RecordingGroupNode.java b/src/source/recording/RecordingGroupNode.java index 8eb2029a..3e9d4631 100644 --- a/src/source/recording/RecordingGroupNode.java +++ b/src/source/recording/RecordingGroupNode.java @@ -24,17 +24,28 @@ import java.util.List; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; +import settings.SettingsManager; +import source.SourceManager; import controller.BaseNode; public class RecordingGroupNode extends BaseNode { private static final long serialVersionUID = 1L; - - public RecordingGroupNode() + + private SettingsManager mSettingsManager; + + public RecordingGroupNode( SourceManager sourceManager, SettingsManager settingsManager ) { - super( null ); + super( sourceManager ); + + mSettingsManager = settingsManager; } + private SourceManager getSourceManager() + { + return (SourceManager)getUserObject(); + } + public String toString() { return "Recordings [" + this.getChildCount() + "]"; @@ -53,13 +64,12 @@ public class RecordingGroupNode extends BaseNode { RecordingConfiguration config = new RecordingConfiguration(); - getModel().getResourceManager().getSettingsManager() - .addRecordingConfiguration( config ); + mSettingsManager.addRecordingConfiguration( config ); - Recording recording = getModel().getResourceManager() + Recording recording = getSourceManager() .getRecordingSourceManager().addRecording( config ); - RecordingNode node = new RecordingNode( recording ); + RecordingNode node = new RecordingNode( getSourceManager(), recording ); getModel().addNode( node, RecordingGroupNode.this, 0 ); @@ -76,12 +86,12 @@ public class RecordingGroupNode extends BaseNode public void loadRecordings() { - List recordings = getModel().getResourceManager() + List recordings = getSourceManager() .getRecordingSourceManager().getRecordings(); for( Recording recording: recordings ) { - RecordingNode node = new RecordingNode( recording ); + RecordingNode node = new RecordingNode( getSourceManager(), recording ); getModel().addNode( node, this, 0 ); } diff --git a/src/source/recording/RecordingNode.java b/src/source/recording/RecordingNode.java index 54ec12fd..920602e3 100644 --- a/src/source/recording/RecordingNode.java +++ b/src/source/recording/RecordingNode.java @@ -8,6 +8,7 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; +import source.SourceManager; import controller.BaseNode; public class RecordingNode extends BaseNode @@ -15,8 +16,10 @@ public class RecordingNode extends BaseNode private static final long serialVersionUID = 1L; private JPanel mEditor; + + private SourceManager mSourceManager; - public RecordingNode( Recording recording ) + public RecordingNode( SourceManager sourceManager, Recording recording ) { super( recording ); } @@ -64,7 +67,7 @@ public class RecordingNode extends BaseNode } else { - getModel().getResourceManager().getRecordingSourceManager() + mSourceManager.getRecordingSourceManager() .removeRecording( getRecording() ); getModel().removeNodeFromParent( RecordingNode.this ); diff --git a/src/source/recording/RecordingSourceManager.java b/src/source/recording/RecordingSourceManager.java index 0fcabaef..8c2f444f 100644 --- a/src/source/recording/RecordingSourceManager.java +++ b/src/source/recording/RecordingSourceManager.java @@ -31,21 +31,23 @@ import source.config.SourceConfigRecording; import source.config.SourceConfiguration; import source.tuner.TunerChannel; import source.tuner.TunerChannelSource; -import controller.ResourceManager; +import controller.ThreadPoolManager; public class RecordingSourceManager { private final static Logger mLog = LoggerFactory.getLogger( RecordingSourceManager.class ); - private ResourceManager mResourceManager; - private ArrayList mRecordings = new ArrayList(); - public RecordingSourceManager( ResourceManager resourceManager ) + private SettingsManager mSettingsManager; + private ThreadPoolManager mThreadPoolManager; + + public RecordingSourceManager( SettingsManager settingsManager, + ThreadPoolManager threadPoolManager ) { - mResourceManager = resourceManager; - + mSettingsManager = settingsManager; + mThreadPoolManager = threadPoolManager; loadRecordings(); } @@ -71,9 +73,7 @@ public class RecordingSourceManager if( recording != null ) { - retVal = recording.getChannel( - mResourceManager.getThreadPoolManager(), - tunerChannel ); + retVal = recording.getChannel( mThreadPoolManager, tunerChannel ); } else { @@ -116,7 +116,7 @@ public class RecordingSourceManager public Recording addRecording( RecordingConfiguration config ) { - Recording recording = new Recording( mResourceManager, config ); + Recording recording = new Recording( mSettingsManager, config ); mRecordings.add( recording ); @@ -126,7 +126,7 @@ public class RecordingSourceManager public void removeRecording( Recording recording ) { /* Remove the config from the settings manager */ - mResourceManager.getSettingsManager().removeRecordingConfiguration( + mSettingsManager.removeRecordingConfiguration( recording.getRecordingConfiguration() ); mRecordings.remove( recording ); @@ -134,24 +134,17 @@ public class RecordingSourceManager private void loadRecordings() { - if( mResourceManager != null ) - { - SettingsManager settingsManager = mResourceManager.getSettingsManager(); - - if( settingsManager != null ) - { - ArrayList recordingConfigurations = - settingsManager.getRecordingConfigurations(); + ArrayList recordingConfigurations = + mSettingsManager.getRecordingConfigurations(); - mLog.info( "discovered [" + recordingConfigurations.size() + "] recording configurations" ); - - for( RecordingConfiguration config: recordingConfigurations ) - { - Recording recording = new Recording( mResourceManager, config ); - - mRecordings.add( recording ); - } - } - } - } + mLog.info( "RecordingSourceManager - discovered [" + + recordingConfigurations.size() + "] recording configurations" ); + + for( RecordingConfiguration config: recordingConfigurations ) + { + Recording recording = new Recording( mSettingsManager, config ); + + mRecordings.add( recording ); + } + } } diff --git a/src/buffer/ShortComplexByteBuffer.java b/src/source/tuner/ITunerChannelProvider.java similarity index 54% rename from src/buffer/ShortComplexByteBuffer.java rename to src/source/tuner/ITunerChannelProvider.java index 2aff0558..06f7b2fa 100644 --- a/src/buffer/ShortComplexByteBuffer.java +++ b/src/source/tuner/ITunerChannelProvider.java @@ -1,6 +1,6 @@ /******************************************************************************* * SDR Trunk - * Copyright (C) 2014 Dennis Sheirer + * Copyright (C) 2014-2016 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 @@ -15,39 +15,31 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see ******************************************************************************/ -package buffer; +package source.tuner; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.Enumeration; +import java.util.concurrent.RejectedExecutionException; -import sample.complex.Complex; +import source.SourceException; +import controller.ThreadPoolManager; -public class ShortComplexByteBuffer implements Enumeration +public interface ITunerChannelProvider { - private ByteBuffer mByteBuffer; - - public ShortComplexByteBuffer( byte[] bytes, ByteOrder endianness ) - { - mByteBuffer = ByteBuffer.wrap( bytes ); - mByteBuffer.order( endianness ); - } - - public byte[] array() - { - return mByteBuffer.array(); - } + /** + * 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; - @Override - public boolean hasMoreElements() - { - return mByteBuffer.hasRemaining(); - } - - @Override - public Complex nextElement() - { - return new Complex( (float)mByteBuffer.getShort(), - (float)mByteBuffer.getShort() ); - } + /** + * Releases the tuned channel resources + * + * @param channel - previously obtained tuner channel + */ + public abstract void releaseChannel( TunerChannelSource source ); + + } diff --git a/src/source/tuner/Tuner.java b/src/source/tuner/Tuner.java index e274c97f..805a3cb5 100644 --- a/src/source/tuner/Tuner.java +++ b/src/source/tuner/Tuner.java @@ -27,20 +27,18 @@ import org.slf4j.LoggerFactory; import sample.Listener; import sample.complex.ComplexBuffer; +import settings.SettingsManager; import source.SourceException; -import source.tuner.frequency.FrequencyChangeBroadcaster; import source.tuner.frequency.FrequencyChangeEvent; -import source.tuner.frequency.FrequencyChangeListener; import source.tuner.frequency.FrequencyChangeEvent.Event; -import controller.ResourceManager; +import source.tuner.frequency.IFrequencyChangeProcessor; import controller.ThreadPoolManager; /** * Tuner - provides tuner channel sources, representing a channel frequency */ -public abstract class Tuner implements FrequencyChangeBroadcaster, - FrequencyChangeListener, - TunerChannelProvider +public abstract class Tuner implements IFrequencyChangeProcessor, + ITunerChannelProvider { private final static Logger mLog = LoggerFactory.getLogger( Tuner.class ); @@ -53,8 +51,8 @@ public abstract class Tuner implements FrequencyChangeBroadcaster, protected CopyOnWriteArrayList> mSampleListeners = new CopyOnWriteArrayList>(); - protected CopyOnWriteArrayList - mFrequencyChangeListeners = new CopyOnWriteArrayList(); + protected CopyOnWriteArrayList + mFrequencyChangeProcessors = new CopyOnWriteArrayList(); public Tuner( String name ) { @@ -69,7 +67,7 @@ public abstract class Tuner implements FrequencyChangeBroadcaster, public void dispose() { mSampleListeners.clear(); - mFrequencyChangeListeners.clear(); + mFrequencyChangeProcessors.clear(); } public void setName( String name ) @@ -80,7 +78,7 @@ public abstract class Tuner implements FrequencyChangeBroadcaster, /** * Return an editor panel for the tuner */ - public abstract JPanel getEditor( ResourceManager resourceManager ); + public abstract JPanel getEditor( SettingsManager settingsManager ); /** @@ -191,17 +189,17 @@ public abstract class Tuner implements FrequencyChangeBroadcaster, * Adds the frequency change listener to receive frequency and/or bandwidth * change events */ - public void addListener( FrequencyChangeListener listener ) + public void addFrequencyChangeProcessor( IFrequencyChangeProcessor processor ) { - mFrequencyChangeListeners.add( listener ); + mFrequencyChangeProcessors.add( processor ); } /** * Removes the frequency change listener */ - public void removeListener( FrequencyChangeListener listener ) + public void removeFrequencyChangeProcessor( IFrequencyChangeProcessor processor ) { - mFrequencyChangeListeners.remove( listener ); + mFrequencyChangeProcessors.remove( processor ); } /** @@ -210,7 +208,7 @@ public abstract class Tuner implements FrequencyChangeBroadcaster, public void broadcastFrequencyChange( long frequency ) { broadcastFrequencyChangeEvent( - new FrequencyChangeEvent( Event.FREQUENCY_CHANGE_NOTIFICATION, frequency ) ); + new FrequencyChangeEvent( Event.NOTIFICATION_FREQUENCY_CHANGE, frequency ) ); } /** @@ -219,7 +217,7 @@ public abstract class Tuner implements FrequencyChangeBroadcaster, public void broadcastSampleRateChange( int sampleRate ) { broadcastFrequencyChangeEvent( - new FrequencyChangeEvent( Event.SAMPLE_RATE_CHANGE_NOTIFICATION, sampleRate ) ); + new FrequencyChangeEvent( Event.NOTIFICATION_SAMPLE_RATE_CHANGE, sampleRate ) ); } /** @@ -228,7 +226,7 @@ public abstract class Tuner implements FrequencyChangeBroadcaster, public void broadcastActualSampleRateChange( int actualSampleRate ) { broadcastFrequencyChangeEvent( - new FrequencyChangeEvent( Event.SAMPLE_RATE_CHANGE_NOTIFICATION, actualSampleRate ) ); + new FrequencyChangeEvent( Event.NOTIFICATION_SAMPLE_RATE_CHANGE, actualSampleRate ) ); } /** @@ -236,9 +234,9 @@ public abstract class Tuner implements FrequencyChangeBroadcaster, */ public void broadcastFrequencyChangeEvent( FrequencyChangeEvent event ) { - for( FrequencyChangeListener listener: mFrequencyChangeListeners ) + for( IFrequencyChangeProcessor processor: mFrequencyChangeProcessors ) { - listener.frequencyChanged( event ); + processor.frequencyChanged( event ); } } diff --git a/src/source/tuner/TunerChannelProvider.java b/src/source/tuner/TunerChannelProvider.java deleted file mode 100644 index f8fabe48..00000000 --- a/src/source/tuner/TunerChannelProvider.java +++ /dev/null @@ -1,28 +0,0 @@ -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 ); - - -} diff --git a/src/source/tuner/TunerChannelSource.java b/src/source/tuner/TunerChannelSource.java index 0c61dc60..010a6f7b 100644 --- a/src/source/tuner/TunerChannelSource.java +++ b/src/source/tuner/TunerChannelSource.java @@ -1,6 +1,6 @@ /******************************************************************************* * SDR Trunk - * Copyright (C) 2014,2015 Dennis Sheirer + * Copyright (C) 2014-2016 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 @@ -36,7 +36,7 @@ import source.ComplexSource; import source.SourceException; import source.tuner.frequency.FrequencyChangeEvent; import source.tuner.frequency.FrequencyChangeEvent.Event; -import source.tuner.frequency.FrequencyChangeListener; +import source.tuner.frequency.IFrequencyChangeProcessor; import controller.ThreadPoolManager; import controller.ThreadPoolManager.ThreadType; import dsp.filter.FilterFactory; @@ -45,8 +45,7 @@ import dsp.filter.cic.ComplexPrimeCICDecimate; import dsp.mixer.Oscillator; public class TunerChannelSource extends ComplexSource - implements FrequencyChangeListener, - Listener + implements IFrequencyChangeProcessor, Listener { private final static Logger mLog = LoggerFactory.getLogger( TunerChannelSource.class ); @@ -61,7 +60,7 @@ public class TunerChannelSource extends ComplexSource private Oscillator mMixer; private ComplexPrimeCICDecimate mDecimationFilter; private Listener mListener; - private FrequencyChangeListener mFrequencyChangeListener; + private IFrequencyChangeProcessor mFrequencyChangeProcessor; private ThreadPoolManager mThreadPoolManager; private ScheduledFuture mTaskHandle; @@ -71,17 +70,35 @@ public class TunerChannelSource extends ComplexSource private DecimationProcessor mDecimationProcessor = new DecimationProcessor(); - public TunerChannelSource( ThreadPoolManager threadPoolManager, - Tuner tuner, + private AtomicBoolean mRunning = new AtomicBoolean(); + private boolean mExpended = false; + + /** + * Provides a Digital Drop Channel (DDC) to decimate the IQ output from a + * tuner down to a 48 kHz IQ channel rate. + * + * Note: this class can only be used once (started and stopped) and a new + * tuner channel source must be requested from the tuner once this object + * has been stopped. This is because channels are managed dynamically and + * center tuned frequency may have changed since this source was obtained + * and thus the tuner might no longer be able to source this channel once it + * has been stopped. + * + * @param threadPoolManager to use for decimation processing task + * @param tuner to obtain wideband IQ samples from + * @param tunerChannel specifying the center frequency for the DDC + * @throws RejectedExecutionException if the thread pool manager cannot + * accept the decimation processing task + * @throws SourceException if the tuner has an issue providing IQ samples + */ + public TunerChannelSource( ThreadPoolManager threadPoolManager, Tuner tuner, TunerChannel tunerChannel ) throws RejectedExecutionException, SourceException { - super( "Tuner Channel Source" ); - mThreadPoolManager = threadPoolManager; mTuner = tuner; - mTuner.addListener( (FrequencyChangeListener)this ); + mTuner.addListener( this ); mTunerChannel = tunerChannel; @@ -94,59 +111,87 @@ public class TunerChannelSource extends ComplexSource /* Fire a sample rate change event to setup the decimation chain */ frequencyChanged( new FrequencyChangeEvent( - Event.SAMPLE_RATE_CHANGE_NOTIFICATION, mTuner.getSampleRate() ) ); - - /* Schedule the decimation task to run every 20 ms (50 iterations/second) */ - mTaskHandle = mThreadPoolManager.scheduleFixedRate( ThreadType.DECIMATION, - mDecimationProcessor, 20, TimeUnit.MILLISECONDS ); - - /* Finally, register to receive samples from the tuner */ - mTuner.addListener( (Listener)this ); + Event.NOTIFICATION_SAMPLE_RATE_CHANGE, mTuner.getSampleRate() ) ); } + @Override + public void reset() + { + } + + + @Override + public void start() + { + if( mExpended ) + { + throw new IllegalStateException( "Attempt to re-start an expended " + + "tuner channel source. TunerChannelSource objects can only " + + "be used once. " ); + } + + if( mRunning.compareAndSet( false, true )) + { + /* Schedule the decimation task to run every 20 ms (50 iterations/second) */ + mTaskHandle = mThreadPoolManager.scheduleFixedRate( ThreadType.DECIMATION, + mDecimationProcessor, 20, TimeUnit.MILLISECONDS ); + + /* Finally, register to receive samples from the tuner */ + mTuner.addListener( (Listener)this ); + } + else + { + mLog.warn( "Attempt to start() and already running tuner channel " + + "source was ignored" ); + } + } + + + @Override + public void stop() + { + if( mRunning.compareAndSet( true, false )) + { + mTuner.releaseChannel( this ); + mDecimationProcessor.shutdown(); + + if( mThreadPoolManager != null && mTaskHandle != null ) + { + mThreadPoolManager.cancel( mTaskHandle ); + mTaskHandle = null; + } + + mBuffer.clear(); + + mExpended = true; + } + else + { + mLog.warn( "Attempt to stop() and already stopped tuner channel " + + "source was ignored" ); + } + } + + + @Override public void dispose() { - /* Tell the tuner to release/unregister our resources */ - mTuner.removeListener( (FrequencyChangeListener)this ); - mTuner.releaseChannel( this ); - mTuner = null; - mTunerChannel = null; - - /* Flag the decimation processor to shutdown */ - if( mDecimationProcessor != null ) - { - mDecimationProcessor.dispose(); - } - + if( !mRunning.get() ) + { + /* Tell the tuner to release/unregister our resources */ + mTuner.removeFrequencyChangeProcessor( this ); + mTuner = null; + mTunerChannel = null; + mBuffer = null; + mFrequencyChangeProcessor = null; + mListener = null; + mMixer = null; + mDecimationFilter.dispose(); + mDecimationFilter = null; + } } - /** - * Cleanup method to allow the decimation processor to perform final cleanup - * once it gracefully shuts itself down - */ - private void cleanup() - { - if( mTaskHandle != null ) - { - mThreadPoolManager.cancel( mTaskHandle ); - mThreadPoolManager = null; - mTaskHandle = null; - } - - - mBuffer.clear(); - mBuffer = null; - - mFrequencyChangeListener = null; - mListener = null; - - mMixer = null; - - mDecimationFilter.dispose(); - mDecimationFilter = null; - } - public Tuner getTuner() { return mTuner; @@ -160,18 +205,21 @@ public class TunerChannelSource extends ComplexSource @Override public void receive( ComplexBuffer buffer ) { - mBuffer.add( buffer ); + if( mRunning.get() ) + { + mBuffer.add( buffer ); + } } - public void setFrequencyChangeListener( FrequencyChangeListener listener ) + public void setFrequencyChangeListener( IFrequencyChangeProcessor processor ) { - mFrequencyChangeListener = listener; + mFrequencyChangeProcessor = processor; } @Override public void setListener( Listener listener ) { - /* Get a pointer to the listener so that if we have to change the + /* Save a pointer to the listener so that if we have to change the * decimation filter, we can re-add the listener */ mListener = listener; @@ -192,31 +240,31 @@ public class TunerChannelSource extends ComplexSource public void frequencyChanged( FrequencyChangeEvent event ) { // Echo the event to the registered event listener - if( mFrequencyChangeListener != null ) + if( mFrequencyChangeProcessor != null ) { - mFrequencyChangeListener.frequencyChanged( event ); + mFrequencyChangeProcessor.frequencyChanged( event ); } switch( event.getEvent() ) { - case FREQUENCY_CHANGE_NOTIFICATION: + case NOTIFICATION_FREQUENCY_CHANGE: mTunerFrequency = event.getValue().longValue(); updateMixerFrequencyOffset(); break; - case CHANNEL_FREQUENCY_CORRECTION_CHANGE_REQUEST: + case REQUEST_CHANNEL_FREQUENCY_CORRECTION_CHANGE: mChannelFrequencyCorrection = event.getValue().intValue(); updateMixerFrequencyOffset(); - if( mFrequencyChangeListener != null ) + if( mFrequencyChangeProcessor != null ) { - mFrequencyChangeListener.frequencyChanged( + mFrequencyChangeProcessor.frequencyChanged( new FrequencyChangeEvent( - Event.CHANNEL_FREQUENCY_CORRECTION_CHANGE_NOTIFICATION, + Event.NOTIFICATION_CHANNEL_FREQUENCY_CORRECTION_CHANGE, mChannelFrequencyCorrection ) ); } break; - case SAMPLE_RATE_CHANGE_NOTIFICATION: + case NOTIFICATION_SAMPLE_RATE_CHANGE: int sampleRate = event.getValue().intValue(); if( mTunerSampleRate != sampleRate ) @@ -272,12 +320,12 @@ public class TunerChannelSource extends ComplexSource */ public class DecimationProcessor implements Runnable { - private AtomicBoolean mDispose = new AtomicBoolean( false ); + private boolean mProcessing = true; private List mSampleBuffers = new ArrayList(); - public void dispose() + public void shutdown() { - mDispose.set( true ); + mProcessing = false; } @Override @@ -288,64 +336,66 @@ public class TunerChannelSource extends ComplexSource * run the program out of memory */ try { - if( mBuffer != null ) + if( mProcessing ) { - mBuffer.drainTo( mSampleBuffers, 4 ); - - for( Buffer buffer: mSampleBuffers ) + if( mBuffer != null ) { - /* Check to see if we've been shutdown */ - if( mDispose.get() ) + mBuffer.drainTo( mSampleBuffers, 4 ); + + for( Buffer buffer: mSampleBuffers ) { - cleanup(); - return; - } - else - { - float[] samples = buffer.getSamples(); - - /* We make a copy of the buffer so that we don't affect - * anyone else that is using the same buffer, like other - * channels or the spectral display */ - float[] translated = new float[ samples.length ]; - - /* Perform frequency translation */ - for( int x = 0; x < samples.length; x += 2 ) + /* Check to see if we've been shutdown */ + if( !mProcessing ) { - mMixer.rotate(); + mBuffer.clear(); + return; + } + else + { + float[] samples = buffer.getSamples(); + + /* We make a copy of the buffer so that we don't affect + * anyone else that is using the same buffer, like other + * channels or the spectral display */ + float[] translated = new float[ samples.length ]; - translated[ x ] = Complex.multiplyInphase( - samples[ x ], samples[ x + 1 ], mMixer.inphase(), mMixer.quadrature() ); - - translated[ x + 1 ] = Complex.multiplyQuadrature( + /* Perform frequency translation */ + for( int x = 0; x < samples.length; x += 2 ) + { + mMixer.rotate(); + + translated[ x ] = Complex.multiplyInphase( samples[ x ], samples[ x + 1 ], mMixer.inphase(), mMixer.quadrature() ); - } - - if( mDecimationFilter != null ) - { - mDecimationFilter.receive( new ComplexBuffer( translated ) ); + + translated[ x + 1 ] = Complex.multiplyQuadrature( + samples[ x ], samples[ x + 1 ], mMixer.inphase(), mMixer.quadrature() ); + } + + if( mProcessing && mDecimationFilter != null ) + { + mDecimationFilter.receive( new ComplexBuffer( translated ) ); + } } } + + mSampleBuffers.clear(); } - - mSampleBuffers.clear(); } } catch( Exception e ) { - /* Only log the stack trace if we've haven't been shutdown and - * this is a true error */ - if( !mDispose.get() ) + /* Only log the stack trace if we're still processing */ + if( mProcessing ) { mLog.error( "Error encountered during decimation process", e ); } } /* Check to see if we've been shutdown */ - if( mDispose.get() ) + if( !mProcessing ) { + mBuffer.clear(); mSampleBuffers.clear(); - cleanup(); } } } diff --git a/src/source/tuner/TunerController.java b/src/source/tuner/TunerController.java index aacb5f6b..44682e7a 100644 --- a/src/source/tuner/TunerController.java +++ b/src/source/tuner/TunerController.java @@ -25,9 +25,10 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import source.SourceException; -import source.tuner.frequency.FrequencyChangeListener; import source.tuner.frequency.FrequencyController; import source.tuner.frequency.FrequencyController.Tunable; +import source.tuner.frequency.IFrequencyChangeProcessor; +import source.tuner.frequency.IFrequencyChangeListener; import controller.ThreadPoolManager; public abstract class TunerController implements Tunable @@ -36,7 +37,11 @@ public abstract class TunerController implements Tunable LoggerFactory.getLogger( TunerController.class ); /* List of currently tuned channels being served to demod channels */ +<<<<<<< Upstream, based on origin/master private SortedSet mTunedChannels = new ConcurrentSkipListSet<>(); +======= + protected ArrayList mTunedChannels = new ArrayList<>(); +>>>>>>> 20e3bee Work in progress. -Started work on new channel editor channel viewer/controller -Removed a number of unused buffer package classes -Moved automatic frequency control to be a module and removed special handling -Added IUnfilteredRealBufferListener & Provider interfaces -Completely removed the ResourceManager class protected FrequencyController mFrequencyController; private int mMiddleUnusable; private double mUsableBandwidthPercentage; @@ -359,16 +364,16 @@ public abstract class TunerController implements Tunable * Note: this is normally used by the Tuner. Any additional listeners can * be registered on the tuner. */ - public void addListener( FrequencyChangeListener listener ) + public void addListener( IFrequencyChangeProcessor processor ) { - mFrequencyController.addListener( listener ); + mFrequencyController.addListener( processor ); } /** * Removes the frequency change listener */ - public void removeListener( FrequencyChangeListener listener ) + public void removeListener( IFrequencyChangeProcessor processor ) { - mFrequencyController.removeListener( listener ); + mFrequencyController.removeFrequencyChangeProcessor( processor ); } } diff --git a/src/source/tuner/TunerEditor.java b/src/source/tuner/TunerEditor.java index 15b3d650..2be792a1 100644 --- a/src/source/tuner/TunerEditor.java +++ b/src/source/tuner/TunerEditor.java @@ -17,21 +17,23 @@ ******************************************************************************/ package source.tuner; +import controller.channel.Channel; +import controller.channel.ConfigurationValidationException; import gui.control.JFrequencyControl; import source.SourceEditor; +import source.SourceManager; 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( ResourceManager resourceManager, + public TunerEditor( SourceManager sourceManager, SourceConfiguration config ) { - super( resourceManager, config ); + super( sourceManager, config ); initGUI(); } @@ -56,4 +58,18 @@ public class TunerEditor extends SourceEditor add( mFrequencyControl ); } + + @Override + public void setConfiguration( Channel channel ) + { + // TODO Auto-generated method stub + + } + + @Override + public void validateConfiguration() throws ConfigurationValidationException + { + // TODO Auto-generated method stub + + } } diff --git a/src/source/tuner/TunerManager.java b/src/source/tuner/TunerManager.java index 345757f3..3d6f351c 100644 --- a/src/source/tuner/TunerManager.java +++ b/src/source/tuner/TunerManager.java @@ -30,6 +30,7 @@ import org.usb4java.DeviceDescriptor; import org.usb4java.DeviceList; import org.usb4java.LibUsb; +import settings.SettingsManager; import source.Source; import source.SourceException; import source.config.SourceConfigTuner; @@ -46,22 +47,25 @@ import source.tuner.rtl.RTL2832Tuner; import source.tuner.rtl.RTL2832TunerController; import source.tuner.rtl.e4k.E4KTunerController; import source.tuner.rtl.r820t.R820TTunerController; -import controller.ResourceManager; +import controller.ThreadPoolManager; public class TunerManager { private final static Logger mLog = LoggerFactory.getLogger( TunerManager.class ); - private ResourceManager mResourceManager; private ArrayList mTuners = new ArrayList(); + + private MixerManager mMixerManager; + private SettingsManager mSettingsManager; + private ThreadPoolManager mThreadPoolManager; - public TunerManager( ResourceManager resourceManager ) + public TunerManager( MixerManager mixerManager, + SettingsManager settingsManager, + ThreadPoolManager threadPoolManager ) { - mResourceManager = resourceManager; - - /* initialize mixers */ - MixerManager.getInstance(); + mSettingsManager = settingsManager; + mThreadPoolManager = threadPoolManager; initTuners(); } @@ -100,8 +104,7 @@ public class TunerManager try { - retVal = tuner.getChannel( - mResourceManager.getThreadPoolManager(), tunerChannel ); + retVal = tuner.getChannel( mThreadPoolManager, tunerChannel ); } catch ( RejectedExecutionException ree ) { @@ -261,7 +264,7 @@ public class TunerManager try { AirspyTunerController airspyController = - new AirspyTunerController( device, mResourceManager.getThreadPoolManager() ); + new AirspyTunerController( device, mThreadPoolManager ); airspyController.init(); @@ -397,7 +400,7 @@ public class TunerManager { HackRFTunerController hackRFController = new HackRFTunerController( device, descriptor, - mResourceManager.getThreadPoolManager() ); + mThreadPoolManager ); hackRFController.init(); @@ -449,7 +452,7 @@ public class TunerManager { E4KTunerController controller = new E4KTunerController( device, deviceDescriptor, - mResourceManager.getThreadPoolManager() ); + mThreadPoolManager ); controller.init(); @@ -476,7 +479,7 @@ public class TunerManager { R820TTunerController controller = new R820TTunerController( device, deviceDescriptor, - mResourceManager.getThreadPoolManager() ); + mThreadPoolManager ); controller.init(); @@ -526,12 +529,11 @@ public class TunerManager */ private TunerConfiguration getTunerConfiguration( Tuner tuner ) { - TunerConfigurationAssignment selected = mResourceManager - .getSettingsManager().getSelectedTunerConfiguration( - tuner.getTunerType(), tuner.getUniqueID() ); + TunerConfigurationAssignment selected = mSettingsManager + .getSelectedTunerConfiguration( tuner.getTunerType(), tuner.getUniqueID() ); - ArrayList configs = mResourceManager - .getSettingsManager().getTunerConfigurations( tuner.getTunerType() ); + ArrayList configs = mSettingsManager + .getTunerConfigurations( tuner.getTunerType() ); TunerConfiguration config = null; @@ -553,13 +555,13 @@ public class TunerManager //If we're still null at this point, create a default config if( config == null ) { - config = mResourceManager.getSettingsManager() - .addNewTunerConfiguration( tuner.getTunerType(), "Default" ); + config = mSettingsManager.addNewTunerConfiguration( + tuner.getTunerType(), "Default" ); } //Persist the config as the selected tuner configuration. The method //auto-saves the setting - mResourceManager.getSettingsManager().setSelectedTunerConfiguration( + mSettingsManager.setSelectedTunerConfiguration( tuner.getTunerType(), tuner.getUniqueID(), config ); return config; @@ -579,7 +581,7 @@ public class TunerManager private MixerTunerDataLine getMixerTunerDataLine( TunerType tunerClass ) { Collection datalines = - MixerManager.getInstance().getMixerTunerDataLines(); + mMixerManager.getMixerTunerDataLines(); for( MixerTunerDataLine mixerTDL: datalines ) { diff --git a/src/source/tuner/TunerNode.java b/src/source/tuner/TunerNode.java index 626cda6b..63aabd9c 100644 --- a/src/source/tuner/TunerNode.java +++ b/src/source/tuner/TunerNode.java @@ -28,15 +28,17 @@ import javax.swing.JPopupMenu; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import playlist.PlaylistManager; +import settings.SettingsManager; import source.SourceException; import source.tuner.frequency.FrequencyChangeEvent; -import source.tuner.frequency.FrequencyChangeListener; +import source.tuner.frequency.IFrequencyChangeProcessor; import spectrum.SpectrumFrame; import controller.BaseNode; -import controller.ResourceManager; import controller.channel.ChannelModel; +import controller.channel.ChannelProcessingManager; -public class TunerNode extends BaseNode implements FrequencyChangeListener +public class TunerNode extends BaseNode implements IFrequencyChangeProcessor { private final static Logger mLog = LoggerFactory.getLogger( TunerNode.class ); @@ -48,14 +50,24 @@ public class TunerNode extends BaseNode implements FrequencyChangeListener private long mFrequency; private int mSampleRate; private ChannelModel mChannelModel; + private ChannelProcessingManager mChannelProcessingManager; + private PlaylistManager mPlaylistManager; + private SettingsManager mSettingsManager; - public TunerNode( ChannelModel channelModel, Tuner tuner ) + public TunerNode( ChannelModel channelModel, + ChannelProcessingManager channelProcessingManager, + PlaylistManager playlistManager, + SettingsManager settingsManager, + Tuner tuner ) { super( tuner ); //does this make it a super tuner? mChannelModel = channelModel; + mChannelProcessingManager = channelProcessingManager; + mPlaylistManager = playlistManager; + mSettingsManager = settingsManager; - tuner.addListener( this ); + tuner.addFrequencyChangeProcessor( this ); try { @@ -72,7 +84,7 @@ public class TunerNode extends BaseNode implements FrequencyChangeListener @Override public JPanel getEditor() { - return getTuner().getEditor( getModel().getResourceManager() ); + return getTuner().getEditor( mSettingsManager ); } public Tuner getTuner() @@ -117,11 +129,9 @@ public class TunerNode extends BaseNode implements FrequencyChangeListener @Override public void actionPerformed( ActionEvent e ) { - ResourceManager rm = getModel().getResourceManager(); - - SpectrumFrame frame = new SpectrumFrame( mChannelModel, - rm.getController(), rm.getPlaylistManager(), - rm.getSettingsManager(), getTuner() ); + SpectrumFrame frame = new SpectrumFrame( getModel(), mChannelModel, + mChannelProcessingManager, mPlaylistManager, + mSettingsManager, getTuner() ); } } ); @@ -135,7 +145,7 @@ public class TunerNode extends BaseNode implements FrequencyChangeListener { switch( event.getEvent() ) { - case FREQUENCY_CHANGE_NOTIFICATION: + case NOTIFICATION_FREQUENCY_CHANGE: long frequency = event.getValue().longValue(); if( mFrequency != frequency ) @@ -144,7 +154,7 @@ public class TunerNode extends BaseNode implements FrequencyChangeListener getModel().nodeChanged( TunerNode.this ); } break; - case SAMPLE_RATE_CHANGE_NOTIFICATION: + case NOTIFICATION_SAMPLE_RATE_CHANGE: int sampleRate = event.getValue().intValue(); if( mSampleRate != sampleRate ) diff --git a/src/source/tuner/airspy/AirspyTuner.java b/src/source/tuner/airspy/AirspyTuner.java index 36df0315..345b3456 100644 --- a/src/source/tuner/airspy/AirspyTuner.java +++ b/src/source/tuner/airspy/AirspyTuner.java @@ -26,6 +26,7 @@ import org.slf4j.LoggerFactory; import sample.Listener; import sample.complex.ComplexBuffer; +import settings.SettingsManager; import source.SourceException; import source.tuner.Tuner; import source.tuner.TunerChannel; @@ -34,7 +35,6 @@ import source.tuner.TunerClass; import source.tuner.TunerConfiguration; import source.tuner.TunerType; import source.tuner.airspy.AirspyTunerController.BoardID; -import controller.ResourceManager; import controller.ThreadPoolManager; public class AirspyTuner extends Tuner @@ -55,9 +55,9 @@ public class AirspyTuner extends Tuner } @Override - public JPanel getEditor( ResourceManager resourceManager ) + public JPanel getEditor( SettingsManager settingsManager ) { - return new AirspyTunerEditorPanel( this, resourceManager ); + return new AirspyTunerEditorPanel( this, settingsManager ); } public AirspyTunerController getController() diff --git a/src/source/tuner/airspy/AirspyTunerConfigurationPanel.java b/src/source/tuner/airspy/AirspyTunerConfigurationPanel.java index e2d31475..937a63f8 100644 --- a/src/source/tuner/airspy/AirspyTunerConfigurationPanel.java +++ b/src/source/tuner/airspy/AirspyTunerConfigurationPanel.java @@ -45,13 +45,13 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.usb4java.LibUsbException; +import settings.SettingsManager; import source.SourceException; import source.tuner.TunerConfiguration; import source.tuner.TunerConfigurationAssignment; import source.tuner.TunerType; import source.tuner.airspy.AirspyTunerController.Gain; import source.tuner.airspy.AirspyTunerController.GainMode; -import controller.ResourceManager; public class AirspyTunerConfigurationPanel extends JPanel { @@ -60,7 +60,7 @@ public class AirspyTunerConfigurationPanel extends JPanel private static final long serialVersionUID = 1L; - private ResourceManager mResourceManager; + private SettingsManager mSettingsManager; private AirspyTunerController mController; private AirspyTunerConfiguration mSelectedConfig; @@ -94,10 +94,10 @@ public class AirspyTunerConfigurationPanel extends JPanel private JSlider mMixerGain; - public AirspyTunerConfigurationPanel( ResourceManager resourceManager, + public AirspyTunerConfigurationPanel( SettingsManager settingsManager, AirspyTunerController controller ) { - mResourceManager = resourceManager; + mSettingsManager = settingsManager; mController = controller; init(); @@ -126,8 +126,7 @@ public class AirspyTunerConfigurationPanel extends JPanel if( serial != null ) { - savedConfig = mResourceManager - .getSettingsManager().getSelectedTunerConfiguration( + savedConfig = mSettingsManager.getSelectedTunerConfiguration( TunerType.AIRSPY_R820T, serial ); } @@ -146,8 +145,7 @@ public class AirspyTunerConfigurationPanel extends JPanel if( serial != null ) { - mResourceManager.getSettingsManager() - .setSelectedTunerConfiguration( TunerType.AIRSPY_R820T, + mSettingsManager.setSelectedTunerConfiguration( TunerType.AIRSPY_R820T, serial, mSelectedConfig ); } } @@ -518,8 +516,7 @@ public class AirspyTunerConfigurationPanel extends JPanel public void actionPerformed( ActionEvent e ) { TunerConfiguration config = - mResourceManager.getSettingsManager() - .addNewTunerConfiguration( + mSettingsManager.addNewTunerConfiguration( TunerType.AIRSPY_R820T, "New Configuration" ); @@ -558,8 +555,7 @@ public class AirspyTunerConfigurationPanel extends JPanel if( n == JOptionPane.YES_OPTION ) { - mResourceManager.getSettingsManager() - .deleteTunerConfiguration( selected ); + mSettingsManager.deleteTunerConfiguration( selected ); mComboConfigurations.setModel( getModel() ); @@ -635,7 +631,7 @@ public class AirspyTunerConfigurationPanel extends JPanel mGainModeCombo.setSelectedItem( Gain.getGainMode( gain ) ); mGain.setValue( gain.getValue() ); - mResourceManager.getSettingsManager().setSelectedTunerConfiguration( + mSettingsManager.setSelectedTunerConfiguration( TunerType.AIRSPY_R820T, mController.getDeviceInfo().getSerialNumber(), config ); save(); @@ -661,8 +657,7 @@ public class AirspyTunerConfigurationPanel extends JPanel private ComboBoxModel getModel() { ArrayList configs = - mResourceManager.getSettingsManager() - .getTunerConfigurations( TunerType.AIRSPY_R820T ); + mSettingsManager.getTunerConfigurations( TunerType.AIRSPY_R820T ); DefaultComboBoxModel model = new DefaultComboBoxModel(); @@ -681,8 +676,7 @@ public class AirspyTunerConfigurationPanel extends JPanel private AirspyTunerConfiguration getNamedConfiguration( String name ) { ArrayList configs = - mResourceManager.getSettingsManager() - .getTunerConfigurations( TunerType.AIRSPY_R820T ); + mSettingsManager.getTunerConfigurations( TunerType.AIRSPY_R820T ); for( TunerConfiguration config: configs ) { @@ -700,6 +694,6 @@ public class AirspyTunerConfigurationPanel extends JPanel */ private void save() { - mResourceManager.getSettingsManager().save(); + mSettingsManager.save(); } } diff --git a/src/source/tuner/airspy/AirspyTunerEditorPanel.java b/src/source/tuner/airspy/AirspyTunerEditorPanel.java index d15037f7..7305fce4 100644 --- a/src/source/tuner/airspy/AirspyTunerEditorPanel.java +++ b/src/source/tuner/airspy/AirspyTunerEditorPanel.java @@ -29,17 +29,16 @@ import net.miginfocom.swing.MigLayout; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import settings.SettingsManager; import source.SourceException; import source.tuner.frequency.FrequencyChangeEvent; import source.tuner.frequency.FrequencyChangeEvent.Event; -import source.tuner.frequency.FrequencyChangeListener; +import source.tuner.frequency.IFrequencyChangeProcessor; import com.jidesoft.swing.JideTabbedPane; -import controller.ResourceManager; - public class AirspyTunerEditorPanel extends JPanel - implements FrequencyChangeListener + implements IFrequencyChangeProcessor { private static final long serialVersionUID = 1L; @@ -50,14 +49,14 @@ public class AirspyTunerEditorPanel extends JPanel private AirspyTuner mTuner; private AirspyTunerController mController; - private ResourceManager mResourceManager; + private SettingsManager mSettingsManager; public AirspyTunerEditorPanel( AirspyTuner tuner, - ResourceManager resourceManager ) + SettingsManager settingsManager ) { mTuner = tuner; mController = mTuner.getController(); - mResourceManager = resourceManager; + mSettingsManager = settingsManager; initGUI(); } @@ -76,7 +75,7 @@ public class AirspyTunerEditorPanel extends JPanel /* Add frequency control as frequency change listener. This creates a * feedback loop, so the control does not rebroadcast the event */ - mTuner.addListener( mFrequencyControl ); + mTuner.addFrequencyChangeProcessor( mFrequencyControl ); mFrequencyControl.setFrequency( mController.getFrequency(), false ); @@ -89,7 +88,7 @@ public class AirspyTunerEditorPanel extends JPanel add( tabs, "span,grow,push" ); tabs.add( "Config", new AirspyTunerConfigurationPanel( - mResourceManager, mTuner.getController() ) ); + mSettingsManager, mTuner.getController() ) ); tabs.add( "Info", new AirspyInformationPanel( mTuner.getController() ) ); } @@ -97,7 +96,7 @@ public class AirspyTunerEditorPanel extends JPanel @Override public void frequencyChanged( FrequencyChangeEvent event ) { - if( event.getEvent() == Event.FREQUENCY_CHANGE_NOTIFICATION ) + if( event.getEvent() == Event.NOTIFICATION_FREQUENCY_CHANGE ) { try { diff --git a/src/source/tuner/ettus/B100Tuner.java b/src/source/tuner/ettus/B100Tuner.java index 9ec27054..11cbc94f 100644 --- a/src/source/tuner/ettus/B100Tuner.java +++ b/src/source/tuner/ettus/B100Tuner.java @@ -24,6 +24,7 @@ import javax.swing.JPanel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import settings.SettingsManager; import source.SourceException; import source.tuner.Tuner; import source.tuner.TunerChannel; @@ -32,7 +33,6 @@ import source.tuner.TunerClass; import source.tuner.TunerConfiguration; import source.tuner.TunerType; import source.tuner.usb.USBTunerDevice; -import controller.ResourceManager; import controller.ThreadPoolManager; public class B100Tuner extends Tuner @@ -69,9 +69,9 @@ public class B100Tuner extends Tuner } @Override - public JPanel getEditor( ResourceManager resourceManager ) + public JPanel getEditor( SettingsManager settingsManager ) { - return new B100TunerEditorPanel( this, resourceManager ); + return new B100TunerEditorPanel( this, settingsManager ); } @Override diff --git a/src/source/tuner/ettus/B100TunerEditorPanel.java b/src/source/tuner/ettus/B100TunerEditorPanel.java index 964ac4ee..aadd2fec 100644 --- a/src/source/tuner/ettus/B100TunerEditorPanel.java +++ b/src/source/tuner/ettus/B100TunerEditorPanel.java @@ -22,19 +22,19 @@ import javax.swing.JLabel; import javax.swing.JPanel; import net.miginfocom.swing.MigLayout; -import controller.ResourceManager; +import settings.SettingsManager; public class B100TunerEditorPanel extends JPanel { private static final long serialVersionUID = 1L; private B100Tuner mTuner; - private ResourceManager mResourceManager; + private SettingsManager mSettingsManager; - public B100TunerEditorPanel( B100Tuner tuner, ResourceManager resourceManager ) + public B100TunerEditorPanel( B100Tuner tuner, SettingsManager settingsManager ) { mTuner = tuner; - mResourceManager = resourceManager; + mSettingsManager = settingsManager; init(); } diff --git a/src/source/tuner/fcd/FCDTuner.java b/src/source/tuner/fcd/FCDTuner.java index ea84063c..e3d680a5 100644 --- a/src/source/tuner/fcd/FCDTuner.java +++ b/src/source/tuner/fcd/FCDTuner.java @@ -24,6 +24,7 @@ import javax.swing.JPanel; import sample.Listener; import sample.adapter.ShortAdapter; import sample.complex.ComplexBuffer; +import settings.SettingsManager; import source.SourceException; import source.tuner.MixerTuner; import source.tuner.MixerTunerDataLine; @@ -32,8 +33,6 @@ import source.tuner.TunerChannelSource; import source.tuner.TunerClass; import source.tuner.TunerConfiguration; import source.tuner.TunerType; -import source.tuner.frequency.FrequencyChangeListener; -import controller.ResourceManager; import controller.ThreadPoolManager; public class FCDTuner extends MixerTuner @@ -48,7 +47,7 @@ public class FCDTuner extends MixerTuner new ShortAdapter() ); mController = controller; - mController.addListener( (FrequencyChangeListener)this ); + mController.addListener( this ); } public void dispose() @@ -82,9 +81,9 @@ public class FCDTuner extends MixerTuner } @Override - public JPanel getEditor( ResourceManager resourceManager ) + public JPanel getEditor( SettingsManager settingsManager ) { - return mController.getEditor( this, resourceManager ); + return mController.getEditor( this, settingsManager ); } @Override diff --git a/src/source/tuner/fcd/FCDTunerController.java b/src/source/tuner/fcd/FCDTunerController.java index 8e6ff030..ca602ed2 100644 --- a/src/source/tuner/fcd/FCDTunerController.java +++ b/src/source/tuner/fcd/FCDTunerController.java @@ -33,13 +33,13 @@ import org.usb4java.DeviceHandle; import org.usb4java.LibUsb; import org.usb4java.LibUsbException; +import settings.SettingsManager; import source.SourceException; import source.tuner.TunerClass; import source.tuner.TunerConfiguration; import source.tuner.TunerController; import source.tuner.TunerType; import source.tuner.fcd.proV1.FCD1TunerController.Block; -import controller.ResourceManager; public abstract class FCDTunerController extends TunerController { @@ -150,7 +150,7 @@ public abstract class FCDTunerController extends TunerController * Editor panel (GUI) component. */ public abstract JPanel getEditor( FCDTuner tuner, - ResourceManager resourceManager ); + SettingsManager settingsManager ); /** * Applies the settings in the tuner configuration diff --git a/src/source/tuner/fcd/proV1/FCD1TunerConfigurationPanel.java b/src/source/tuner/fcd/proV1/FCD1TunerConfigurationPanel.java index bfbe7fbb..b54bef0b 100644 --- a/src/source/tuner/fcd/proV1/FCD1TunerConfigurationPanel.java +++ b/src/source/tuner/fcd/proV1/FCD1TunerConfigurationPanel.java @@ -47,6 +47,7 @@ import net.miginfocom.swing.MigLayout; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import settings.SettingsManager; import source.SourceException; import source.tuner.TunerConfiguration; import source.tuner.TunerType; @@ -56,15 +57,13 @@ import source.tuner.fcd.proV1.FCD1TunerController.MixerGain; import com.jidesoft.swing.JideTabbedPane; -import controller.ResourceManager; - public class FCD1TunerConfigurationPanel extends JPanel { private final static Logger mLog = LoggerFactory.getLogger( FCD1TunerConfigurationPanel.class ); private static final long serialVersionUID = 1L; - private ResourceManager mResourceManager; + private SettingsManager mSettingsManager; private FCD1TunerController mController; private FCD1TunerConfiguration mSelectedConfig; @@ -81,10 +80,10 @@ public class FCD1TunerConfigurationPanel extends JPanel private CorrectionSpinner mCorrectionGain; private CorrectionSpinner mCorrectionPhase; - public FCD1TunerConfigurationPanel( ResourceManager resourceManager, + public FCD1TunerConfigurationPanel( SettingsManager settingsManager, FCD1TunerController controller ) { - mResourceManager = resourceManager; + mSettingsManager = settingsManager; mController = controller; mSelectedConfig = controller.getTunerConfiguration(); @@ -428,8 +427,7 @@ public class FCD1TunerConfigurationPanel extends JPanel public void actionPerformed( ActionEvent e ) { TunerConfiguration config = - mResourceManager.getSettingsManager() - .addNewTunerConfiguration( + mSettingsManager.addNewTunerConfiguration( TunerType.FUNCUBE_DONGLE_PRO, "New Configuration" ); @@ -472,8 +470,7 @@ public class FCD1TunerConfigurationPanel extends JPanel if( n == JOptionPane.YES_OPTION ) { - mResourceManager.getSettingsManager() - .deleteTunerConfiguration( selected ); + mSettingsManager.deleteTunerConfiguration( selected ); mComboConfigurations.setModel( getModel() ); @@ -508,8 +505,7 @@ public class FCD1TunerConfigurationPanel extends JPanel mCorrectionGain.setValue( config.getGainCorrection() ); mCorrectionPhase.setValue( config.getPhaseCorrection() ); - mResourceManager.getSettingsManager() - .setSelectedTunerConfiguration( + mSettingsManager.setSelectedTunerConfiguration( TunerType.FUNCUBE_DONGLE_PRO, mController.getUSBAddress(), config ); } @@ -529,8 +525,7 @@ public class FCD1TunerConfigurationPanel extends JPanel private ComboBoxModel getModel() { ArrayList configs = - mResourceManager.getSettingsManager() - .getTunerConfigurations( TunerType.FUNCUBE_DONGLE_PRO ); + mSettingsManager.getTunerConfigurations( TunerType.FUNCUBE_DONGLE_PRO ); DefaultComboBoxModel model = new DefaultComboBoxModel(); @@ -547,8 +542,7 @@ public class FCD1TunerConfigurationPanel extends JPanel private FCD1TunerConfiguration getNamedConfiguration( String name ) { ArrayList configs = - mResourceManager.getSettingsManager() - .getTunerConfigurations( TunerType.FUNCUBE_DONGLE_PRO ); + mSettingsManager.getTunerConfigurations( TunerType.FUNCUBE_DONGLE_PRO ); for( TunerConfiguration config: configs ) { @@ -563,7 +557,7 @@ public class FCD1TunerConfigurationPanel extends JPanel private void save() { - mResourceManager.getSettingsManager().save(); + mSettingsManager.save(); } public enum Correction { GAIN, PHASE, DC_INPHASE, DC_QUADRATURE }; diff --git a/src/source/tuner/fcd/proV1/FCD1TunerController.java b/src/source/tuner/fcd/proV1/FCD1TunerController.java index 9d56b0f4..8de3053c 100644 --- a/src/source/tuner/fcd/proV1/FCD1TunerController.java +++ b/src/source/tuner/fcd/proV1/FCD1TunerController.java @@ -29,6 +29,7 @@ import org.slf4j.LoggerFactory; import org.usb4java.Device; import org.usb4java.DeviceDescriptor; +import settings.SettingsManager; import source.SourceException; import source.tuner.TunerClass; import source.tuner.TunerConfiguration; @@ -36,7 +37,6 @@ import source.tuner.TunerType; import source.tuner.fcd.FCDCommand; import source.tuner.fcd.FCDTuner; import source.tuner.fcd.FCDTunerController; -import controller.ResourceManager; public class FCD1TunerController extends FCDTunerController { @@ -148,11 +148,11 @@ public class FCD1TunerController extends FCDTunerController } @Override - public JPanel getEditor( FCDTuner tuner, ResourceManager resourceManager ) + public JPanel getEditor( FCDTuner tuner, SettingsManager settingsManager ) { if( mEditor == null ) { - mEditor = new FCD1TunerEditorPanel( tuner, resourceManager ); + mEditor = new FCD1TunerEditorPanel( tuner, settingsManager ); } return mEditor; diff --git a/src/source/tuner/fcd/proV1/FCD1TunerEditorPanel.java b/src/source/tuner/fcd/proV1/FCD1TunerEditorPanel.java index 317fcaeb..83512616 100644 --- a/src/source/tuner/fcd/proV1/FCD1TunerEditorPanel.java +++ b/src/source/tuner/fcd/proV1/FCD1TunerEditorPanel.java @@ -29,18 +29,17 @@ import net.miginfocom.swing.MigLayout; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import settings.SettingsManager; import source.SourceException; import source.tuner.fcd.FCDTuner; import source.tuner.fcd.FCDTunerDetailsPanel; import source.tuner.frequency.FrequencyChangeEvent; -import source.tuner.frequency.FrequencyChangeListener; import source.tuner.frequency.FrequencyChangeEvent.Event; +import source.tuner.frequency.IFrequencyChangeProcessor; import com.jidesoft.swing.JideTabbedPane; -import controller.ResourceManager; - -public class FCD1TunerEditorPanel extends JPanel implements FrequencyChangeListener +public class FCD1TunerEditorPanel extends JPanel implements IFrequencyChangeProcessor { private static final long serialVersionUID = 1L; private final static Logger mLog = @@ -48,15 +47,15 @@ public class FCD1TunerEditorPanel extends JPanel implements FrequencyChangeListe private FCDTuner mTuner; private FCD1TunerController mController; - private ResourceManager mResourceManager; + private SettingsManager mSettingsManager; private JFrequencyControl mFrequencyControl; - public FCD1TunerEditorPanel( FCDTuner tuner, ResourceManager resourceManager ) + public FCD1TunerEditorPanel( FCDTuner tuner, SettingsManager settingsManager ) { mTuner = tuner; mController = (FCD1TunerController)mTuner.getController(); - mResourceManager = resourceManager; + mSettingsManager = settingsManager; initGUI(); } @@ -74,7 +73,7 @@ public class FCD1TunerEditorPanel extends JPanel implements FrequencyChangeListe /* Add frequency control as listener to tuner to get frequency changes * that are invoked elsewhere, to keep the control in sync with the * frequency */ - mTuner.addListener( mFrequencyControl ); + mTuner.addFrequencyChangeProcessor( mFrequencyControl ); mFrequencyControl.setFrequency( mController.getFrequency(), false ); @@ -85,7 +84,7 @@ public class FCD1TunerEditorPanel extends JPanel implements FrequencyChangeListe tabs.setForeground( Color.BLACK ); tabs.add( "Configuration", new FCD1TunerConfigurationPanel( - mResourceManager, mController ) ); + mSettingsManager, mController ) ); tabs.add( "Info", new FCDTunerDetailsPanel( mController ) ); @@ -95,7 +94,7 @@ public class FCD1TunerEditorPanel extends JPanel implements FrequencyChangeListe @Override public void frequencyChanged( FrequencyChangeEvent event ) { - if( event.getEvent() == Event.FREQUENCY_CHANGE_NOTIFICATION ) + if( event.getEvent() == Event.NOTIFICATION_FREQUENCY_CHANGE ) { try { diff --git a/src/source/tuner/fcd/proplusV2/FCD2TunerConfigurationPanel.java b/src/source/tuner/fcd/proplusV2/FCD2TunerConfigurationPanel.java index bb6acbea..8bd20ac9 100644 --- a/src/source/tuner/fcd/proplusV2/FCD2TunerConfigurationPanel.java +++ b/src/source/tuner/fcd/proplusV2/FCD2TunerConfigurationPanel.java @@ -46,11 +46,11 @@ import net.miginfocom.swing.MigLayout; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import settings.SettingsManager; import source.SourceException; import source.tuner.TunerConfiguration; import source.tuner.TunerConfigurationAssignment; import source.tuner.TunerType; -import controller.ResourceManager; public class FCD2TunerConfigurationPanel extends JPanel { @@ -58,7 +58,7 @@ public class FCD2TunerConfigurationPanel extends JPanel LoggerFactory.getLogger( FCD2TunerConfigurationPanel.class ); private static final long serialVersionUID = 1L; - private ResourceManager mResourceManager; + private SettingsManager mSettingsManager; private FCD2TunerController mController; private FCD2TunerConfiguration mSelectedConfig; private JButton mNewConfiguration; @@ -69,10 +69,10 @@ public class FCD2TunerConfigurationPanel extends JPanel private JCheckBox mMixerGain; private JSpinner mFrequencyCorrection; - public FCD2TunerConfigurationPanel( ResourceManager resourceManager, + public FCD2TunerConfigurationPanel( SettingsManager settingsManager, FCD2TunerController controller ) { - mResourceManager = resourceManager; + mSettingsManager = settingsManager; mController = controller; init(); @@ -218,8 +218,8 @@ public class FCD2TunerConfigurationPanel extends JPanel * Lookup the save config and apply that config to update all of the * controls */ - TunerConfigurationAssignment savedConfig = mResourceManager - .getSettingsManager().getSelectedTunerConfiguration( + TunerConfigurationAssignment savedConfig = mSettingsManager + .getSelectedTunerConfiguration( TunerType.FUNCUBE_DONGLE_PRO_PLUS, mController.getUSBAddress() ); @@ -234,7 +234,7 @@ public class FCD2TunerConfigurationPanel extends JPanel mSelectedConfig = mComboConfigurations.getItemAt( 0 ); //Store this config as the default for this tuner at this address - mResourceManager.getSettingsManager() + mSettingsManager .setSelectedTunerConfiguration( TunerType.FUNCUBE_DONGLE_PRO_PLUS, mController.getUSBAddress(), mSelectedConfig ); @@ -253,7 +253,7 @@ public class FCD2TunerConfigurationPanel extends JPanel public void actionPerformed( ActionEvent e ) { TunerConfiguration config = - mResourceManager.getSettingsManager() + mSettingsManager .addNewTunerConfiguration( TunerType.FUNCUBE_DONGLE_PRO_PLUS, "New Configuration" ); @@ -293,7 +293,7 @@ public class FCD2TunerConfigurationPanel extends JPanel if( n == JOptionPane.YES_OPTION ) { - mResourceManager.getSettingsManager() + mSettingsManager .deleteTunerConfiguration( selected ); mComboConfigurations.setModel( getModel() ); @@ -322,7 +322,7 @@ public class FCD2TunerConfigurationPanel extends JPanel mMixerGain.setSelected( config.getGainMixer() ); mFrequencyCorrection.setValue( config.getFrequencyCorrection() ); - mResourceManager.getSettingsManager().setSelectedTunerConfiguration( + mSettingsManager.setSelectedTunerConfiguration( TunerType.FUNCUBE_DONGLE_PRO_PLUS, mController.getUSBAddress(), config ); } @@ -342,7 +342,7 @@ public class FCD2TunerConfigurationPanel extends JPanel private ComboBoxModel getModel() { ArrayList configs = - mResourceManager.getSettingsManager() + mSettingsManager .getTunerConfigurations( TunerType.FUNCUBE_DONGLE_PRO_PLUS ); DefaultComboBoxModel model = @@ -359,7 +359,7 @@ public class FCD2TunerConfigurationPanel extends JPanel private FCD2TunerConfiguration getNamedConfiguration( String name ) { ArrayList configs = - mResourceManager.getSettingsManager() + mSettingsManager .getTunerConfigurations( TunerType.FUNCUBE_DONGLE_PRO_PLUS ); for( TunerConfiguration config: configs ) @@ -375,6 +375,6 @@ public class FCD2TunerConfigurationPanel extends JPanel private void save() { - mResourceManager.getSettingsManager().save(); + mSettingsManager.save(); } } diff --git a/src/source/tuner/fcd/proplusV2/FCD2TunerController.java b/src/source/tuner/fcd/proplusV2/FCD2TunerController.java index 8640ea50..96a31b85 100644 --- a/src/source/tuner/fcd/proplusV2/FCD2TunerController.java +++ b/src/source/tuner/fcd/proplusV2/FCD2TunerController.java @@ -27,6 +27,7 @@ import org.slf4j.LoggerFactory; import org.usb4java.Device; import org.usb4java.DeviceDescriptor; +import settings.SettingsManager; import source.SourceException; import source.tuner.TunerClass; import source.tuner.TunerConfiguration; @@ -34,7 +35,6 @@ import source.tuner.TunerType; import source.tuner.fcd.FCDCommand; import source.tuner.fcd.FCDTuner; import source.tuner.fcd.FCDTunerController; -import controller.ResourceManager; public class FCD2TunerController extends FCDTunerController { @@ -89,11 +89,11 @@ public class FCD2TunerController extends FCDTunerController return TunerType.FUNCUBE_DONGLE_PRO_PLUS; } - public JPanel getEditor( FCDTuner tuner, ResourceManager resourceManager ) + public JPanel getEditor( FCDTuner tuner, SettingsManager settingsManager ) { if( mEditor == null ) { - mEditor = new FCD2TunerEditorPanel( tuner, resourceManager ); + mEditor = new FCD2TunerEditorPanel( tuner, settingsManager ); } return mEditor; diff --git a/src/source/tuner/fcd/proplusV2/FCD2TunerEditorPanel.java b/src/source/tuner/fcd/proplusV2/FCD2TunerEditorPanel.java index e372a544..6f49b4dc 100644 --- a/src/source/tuner/fcd/proplusV2/FCD2TunerEditorPanel.java +++ b/src/source/tuner/fcd/proplusV2/FCD2TunerEditorPanel.java @@ -29,18 +29,17 @@ import net.miginfocom.swing.MigLayout; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import settings.SettingsManager; import source.SourceException; import source.tuner.fcd.FCDTuner; import source.tuner.fcd.FCDTunerDetailsPanel; import source.tuner.frequency.FrequencyChangeEvent; -import source.tuner.frequency.FrequencyChangeListener; import source.tuner.frequency.FrequencyChangeEvent.Event; +import source.tuner.frequency.IFrequencyChangeProcessor; import com.jidesoft.swing.JideTabbedPane; -import controller.ResourceManager; - -public class FCD2TunerEditorPanel extends JPanel implements FrequencyChangeListener +public class FCD2TunerEditorPanel extends JPanel implements IFrequencyChangeProcessor { private final static Logger mLog = LoggerFactory.getLogger( FCD2TunerEditorPanel.class ); @@ -48,15 +47,15 @@ public class FCD2TunerEditorPanel extends JPanel implements FrequencyChangeListe private FCDTuner mTuner; private FCD2TunerController mController; - private ResourceManager mResourceManager; + private SettingsManager mSettingsManager; private JFrequencyControl mFrequencyControl; - public FCD2TunerEditorPanel( FCDTuner tuner, ResourceManager resourceManager ) + public FCD2TunerEditorPanel( FCDTuner tuner, SettingsManager settingsManager ) { mTuner = tuner; mController = (FCD2TunerController)mTuner.getController(); - mResourceManager = resourceManager; + mSettingsManager = settingsManager; initGUI(); } @@ -73,7 +72,7 @@ public class FCD2TunerEditorPanel extends JPanel implements FrequencyChangeListe /* Add frequency control as frequency change listener. This creates a * feedback loop, so the control does not rebroadcast the event */ - mTuner.addListener( mFrequencyControl ); + mTuner.addFrequencyChangeProcessor( mFrequencyControl ); mFrequencyControl.setFrequency( mController.getFrequency(), false ); @@ -84,7 +83,7 @@ public class FCD2TunerEditorPanel extends JPanel implements FrequencyChangeListe tabs.setForeground( Color.BLACK ); tabs.add( "Configuration", new FCD2TunerConfigurationPanel( - mResourceManager, mController ) ); + mSettingsManager, mController ) ); tabs.add( "Info", new FCDTunerDetailsPanel( mController ) ); @@ -94,7 +93,7 @@ public class FCD2TunerEditorPanel extends JPanel implements FrequencyChangeListe @Override public void frequencyChanged( FrequencyChangeEvent event ) { - if( event.getEvent() == Event.FREQUENCY_CHANGE_NOTIFICATION ) + if( event.getEvent() == Event.NOTIFICATION_FREQUENCY_CHANGE ) { //Disregard the bandwidth, which shouldn't be changing try diff --git a/src/source/tuner/frequency/AutomaticFrequencyControl_R.java b/src/source/tuner/frequency/AutomaticFrequencyControl_R.java deleted file mode 100644 index 994ff0c6..00000000 --- a/src/source/tuner/frequency/AutomaticFrequencyControl_R.java +++ /dev/null @@ -1,181 +0,0 @@ -package source.tuner.frequency; - -/******************************************************************************* - * SDR Trunk - * Copyright (C) 2015 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 - ******************************************************************************/ - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import sample.real.RealSampleListener; -import source.tuner.frequency.FrequencyChangeEvent.Event; -import buffer.FloatAveragingBuffer; - -public class AutomaticFrequencyControl_R extends FrequencyCorrectionControl - implements RealSampleListener -{ - private final static Logger mLog = - LoggerFactory.getLogger( AutomaticFrequencyControl_R.class ); - - private static float LARGE_ERROR = 0.300f; - private static float MEDIUM_ERROR = 0.150f; - private static float SMALL_ERROR = 0.030f; - private static float FINE_ERROR = 0.015f; - - private static int LARGE_FREQUENCY_CORRECTION = 1500; //Hertz - private static int MEDIUM_FREQUENCY_CORRECTION = 500; - private static int SMALL_FREQUENCY_CORRECTION = 100; - private static int FINE_FREQUENCY_CORRECTION = 50; - - private static int SAMPLE_THRESHOLD = 15000; - private Mode mMode = Mode.FAST; - - private FloatAveragingBuffer mBuffer = - new FloatAveragingBuffer( SAMPLE_THRESHOLD ); - - private int mSampleCounter = 0; - private int mSkipCounter = 0; - private int mSkipThreshold = 4; - private int mErrorCorrection = 0; - - public enum Mode - { - NORMAL,FAST; - } - - /** - * Automatic Frequency Control. Monitors DC bias present in an FM - * demodulated audio stream and issues automatic frequency corrections to - * maintain the DC bias close to zero. - * - * @param maximum - maximum allowable (+/-) frequency correction value. - */ - public AutomaticFrequencyControl_R( int maximum ) - { - super( maximum ); - } - - public void dispose() - { - super.dispose(); - - mBuffer = null; - } - - /** - * Resets the error correction value to zero and broadcasts a change event - */ - public void reset() - { - mErrorCorrection = 0; - mMode = Mode.FAST; - dispatch(); - } - - /** - * Broadcasts a frequency correction change event to the registered listener - */ - private void dispatch() - { - if( mListener != null ) - { - mListener.frequencyChanged( - new FrequencyChangeEvent( Event.CHANNEL_FREQUENCY_CORRECTION_CHANGE_NOTIFICATION, - mErrorCorrection ) ); - } - } - - @Override - public void receive( float sample ) - { - if( mMode == Mode.FAST ) - { - float average = mBuffer.get( sample ); - - mSampleCounter++; - - if( mSampleCounter >= SAMPLE_THRESHOLD ) - { - mSampleCounter = 0; - - update( average ); - } - } - else - { - mSkipCounter++; - - if( mSkipCounter >= mSkipThreshold ) - { - mSkipCounter = 0; - - float average = mBuffer.get( sample ); - - mSampleCounter++; - - if( mSampleCounter >= SAMPLE_THRESHOLD ) - { - mSampleCounter = 0; - - update( average ); - } - } - } - } - - private void update( float average ) - { - mMode = Mode.NORMAL; - - if( average > LARGE_ERROR ) - { - adjust( -LARGE_FREQUENCY_CORRECTION ); - mMode = Mode.FAST; - } - else if( average > MEDIUM_ERROR ) - { - adjust( -MEDIUM_FREQUENCY_CORRECTION ); - mMode = Mode.FAST; - } - else if( average > SMALL_ERROR ) - { - adjust( -SMALL_FREQUENCY_CORRECTION ); - } - else if( average > FINE_ERROR ) - { - adjust( -FINE_FREQUENCY_CORRECTION ); - } - else if( average < -LARGE_ERROR ) - { - adjust( LARGE_FREQUENCY_CORRECTION ); - mMode = Mode.FAST; - } - else if( average < -MEDIUM_ERROR ) - { - adjust( MEDIUM_FREQUENCY_CORRECTION ); - mMode = Mode.FAST; - } - else if( average < -SMALL_ERROR ) - { - adjust( SMALL_FREQUENCY_CORRECTION ); - } - else if( average < -FINE_ERROR ) - { - adjust( FINE_FREQUENCY_CORRECTION ); - } - } -} diff --git a/src/source/tuner/frequency/AutomaticFrequencyControl_RB.java b/src/source/tuner/frequency/AutomaticFrequencyControl_RB.java deleted file mode 100644 index 73970ec2..00000000 --- a/src/source/tuner/frequency/AutomaticFrequencyControl_RB.java +++ /dev/null @@ -1,197 +0,0 @@ -package source.tuner.frequency; - -/******************************************************************************* - * SDR Trunk - * Copyright (C) 2015 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 - ******************************************************************************/ - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import sample.Listener; -import sample.real.RealBuffer; -import source.tuner.frequency.FrequencyChangeEvent.Event; -import buffer.FloatAveragingBuffer; - -public class AutomaticFrequencyControl_RB extends FrequencyCorrectionControl - implements Listener -{ - private final static Logger mLog = - LoggerFactory.getLogger( AutomaticFrequencyControl_RB.class ); - - private static float LARGE_ERROR = 0.300f; - private static float MEDIUM_ERROR = 0.150f; - private static float SMALL_ERROR = 0.030f; - private static float FINE_ERROR = 0.015f; - - private static int LARGE_FREQUENCY_CORRECTION = 1500; //Hertz - private static int MEDIUM_FREQUENCY_CORRECTION = 500; - private static int SMALL_FREQUENCY_CORRECTION = 100; - private static int FINE_FREQUENCY_CORRECTION = 50; - - private static int SAMPLE_THRESHOLD = 15000; - private Mode mMode = Mode.FAST; - - private FloatAveragingBuffer mBuffer = - new FloatAveragingBuffer( SAMPLE_THRESHOLD ); - - private int mSampleCounter = 0; - private int mSkipCounter = 0; - private int mSkipThreshold = 4; - private int mErrorCorrection = 0; - - public enum Mode - { - NORMAL,FAST; - } - - /** - * Automatic Frequency Control. Monitors DC bias present in an FM - * demodulated audio stream and issues automatic frequency corrections to - * maintain the DC bias close to zero. - * - * @param maximum - maximum allowable (+/-) frequency correction value. - */ - public AutomaticFrequencyControl_RB( int maximum ) - { - super( maximum ); - } - - public void dispose() - { - super.dispose(); - - mBuffer = null; - } - - /** - * Resets the error correction value to zero and broadcasts a change event - */ - public void reset() - { - super.reset(); - - mMode = Mode.FAST; - dispatch(); - } - - /** - * Broadcasts a frequency correction change event to the registered listener - */ - private void dispatch() - { - if( mListener != null ) - { - mListener.frequencyChanged( - new FrequencyChangeEvent( Event.CHANNEL_FREQUENCY_CORRECTION_CHANGE_NOTIFICATION, - mErrorCorrection ) ); - } - } - - @Override - public void receive( RealBuffer t ) - { - float average = 0.0f; - - for( float sample: t.getSamples() ) - { - average = mBuffer.get( sample ); - } - - //TODO: fix this - -// update( average ); - } - - public void receive( float sample ) - { - if( mMode == Mode.FAST ) - { - float average = mBuffer.get( sample ); - - mSampleCounter++; - - if( mSampleCounter >= SAMPLE_THRESHOLD ) - { - mSampleCounter = 0; - - update( average ); - } - } - else - { - mSkipCounter++; - - if( mSkipCounter >= mSkipThreshold ) - { - mSkipCounter = 0; - - float average = mBuffer.get( sample ); - - mSampleCounter++; - - if( mSampleCounter >= SAMPLE_THRESHOLD ) - { - mSampleCounter = 0; - - update( average ); - } - } - } - } - - private void update( float average ) - { - mMode = Mode.NORMAL; - - if( average > LARGE_ERROR ) - { - adjust( -LARGE_FREQUENCY_CORRECTION ); - mMode = Mode.FAST; - } - else if( average > MEDIUM_ERROR ) - { - adjust( -MEDIUM_FREQUENCY_CORRECTION ); - mMode = Mode.FAST; - } - else if( average > SMALL_ERROR ) - { - adjust( -SMALL_FREQUENCY_CORRECTION ); - } - else if( average > FINE_ERROR ) - { - adjust( -FINE_FREQUENCY_CORRECTION ); - } - else if( average < -LARGE_ERROR ) - { - adjust( LARGE_FREQUENCY_CORRECTION ); - mMode = Mode.FAST; - } - else if( average < -MEDIUM_ERROR ) - { - adjust( MEDIUM_FREQUENCY_CORRECTION ); - mMode = Mode.FAST; - } - else if( average < -SMALL_ERROR ) - { - adjust( SMALL_FREQUENCY_CORRECTION ); - } - else if( average < -FINE_ERROR ) - { - adjust( FINE_FREQUENCY_CORRECTION ); - } - } -} diff --git a/src/source/tuner/frequency/DCTrackingFrequencyControl.java b/src/source/tuner/frequency/DCTrackingFrequencyControl.java new file mode 100644 index 00000000..17704dfd --- /dev/null +++ b/src/source/tuner/frequency/DCTrackingFrequencyControl.java @@ -0,0 +1,135 @@ +package source.tuner.frequency; + +/******************************************************************************* + * SDR Trunk + * Copyright (C) 2016 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 + ******************************************************************************/ + +import module.Module; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import sample.Listener; +import sample.real.RealBuffer; +import source.tuner.frequency.FrequencyChangeEvent.Event; + +public class DCTrackingFrequencyControl extends Module + implements Listener, IFrequencyChangeProvider +{ + private final static Logger mLog = + LoggerFactory.getLogger( DCTrackingFrequencyControl.class ); + + private static float COARSE_THRESHOLD = 0.1f; + private static float LOOP_GAIN = 0.1f; + private static float COARSE_GAIN = 1000.0f; + private static float FINE_GAIN = 100.0f; + private int mErrorCorrection = 0; + private int mMaximumFrequencyCorrection = 0; + private Listener mListener; + + /** + * DC offset Automatic Frequency Control. Monitors DC bias present in an FM + * demodulated audio stream and issues automatic frequency corrections to + * maintain the DC bias close to zero. + * + * @param maximum - maximum allowable (+/-) frequency correction value. + */ + public DCTrackingFrequencyControl( int maximum ) + { + mMaximumFrequencyCorrection = maximum; + } + + public void dispose() + { + mListener = null; + } + + @Override + public void receive( RealBuffer buffer ) + { + double sum = 0.0d; + + for( float sample: buffer.getSamples() ) + { + sum += sample; + } + + float mean = (float)( sum / (double)buffer.getSamples().length ); + + float adjustment = 0.0f; + + if( mean > COARSE_THRESHOLD || mean < - COARSE_THRESHOLD ) + { + adjustment = mean * COARSE_GAIN; + } + else + { + adjustment = mean * FINE_GAIN; + } + + setErrorCorrection( mErrorCorrection + (int)( (float)adjustment * LOOP_GAIN ) ); + } + + private void setErrorCorrection( int correction ) + { + if( mListener != null ) + { + if( correction > mMaximumFrequencyCorrection ) + { + correction = mMaximumFrequencyCorrection; + } + else if( correction < -mMaximumFrequencyCorrection ) + { + correction = -mMaximumFrequencyCorrection; + } + + if( correction != mErrorCorrection ) + { + mListener.receive( new FrequencyChangeEvent( + Event.REQUEST_CHANNEL_FREQUENCY_CORRECTION_CHANGE, correction ) ); + } + } + } + + @Override + public void setFrequencyChangeListener( Listener listener ) + { + mListener = listener; + } + + @Override + public void removeFrequencyChangeListener() + { + mListener = null; + } + + @Override + public void start() + { + } + + @Override + public void stop() + { + } + + @Override + public void reset() + { + setErrorCorrection( 0 ); + } +} diff --git a/src/source/tuner/frequency/FrequencyChangeBroadcaster.java b/src/source/tuner/frequency/FrequencyChangeBroadcaster.java deleted file mode 100644 index 89c03bf6..00000000 --- a/src/source/tuner/frequency/FrequencyChangeBroadcaster.java +++ /dev/null @@ -1,26 +0,0 @@ -/******************************************************************************* - * 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 - ******************************************************************************/ -package source.tuner.frequency; - - -public interface FrequencyChangeBroadcaster -{ - public abstract void addListener( FrequencyChangeListener listener ); - - public abstract void removeListener( FrequencyChangeListener listener ); -} diff --git a/src/source/tuner/frequency/FrequencyChangeEvent.java b/src/source/tuner/frequency/FrequencyChangeEvent.java index 87f82f08..afadd058 100644 --- a/src/source/tuner/frequency/FrequencyChangeEvent.java +++ b/src/source/tuner/frequency/FrequencyChangeEvent.java @@ -4,11 +4,12 @@ public class FrequencyChangeEvent { public enum Event { - FREQUENCY_CHANGE_NOTIFICATION, - FREQUENCY_CORRECTION_CHANGE_NOTIFICATION, - CHANNEL_FREQUENCY_CORRECTION_CHANGE_NOTIFICATION, - CHANNEL_FREQUENCY_CORRECTION_CHANGE_REQUEST, - SAMPLE_RATE_CHANGE_NOTIFICATION; + NOTIFICATION_FREQUENCY_CHANGE, + NOTIFICATION_FREQUENCY_CORRECTION_CHANGE, + NOTIFICATION_CHANNEL_FREQUENCY_CORRECTION_CHANGE, + NOTIFICATION_SAMPLE_RATE_CHANGE, + + REQUEST_CHANNEL_FREQUENCY_CORRECTION_CHANGE; } private Event mEvent; diff --git a/src/source/tuner/frequency/FrequencyChangeProcessorWrapper.java b/src/source/tuner/frequency/FrequencyChangeProcessorWrapper.java new file mode 100644 index 00000000..1b96ae8b --- /dev/null +++ b/src/source/tuner/frequency/FrequencyChangeProcessorWrapper.java @@ -0,0 +1,32 @@ +package source.tuner.frequency; + +import sample.Listener; + +public class FrequencyChangeProcessorWrapper + implements IFrequencyChangeListener, Listener +{ + private IFrequencyChangeProcessor mProcessor; + + /** + * Provides IFrequencyChangeListener wrapper for an IFrequencyChangeProcessor + */ + public FrequencyChangeProcessorWrapper( IFrequencyChangeProcessor handler ) + { + mProcessor = handler; + } + + @Override + public Listener getFrequencyChangeListener() + { + return this; + } + + @Override + public void receive( FrequencyChangeEvent event ) + { + if( mProcessor != null ) + { + mProcessor.frequencyChanged( event ); + } + } +} diff --git a/src/source/tuner/frequency/FrequencyController.java b/src/source/tuner/frequency/FrequencyController.java index 51bab16f..f1c6753d 100644 --- a/src/source/tuner/frequency/FrequencyController.java +++ b/src/source/tuner/frequency/FrequencyController.java @@ -37,8 +37,7 @@ public class FrequencyController private double mFrequencyCorrection = 0d; private int mSampleRate = 0; - private ArrayList mListeners = - new ArrayList(); + private ArrayList mProcessors = new ArrayList<>(); public FrequencyController( Tunable tunable, long minFrequency, @@ -181,20 +180,21 @@ public class FrequencyController /** * Adds listener to receive frequency change events */ - public void addListener( FrequencyChangeListener listener ) +//TODO: rename this to addFrequencyChangeProcessor() + public void addListener( IFrequencyChangeProcessor processor ) { - if( !mListeners.contains( listener ) ) + if( !mProcessors.contains( processor ) ) { - mListeners.add( listener ); + mProcessors.add( processor ); } } /** * Removes listener from receiving frequency change events */ - public void removeListener( FrequencyChangeListener listener ) + public void removeFrequencyChangeProcessor( IFrequencyChangeProcessor processor ) { - mListeners.remove( listener ); + mProcessors.remove( processor ); } @@ -205,7 +205,7 @@ public class FrequencyController protected void broadcastFrequencyChange() { broadcastFrequencyChangeEvent( - new FrequencyChangeEvent( Event.FREQUENCY_CHANGE_NOTIFICATION, mFrequency ) ); + new FrequencyChangeEvent( Event.NOTIFICATION_FREQUENCY_CHANGE, mFrequency ) ); } /** @@ -214,7 +214,7 @@ public class FrequencyController protected void broadcastFrequencyErrorChange() { broadcastFrequencyChangeEvent( - new FrequencyChangeEvent( Event.FREQUENCY_CORRECTION_CHANGE_NOTIFICATION, mFrequencyCorrection ) ); + new FrequencyChangeEvent( Event.NOTIFICATION_FREQUENCY_CORRECTION_CHANGE, mFrequencyCorrection ) ); } /** @@ -223,14 +223,14 @@ public class FrequencyController protected void broadcastSampleRateChange() { broadcastFrequencyChangeEvent( - new FrequencyChangeEvent( Event.SAMPLE_RATE_CHANGE_NOTIFICATION, mSampleRate ) ); + new FrequencyChangeEvent( Event.NOTIFICATION_SAMPLE_RATE_CHANGE, mSampleRate ) ); } public void broadcastFrequencyChangeEvent( FrequencyChangeEvent event ) { - for( FrequencyChangeListener listener: mListeners ) + for( IFrequencyChangeProcessor processor: mProcessors ) { - listener.frequencyChanged( event ); + processor.frequencyChanged( event ); } } diff --git a/src/source/tuner/frequency/FrequencyCorrectionControl.java b/src/source/tuner/frequency/FrequencyCorrectionControl.java deleted file mode 100644 index 77255bb0..00000000 --- a/src/source/tuner/frequency/FrequencyCorrectionControl.java +++ /dev/null @@ -1,161 +0,0 @@ -package source.tuner.frequency; - -/******************************************************************************* - * SDR Trunk - * Copyright (C) 2015 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 - ******************************************************************************/ -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import source.tuner.frequency.FrequencyChangeEvent.Event; - -/** - * Frequency control for providing frequency error correction to a tuned channel - */ -public class FrequencyCorrectionControl implements FrequencyChangeListener -{ - private final static Logger mLog = - LoggerFactory.getLogger( FrequencyCorrectionControl.class ); - - protected FrequencyChangeListener mListener; - protected FrequencyCorrectionResetListener mResetListener; - - protected int mChannelFrequencyCorrection = 0; - private int mMaximumCorrection = 3000; - - /** - * Frequency correction controller. - * - * @param maximum - defines the maximum +/- allowable frequency correction - * value - */ - public FrequencyCorrectionControl( int maximum ) - { - mMaximumCorrection = maximum; - } - - /** - * Cleanup - */ - public void dispose() - { - mListener = null; - mResetListener = null; - } - - /** - * Registers a listener to receive frequency correction events - */ - public void setFrequencyChangeListener( FrequencyChangeListener listener ) - { - mListener = listener; - } - - /** - * Registers a listener to receive frequency correction resets - */ - public void setListener( FrequencyCorrectionResetListener listener ) - { - mResetListener = listener; - } - - /** - * Listener for source frequency or frequency offset value changes to - * reset this frequency controller value to zero. - */ - @Override - public void frequencyChanged( FrequencyChangeEvent event ) - { - Event attribute = event.getEvent(); - - switch( attribute ) - { - //Direct the listener to reset when frequency correction (PPM) or - //sample rate changes - case FREQUENCY_CORRECTION_CHANGE_NOTIFICATION: - case SAMPLE_RATE_CHANGE_NOTIFICATION: - reset(); - break; - default: - break; - } - } - - /** - * Resets frequency correction value to zero and notifies any reset - * listeners - */ - public void reset() - { - if( mResetListener != null ) - { - mResetListener.resetFrequencyCorrection(); - } - } - - /** - * Sets frequency correction to the specified value and broadcasts a change - * request - */ - public void setFrequencyCorrection( int correction ) - { - mChannelFrequencyCorrection = correction; - - /* Limit frequency correction to +/- max correction value */ - if( mChannelFrequencyCorrection > mMaximumCorrection ) - { - mChannelFrequencyCorrection = mMaximumCorrection; - } - else if( mChannelFrequencyCorrection < -mMaximumCorrection ) - { - mChannelFrequencyCorrection = -mMaximumCorrection; - } - - /* Broadcast a change request */ - if( mListener != null ) - { - mListener.frequencyChanged( new FrequencyChangeEvent( - Event.CHANNEL_FREQUENCY_CORRECTION_CHANGE_REQUEST, - mChannelFrequencyCorrection ) ); - } - } - - /** - * Increments the frequency error correction value by the specified adjustment - */ - public void adjust( int adjustment ) - { - setFrequencyCorrection( getErrorCorrection() + adjustment ); - } - - /** - * Current frequency error correction value - * @return - */ - public int getErrorCorrection() - { - return mChannelFrequencyCorrection; - } - - /** - * Listener interface to be notified when this control is reset to a zero - * frequency correction value - */ - public interface FrequencyCorrectionResetListener - { - public void resetFrequencyCorrection(); - } -} diff --git a/src/source/tuner/frequency/FrequencyChangeListener.java b/src/source/tuner/frequency/IFrequencyChangeListener.java similarity index 90% rename from src/source/tuner/frequency/FrequencyChangeListener.java rename to src/source/tuner/frequency/IFrequencyChangeListener.java index fab9f28a..99b75804 100644 --- a/src/source/tuner/frequency/FrequencyChangeListener.java +++ b/src/source/tuner/frequency/IFrequencyChangeListener.java @@ -17,6 +17,8 @@ ******************************************************************************/ package source.tuner.frequency; +import sample.Listener; + /** * Interface for broadcasting changes to frequency, bandwidth, sample rate, @@ -26,7 +28,7 @@ package source.tuner.frequency; * frequency value. All frequency correction aspects should be handled within * the device that implements the tuning of the frequency. */ -public interface FrequencyChangeListener +public interface IFrequencyChangeListener { - public void frequencyChanged( FrequencyChangeEvent event ); + public Listener getFrequencyChangeListener(); } diff --git a/src/source/tuner/frequency/IFrequencyChangeProcessor.java b/src/source/tuner/frequency/IFrequencyChangeProcessor.java new file mode 100644 index 00000000..479d8e8d --- /dev/null +++ b/src/source/tuner/frequency/IFrequencyChangeProcessor.java @@ -0,0 +1,6 @@ +package source.tuner.frequency; + +public interface IFrequencyChangeProcessor +{ + public void frequencyChanged( FrequencyChangeEvent event ); +} diff --git a/src/source/tuner/frequency/IFrequencyChangeProvider.java b/src/source/tuner/frequency/IFrequencyChangeProvider.java new file mode 100644 index 00000000..919126e7 --- /dev/null +++ b/src/source/tuner/frequency/IFrequencyChangeProvider.java @@ -0,0 +1,9 @@ +package source.tuner.frequency; + +import sample.Listener; + +public interface IFrequencyChangeProvider +{ + public void setFrequencyChangeListener( Listener listener ); + public void removeFrequencyChangeListener(); +} diff --git a/src/source/tuner/frequency/IFrequencyCorrectionController.java b/src/source/tuner/frequency/IFrequencyCorrectionController.java deleted file mode 100644 index e937bd4a..00000000 --- a/src/source/tuner/frequency/IFrequencyCorrectionController.java +++ /dev/null @@ -1,8 +0,0 @@ -package source.tuner.frequency; - - -public interface IFrequencyCorrectionController -{ - public boolean hasFrequencyCorrectionControl(); - public FrequencyCorrectionControl getFrequencyCorrectionControl(); -} diff --git a/src/source/tuner/hackrf/HackRFTuner.java b/src/source/tuner/hackrf/HackRFTuner.java index 4b38c4bd..154c55bc 100644 --- a/src/source/tuner/hackrf/HackRFTuner.java +++ b/src/source/tuner/hackrf/HackRFTuner.java @@ -26,6 +26,7 @@ import org.slf4j.LoggerFactory; import sample.Listener; import sample.complex.ComplexBuffer; +import settings.SettingsManager; import source.SourceException; import source.tuner.Tuner; import source.tuner.TunerChannel; @@ -34,7 +35,6 @@ import source.tuner.TunerClass; import source.tuner.TunerConfiguration; import source.tuner.TunerType; import source.tuner.hackrf.HackRFTunerController.BoardID; -import controller.ResourceManager; import controller.ThreadPoolManager; public class HackRFTuner extends Tuner @@ -76,9 +76,9 @@ public class HackRFTuner extends Tuner } @Override - public JPanel getEditor( ResourceManager resourceManager ) + public JPanel getEditor( SettingsManager settingsManager ) { - return new HackRFTunerEditorPanel( this, resourceManager ); + return new HackRFTunerEditorPanel( this, settingsManager ); } @Override diff --git a/src/source/tuner/hackrf/HackRFTunerConfigurationPanel.java b/src/source/tuner/hackrf/HackRFTunerConfigurationPanel.java index b5ec8acb..1acd7269 100644 --- a/src/source/tuner/hackrf/HackRFTunerConfigurationPanel.java +++ b/src/source/tuner/hackrf/HackRFTunerConfigurationPanel.java @@ -48,6 +48,7 @@ import net.miginfocom.swing.MigLayout; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import settings.SettingsManager; import source.SourceException; import source.tuner.TunerConfiguration; import source.tuner.TunerConfigurationAssignment; @@ -55,7 +56,6 @@ import source.tuner.TunerType; import source.tuner.hackrf.HackRFTunerController.HackRFLNAGain; import source.tuner.hackrf.HackRFTunerController.HackRFSampleRate; import source.tuner.hackrf.HackRFTunerController.HackRFVGAGain; -import controller.ResourceManager; public class HackRFTunerConfigurationPanel extends JPanel { @@ -64,7 +64,7 @@ public class HackRFTunerConfigurationPanel extends JPanel private static final long serialVersionUID = 1L; - private ResourceManager mResourceManager; + private SettingsManager mSettingsManager; private HackRFTunerController mController; private HackRFTunerConfiguration mSelectedConfig; @@ -81,10 +81,10 @@ public class HackRFTunerConfigurationPanel extends JPanel private JComboBox mComboSampleRate; - public HackRFTunerConfigurationPanel( ResourceManager resourceManager, + public HackRFTunerConfigurationPanel( SettingsManager settingsManager, HackRFTunerController controller ) { - mResourceManager = resourceManager; + mSettingsManager = settingsManager; mController = controller; init(); @@ -119,8 +119,7 @@ public class HackRFTunerConfigurationPanel extends JPanel if( serial != null ) { - savedConfig = mResourceManager - .getSettingsManager().getSelectedTunerConfiguration( + savedConfig = mSettingsManager.getSelectedTunerConfiguration( TunerType.HACKRF, serial ); } @@ -139,7 +138,7 @@ public class HackRFTunerConfigurationPanel extends JPanel if( serial != null ) { - mResourceManager.getSettingsManager() + mSettingsManager .setSelectedTunerConfiguration( TunerType.HACKRF, serial, mSelectedConfig ); } @@ -418,7 +417,7 @@ public class HackRFTunerConfigurationPanel extends JPanel public void actionPerformed( ActionEvent e ) { TunerConfiguration config = - mResourceManager.getSettingsManager() + mSettingsManager .addNewTunerConfiguration( TunerType.HACKRF, "New Configuration" ); @@ -458,7 +457,7 @@ public class HackRFTunerConfigurationPanel extends JPanel if( n == JOptionPane.YES_OPTION ) { - mResourceManager.getSettingsManager() + mSettingsManager .deleteTunerConfiguration( selected ); mComboConfigurations.setModel( getModel() ); @@ -494,7 +493,7 @@ public class HackRFTunerConfigurationPanel extends JPanel mComboSampleRate.setSelectedItem( mSelectedConfig.getSampleRate() ); - mResourceManager.getSettingsManager().setSelectedTunerConfiguration( + mSettingsManager.setSelectedTunerConfiguration( TunerType.HACKRF, mController.getSerial().getSerialNumber(), config ); } catch ( UsbException | SourceException e1 ) @@ -518,7 +517,7 @@ public class HackRFTunerConfigurationPanel extends JPanel private ComboBoxModel getModel() { ArrayList configs = - mResourceManager.getSettingsManager() + mSettingsManager .getTunerConfigurations( TunerType.HACKRF ); DefaultComboBoxModel model = @@ -538,7 +537,7 @@ public class HackRFTunerConfigurationPanel extends JPanel private HackRFTunerConfiguration getNamedConfiguration( String name ) { ArrayList configs = - mResourceManager.getSettingsManager() + mSettingsManager .getTunerConfigurations( TunerType.HACKRF ); for( TunerConfiguration config: configs ) @@ -557,6 +556,6 @@ public class HackRFTunerConfigurationPanel extends JPanel */ private void save() { - mResourceManager.getSettingsManager().save(); + mSettingsManager.save(); } } diff --git a/src/source/tuner/hackrf/HackRFTunerEditorPanel.java b/src/source/tuner/hackrf/HackRFTunerEditorPanel.java index 9c4d8490..fe32f16a 100644 --- a/src/source/tuner/hackrf/HackRFTunerEditorPanel.java +++ b/src/source/tuner/hackrf/HackRFTunerEditorPanel.java @@ -30,18 +30,16 @@ import net.miginfocom.swing.MigLayout; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import settings.SettingsManager; import source.SourceException; import source.tuner.frequency.FrequencyChangeEvent; -import source.tuner.frequency.FrequencyChangeListener; import source.tuner.frequency.FrequencyChangeEvent.Event; +import source.tuner.frequency.IFrequencyChangeProcessor; import source.tuner.hackrf.HackRFTunerController.BoardID; import com.jidesoft.swing.JideTabbedPane; -import controller.ResourceManager; - -public class HackRFTunerEditorPanel extends JPanel - implements FrequencyChangeListener +public class HackRFTunerEditorPanel extends JPanel implements IFrequencyChangeProcessor { private static final long serialVersionUID = 1L; @@ -52,14 +50,14 @@ public class HackRFTunerEditorPanel extends JPanel private HackRFTuner mTuner; private HackRFTunerController mController; - private ResourceManager mResourceManager; + private SettingsManager mSettingsManager; public HackRFTunerEditorPanel( HackRFTuner tuner, - ResourceManager resourceManager ) + SettingsManager resourceManager ) { mTuner = tuner; mController = mTuner.getController(); - mResourceManager = resourceManager; + mSettingsManager = resourceManager; initGUI(); } @@ -89,7 +87,7 @@ public class HackRFTunerEditorPanel extends JPanel /* Add frequency control as frequency change listener. This creates a * feedback loop, so the control does not rebroadcast the event */ - mTuner.addListener( mFrequencyControl ); + mTuner.addFrequencyChangeProcessor( mFrequencyControl ); mFrequencyControl.setFrequency( mController.getFrequency(), false ); @@ -102,7 +100,7 @@ public class HackRFTunerEditorPanel extends JPanel add( tabs, "span,grow,push" ); tabs.add( "Config", new HackRFTunerConfigurationPanel( - mResourceManager, mTuner.getController() ) ); + mSettingsManager, mTuner.getController() ) ); tabs.add( "Info", new HackRFInformationPanel( mTuner.getController() ) ); } @@ -110,7 +108,7 @@ public class HackRFTunerEditorPanel extends JPanel @Override public void frequencyChanged( FrequencyChangeEvent event ) { - if( event.getEvent() == Event.FREQUENCY_CHANGE_NOTIFICATION ) + if( event.getEvent() == Event.NOTIFICATION_FREQUENCY_CHANGE ) { try { diff --git a/src/source/tuner/rtl/RTL2832Tuner.java b/src/source/tuner/rtl/RTL2832Tuner.java index 02634918..4af1a8d7 100644 --- a/src/source/tuner/rtl/RTL2832Tuner.java +++ b/src/source/tuner/rtl/RTL2832Tuner.java @@ -27,6 +27,7 @@ import org.usb4java.LibUsbException; import sample.Listener; import sample.complex.ComplexBuffer; +import settings.SettingsManager; import source.SourceException; import source.tuner.Tuner; import source.tuner.TunerChannel; @@ -34,9 +35,8 @@ import source.tuner.TunerChannelSource; import source.tuner.TunerClass; import source.tuner.TunerConfiguration; import source.tuner.TunerType; -import source.tuner.frequency.FrequencyChangeListener; +import source.tuner.frequency.IFrequencyChangeListener; import source.tuner.rtl.RTL2832TunerController.SampleRate; -import controller.ResourceManager; import controller.ThreadPoolManager; public class RTL2832Tuner extends Tuner @@ -57,7 +57,7 @@ public class RTL2832Tuner extends Tuner mTunerClass = tunerClass; mController = controller; - mController.addListener( (FrequencyChangeListener)this ); + mController.addListener( this ); } public void dispose() @@ -89,9 +89,9 @@ public class RTL2832Tuner extends Tuner } @Override - public JPanel getEditor( ResourceManager resourceManager ) + public JPanel getEditor( SettingsManager settingsManager ) { - return mController.getEditor( resourceManager ); + return mController.getEditor( settingsManager ); } @Override diff --git a/src/source/tuner/rtl/RTL2832TunerController.java b/src/source/tuner/rtl/RTL2832TunerController.java index d419c782..e972c1d0 100644 --- a/src/source/tuner/rtl/RTL2832TunerController.java +++ b/src/source/tuner/rtl/RTL2832TunerController.java @@ -52,13 +52,11 @@ import sample.Broadcaster; import sample.Listener; import sample.adapter.ByteSampleAdapter; import sample.complex.ComplexBuffer; +import settings.SettingsManager; import source.SourceException; import source.tuner.TunerController; import source.tuner.TunerType; -import source.tuner.frequency.FrequencyChangeEvent; -import source.tuner.frequency.FrequencyChangeEvent.Event; import buffer.FloatAveragingBuffer; -import controller.ResourceManager; import controller.ThreadPoolManager; import controller.ThreadPoolManager.ThreadType; @@ -364,7 +362,7 @@ public abstract class RTL2832TunerController extends TunerController } } - public abstract JPanel getEditor( ResourceManager resourceManager ); + public abstract JPanel getEditor( SettingsManager settingsManager ); public abstract void setSampleRateFilters( int sampleRate ) throws SourceException; diff --git a/src/source/tuner/rtl/e4k/E4KTunerConfigurationPanel.java b/src/source/tuner/rtl/e4k/E4KTunerConfigurationPanel.java index cce675b4..ed3a4ac7 100644 --- a/src/source/tuner/rtl/e4k/E4KTunerConfigurationPanel.java +++ b/src/source/tuner/rtl/e4k/E4KTunerConfigurationPanel.java @@ -48,6 +48,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.usb4java.LibUsbException; +import settings.SettingsManager; import source.SourceException; import source.tuner.TunerConfiguration; import source.tuner.TunerConfigurationAssignment; @@ -57,7 +58,6 @@ import source.tuner.rtl.e4k.E4KTunerController.E4KEnhanceGain; import source.tuner.rtl.e4k.E4KTunerController.E4KGain; import source.tuner.rtl.e4k.E4KTunerController.E4KLNAGain; import source.tuner.rtl.e4k.E4KTunerController.E4KMixerGain; -import controller.ResourceManager; public class E4KTunerConfigurationPanel extends JPanel { @@ -65,7 +65,7 @@ public class E4KTunerConfigurationPanel extends JPanel private final static Logger mLog = LoggerFactory.getLogger( E4KTunerConfigurationPanel.class ); - private ResourceManager mResourceManager; + private SettingsManager mSettingsManager; private E4KTunerController mController; private E4KTunerConfiguration mSelectedConfig; @@ -84,10 +84,10 @@ public class E4KTunerConfigurationPanel extends JPanel private JComboBox mComboSampleRate; - public E4KTunerConfigurationPanel( ResourceManager resourceManager, + public E4KTunerConfigurationPanel( SettingsManager settingsManager, E4KTunerController controller ) { - mResourceManager = resourceManager; + mSettingsManager = settingsManager; mController = controller; init(); @@ -108,8 +108,8 @@ public class E4KTunerConfigurationPanel extends JPanel mComboConfigurations.setModel( getModel() ); /* Determine which tuner configuration should be selected/displayed */ - TunerConfigurationAssignment savedConfig = mResourceManager - .getSettingsManager().getSelectedTunerConfiguration( + TunerConfigurationAssignment savedConfig = mSettingsManager + .getSelectedTunerConfiguration( TunerType.ELONICS_E4000, mController.getUniqueID() ); if( savedConfig != null ) @@ -124,7 +124,7 @@ public class E4KTunerConfigurationPanel extends JPanel mSelectedConfig = mComboConfigurations.getItemAt( 0 ); //Store this config as the default for this tuner at this address - mResourceManager.getSettingsManager() + mSettingsManager .setSelectedTunerConfiguration( TunerType.ELONICS_E4000, mController.getUniqueID(), mSelectedConfig ); @@ -168,7 +168,7 @@ public class E4KTunerConfigurationPanel extends JPanel /* Reset this named config as the assigned config for this * tuner */ - mResourceManager.getSettingsManager() + mSettingsManager .setSelectedTunerConfiguration( TunerType.ELONICS_E4000, mController.getUniqueID(), mSelectedConfig ); @@ -542,7 +542,7 @@ public class E4KTunerConfigurationPanel extends JPanel public void actionPerformed( ActionEvent e ) { TunerConfiguration config = - mResourceManager.getSettingsManager() + mSettingsManager .addNewTunerConfiguration( TunerType.ELONICS_E4000, "New Configuration" ); @@ -582,7 +582,7 @@ public class E4KTunerConfigurationPanel extends JPanel if( n == JOptionPane.YES_OPTION ) { - mResourceManager.getSettingsManager() + mSettingsManager .deleteTunerConfiguration( selected ); mComboConfigurations.setModel( getModel() ); @@ -623,7 +623,7 @@ public class E4KTunerConfigurationPanel extends JPanel mComboSampleRate.setSelectedItem( mSelectedConfig.getSampleRate() ); - mResourceManager.getSettingsManager().setSelectedTunerConfiguration( + mSettingsManager.setSelectedTunerConfiguration( TunerType.ELONICS_E4000, mController.getUniqueID(), config ); } catch ( SourceException e1 ) @@ -647,7 +647,7 @@ public class E4KTunerConfigurationPanel extends JPanel private ComboBoxModel getModel() { ArrayList configs = - mResourceManager.getSettingsManager() + mSettingsManager .getTunerConfigurations( TunerType.ELONICS_E4000 ); DefaultComboBoxModel model = @@ -667,7 +667,7 @@ public class E4KTunerConfigurationPanel extends JPanel private E4KTunerConfiguration getNamedConfiguration( String name ) { ArrayList configs = - mResourceManager.getSettingsManager() + mSettingsManager .getTunerConfigurations( TunerType.ELONICS_E4000 ); for( TunerConfiguration config: configs ) @@ -686,6 +686,6 @@ public class E4KTunerConfigurationPanel extends JPanel */ private void save() { - mResourceManager.getSettingsManager().save(); + mSettingsManager.save(); } } diff --git a/src/source/tuner/rtl/e4k/E4KTunerController.java b/src/source/tuner/rtl/e4k/E4KTunerController.java index 6bdfb149..b727fa74 100644 --- a/src/source/tuner/rtl/e4k/E4KTunerController.java +++ b/src/source/tuner/rtl/e4k/E4KTunerController.java @@ -30,11 +30,11 @@ import org.usb4java.DeviceHandle; import org.usb4java.LibUsb; import org.usb4java.LibUsbException; +import settings.SettingsManager; import source.SourceException; import source.tuner.TunerConfiguration; import source.tuner.TunerType; import source.tuner.rtl.RTL2832TunerController; -import controller.ResourceManager; import controller.ThreadPoolManager; public class E4KTunerController extends RTL2832TunerController @@ -252,11 +252,11 @@ public class E4KTunerController extends RTL2832TunerController } } - public JPanel getEditor( ResourceManager resourceManager ) + public JPanel getEditor( SettingsManager settingsManager ) { if( mEditor == null ) { - mEditor = new E4KTunerEditorPanel( this, resourceManager ); + mEditor = new E4KTunerEditorPanel( this, settingsManager ); } return mEditor; diff --git a/src/source/tuner/rtl/e4k/E4KTunerEditorPanel.java b/src/source/tuner/rtl/e4k/E4KTunerEditorPanel.java index 5c883748..fe797d55 100644 --- a/src/source/tuner/rtl/e4k/E4KTunerEditorPanel.java +++ b/src/source/tuner/rtl/e4k/E4KTunerEditorPanel.java @@ -30,17 +30,16 @@ import net.miginfocom.swing.MigLayout; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import settings.SettingsManager; import source.SourceException; import source.tuner.frequency.FrequencyChangeEvent; -import source.tuner.frequency.FrequencyChangeListener; import source.tuner.frequency.FrequencyChangeEvent.Event; +import source.tuner.frequency.IFrequencyChangeProcessor; import source.tuner.rtl.RTL2832InfoPanel; import com.jidesoft.swing.JideTabbedPane; -import controller.ResourceManager; - -public class E4KTunerEditorPanel extends JPanel implements FrequencyChangeListener +public class E4KTunerEditorPanel extends JPanel implements IFrequencyChangeProcessor { private final static Logger mLog = LoggerFactory.getLogger( E4KTunerEditorPanel.class ); @@ -48,15 +47,15 @@ public class E4KTunerEditorPanel extends JPanel implements FrequencyChangeListen private static final long serialVersionUID = 1L; private E4KTunerController mController; - private ResourceManager mResourceManager; + private SettingsManager mSettingsManager; private JFrequencyControl mFrequencyControl; public E4KTunerEditorPanel( E4KTunerController controller, - ResourceManager resourceManager ) + SettingsManager settingsManager ) { mController = controller; - mResourceManager = resourceManager; + mSettingsManager = settingsManager; initGUI(); } @@ -84,7 +83,7 @@ public class E4KTunerEditorPanel extends JPanel implements FrequencyChangeListen tabs.setForeground( Color.BLACK ); tabs.addTab( "Configuration", - new E4KTunerConfigurationPanel( mResourceManager, mController ) ); + new E4KTunerConfigurationPanel( mSettingsManager, mController ) ); tabs.addTab( "Info", new RTL2832InfoPanel( mController ) ); @@ -98,7 +97,7 @@ public class E4KTunerEditorPanel extends JPanel implements FrequencyChangeListen @Override public void frequencyChanged( FrequencyChangeEvent event ) { - if( event.getEvent() == Event.FREQUENCY_CHANGE_NOTIFICATION ) + if( event.getEvent() == Event.NOTIFICATION_FREQUENCY_CHANGE ) { final long frequency = event.getValue().longValue(); diff --git a/src/source/tuner/rtl/r820t/R820TTunerConfigurationPanel.java b/src/source/tuner/rtl/r820t/R820TTunerConfigurationPanel.java index fe08d0c3..413dc8ea 100644 --- a/src/source/tuner/rtl/r820t/R820TTunerConfigurationPanel.java +++ b/src/source/tuner/rtl/r820t/R820TTunerConfigurationPanel.java @@ -48,6 +48,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.usb4java.LibUsbException; +import settings.SettingsManager; import source.SourceException; import source.tuner.TunerConfiguration; import source.tuner.TunerConfigurationAssignment; @@ -57,7 +58,6 @@ import source.tuner.rtl.r820t.R820TTunerController.R820TGain; import source.tuner.rtl.r820t.R820TTunerController.R820TLNAGain; import source.tuner.rtl.r820t.R820TTunerController.R820TMixerGain; import source.tuner.rtl.r820t.R820TTunerController.R820TVGAGain; -import controller.ResourceManager; public class R820TTunerConfigurationPanel extends JPanel { @@ -67,7 +67,7 @@ public class R820TTunerConfigurationPanel extends JPanel private static final long serialVersionUID = 1L; private static final R820TGain DEFAULT_GAIN = R820TGain.GAIN_279; - private ResourceManager mResourceManager; + private SettingsManager mSettingsManager; private R820TTunerController mController; private R820TTunerConfiguration mSelectedConfig; @@ -86,10 +86,10 @@ public class R820TTunerConfigurationPanel extends JPanel private JComboBox mComboSampleRate; - public R820TTunerConfigurationPanel( ResourceManager resourceManager, + public R820TTunerConfigurationPanel( SettingsManager settingsManager, R820TTunerController controller ) { - mResourceManager = resourceManager; + mSettingsManager = settingsManager; mController = controller; init(); @@ -110,8 +110,8 @@ public class R820TTunerConfigurationPanel extends JPanel mComboConfigurations.setModel( getModel() ); /* Determine which tuner configuration should be selected/displayed */ - TunerConfigurationAssignment savedConfig = mResourceManager - .getSettingsManager().getSelectedTunerConfiguration( + TunerConfigurationAssignment savedConfig = mSettingsManager + .getSelectedTunerConfiguration( TunerType.RAFAELMICRO_R820T, mController.getUniqueID() ); if( savedConfig != null ) @@ -126,7 +126,7 @@ public class R820TTunerConfigurationPanel extends JPanel mSelectedConfig = mComboConfigurations.getItemAt( 0 ); //Store this config as the default for this tuner at this address - mResourceManager.getSettingsManager() + mSettingsManager .setSelectedTunerConfiguration( TunerType.RAFAELMICRO_R820T, mController.getUniqueID(), mSelectedConfig ); @@ -549,7 +549,7 @@ public class R820TTunerConfigurationPanel extends JPanel public void actionPerformed( ActionEvent e ) { TunerConfiguration config = - mResourceManager.getSettingsManager() + mSettingsManager .addNewTunerConfiguration( TunerType.RAFAELMICRO_R820T, "New Configuration" ); @@ -589,7 +589,7 @@ public class R820TTunerConfigurationPanel extends JPanel if( n == JOptionPane.YES_OPTION ) { - mResourceManager.getSettingsManager() + mSettingsManager .deleteTunerConfiguration( selected ); mComboConfigurations.setModel( getModel() ); @@ -630,7 +630,7 @@ public class R820TTunerConfigurationPanel extends JPanel mComboSampleRate.setSelectedItem( mSelectedConfig.getSampleRate() ); - mResourceManager.getSettingsManager().setSelectedTunerConfiguration( + mSettingsManager.setSelectedTunerConfiguration( TunerType.RAFAELMICRO_R820T, mController.getUniqueID(), config ); } catch ( SourceException e1 ) @@ -654,7 +654,7 @@ public class R820TTunerConfigurationPanel extends JPanel private ComboBoxModel getModel() { ArrayList configs = - mResourceManager.getSettingsManager() + mSettingsManager .getTunerConfigurations( TunerType.RAFAELMICRO_R820T ); DefaultComboBoxModel model = @@ -674,7 +674,7 @@ public class R820TTunerConfigurationPanel extends JPanel private R820TTunerConfiguration getNamedConfiguration( String name ) { ArrayList configs = - mResourceManager.getSettingsManager() + mSettingsManager .getTunerConfigurations( TunerType.RAFAELMICRO_R820T ); for( TunerConfiguration config: configs ) @@ -693,6 +693,6 @@ public class R820TTunerConfigurationPanel extends JPanel */ private void save() { - mResourceManager.getSettingsManager().save(); + mSettingsManager.save(); } } diff --git a/src/source/tuner/rtl/r820t/R820TTunerController.java b/src/source/tuner/rtl/r820t/R820TTunerController.java index 4713697d..109458e2 100644 --- a/src/source/tuner/rtl/r820t/R820TTunerController.java +++ b/src/source/tuner/rtl/r820t/R820TTunerController.java @@ -33,11 +33,11 @@ import org.usb4java.Device; import org.usb4java.DeviceDescriptor; import org.usb4java.LibUsbException; +import settings.SettingsManager; import source.SourceException; import source.tuner.TunerConfiguration; import source.tuner.TunerType; import source.tuner.rtl.RTL2832TunerController; -import controller.ResourceManager; import controller.ThreadPoolManager; public class R820TTunerController extends RTL2832TunerController @@ -139,11 +139,11 @@ public class R820TTunerController extends RTL2832TunerController /** * Controller gui editor component for this tuner */ - public JPanel getEditor( ResourceManager resourceManager ) + public JPanel getEditor( SettingsManager settingsManager ) { if( mEditor == null ) { - mEditor = new R820TTunerEditorPanel( this, resourceManager ); + mEditor = new R820TTunerEditorPanel( this, settingsManager ); } return mEditor; diff --git a/src/source/tuner/rtl/r820t/R820TTunerEditorPanel.java b/src/source/tuner/rtl/r820t/R820TTunerEditorPanel.java index f59d29a7..c761a07a 100644 --- a/src/source/tuner/rtl/r820t/R820TTunerEditorPanel.java +++ b/src/source/tuner/rtl/r820t/R820TTunerEditorPanel.java @@ -30,17 +30,16 @@ import net.miginfocom.swing.MigLayout; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import settings.SettingsManager; import source.SourceException; import source.tuner.frequency.FrequencyChangeEvent; -import source.tuner.frequency.FrequencyChangeListener; import source.tuner.frequency.FrequencyChangeEvent.Event; +import source.tuner.frequency.IFrequencyChangeProcessor; import source.tuner.rtl.RTL2832InfoPanel; import com.jidesoft.swing.JideTabbedPane; -import controller.ResourceManager; - -public class R820TTunerEditorPanel extends JPanel implements FrequencyChangeListener +public class R820TTunerEditorPanel extends JPanel implements IFrequencyChangeProcessor { private final static Logger mLog = LoggerFactory.getLogger( R820TTunerEditorPanel.class ); @@ -48,15 +47,15 @@ public class R820TTunerEditorPanel extends JPanel implements FrequencyChangeList private static final long serialVersionUID = 1L; private R820TTunerController mController; - private ResourceManager mResourceManager; + private SettingsManager mSettingsManager; private JFrequencyControl mFrequencyControl; public R820TTunerEditorPanel( R820TTunerController controller, - ResourceManager resourceManager ) + SettingsManager settingsManager ) { mController = controller; - mResourceManager = resourceManager; + mSettingsManager = settingsManager; initGUI(); } @@ -83,7 +82,7 @@ public class R820TTunerEditorPanel extends JPanel implements FrequencyChangeList tabs.setForeground( Color.BLACK ); tabs.addTab( "Configuration", - new R820TTunerConfigurationPanel( mResourceManager, mController ) ); + new R820TTunerConfigurationPanel( mSettingsManager, mController ) ); tabs.addTab( "Info", new RTL2832InfoPanel( mController ) ); @@ -97,7 +96,7 @@ public class R820TTunerEditorPanel extends JPanel implements FrequencyChangeList @Override public void frequencyChanged( FrequencyChangeEvent event ) { - if( event.getEvent() == Event.FREQUENCY_CHANGE_NOTIFICATION ) + if( event.getEvent() == Event.NOTIFICATION_FREQUENCY_CHANGE ) { final long frequency = event.getValue().longValue(); diff --git a/src/source/wave/ComplexWaveSource.java b/src/source/wave/ComplexWaveSource.java index 235c4717..9e4a65a8 100644 --- a/src/source/wave/ComplexWaveSource.java +++ b/src/source/wave/ComplexWaveSource.java @@ -51,11 +51,42 @@ public class ComplexWaveSource extends ComplexSource implements IControllableFil public ComplexWaveSource( File file ) throws IOException { - super( file.getAbsolutePath() ); - mFile = file; } + @Override + public void reset() + { + stop(); + start(); + } + + @Override + public void start() + { + try + { + open(); + } + catch ( IOException | UnsupportedAudioFileException e ) + { + mLog.error( "Error starting complex wave source" ); + } + } + + @Override + public void stop() + { + try + { + close(); + } + catch ( IOException e ) + { + mLog.error( "Error stopping complex wave source" ); + } + } + @Override public long getFrameCount() throws IOException { diff --git a/src/source/wave/RealWaveSource.java b/src/source/wave/RealWaveSource.java index a7251674..9af020c1 100644 --- a/src/source/wave/RealWaveSource.java +++ b/src/source/wave/RealWaveSource.java @@ -52,11 +52,46 @@ public class RealWaveSource extends RealSource public RealWaveSource( File file ) throws IOException { - super( file.getAbsolutePath() ); - mFile = file; } + + @Override + public void reset() + { + stop(); + start(); + } + + + @Override + public void start() + { + try + { + open(); + } + catch ( IOException | UnsupportedAudioFileException e ) + { + mLog.error( "Error starting real wave source", e ); + } + } + + + @Override + public void stop() + { + try + { + close(); + } + catch ( IOException e ) + { + mLog.error( "Error stopping real wave source", e ); + } + } + + @Override public long getFrameCount() throws IOException { diff --git a/src/spectrum/ChannelSpectrumPanel.java b/src/spectrum/ChannelSpectrumPanel.java index 5a87dc4c..9a2b134f 100644 --- a/src/spectrum/ChannelSpectrumPanel.java +++ b/src/spectrum/ChannelSpectrumPanel.java @@ -6,7 +6,6 @@ import java.awt.event.ComponentListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; -import java.util.Arrays; import java.util.concurrent.atomic.AtomicBoolean; import javax.swing.JLayeredPane; @@ -16,15 +15,16 @@ import javax.swing.JPopupMenu; import javax.swing.JSeparator; import javax.swing.SwingUtilities; +import module.ProcessingChain; +import net.miginfocom.swing.MigLayout; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import net.miginfocom.swing.MigLayout; import sample.Listener; import sample.SampleType; import sample.complex.ComplexBuffer; import sample.real.RealBuffer; -import sample.real.RealSampleListener; import settings.ColorSetting.ColorSettingName; import settings.ColorSettingMenuItem; import settings.Setting; @@ -40,15 +40,13 @@ import spectrum.menu.FFTWindowTypeItem; import spectrum.menu.FrameRateItem; import spectrum.menu.SmoothingItem; import spectrum.menu.SmoothingTypeItem; -import controller.ResourceManager; import controller.channel.Channel; import controller.channel.ChannelEvent; import controller.channel.ChannelEventListener; +import controller.channel.ChannelProcessingManager; import dsp.filter.Filters; -import dsp.filter.FloatHalfBandFilter; import dsp.filter.Window.WindowType; import dsp.filter.halfband.real.HalfBandFilter_RB_RB; -import dsp.filter.hilbert.HilbertTransform; import dsp.filter.smoothing.SmoothingFilter.SmoothingType; public class ChannelSpectrumPanel extends JPanel @@ -61,7 +59,6 @@ public class ChannelSpectrumPanel extends JPanel private static final long serialVersionUID = 1L; -// private ResourceManager mResourceManager; private DFTProcessor mDFTProcessor = new DFTProcessor( SampleType.REAL ); private DFTResultsConverter mDFTConverter = new RealDecibelConverter(); private JLayeredPane mLayeredPane; @@ -80,10 +77,13 @@ public class ChannelSpectrumPanel extends JPanel private AtomicBoolean mEnabled = new AtomicBoolean(); private SettingsManager mSettingsManager; + private ChannelProcessingManager mChannelProcessingManager; - public ChannelSpectrumPanel( SettingsManager settingsManager ) + public ChannelSpectrumPanel( SettingsManager settingsManager, + ChannelProcessingManager channelProcessingManager ) { mSettingsManager = settingsManager; + mChannelProcessingManager = channelProcessingManager; if( mSettingsManager != null ) { @@ -99,7 +99,7 @@ public class ChannelSpectrumPanel extends JPanel /* Set the DFTProcessor to the decimated 24kHz sample rate */ mDFTProcessor.frequencyChanged( - new FrequencyChangeEvent( Event.SAMPLE_RATE_CHANGE_NOTIFICATION, 24000 ) ); + new FrequencyChangeEvent( Event.NOTIFICATION_SAMPLE_RATE_CHANGE, 24000 ) ); initGui(); } @@ -167,14 +167,17 @@ public class ChannelSpectrumPanel extends JPanel switch( event.getEvent() ) { case NOTIFICATION_SELECTION_CHANGE: - if( !event.getChannel().isSelected() ) + //ChannelSelectionManager ensures that only 1 channel can be + //selected and any previously selected channel will be first + //deselected before we get a new selection event + if( event.getChannel().isSelected() ) { - stop(); + if( mCurrentChannel != null ) + { + stop(); + mCurrentChannel = null; + } - mCurrentChannel = null; - } - else - { mCurrentChannel = event.getChannel(); if( mEnabled.get() ) @@ -182,17 +185,13 @@ public class ChannelSpectrumPanel extends JPanel start(); } } - if( event.getChannel().isSelected() && - mCurrentChannel != event.getChannel() ) + else { stop(); - - mCurrentChannel = event.getChannel(); - - start(); + mCurrentChannel = null; } break; - case REQUEST_DISABLE: + case NOTIFICATION_PROCESSING_STOP: if( event.getChannel() == mCurrentChannel ) { if( mEnabled.get() ) @@ -203,32 +202,36 @@ public class ChannelSpectrumPanel extends JPanel mCurrentChannel = null; } break; - case REQUEST_ENABLE: - if( event.getChannel() == mCurrentChannel && - !event.getChannel().isProcessing() ) - { - stop(); - mCurrentChannel = null; - } - break; } } private void start() { - if( mEnabled.get() && mCurrentChannel != null && mCurrentChannel.isProcessing() ) + if( mEnabled.get() && mCurrentChannel != null && mCurrentChannel.getEnabled() ) { - mCurrentChannel.getProcessingChain().addRealBufferListener( this ); - mDFTProcessor.start(); + ProcessingChain processingChain = mChannelProcessingManager + .getProcessingChain( mCurrentChannel ); + + if( processingChain != null ) + { + processingChain.addRealBufferListener( this ); + + mDFTProcessor.start(); + } } } private void stop() { - - if( mCurrentChannel != null && mCurrentChannel.isProcessing() ) + if( mCurrentChannel != null && mCurrentChannel.getEnabled() ) { - mCurrentChannel.getProcessingChain().removeRealBufferListener( this ); + ProcessingChain processingChain = mChannelProcessingManager + .getProcessingChain( mCurrentChannel ); + + if( processingChain != null ) + { + processingChain.removeRealBufferListener( this ); + } } mDFTProcessor.stop(); diff --git a/src/spectrum/DFTProcessor.java b/src/spectrum/DFTProcessor.java index ef9b745f..207d9eb9 100644 --- a/src/spectrum/DFTProcessor.java +++ b/src/spectrum/DFTProcessor.java @@ -36,7 +36,7 @@ import sample.Listener; import sample.SampleType; import sample.complex.ComplexBuffer; import source.tuner.frequency.FrequencyChangeEvent; -import source.tuner.frequency.FrequencyChangeListener; +import source.tuner.frequency.IFrequencyChangeProcessor; import spectrum.converter.DFTResultsConverter; import controller.NamingThreadFactory; import dsp.filter.Window; @@ -47,7 +47,7 @@ import dsp.filter.Window.WindowType; * of DFT results, using configurable fft size and output dispatch timelines. */ public class DFTProcessor implements Listener, - FrequencyChangeListener, + IFrequencyChangeProcessor, IDFTWidthChangeProcessor { private final static Logger mLog = @@ -494,7 +494,7 @@ public class DFTProcessor implements Listener, { switch( event.getEvent() ) { - case SAMPLE_RATE_CHANGE_NOTIFICATION: + case NOTIFICATION_SAMPLE_RATE_CHANGE: mSampleRate = event.getValue().intValue(); calculateConsumptionRate(); break; diff --git a/src/spectrum/OverlayPanel.java b/src/spectrum/OverlayPanel.java index f51f744d..7e1aadf1 100644 --- a/src/spectrum/OverlayPanel.java +++ b/src/spectrum/OverlayPanel.java @@ -46,7 +46,7 @@ import settings.SettingChangeListener; import settings.SettingsManager; import source.tuner.TunerChannel; import source.tuner.frequency.FrequencyChangeEvent; -import source.tuner.frequency.FrequencyChangeListener; +import source.tuner.frequency.IFrequencyChangeProcessor; import controller.channel.Channel; import controller.channel.Channel.ChannelType; import controller.channel.ChannelEvent; @@ -55,7 +55,7 @@ import controller.channel.ChannelModel; public class OverlayPanel extends JPanel implements ChannelEventListener, - FrequencyChangeListener, + IFrequencyChangeProcessor, SettingChangeListener { private static final long serialVersionUID = 1L; @@ -528,14 +528,14 @@ public class OverlayPanel extends JPanel { if( mChannelDisplay == ChannelDisplay.ALL || ( mChannelDisplay == ChannelDisplay.ENABLED && - channel.isProcessing() ) ) + channel.getEnabled() ) ) { //Choose the correct background color to use if( channel.isSelected() ) { graphics.setColor( mColorChannelConfigSelected ); } - else if( channel.isProcessing() ) + else if( channel.getEnabled() ) { graphics.setColor( mColorChannelConfigProcessing ); } @@ -613,9 +613,11 @@ public class OverlayPanel extends JPanel drawChannelCenterLine( graphics, frequencyAxis ); /* Draw Automatic Frequency Control line */ - if( channel.hasFrequencyControl() ) + int correction = channel.getChannelFrequencyCorrection(); + + if( correction != 0 ) { - long error = frequency + channel.getFrequencyCorrection(); + long error = frequency + correction; drawAFC( graphics, frequencyAxis, getAxisFromFrequency( error ) ); } @@ -674,11 +676,11 @@ public class OverlayPanel extends JPanel { switch( event.getEvent() ) { - case SAMPLE_RATE_CHANGE_NOTIFICATION: + case NOTIFICATION_SAMPLE_RATE_CHANGE: mBandwidth = event.getValue().intValue(); mLabelSizeMonitor.update(); break; - case FREQUENCY_CHANGE_NOTIFICATION: + case NOTIFICATION_FREQUENCY_CHANGE: mFrequency = event.getValue().longValue(); mLabelSizeMonitor.update(); break; diff --git a/src/spectrum/SpectralDisplayPanel.java b/src/spectrum/SpectralDisplayPanel.java index e03d27e9..f8d1acd9 100644 --- a/src/spectrum/SpectralDisplayPanel.java +++ b/src/spectrum/SpectralDisplayPanel.java @@ -66,7 +66,7 @@ import source.tuner.Tuner; import source.tuner.TunerSelectionListener; import source.tuner.frequency.FrequencyChangeEvent; import source.tuner.frequency.FrequencyChangeEvent.Event; -import source.tuner.frequency.FrequencyChangeListener; +import source.tuner.frequency.IFrequencyChangeProcessor; import spectrum.OverlayPanel.ChannelDisplay; import spectrum.converter.ComplexDecibelConverter; import spectrum.converter.DFTResultsConverter; @@ -82,13 +82,14 @@ import com.jidesoft.swing.JideSplitPane; import controller.ConfigurationControllerModel; import controller.channel.Channel; import controller.channel.ChannelModel; +import controller.channel.ChannelProcessingManager; import controller.channel.ChannelUtils; import dsp.filter.Window.WindowType; import dsp.filter.smoothing.SmoothingFilter.SmoothingType; public class SpectralDisplayPanel extends JPanel implements Listener, - FrequencyChangeListener, + IFrequencyChangeProcessor, IDFTWidthChangeProcessor, TunerSelectionListener { @@ -115,9 +116,11 @@ public class SpectralDisplayPanel extends JPanel private OverlayPanel mOverlayPanel; private DFTProcessor mDFTProcessor; private DFTResultsConverter mDFTConverter; + private ConfigurationControllerModel mControllerModel; + private ChannelModel mChannelModel; + private ChannelProcessingManager mChannelProcessingManager; private PlaylistManager mPlaylistManager; private SettingsManager mSettingsManager; - private ConfigurationControllerModel mController; private Tuner mTuner; /** @@ -132,23 +135,26 @@ public class SpectralDisplayPanel extends JPanel * the DFT is translated to decibels for display in the spectrum and * waterfall components. */ - public SpectralDisplayPanel( ChannelModel channelModel, - ConfigurationControllerModel controller, + public SpectralDisplayPanel( ConfigurationControllerModel controllerModel, + ChannelModel channelModel, + ChannelProcessingManager channelProcessingManager, PlaylistManager playlistManager, SettingsManager settingsManager ) { - mController = controller; + mControllerModel = controllerModel; + mChannelModel = channelModel; + mChannelProcessingManager = channelProcessingManager; mPlaylistManager = playlistManager; mSettingsManager = settingsManager; mSpectrumPanel = new SpectrumPanel( mSettingsManager ); - mOverlayPanel = new OverlayPanel( mSettingsManager, channelModel ); + mOverlayPanel = new OverlayPanel( mSettingsManager, mChannelModel ); mWaterfallPanel = new WaterfallPanel( mSettingsManager ); //Register to receive tuner selection events - if( mController != null ) + if( mControllerModel != null ) { - mController.addListener( (TunerSelectionListener)this ); + mControllerModel.addListener( (TunerSelectionListener)this ); } init(); @@ -189,12 +195,12 @@ public class SpectralDisplayPanel extends JPanel /* De-register from receiving samples when the window closes */ clearTuner(); - if( mController != null ) + if( mControllerModel != null ) { - mController.removeListener( (TunerSelectionListener)this ); + mControllerModel.removeListener( (TunerSelectionListener)this ); } - mController = null; + mControllerModel = null; mPlaylistManager = null; mSettingsManager = null; @@ -426,7 +432,6 @@ public class SpectralDisplayPanel extends JPanel /** * Receives frequency change events -- primarily from tuner components. */ - @Override public void frequencyChanged( FrequencyChangeEvent event ) { mOverlayPanel.frequencyChanged( event ); @@ -458,7 +463,7 @@ public class SpectralDisplayPanel extends JPanel if( mTuner != null ) { //Register to receive frequency change events - mTuner.addListener( (FrequencyChangeListener)this ); + mTuner.addFrequencyChangeProcessor( this ); //Register the dft processor to receive samples from the tuner mTuner.addListener( (Listener)mDFTProcessor ); @@ -470,10 +475,10 @@ public class SpectralDisplayPanel extends JPanel try { frequencyChanged( new FrequencyChangeEvent( - Event.FREQUENCY_CHANGE_NOTIFICATION, mTuner.getFrequency() ) ); + Event.NOTIFICATION_FREQUENCY_CHANGE, mTuner.getFrequency() ) ); frequencyChanged( new FrequencyChangeEvent( - Event.SAMPLE_RATE_CHANGE_NOTIFICATION, mTuner.getSampleRate() ) ); + Event.NOTIFICATION_SAMPLE_RATE_CHANGE, mTuner.getSampleRate() ) ); } catch ( SourceException e ) { @@ -491,7 +496,7 @@ public class SpectralDisplayPanel extends JPanel if( mTuner != null ) { //Deregister for frequency change events from the tuner - mTuner.removeListener( (FrequencyChangeListener)this ); + mTuner.removeFrequencyChangeProcessor( this ); //Deregister the dft processor from receiving samples mTuner.removeListener( (Listener)mDFTProcessor ); @@ -652,8 +657,9 @@ public class SpectralDisplayPanel extends JPanel for( Channel channel: channels ) { - JMenu channelMenu = ChannelUtils.getContextMenu( - mPlaylistManager, channel, SpectralDisplayPanel.this ); + JMenu channelMenu = ChannelUtils.getContextMenu( mChannelModel, + mChannelProcessingManager, mPlaylistManager, channel, + SpectralDisplayPanel.this ); if( channelMenu != null ) { @@ -675,10 +681,7 @@ public class SpectralDisplayPanel extends JPanel for( DecoderType type: DecoderType.getPrimaryDecoders() ) { - decoderMenu.add( new DecoderItem( mController, - frequency, - type ) ); - + decoderMenu.add( new DecoderItem( type, frequency ) ); } frequencyMenu.add( decoderMenu ); @@ -957,17 +960,14 @@ public class SpectralDisplayPanel extends JPanel { private static final long serialVersionUID = 1L; - private ConfigurationControllerModel mController; + private ChannelModel mChannelModel; private long mFrequency; private DecoderType mDecoder; - public DecoderItem( ConfigurationControllerModel controller, - long frequency, - DecoderType type ) + public DecoderItem( DecoderType type, long frequency ) { super( type.getDisplayString() ); - mController = controller; mFrequency = frequency; mDecoder = type; @@ -976,7 +976,7 @@ public class SpectralDisplayPanel extends JPanel @Override public void actionPerformed( ActionEvent e ) { - mController.createChannel( mFrequency, mDecoder ); + mChannelModel.createChannel( mDecoder, mFrequency ); } } ); } diff --git a/src/spectrum/SpectrumFrame.java b/src/spectrum/SpectrumFrame.java index aa39a2f2..f3e6eac4 100644 --- a/src/spectrum/SpectrumFrame.java +++ b/src/spectrum/SpectrumFrame.java @@ -28,18 +28,18 @@ import playlist.PlaylistManager; import settings.SettingsManager; import source.tuner.Tuner; import controller.ConfigurationControllerModel; -import controller.ResourceManager; import controller.channel.ChannelModel; +import controller.channel.ChannelProcessingManager; public class SpectrumFrame extends JFrame implements WindowListener { private static final long serialVersionUID = 1L; - private ResourceManager mResourceManager; private SpectralDisplayPanel mSpectralDisplayPanel; - public SpectrumFrame( ChannelModel channelModel, - ConfigurationControllerModel controller, + public SpectrumFrame( ConfigurationControllerModel controllerModel, + ChannelModel channelModel, + ChannelProcessingManager channelProcessingManager, PlaylistManager playlistManager, SettingsManager settingsManager, Tuner tuner ) @@ -50,8 +50,8 @@ public class SpectrumFrame extends JFrame implements WindowListener setLayout( new MigLayout( "insets 0 0 0 0", "[grow]", "[grow]") ); - mSpectralDisplayPanel = new SpectralDisplayPanel( channelModel, - controller, playlistManager, settingsManager ); + mSpectralDisplayPanel = new SpectralDisplayPanel( controllerModel, + channelModel, channelProcessingManager, playlistManager, settingsManager ); mSpectralDisplayPanel.tunerSelected( tuner ); add( mSpectralDisplayPanel, "grow" );