Compare commits

...

10 Commits

Author SHA1 Message Date
denny
d8a20b5adb Updating build to beta 5 2016-02-13 09:10:06 -05:00
denny
c670f1d855 Resolves issue with audio playback state becoming disconnected with
AudioManager connection class monitoring of the playback state.  Adds a
line listener to monitor when the line is started/stopped and responds
accordingly.

Removes squelch control from mono and stereo audio playback components
which was a holdover -- squelch state is now managed within the 
audio component for each processing chain.
2016-02-13 09:07:37 -05:00
denny
1dc0125ef4 Resolves issue with LTR standard calls - ending state was not monitoring
the correct channel number on call ends.
2016-02-12 20:54:14 -05:00
denny
225e747d6e Updated README 2016-02-07 10:04:23 -05:00
denny
36f9953156 Updated README 2016-02-07 09:40:25 -05:00
denny
47c452e7e6 README update 2016-02-07 09:28:09 -05:00
denny
06c8bba97e Updated README with version 0.2.0 wiki updates. 2016-02-07 09:26:25 -05:00
denny
a25bb83dea Talkgroup ID Editor - updates help text in editor window 2016-02-06 09:34:13 -05:00
denny
8e11cb4554 Removes audio inversion from talkgroup id and editor. The audio
processing architecture will be updated in the next version and will
handle identifying and processing audio inversion on a per-alias basis.
2016-02-06 09:30:52 -05:00
denny
2892e4609e Removes the 'No Tuner' color change sub-menu from the decoding channels
list.  This is no longer a valid channel state since any decoding
channels that fail to get a tuner source will not be displayed.
2016-02-06 08:24:46 -05:00
11 changed files with 78 additions and 144 deletions

View File

