Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#1847 Spectral Display of Multi-Frequency Channel Configurations #1848

Merged
merged 1 commit into from
Feb 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 62 additions & 45 deletions src/main/java/io/github/dsheirer/controller/channel/Channel.java
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2024 Dennis Sheirer
*
* * ******************************************************************************
* * Copyright (C) 2014-2020 Dennis Sheirer
* *
* * This program is free software: you can redistribute it and/or modify
* * it under the terms of the GNU General Public License as published by
* * the Free Software Foundation, either version 3 of the License, or
* * (at your option) any later version.
* *
* * This program is distributed in the hope that it will be useful,
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* * GNU General Public License for more details.
* *
* * You should have received a copy of the GNU General Public License
* * along with this program. If not, see <http://www.gnu.org/licenses/>
* * *****************************************************************************
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
package io.github.dsheirer.controller.channel;

Expand All @@ -35,13 +32,16 @@
import io.github.dsheirer.record.config.RecordConfiguration;
import io.github.dsheirer.sample.Listener;
import io.github.dsheirer.source.SourceEvent;
import io.github.dsheirer.source.SourceType;
import io.github.dsheirer.source.config.SourceConfigFactory;
import io.github.dsheirer.source.config.SourceConfigRecording;
import io.github.dsheirer.source.config.SourceConfigTuner;
import io.github.dsheirer.source.config.SourceConfigTunerMultipleFrequency;
import io.github.dsheirer.source.config.SourceConfiguration;
import io.github.dsheirer.source.tuner.channel.TunerChannel;
import java.beans.Transient;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import javafx.beans.Observable;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.IntegerProperty;
Expand All @@ -55,9 +55,6 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.beans.Transient;
import java.util.Objects;

@JacksonXmlRootElement(localName = "channel")
public class Channel extends Configuration implements Listener<SourceEvent>
{
Expand Down Expand Up @@ -88,7 +85,7 @@ public enum ChannelType
private BooleanProperty mAutoStart = new SimpleBooleanProperty();
private IntegerProperty mAutoStartOrder = new SimpleIntegerProperty();
private boolean mSelected;
private TunerChannel mTunerChannel = null;
private List<TunerChannel> mTunerChannels = null;

private ChannelType mChannelType = ChannelType.STANDARD;

Expand Down Expand Up @@ -634,9 +631,8 @@ public void setSourceConfiguration(SourceConfiguration config)

updateFrequencies();

//Clear the tune channel object so that it can be recreated if the
//source configuration changes
mTunerChannel = null;
//Clear the tune channels object so that it can be recreated if the source configuration changes
mTunerChannels = null;
}

/**
Expand Down Expand Up @@ -680,35 +676,50 @@ public void setRecordConfiguration(RecordConfiguration config)
}

/**
* 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.
* 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.
*
* If the source configuration is not a tuner or recording, this method
* returns null.
* If the source configuration is not a tuner or recording, this method returns an empty list.
*/
@JsonIgnore
public TunerChannel getTunerChannel()
public List<TunerChannel> getTunerChannels()
{
if(mTunerChannel == null)
if(mTunerChannels == null && mSourceConfiguration != null)
{
if(mSourceConfiguration.getSourceType() == SourceType.TUNER)
{
SourceConfigTuner config = (SourceConfigTuner)mSourceConfiguration;
mTunerChannels = new ArrayList<>();

mTunerChannel = new TunerChannel(config.getFrequency(),
mDecodeConfiguration.getChannelSpecification().getBandwidth());
}
else if(mSourceConfiguration.getSourceType() == SourceType.RECORDING)
switch(mSourceConfiguration.getSourceType())
{
SourceConfigRecording config = (SourceConfigRecording)mSourceConfiguration;

mTunerChannel = new TunerChannel(config.getFrequency(),
mDecodeConfiguration.getChannelSpecification().getBandwidth());
case TUNER:
if(mSourceConfiguration instanceof SourceConfigTuner tunerConfig)
{
mTunerChannels.add(new TunerChannel(tunerConfig.getFrequency(),
mDecodeConfiguration.getChannelSpecification().getBandwidth()));
}
break;
case TUNER_MULTIPLE_FREQUENCIES:
if(mSourceConfiguration instanceof SourceConfigTunerMultipleFrequency multiConfig)
{
for(long frequency: multiConfig.getFrequencies())
{
mTunerChannels.add(new TunerChannel(frequency,
mDecodeConfiguration.getChannelSpecification().getBandwidth()));
}
}
break;
case RECORDING:
if(mSourceConfiguration instanceof SourceConfigRecording recordingConfig)
{
mTunerChannels.add(new TunerChannel(recordingConfig.getFrequency(),
mDecodeConfiguration.getChannelSpecification().getBandwidth()));
}
break;
default:
mLog.warn("Unrecognized channel source type: " + mSourceConfiguration.getSourceType());
}
}

return mTunerChannel;
return mTunerChannels;
}

