From 4e92a6e3506a92bfc8da2b57d87c057dc51b3fcc Mon Sep 17 00:00:00 2001 From: Denny Sheirer Date: Sun, 20 Jan 2019 15:14:56 +0000 Subject: [PATCH] Resolves #494 (#495) Adds support to AM and FM decoders to record all audio produced by the decoder. --- .../audio/AudioMetadataProcessor.java | 10 +- .../io/github/dsheirer/audio/AudioModule.java | 48 ++++-- .../module/decode/DecoderFactory.java | 18 ++- .../module/decode/am/AMDecoderEditor.java | 139 ++++++++++-------- .../module/decode/am/DecodeConfigAM.java | 49 +++--- .../module/decode/nbfm/DecodeConfigNBFM.java | 44 ++++-- .../module/decode/nbfm/NBFMDecoderEditor.java | 47 ++++-- 7 files changed, 236 insertions(+), 119 deletions(-) diff --git a/src/main/java/io/github/dsheirer/audio/AudioMetadataProcessor.java b/src/main/java/io/github/dsheirer/audio/AudioMetadataProcessor.java index 4541195e..9559ffa6 100644 --- a/src/main/java/io/github/dsheirer/audio/AudioMetadataProcessor.java +++ b/src/main/java/io/github/dsheirer/audio/AudioMetadataProcessor.java @@ -1,7 +1,7 @@ /* * ****************************************************************************** * sdrtrunk - * Copyright (C) 2014-2018 Dennis Sheirer + * Copyright (C) 2014-2019 Dennis Sheirer * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -71,8 +71,14 @@ public class AudioMetadataProcessor if(aliasList != null) { audioPacket.addBroadcastChannels(aliasList.getBroadcastChannels(audioPacket.getIdentifierCollection())); - audioPacket.setRecordable(aliasList.isRecordable(audioPacket.getIdentifierCollection())); audioPacket.setMonitoringPriority(aliasList.getAudioPlaybackPriority(audioPacket.getIdentifierCollection())); + + //If the audio packet is already marked recordable, leave it alone, otherwise attempt to determine + //if we should record the audio packet from the aliased identifiers + if(!audioPacket.isRecordable()) + { + audioPacket.setRecordable(aliasList.isRecordable(audioPacket.getIdentifierCollection())); + } } } } diff --git a/src/main/java/io/github/dsheirer/audio/AudioModule.java b/src/main/java/io/github/dsheirer/audio/AudioModule.java index ceb0efe1..2d034ca1 100644 --- a/src/main/java/io/github/dsheirer/audio/AudioModule.java +++ b/src/main/java/io/github/dsheirer/audio/AudioModule.java @@ -1,18 +1,22 @@ -/******************************************************************************* - * sdr-trunk - * Copyright (C) 2014-2018 Dennis Sheirer +/* + * ****************************************************************************** + * sdrtrunk + * Copyright (C) 2014-2019 Dennis Sheirer * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any - * later version. + * This program is 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. + * 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 - * - ******************************************************************************/ + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + * ***************************************************************************** + */ package io.github.dsheirer.audio; import io.github.dsheirer.audio.squelch.SquelchState; @@ -72,6 +76,7 @@ public class AudioModule extends AbstractAudioModule implements IReusableBufferL private RealFIRFilter2 mHighPassFilter = new RealFIRFilter2(sHighPassFilterCoefficients); private SquelchStateListener mSquelchStateListener = new SquelchStateListener(); private SquelchState mSquelchState = SquelchState.SQUELCH; + private boolean mRecordAudioOverride; /** * Creates an Audio Module. @@ -87,6 +92,16 @@ public class AudioModule extends AbstractAudioModule implements IReusableBufferL mSquelchStateListener = null; } + /** + * Sets all audio packets as recordable when the argument is true. Otherwise, defers to the aliased identifiers + * from the identifier collection to determine whether to record the audio or not. + * @param recordAudio set to true to mark all audio as recordable. + */ + public void setRecordAudio(boolean recordAudio) + { + mRecordAudioOverride = recordAudio; + } + @Override public void reset() { @@ -109,6 +124,11 @@ public class AudioModule extends AbstractAudioModule implements IReusableBufferL endAudioPacket.resetAttributes(); endAudioPacket.setAudioChannelId(getAudioChannelId()); endAudioPacket.setIdentifierCollection(getIdentifierCollection().copyOf()); + + if(mRecordAudioOverride) + { + endAudioPacket.setRecordable(true); + } endAudioPacket.incrementUserCount(); getAudioPacketListener().receive(endAudioPacket); } @@ -132,6 +152,10 @@ public class AudioModule extends AbstractAudioModule implements IReusableBufferL audioPacket.resetAttributes(); audioPacket.setAudioChannelId(getAudioChannelId()); audioPacket.loadAudioFrom(highPassFiltered); + if(mRecordAudioOverride) + { + audioPacket.setRecordable(true); + } audioPacket.setIdentifierCollection(getIdentifierCollection().copyOf()); getAudioPacketListener().receive(audioPacket); diff --git a/src/main/java/io/github/dsheirer/module/decode/DecoderFactory.java b/src/main/java/io/github/dsheirer/module/decode/DecoderFactory.java index 722956af..a505b51f 100644 --- a/src/main/java/io/github/dsheirer/module/decode/DecoderFactory.java +++ b/src/main/java/io/github/dsheirer/module/decode/DecoderFactory.java @@ -150,7 +150,14 @@ public class DecoderFactory case AM: modules.add(new AMDecoder(decodeConfig)); modules.add(new AlwaysUnsquelchedDecoderState(DecoderType.AM, channel.getName())); - modules.add(new AudioModule()); + AudioModule audioModuleAM = new AudioModule(); + + //Check if the user wants all audio recorded .. + if(((DecodeConfigAM)decodeConfig).getRecordAudio()) + { + audioModuleAM.setRecordAudio(true); + } + modules.add(audioModuleAM); if(channel.getSourceConfiguration().getSourceType() == SourceType.TUNER) { modules.add(new AMDemodulatorModule(AM_CHANNEL_BANDWIDTH, DEMODULATED_AUDIO_SAMPLE_RATE)); @@ -159,7 +166,14 @@ public class DecoderFactory case NBFM: modules.add(new NBFMDecoder(decodeConfig)); modules.add(new AlwaysUnsquelchedDecoderState(DecoderType.NBFM, channel.getName())); - modules.add(new AudioModule()); + AudioModule audioModuleFM = new AudioModule(); + + //Check if the user wants all audio recorded .. + if(((DecodeConfigNBFM)decodeConfig).getRecordAudio()) + { + audioModuleFM.setRecordAudio(true); + } + modules.add(audioModuleFM); if(channel.getSourceConfiguration().getSourceType() == SourceType.TUNER) { modules.add(new FMDemodulatorModule(FM_CHANNEL_BANDWIDTH, DEMODULATED_AUDIO_SAMPLE_RATE)); diff --git a/src/main/java/io/github/dsheirer/module/decode/am/AMDecoderEditor.java b/src/main/java/io/github/dsheirer/module/decode/am/AMDecoderEditor.java index 56a87460..8207c068 100644 --- a/src/main/java/io/github/dsheirer/module/decode/am/AMDecoderEditor.java +++ b/src/main/java/io/github/dsheirer/module/decode/am/AMDecoderEditor.java @@ -1,20 +1,22 @@ -/******************************************************************************* - * 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 - ******************************************************************************/ +/* + * ****************************************************************************** + * sdrtrunk + * Copyright (C) 2014-2019 Dennis Sheirer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + * ***************************************************************************** + */ package io.github.dsheirer.module.decode.am; import io.github.dsheirer.controller.channel.Channel; @@ -23,53 +25,74 @@ import io.github.dsheirer.gui.editor.EditorValidationException; import io.github.dsheirer.gui.editor.ValidatingEditor; import net.miginfocom.swing.MigLayout; -import javax.swing.*; +import javax.swing.JCheckBox; +import javax.swing.JLabel; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; public class AMDecoderEditor extends ValidatingEditor { private static final long serialVersionUID = 1L; - - public AMDecoderEditor() - { - setLayout( new MigLayout( "insets 0 0 0 0", "", "" ) ); - add( new JLabel( "AM Decoder" ) ); - } + private JCheckBox mCheckBoxRecordAudio; - @Override - public void validate( Editor editor ) throws EditorValidationException - { - } + public AMDecoderEditor() + { + setLayout(new MigLayout("insets 0 0 0 0", "", "")); + add(new JLabel("AM Decoder")); + mCheckBoxRecordAudio = new JCheckBox("Record Audio"); + mCheckBoxRecordAudio.setEnabled(false); + mCheckBoxRecordAudio.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + setModified(true); + } + }); + add(mCheckBoxRecordAudio); + } - @Override - public void setItem( Channel item ) - { - super.setItem( item ); + @Override + public void validate(Editor editor) throws EditorValidationException + { + } - if( hasItem() ) - { - if( getItem().getDecodeConfiguration() instanceof DecodeConfigAM ) - { - setModified( false ); - } - else - { - setModified( true ); - } - } - else - { - setModified( false ); - } - } + @Override + public void setItem(Channel item) + { + super.setItem(item); - @Override - public void save() - { - if( hasItem() && isModified() ) - { - getItem().setDecodeConfiguration( new DecodeConfigAM() ); - } - - setModified( false ); - } + if(hasItem()) + { + if(getItem().getDecodeConfiguration() instanceof DecodeConfigAM) + { + DecodeConfigAM config = (DecodeConfigAM)getItem().getDecodeConfiguration(); + mCheckBoxRecordAudio.setSelected(config.getRecordAudio()); + mCheckBoxRecordAudio.setEnabled(true); + setModified(false); + } + else + { + setModified(true); + } + } + else + { + mCheckBoxRecordAudio.setEnabled(false); + setModified(false); + } + } + + @Override + public void save() + { + if(hasItem() && isModified()) + { + DecodeConfigAM config = new DecodeConfigAM(); + config.setRecordAudio(mCheckBoxRecordAudio.isSelected()); + getItem().setDecodeConfiguration(config); + } + + setModified(false); + } } diff --git a/src/main/java/io/github/dsheirer/module/decode/am/DecodeConfigAM.java b/src/main/java/io/github/dsheirer/module/decode/am/DecodeConfigAM.java index 1e12fc5b..ca9cc4ce 100644 --- a/src/main/java/io/github/dsheirer/module/decode/am/DecodeConfigAM.java +++ b/src/main/java/io/github/dsheirer/module/decode/am/DecodeConfigAM.java @@ -1,20 +1,22 @@ -/******************************************************************************* - * 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 - ******************************************************************************/ +/* + * ****************************************************************************** + * sdrtrunk + * Copyright (C) 2014-2019 Dennis Sheirer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + * ***************************************************************************** + */ package io.github.dsheirer.module.decode.am; import com.fasterxml.jackson.annotation.JsonIgnore; @@ -25,10 +27,23 @@ import io.github.dsheirer.source.tuner.channel.ChannelSpecification; public class DecodeConfigAM extends DecodeConfiguration { + private boolean mRecordAudio = false; + public DecodeConfigAM() { } + @JacksonXmlProperty(isAttribute = true, localName = "recordAudio") + public boolean getRecordAudio() + { + return mRecordAudio; + } + + public void setRecordAudio(boolean recordAudio) + { + mRecordAudio = recordAudio; + } + /** * Source channel specification for this decoder */ diff --git a/src/main/java/io/github/dsheirer/module/decode/nbfm/DecodeConfigNBFM.java b/src/main/java/io/github/dsheirer/module/decode/nbfm/DecodeConfigNBFM.java index f1bef7d4..588b4e79 100644 --- a/src/main/java/io/github/dsheirer/module/decode/nbfm/DecodeConfigNBFM.java +++ b/src/main/java/io/github/dsheirer/module/decode/nbfm/DecodeConfigNBFM.java @@ -1,20 +1,22 @@ -/******************************************************************************* - * SDR Trunk - * Copyright (C) 2014 Dennis Sheirer +/* + * ****************************************************************************** + * sdrtrunk + * Copyright (C) 2014-2019 Dennis Sheirer * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This program is 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. + * 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 - ******************************************************************************/ + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + * ***************************************************************************** + */ package io.github.dsheirer.module.decode.nbfm; import com.fasterxml.jackson.annotation.JsonIgnore; @@ -26,6 +28,7 @@ import io.github.dsheirer.source.tuner.channel.ChannelSpecification; public class DecodeConfigNBFM extends DecodeConfiguration { private Bandwidth mBandwidth = Bandwidth.BW_12_5; + private boolean mRecordAudio = false; public DecodeConfigNBFM() { @@ -68,6 +71,17 @@ public class DecodeConfigNBFM extends DecodeConfiguration mBandwidth = bandwidth; } + @JacksonXmlProperty(isAttribute = true, localName = "recordAudio") + public boolean getRecordAudio() + { + return mRecordAudio; + } + + public void setRecordAudio(boolean recordAudio) + { + mRecordAudio = recordAudio; + } + public enum Bandwidth { BW_12_5("12.5 kHz"), @@ -85,5 +99,5 @@ public class DecodeConfigNBFM extends DecodeConfiguration { return mLabel; } - }; + } } diff --git a/src/main/java/io/github/dsheirer/module/decode/nbfm/NBFMDecoderEditor.java b/src/main/java/io/github/dsheirer/module/decode/nbfm/NBFMDecoderEditor.java index 0329ada5..b267f8e3 100644 --- a/src/main/java/io/github/dsheirer/module/decode/nbfm/NBFMDecoderEditor.java +++ b/src/main/java/io/github/dsheirer/module/decode/nbfm/NBFMDecoderEditor.java @@ -1,18 +1,22 @@ -/******************************************************************************* - * sdr-trunk - * Copyright (C) 2014-2018 Dennis Sheirer +/* + * ****************************************************************************** + * sdrtrunk + * Copyright (C) 2014-2019 Dennis Sheirer * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any - * later version. + * This program is 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. + * 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 - * - ******************************************************************************/ + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + * ***************************************************************************** + */ package io.github.dsheirer.module.decode.nbfm; import io.github.dsheirer.controller.channel.Channel; @@ -23,6 +27,7 @@ import io.github.dsheirer.module.decode.config.DecodeConfiguration; import net.miginfocom.swing.MigLayout; import javax.swing.DefaultComboBoxModel; +import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JLabel; import java.awt.event.ActionEvent; @@ -33,6 +38,7 @@ public class NBFMDecoderEditor extends ValidatingEditor private static final long serialVersionUID = 1L; private JComboBox mComboBandwidth; + private JCheckBox mCheckBoxRecordAudio; public NBFMDecoderEditor() { @@ -41,7 +47,7 @@ public class NBFMDecoderEditor extends ValidatingEditor private void init() { - setLayout(new MigLayout("insets 0 0 0 0,wrap 2", "[right][grow,fill]", "")); + setLayout(new MigLayout("insets 0 0 0 0,wrap 3", "[][][]", "")); mComboBandwidth = new JComboBox<>(); mComboBandwidth.setModel(new DefaultComboBoxModel( @@ -58,6 +64,18 @@ public class NBFMDecoderEditor extends ValidatingEditor add(new JLabel("Bandwidth:")); add(mComboBandwidth); + + mCheckBoxRecordAudio = new JCheckBox("Record Audio"); + mCheckBoxRecordAudio.setEnabled(false); + mCheckBoxRecordAudio.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + setModified(true); + } + }); + add(mCheckBoxRecordAudio); } @Override @@ -73,6 +91,7 @@ public class NBFMDecoderEditor extends ValidatingEditor { DecodeConfigNBFM nbfm = new DecodeConfigNBFM(); nbfm.setBandwidth((DecodeConfigNBFM.Bandwidth)mComboBandwidth.getSelectedItem()); + nbfm.setRecordAudio(mCheckBoxRecordAudio.isSelected()); getItem().setDecodeConfiguration(nbfm); } @@ -82,6 +101,7 @@ public class NBFMDecoderEditor extends ValidatingEditor private void setControlsEnabled(boolean enabled) { mComboBandwidth.setEnabled(enabled); + mCheckBoxRecordAudio.setEnabled(enabled); } @Override @@ -99,6 +119,7 @@ public class NBFMDecoderEditor extends ValidatingEditor { DecodeConfigNBFM nbfm = (DecodeConfigNBFM)config; mComboBandwidth.setSelectedItem(nbfm.getBandwidth()); + mCheckBoxRecordAudio.setSelected(nbfm.getRecordAudio()); setModified(false); } else