@@ -1,18 +1,22 @@
# sdrtrunk
A cross-platform java application for decoding, monitoring, recording and streaming trunked mobile and related radio protocols using Software Defined Radios (SDR).
# sdrtrunk #
A cross-platform java application for decoding, monitoring and recording trunked
mobile and related radio protocols using Software Defined Radios (SDR).
# Documentation #
* [Getting Started](https://github.com/DSheirer/sdrtrunk/wiki/GettingStarted)
* [User's Manual](https://github.com/DSheirer/sdrtrunk/wiki/UserManual)
* [User's Manual (Version 0.2.0)](https://github.com/DSheirer/sdrtrunk/wiki/UserManual)
* [Wiki](https://github.com/DSheirer/sdrtrunk/wiki)
# Support Group and Error Reporting #
You can get help with setting up the sdrtrunk application or report any errors
that you encounter while running the application in the sdrtrunk Google Group at:
* [Support](https://groups.google.com/forum/#!forum/sdrtrunk)
# Updates #
Subscribe to this group to receive updates about new releases and the ongoing
application development effort.
* [Subscribe for Updates](https://groups.google.com/forum/#!forum/sdrtrunk)
![](https://github.com/DSheirer/sdrtrunk/wiki/images/SDRTrunk_application.png)
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-67489234-1', 'auto');
ga('send', 'pageview');
</script>

View File

@@ -7,7 +7,7 @@
<property name="major" value="0"/>
<property name="minor" value="2"/>
<property name="patch" value="0"/>
<property name="release" value="beta.4"/>
<property name="release" value="beta.5"/>
<property name="filename" value="sdrtrunk_${major}.${minor}.${patch}-${release}"/>
<!-- Build properties -->

View File

@@ -27,7 +27,6 @@ import audio.inverted.AudioType;
public class TalkgroupID extends AliasID
{
private String mTalkgroup;
private AudioType mAudioType;
public TalkgroupID()
{
@@ -44,20 +43,9 @@ public class TalkgroupID extends AliasID
mTalkgroup = talkgroup;
}
@XmlAttribute
public AudioType getAudioType()
{
return mAudioType;
}
public void setAudioType( AudioType type )
{
mAudioType = type;
}
public boolean hasAudioType()
{
return mAudioType != null;
return false;
}
public String toString()
@@ -66,13 +54,6 @@ public class TalkgroupID extends AliasID
sb.append( "Talkgroup: " + mTalkgroup );
if( mAudioType != null )
{
sb.append( " [Audio " );
sb.append( mAudioType.getShortDisplayString() );
sb.append( "]" );
}
return sb.toString();
}

View File

@@ -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
@@ -20,9 +20,7 @@ package alias.id.talkgroup;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
@@ -30,7 +28,6 @@ import javax.swing.JTextArea;
import javax.swing.JTextField;
import net.miginfocom.swing.MigLayout;
import audio.inverted.AudioType;
import controller.ConfigurableNode;
public class TalkgroupIDEditor extends JPanel implements ActionListener
@@ -38,19 +35,15 @@ public class TalkgroupIDEditor extends JPanel implements ActionListener
private static final long serialVersionUID = 1L;
private TalkgroupIDNode mTalkgroupIDNode;
private JLabel mLabelName;
private JTextField mTextTalkgroupID;
private JLabel mLabelAudio;
private JComboBox<AudioType> mComboAudioTypes;
private String mHelpText = "Enter a formatted talkgroup identifier.\n\n"
+ "P25 Talkgroup Format: hexadecimal value, 4 characters for "
+ "talkgroup or 6 characters for a mobile radio\n\n"
+ "LTR Talkgroup Format: A-HH-TTT (A=Area, H=Home Repeater, "
+ "T=Talkgroup)\n\n"
+ "Passport Talkgroup Format: xxxxx (up to 5-digit number)\n\n"
+ "Wildcard: use one or more asterisks (*) for any talkgroup digits.\n\n"
+ "Audio: if the talkgroup uses simple frequency inversion, specify"
+ " the inversion frequency from the dropdown list to automatically"
+ " un-invert audio for this specific talkgroup";
+ "Wildcard: use one or more asterisks (*) for any talkgroup digits.";
public TalkgroupIDEditor( TalkgroupIDNode talkgroupIDNode )
{
@@ -72,22 +65,6 @@ public class TalkgroupIDEditor extends JPanel implements ActionListener
add( mTextTalkgroupID, "growx,push" );
add( new JLabel( "Audio:" ) );
mComboAudioTypes = new JComboBox<AudioType>();
mComboAudioTypes.setModel(
new DefaultComboBoxModel<AudioType>( AudioType.values() ) );
AudioType audioType = mTalkgroupIDNode.getTalkgroupID().getAudioType();
if( audioType != null )
{
mComboAudioTypes.setSelectedItem( audioType );
}
add( mComboAudioTypes, "growx,push" );
JButton btnSave = new JButton( "Save" );
btnSave.addActionListener( TalkgroupIDEditor.this );
add( btnSave, "growx,push" );
@@ -117,14 +94,6 @@ public class TalkgroupIDEditor extends JPanel implements ActionListener
((ConfigurableNode)mTalkgroupIDNode.getParent()).sort();
AudioType selected = mComboAudioTypes
.getItemAt( mComboAudioTypes.getSelectedIndex() );
if( selected != null )
{
mTalkgroupIDNode.getTalkgroupID().setAudioType( selected );
}
mTalkgroupIDNode.save();
mTalkgroupIDNode.show();
@@ -139,9 +108,6 @@ public class TalkgroupIDEditor extends JPanel implements ActionListener
{
mTextTalkgroupID.setText(
mTalkgroupIDNode.getTalkgroupID().getTalkgroup() );
mComboAudioTypes.setSelectedItem(
mTalkgroupIDNode.getTalkgroupID().getAudioType() );
}
mTalkgroupIDNode.refresh();

View File

@@ -182,7 +182,8 @@ public class AudioManager implements Listener<AudioPacket>, IAudioController
for( AudioOutputConnection connection: mAudioOutputConnections )
{
if( connection.isConnected() && connection.isInactive() )
if( connection.isInactive() &&
mChannelConnectionMap.containsKey( connection.getSource() ) )
{
mChannelConnectionMap.remove( connection.getSource() );
connection.disconnect();
@@ -424,7 +425,7 @@ public class AudioManager implements Listener<AudioPacket>, IAudioController
}
/**
* Audio output connection manages a connection between a soure and an audio
* Audio output connection manages a connection between a source and an audio
* output and maintains current state information about the audio activity
* received form the source.
*/

View File

@@ -1,9 +1,9 @@
package audio.output;
import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.LineListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -11,18 +11,15 @@ import org.slf4j.LoggerFactory;
import sample.Broadcaster;
import sample.Listener;
import audio.AudioEvent;
import audio.AudioEvent.Type;
import audio.AudioPacket;
import audio.metadata.AudioMetadata;
import controller.ThreadPoolManager;
public abstract class AudioOutput implements Listener<AudioPacket>
public abstract class AudioOutput implements Listener<AudioPacket>, LineListener
{
private final static Logger mLog = LoggerFactory.getLogger( AudioOutput.class );
private AtomicBoolean mSquelched = new AtomicBoolean( false );
private Listener<AudioMetadata> mAudioMetadataListener;
protected Broadcaster<AudioEvent> mAudioEventBroadcaster = new Broadcaster<>();
protected LinkedTransferQueue<AudioPacket> mBuffer = new LinkedTransferQueue<>();
protected ThreadPoolManager mThreadPoolManager;
@@ -74,19 +71,6 @@ public abstract class AudioOutput implements Listener<AudioPacket>
mAudioEventBroadcaster.broadcast( audioEvent );
}
public void setSquelched( boolean squelched )
{
mSquelched.set( squelched );
broadcast( new AudioEvent( squelched ? Type.AUDIO_SQUELCHED :
Type.AUDIO_UNSQUELCHED, getChannelName() ) );
}
public boolean isSquelched()
{
return mSquelched.get();
}
/**
* Registers a single listener to receive audio start and audio stop events
*/

View File

@@ -12,6 +12,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
import javax.sound.sampled.BooleanControl;
import javax.sound.sampled.Control;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.SourceDataLine;
@@ -50,11 +51,9 @@ public class MonoAudioOutput extends AudioOutput
private SourceDataLine mOutput;
private FloatControl mGainControl;
private BooleanControl mMuteControl;
private AudioEvent mAudioStartEvent;
private AudioEvent mAudioStopEvent;
private AudioEvent mAudioContinuationEvent;
private ScheduledFuture<?> mProcessorTask;
public MonoAudioOutput( ThreadPoolManager threadPoolManager, Mixer mixer )
@@ -76,6 +75,7 @@ public class MonoAudioOutput extends AudioOutput
if( mOutput != null )
{
mOutput.open( AudioFormats.PCM_SIGNED_48KHZ_16BITS_MONO, BUFFER_SIZE );
mOutput.addLineListener( this );
mCanProcessAudio = true;
}
}
@@ -162,17 +162,13 @@ public class MonoAudioOutput extends AudioOutput
if( packets.size() > 0 )
{
broadcast( mAudioContinuationEvent );
for( AudioPacket packet: packets )
{
broadcast( mAudioContinuationEvent );
if( mCanProcessAudio )
{
if( isSquelched() )
{
checkStop();
}
else if( packet.getType() == Type.AUDIO )
if( packet.getType() == Type.AUDIO )
{
float[] samples = packet.getAudioBuffer().getSamples();
@@ -216,24 +212,20 @@ public class MonoAudioOutput extends AudioOutput
private void checkStart()
{
if( mCanProcessAudio && !isSquelched() &&
if( mCanProcessAudio &&
!mOutput.isRunning() && mOutput.available() <= START_THRESHOLD )
{
mOutput.start();
mAudioEventBroadcaster.broadcast( mAudioStartEvent );
}
}
private void checkStop()
{
if( mCanProcessAudio && mOutput.isRunning() &&
( mOutput.available() >= STOP_THRESHOLD || isSquelched() ) )
mOutput.available() >= STOP_THRESHOLD )
{
mOutput.drain();
mOutput.stop();
mAudioEventBroadcaster.broadcast( mAudioStopEvent );
}
}
}
@@ -272,4 +264,19 @@ public class MonoAudioOutput extends AudioOutput
{
return mGainControl != null;
}
@Override
public void update( LineEvent event )
{
LineEvent.Type type = event.getType();
if( type == LineEvent.Type.START )
{
mAudioEventBroadcaster.broadcast( mAudioStartEvent );
}
else if( type == LineEvent.Type.STOP )
{
mAudioEventBroadcaster.broadcast( mAudioStopEvent );
}
}
}

View File

@@ -12,6 +12,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
import javax.sound.sampled.BooleanControl;
import javax.sound.sampled.Control;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.SourceDataLine;
@@ -40,9 +41,9 @@ public class StereoAudioOutput extends AudioOutput
private final static int BUFFER_SIZE = 96000;
/* The queue processor will run every 20 milliseconds checking for inbound
* audio and automatically starting or stopping audio playback. We set the
* audio and automatically start or stop audio playback. We set the
* data line available space threshold to start when we're 20 ms away from
* being full, and the stop threshold when 20 ms away from being empty */
* being full and the stop threshold when 20 ms away from being empty */
private final static int SAMPLE_SIZE_40_MS = BUFFER_SIZE / 25;
private final static int START_THRESHOLD = SAMPLE_SIZE_40_MS;
private final static int STOP_THRESHOLD = BUFFER_SIZE - SAMPLE_SIZE_40_MS;
@@ -50,13 +51,10 @@ public class StereoAudioOutput extends AudioOutput
private SourceDataLine mOutput;
private FloatControl mGainControl;
private BooleanControl mMuteControl;
private AudioEvent mAudioStartEvent;
private AudioEvent mAudioStopEvent;
private AudioEvent mAudioContinuationEvent;
private MixerChannel mMixerChannel;
private ScheduledFuture<?> mProcessorTask;
public StereoAudioOutput( ThreadPoolManager threadPoolManager,
@@ -83,6 +81,7 @@ public class StereoAudioOutput extends AudioOutput
if( mOutput != null )
{
mOutput.open( AudioFormats.PCM_SIGNED_48KHZ_16BITS_STEREO, BUFFER_SIZE );
mOutput.addLineListener( this );
mCanProcessAudio = true;
}
}
@@ -202,17 +201,14 @@ public class StereoAudioOutput extends AudioOutput
if( packets.size() > 0 )
{
broadcast( mAudioContinuationEvent );
for( AudioPacket packet: packets )
{
broadcast( mAudioContinuationEvent );
if( mCanProcessAudio )
{
if( isSquelched() )
{
checkStop();
}
else if( packet.getType() == Type.AUDIO )
if( packet.getType() == Type.AUDIO )
{
ByteBuffer buffer = convert(
packet.getAudioBuffer().getSamples() );
@@ -245,24 +241,20 @@ public class StereoAudioOutput extends AudioOutput
private void checkStart()
{
if( mCanProcessAudio && !isSquelched() &&
if( mCanProcessAudio &&
!mOutput.isRunning() && mOutput.available() <= START_THRESHOLD )
{
mOutput.start();
mAudioEventBroadcaster.broadcast( mAudioStartEvent );
}
}
private void checkStop()
{
if( mCanProcessAudio && mOutput.isRunning() &&
( mOutput.available() >= STOP_THRESHOLD || isSquelched() ) )
mOutput.available() >= STOP_THRESHOLD )
{
mOutput.drain();
mOutput.stop();
mAudioEventBroadcaster.broadcast( mAudioStopEvent );
}
}
}
@@ -301,4 +293,20 @@ public class StereoAudioOutput extends AudioOutput
{
return mGainControl != null;
}
@Override
public void update( LineEvent event )
{
LineEvent.Type type = event.getType();
if( type == LineEvent.Type.START )
{
mAudioEventBroadcaster.broadcast( mAudioStartEvent );
}
else if( type == LineEvent.Type.STOP )
{
mAudioEventBroadcaster.broadcast( mAudioStopEvent );
}
}
}

View File

@@ -153,7 +153,9 @@ public class LTRStandardDecoderState extends DecoderState
case CA_ENDD:
CallEndMessage end = (CallEndMessage)message;
int repeater = end.getHomeRepeater();
//Home channel is 31 for call end -- use the free channel
//as the call end channel
int repeater = end.getFree();
mLCNTracker.processCallChannel( repeater );

View File

@@ -253,20 +253,6 @@ public class ChannelList extends JPanel implements ChannelEventListener
idleMenu.add( new ColorSettingResetMenuItem( mSettingsManager,
ColorSettingName.CHANNEL_STATE_GRADIENT_TOP_IDLE ) );
JMenu noTunerMenu = new JMenu( "No Tuner" );
channelsMenu.add( noTunerMenu );
noTunerMenu.add( new ColorSettingMenuItem( mSettingsManager,
ColorSettingName.CHANNEL_STATE_GRADIENT_MIDDLE_NO_TUNER ) );
noTunerMenu.add( new ColorSettingResetMenuItem( mSettingsManager,
ColorSettingName.CHANNEL_STATE_GRADIENT_MIDDLE_NO_TUNER ) );
noTunerMenu.add( new JSeparator() );
noTunerMenu.add( new ColorSettingMenuItem( mSettingsManager,
ColorSettingName.CHANNEL_STATE_GRADIENT_TOP_NO_TUNER ) );
noTunerMenu.add( new ColorSettingResetMenuItem( mSettingsManager,
ColorSettingName.CHANNEL_STATE_GRADIENT_TOP_NO_TUNER ) );
JMenu labelMenu = new JMenu( "Labels" );
colorMenu.add( labelMenu );

View File

@@ -144,11 +144,6 @@ public class ChannelState extends Module implements ICallEventProvider,
mMonitoring.set( false );
}
}
else
{
throw new RuntimeException( "Channel state monitor's scheduled "
+ "future pointer was not null" );
}
}
}