/**
Expand All @@ -717,9 +728,15 @@ else if(mSourceConfiguration.getSourceType() == SourceType.RECORDING)
*/
public boolean isWithin(long minimum, long maximum)
{
TunerChannel tunerChannel = getTunerChannel();
for(TunerChannel tunerChannel: getTunerChannels())
{
if(tunerChannel.overlaps(minimum, maximum))
{
return true;
}
}

return tunerChannel != null && tunerChannel.overlaps(minimum, maximum);
return false;
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2023 Dennis Sheirer
* Copyright (C) 2014-2024 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
Expand Down Expand Up @@ -444,11 +444,11 @@ public void receive(ProcessingChain processingChain)

if(channel != null)
{
TunerChannel tunerChannel = channel.getTunerChannel();
List<TunerChannel> tunerChannels = channel.getTunerChannels();

if(tunerChannel != null)
if(!tunerChannels.isEmpty())
{
mFrequencyOverlayPanel.setChannelBandwidth(tunerChannel.getBandwidth());
mFrequencyOverlayPanel.setChannelBandwidth(tunerChannels.get(0).getBandwidth());
}
}
}
Expand Down
84 changes: 45 additions & 39 deletions src/main/java/io/github/dsheirer/spectrum/OverlayPanel.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2023 Dennis Sheirer
* Copyright (C) 2014-2024 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
Expand Down Expand Up @@ -550,60 +550,63 @@ else if(channel.isProcessing())
graphics.setColor(mColorChannelConfig);
}

TunerChannel tunerChannel = channel.getTunerChannel();
List<TunerChannel> tunerChannels = channel.getTunerChannels();

if(tunerChannel != null)
for(TunerChannel tunerChannel: tunerChannels)
{
double xAxis = getAxisFromFrequency(tunerChannel.getFrequency());
if(tunerChannel.overlaps(getMinDisplayFrequency(), getMaxDisplayFrequency()))
{
double xAxis = getAxisFromFrequency(tunerChannel.getFrequency());

double width = (double)(tunerChannel.getBandwidth()) / (double)getDisplayBandwidth() * getSize().getWidth();
double width = (double)(tunerChannel.getBandwidth()) / (double)getDisplayBandwidth() * getSize().getWidth();

Rectangle2D.Double box =
new Rectangle2D.Double(xAxis - (width / 2.0d), 0.0d, width, getSize().getHeight() - mSpectrumInset);
Rectangle2D.Double box =
new Rectangle2D.Double(xAxis - (width / 2.0d), 0.0d, width, getSize().getHeight() - mSpectrumInset);

//Fill the box with the correct color
graphics.fill(box);
//Fill the box with the correct color
graphics.fill(box);

graphics.draw(box);
graphics.draw(box);

//Change to the line color to render the channel name, etc.
graphics.setColor(mColorSpectrumLine);
//Change to the line color to render the channel name, etc.
graphics.setColor(mColorSpectrumLine);

//Draw the labels starting at yAxis position 0
double yAxis = 0;
//Draw the labels starting at yAxis position 0
double yAxis = 0;

//Draw the system label and adjust the y-axis position
String system = channel.hasSystem() ? channel.getSystem() : " ";
//Draw the system label and adjust the y-axis position
String system = channel.hasSystem() ? channel.getSystem() : " ";

yAxis += drawLabel(graphics, system, this.getFont(), xAxis, yAxis, width);
yAxis += drawLabel(graphics, system, this.getFont(), xAxis, yAxis, width);

//Draw the site label and adjust the y-axis position
String site = channel.hasSite() ? channel.getSite() : " ";
//Draw the site label and adjust the y-axis position
String site = channel.hasSite() ? channel.getSite() : " ";

yAxis += drawLabel(graphics, site, this.getFont(), xAxis, yAxis, width);
yAxis += drawLabel(graphics, site, this.getFont(), xAxis, yAxis, width);

//Draw the channel label and adjust the y-axis position
yAxis += drawLabel(graphics, channel.getName(), this.getFont(), xAxis, yAxis, width);
//Draw the channel label and adjust the y-axis position
yAxis += drawLabel(graphics, channel.getName(), this.getFont(), xAxis, yAxis, width);

//Draw the decoder label
drawLabel(graphics, channel.getDecodeConfiguration().getDecoderType().getShortDisplayString(),
this.getFont(), xAxis, yAxis, width);
//Draw the decoder label
drawLabel(graphics, channel.getDecodeConfiguration().getDecoderType().getShortDisplayString(),
this.getFont(), xAxis, yAxis, width);

long frequency = tunerChannel.getFrequency();
long frequency = tunerChannel.getFrequency();

double frequencyAxis = getAxisFromFrequency(frequency);
double frequencyAxis = getAxisFromFrequency(frequency);

drawChannelCenterLine(graphics, frequencyAxis);

/* Draw Automatic Frequency Control line */
int correction = channel.getChannelFrequencyCorrection();
drawChannelCenterLine(graphics, frequencyAxis);

if(correction != 0)
{
long error = frequency + correction;
/* Draw Automatic Frequency Control line */
int correction = channel.getChannelFrequencyCorrection();

if(correction != 0)
{
long error = frequency + correction;

drawAFC(graphics, frequencyAxis, getAxisFromFrequency(error), width, correction,
tunerChannel.getFrequency());
drawAFC(graphics, frequencyAxis, getAxisFromFrequency(error), width, correction,
tunerChannel.getFrequency());
}
}
}
}
Expand Down Expand Up @@ -796,11 +799,14 @@ public ArrayList<Channel> getChannelsAtFrequency(long frequency)

for(Channel config : mVisibleChannels)
{
TunerChannel channel = config.getTunerChannel();
List<TunerChannel> channels = config.getTunerChannels();

if(channel != null && channel.getMinFrequency() <= frequency && channel.getMaxFrequency() >= frequency)
for(TunerChannel channel: channels)
{
configs.add(config);
if(channel != null && channel.getMinFrequency() <= frequency && channel.getMaxFrequency() >= frequency)
{
configs.add(config);
}
}
}

Expand Down
Loading