mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 16:47:31 -05:00
#1723 Initial commit - audio call management feature.
-Implements Spring Boot and spring dependency injection - significant code refactoring. -Creates database repository with Calls table -Implements AudioManager to update database and manage audio recordings. -Calls paging and searching -Adds audio recording to wave file and places file in the calls database table. -Audio spectrum view with 64 bins. -Updates audio playback manager to process the incoming calls queue and support auto, auto-locked, replay, and mute playback modes. -Adds channel lock/unlock and mute/unmute features. -Adds column configuration editor to change column order & visibility and adds table state monitoring to save any user customization of the column ordering. -Adds call table column sort ordering to the saved table state and restores the sort on application launch. -Adds audio playback channel view options for: Complete, Standard and Minimal. Updates user preferences Audio | Playback section to allow user to select preferred view style.
This commit is contained in:
@@ -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
|
||||
@@ -20,8 +20,8 @@
|
||||
package io.github.dsheirer.gui;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import io.github.dsheirer.alias.AliasModel;
|
||||
import io.github.dsheirer.controller.channel.map.ChannelMap;
|
||||
import io.github.dsheirer.controller.channel.map.ChannelMapModel;
|
||||
import io.github.dsheirer.controller.channel.map.ChannelRange;
|
||||
import io.github.dsheirer.eventbus.MyEventBus;
|
||||
import io.github.dsheirer.gui.icon.IconManager;
|
||||
@@ -37,28 +37,30 @@ import io.github.dsheirer.gui.preference.ViewUserPreferenceEditorRequest;
|
||||
import io.github.dsheirer.gui.preference.calibration.CalibrationDialog;
|
||||
import io.github.dsheirer.gui.viewer.RecordingViewer;
|
||||
import io.github.dsheirer.gui.viewer.ViewRecordingViewerRequest;
|
||||
import io.github.dsheirer.icon.IconModel;
|
||||
import io.github.dsheirer.jmbe.JmbeEditor;
|
||||
import io.github.dsheirer.jmbe.JmbeEditorRequest;
|
||||
import io.github.dsheirer.module.log.EventLogManager;
|
||||
import io.github.dsheirer.monitor.ResourceMonitor;
|
||||
import io.github.dsheirer.monitor.StatusBox;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import javafx.application.Application;
|
||||
import javafx.application.Platform;
|
||||
import javafx.embed.swing.JFXPanel;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.stage.Stage;
|
||||
import jiconfont.javafx.IconFontFX;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Java FX window manager. Handles all secondary Java FX windows that are used within this primarily
|
||||
* Swing application.
|
||||
*/
|
||||
@Component("javaFxWindowManager")
|
||||
public class JavaFxWindowManager extends Application
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(JavaFxWindowManager.class);
|
||||
@@ -67,7 +69,6 @@ public class JavaFxWindowManager extends Application
|
||||
public static final String ICON_MANAGER = "iconmanager";
|
||||
public static final String PLAYLIST_EDITOR = "playlist";
|
||||
public static final String USER_PREFERENCES_EDITOR = "preferences";
|
||||
public static final String STAGE_MONITOR_KEY_CALIBRATION_DIALOG = "calibration.dialog";
|
||||
public static final String STAGE_MONITOR_KEY_CHANNEL_MAP_EDITOR = "channel.map";
|
||||
public static final String STAGE_MONITOR_KEY_RECORDING_VIEWER = "recording.viewer";
|
||||
public static final String STAGE_MONITOR_KEY_ICON_MANAGER_EDITOR = "icon.manager";
|
||||
@@ -75,50 +76,43 @@ public class JavaFxWindowManager extends Application
|
||||
public static final String STAGE_MONITOR_KEY_PLAYLIST_EDITOR = "playlist";
|
||||
public static final String STAGE_MONITOR_KEY_USER_PREFERENCES_EDITOR = "user.preferences";
|
||||
|
||||
private JFXPanel mJFXPanel;
|
||||
@Resource
|
||||
private ChannelMapEditor mChannelMapEditor;
|
||||
@Resource
|
||||
private ChannelMapModel mChannelMapModel;
|
||||
@Resource
|
||||
private IconManager mIconManager;
|
||||
@Resource
|
||||
private JmbeEditor mJmbeEditor;
|
||||
@Resource
|
||||
private PlaylistEditor mPlaylistEditor;
|
||||
private PlaylistManager mPlaylistManager;
|
||||
private TunerManager mTunerManager;
|
||||
@Resource
|
||||
private UserPreferences mUserPreferences;
|
||||
@Resource
|
||||
private UserPreferencesEditor mUserPreferencesEditor;
|
||||
private RecordingViewer mRecordingViewer;
|
||||
|
||||
private JFXPanel mStatusPanel;
|
||||
private RecordingViewer mRecordingViewer;
|
||||
private Stage mChannelMapStage;
|
||||
private Stage mIconManagerStage;
|
||||
private Stage mJmbeEditorStage;
|
||||
private Stage mPlaylistStage;
|
||||
private Stage mUserPreferencesStage;
|
||||
private Stage mRecordingViewerStage;
|
||||
private JFXPanel mStatusPanel;
|
||||
private List<Stage> mStages = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Constructs an instance. Note: this constructor is used for Swing applications.
|
||||
*/
|
||||
public JavaFxWindowManager(UserPreferences userPreferences, TunerManager tunerManager, PlaylistManager playlistManager)
|
||||
{
|
||||
mUserPreferences = userPreferences;
|
||||
mTunerManager = tunerManager;
|
||||
mPlaylistManager = playlistManager;
|
||||
|
||||
setup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance. Note: this constructor is used for standalone JavaFX application testing
|
||||
*/
|
||||
public JavaFxWindowManager()
|
||||
{
|
||||
mUserPreferences = new UserPreferences();
|
||||
AliasModel aliasModel = new AliasModel();
|
||||
EventLogManager eventLogManager = new EventLogManager(aliasModel, mUserPreferences);
|
||||
mTunerManager = new TunerManager(mUserPreferences);
|
||||
mTunerManager.start();
|
||||
mPlaylistManager = new PlaylistManager(mUserPreferences, mTunerManager, aliasModel, eventLogManager, new IconModel());
|
||||
mPlaylistManager.init();
|
||||
setup();
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
private void postConstruct()
|
||||
{
|
||||
//Register this class to receive events via each method annotated with @Subscribe
|
||||
MyEventBus.getGlobalEventBus().register(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -142,24 +136,11 @@ public class JavaFxWindowManager extends Application
|
||||
return mStatusPanel;
|
||||
}
|
||||
|
||||
private void setup()
|
||||
{
|
||||
//Register this class to receive events via each method annotated with @Subscribe
|
||||
MyEventBus.getGlobalEventBus().register(this);
|
||||
|
||||
//Register JavaFX icon fonts
|
||||
IconFontFX.register(jiconfont.icons.font_awesome.FontAwesome.getIconFont());
|
||||
|
||||
createJFXPanel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the runnable on the JavaFX application thread
|
||||
*/
|
||||
private void execute(Runnable runnable)
|
||||
{
|
||||
createJFXPanel();
|
||||
|
||||
if(Platform.isFxApplicationThread())
|
||||
{
|
||||
runnable.run();
|
||||
@@ -170,18 +151,6 @@ public class JavaFxWindowManager extends Application
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a JavaFX panel for Swing application compatibility
|
||||
*/
|
||||
private void createJFXPanel()
|
||||
{
|
||||
if(mJFXPanel == null)
|
||||
{
|
||||
mJFXPanel = new JFXPanel();
|
||||
Platform.setImplicitExit(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes monitoring for all JavaFX stages and shuts down the FX thread, killing all FX windows.
|
||||
*/
|
||||
@@ -189,12 +158,31 @@ public class JavaFxWindowManager extends Application
|
||||
{
|
||||
MyEventBus.getGlobalEventBus().unregister(this);
|
||||
mUserPreferences.getJavaFxPreferences().clearStageMonitors();
|
||||
Platform.exit();
|
||||
|
||||
Platform.runLater(() ->
|
||||
{
|
||||
Iterator<Stage> it = mStages.iterator();
|
||||
|
||||
while(it.hasNext())
|
||||
{
|
||||
try
|
||||
{
|
||||
it.next().close();
|
||||
}
|
||||
catch(Throwable t)
|
||||
{
|
||||
//Do nothing ... we're shutting down
|
||||
}
|
||||
|
||||
it.remove();
|
||||
}
|
||||
|
||||
Platform.exit();
|
||||
});
|
||||
}
|
||||
|
||||
public CalibrationDialog getCalibrationDialog(UserPreferences userPreferences)
|
||||
{
|
||||
createJFXPanel();
|
||||
return new CalibrationDialog(userPreferences);
|
||||
}
|
||||
|
||||
@@ -205,11 +193,11 @@ public class JavaFxWindowManager extends Application
|
||||
{
|
||||
if(mRecordingViewerStage == null)
|
||||
{
|
||||
createJFXPanel();
|
||||
Scene scene = new Scene(getRecordingViewer(), 1100, 800);
|
||||
mRecordingViewerStage = new Stage();
|
||||
mRecordingViewerStage.setTitle("sdrtrunk - Message Recording Viewer (.bits)");
|
||||
mRecordingViewerStage.setScene(scene);
|
||||
mStages.add(mRecordingViewerStage);
|
||||
mUserPreferences.getJavaFxPreferences().monitor(mRecordingViewerStage, STAGE_MONITOR_KEY_RECORDING_VIEWER);
|
||||
}
|
||||
|
||||
@@ -230,11 +218,11 @@ public class JavaFxWindowManager extends Application
|
||||
{
|
||||
if(mIconManagerStage == null)
|
||||
{
|
||||
createJFXPanel();
|
||||
Scene scene = new Scene(getIconManager(), 500, 500);
|
||||
mIconManagerStage = new Stage();
|
||||
mIconManagerStage.setTitle("sdrtrunk - Icon Manager");
|
||||
mIconManagerStage.setScene(scene);
|
||||
mStages.add(mIconManagerStage);
|
||||
mUserPreferences.getJavaFxPreferences().monitor(mIconManagerStage, STAGE_MONITOR_KEY_ICON_MANAGER_EDITOR);
|
||||
}
|
||||
|
||||
@@ -243,11 +231,6 @@ public class JavaFxWindowManager extends Application
|
||||
|
||||
public IconManager getIconManager()
|
||||
{
|
||||
if(mIconManager == null)
|
||||
{
|
||||
mIconManager = new IconManager(mPlaylistManager.getIconModel());
|
||||
}
|
||||
|
||||
return mIconManager;
|
||||
}
|
||||
|
||||
@@ -278,11 +261,11 @@ public class JavaFxWindowManager extends Application
|
||||
{
|
||||
if(mJmbeEditorStage == null)
|
||||
{
|
||||
createJFXPanel();
|
||||
Scene scene = new Scene(getJmbeEditor(), 650, 650);
|
||||
mJmbeEditorStage = new Stage();
|
||||
mJmbeEditorStage.setTitle("sdrtrunk - JMBE Library Updater");
|
||||
mJmbeEditorStage.setScene(scene);
|
||||
mStages.add(mJmbeEditorStage);
|
||||
mUserPreferences.getJavaFxPreferences().monitor(mJmbeEditorStage, STAGE_MONITOR_KEY_JMBE_EDITOR);
|
||||
}
|
||||
|
||||
@@ -291,11 +274,6 @@ public class JavaFxWindowManager extends Application
|
||||
|
||||
public JmbeEditor getJmbeEditor()
|
||||
{
|
||||
if(mJmbeEditor == null)
|
||||
{
|
||||
mJmbeEditor = new JmbeEditor(mUserPreferences);
|
||||
}
|
||||
|
||||
return mJmbeEditor;
|
||||
}
|
||||
|
||||
@@ -304,11 +282,6 @@ public class JavaFxWindowManager extends Application
|
||||
*/
|
||||
public PlaylistEditor getPlaylistEditor()
|
||||
{
|
||||
if(mPlaylistEditor == null)
|
||||
{
|
||||
mPlaylistEditor = new PlaylistEditor(mPlaylistManager, mTunerManager, mUserPreferences);
|
||||
}
|
||||
|
||||
return mPlaylistEditor;
|
||||
}
|
||||
|
||||
@@ -319,11 +292,11 @@ public class JavaFxWindowManager extends Application
|
||||
{
|
||||
if(mPlaylistStage == null)
|
||||
{
|
||||
createJFXPanel();
|
||||
Scene scene = new Scene(getPlaylistEditor(), 1000, 750);
|
||||
mPlaylistStage = new Stage();
|
||||
mPlaylistStage.setTitle("sdrtrunk - Playlist Editor");
|
||||
mPlaylistStage.setScene(scene);
|
||||
mStages.add(mPlaylistStage);
|
||||
mUserPreferences.getJavaFxPreferences().monitor(mPlaylistStage, STAGE_MONITOR_KEY_PLAYLIST_EDITOR);
|
||||
}
|
||||
|
||||
@@ -354,11 +327,6 @@ public class JavaFxWindowManager extends Application
|
||||
*/
|
||||
private UserPreferencesEditor getUserPreferencesEditor()
|
||||
{
|
||||
if(mUserPreferencesEditor == null)
|
||||
{
|
||||
mUserPreferencesEditor = new UserPreferencesEditor(mUserPreferences);
|
||||
}
|
||||
|
||||
return mUserPreferencesEditor;
|
||||
}
|
||||
|
||||
@@ -369,11 +337,11 @@ public class JavaFxWindowManager extends Application
|
||||
{
|
||||
if(mUserPreferencesStage == null)
|
||||
{
|
||||
createJFXPanel();
|
||||
Scene scene = new Scene(getUserPreferencesEditor(), 900, 500);
|
||||
mUserPreferencesStage = new Stage();
|
||||
mUserPreferencesStage.setTitle("sdrtrunk - User Preferences");
|
||||
mUserPreferencesStage.setScene(scene);
|
||||
mStages.add(mUserPreferencesStage);
|
||||
mUserPreferences.getJavaFxPreferences().monitor(mUserPreferencesStage, STAGE_MONITOR_KEY_USER_PREFERENCES_EDITOR);
|
||||
}
|
||||
|
||||
@@ -397,11 +365,6 @@ public class JavaFxWindowManager extends Application
|
||||
*/
|
||||
private ChannelMapEditor getChannelMapEditor()
|
||||
{
|
||||
if(mChannelMapEditor == null)
|
||||
{
|
||||
mChannelMapEditor = new ChannelMapEditor(mPlaylistManager.getChannelMapModel());
|
||||
}
|
||||
|
||||
return mChannelMapEditor;
|
||||
}
|
||||
|
||||
@@ -412,11 +375,11 @@ public class JavaFxWindowManager extends Application
|
||||
{
|
||||
if(mChannelMapStage == null)
|
||||
{
|
||||
createJFXPanel();
|
||||
Scene scene = new Scene(getChannelMapEditor(), 500, 500);
|
||||
mChannelMapStage = new Stage();
|
||||
mChannelMapStage.setTitle("sdrtrunk - Channel Map Editor");
|
||||
mChannelMapStage.setScene(scene);
|
||||
mStages.add(mChannelMapStage);
|
||||
mUserPreferences.getJavaFxPreferences().monitor(mChannelMapStage, STAGE_MONITOR_KEY_CHANNEL_MAP_EDITOR);
|
||||
}
|
||||
|
||||
@@ -489,14 +452,14 @@ public class JavaFxWindowManager extends Application
|
||||
channelMap1.addRange(new ChannelRange(200,299,160000000, 25000));
|
||||
channelMap1.addRange(new ChannelRange(300,399,170000000, 12500));
|
||||
channelMap1.addRange(new ChannelRange(400,499,180000000, 25000));
|
||||
mPlaylistManager.getChannelMapModel().addChannelMap(channelMap1);
|
||||
mChannelMapModel.addChannelMap(channelMap1);
|
||||
|
||||
ChannelMap channelMap2 = new ChannelMap("Test Map 2");
|
||||
channelMap2.addRange(new ChannelRange(1,199,450000000, 12500));
|
||||
channelMap2.addRange(new ChannelRange(200,299,460000000, 25000));
|
||||
channelMap2.addRange(new ChannelRange(300,399,470000000, 12500));
|
||||
channelMap2.addRange(new ChannelRange(400,499,480000000, 25000));
|
||||
mPlaylistManager.getChannelMapModel().addChannelMap(channelMap2);
|
||||
mChannelMapModel.addChannelMap(channelMap2);
|
||||
valid = true;
|
||||
process(new ViewChannelMapEditorRequest());
|
||||
break;
|
||||
|
||||
@@ -18,864 +18,153 @@
|
||||
*/
|
||||
package io.github.dsheirer.gui;
|
||||
|
||||
import com.jidesoft.plaf.LookAndFeelFactory;
|
||||
import com.jidesoft.swing.JideSplitPane;
|
||||
import io.github.dsheirer.alias.AliasModel;
|
||||
import io.github.dsheirer.audio.DuplicateCallDetector;
|
||||
import io.github.dsheirer.audio.broadcast.AudioStreamingManager;
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastFormat;
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastStatusPanel;
|
||||
import io.github.dsheirer.audio.playback.AudioPlaybackManager;
|
||||
import io.github.dsheirer.controller.ControllerPanel;
|
||||
import io.github.dsheirer.controller.channel.Channel;
|
||||
import io.github.dsheirer.controller.channel.ChannelAutoStartFrame;
|
||||
import io.github.dsheirer.controller.channel.ChannelException;
|
||||
import io.github.dsheirer.controller.channel.ChannelSelectionManager;
|
||||
import io.github.dsheirer.eventbus.MyEventBus;
|
||||
import io.github.dsheirer.gui.icon.ViewIconManagerRequest;
|
||||
import io.github.dsheirer.gui.playlist.ViewPlaylistRequest;
|
||||
import io.github.dsheirer.gui.preference.CalibrateRequest;
|
||||
import io.github.dsheirer.gui.preference.PreferenceEditorType;
|
||||
import io.github.dsheirer.gui.preference.ViewUserPreferenceEditorRequest;
|
||||
import io.github.dsheirer.gui.preference.calibration.CalibrationDialog;
|
||||
import io.github.dsheirer.gui.viewer.ViewRecordingViewerRequest;
|
||||
import io.github.dsheirer.icon.IconModel;
|
||||
import io.github.dsheirer.controller.channel.ChannelModel;
|
||||
import io.github.dsheirer.controller.channel.ChannelProcessingManager;
|
||||
import io.github.dsheirer.log.ApplicationLog;
|
||||
import io.github.dsheirer.map.MapService;
|
||||
import io.github.dsheirer.module.log.EventLogManager;
|
||||
import io.github.dsheirer.monitor.ResourceMonitor;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.properties.SystemProperties;
|
||||
import io.github.dsheirer.record.AudioRecordingManager;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.settings.SettingsManager;
|
||||
import io.github.dsheirer.source.tuner.Tuner;
|
||||
import io.github.dsheirer.source.tuner.TunerEvent;
|
||||
import io.github.dsheirer.source.tuner.manager.DiscoveredTuner;
|
||||
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||
import io.github.dsheirer.source.tuner.ui.TunerSpectralDisplayManager;
|
||||
import io.github.dsheirer.spectrum.DisableSpectrumWaterfallMenuItem;
|
||||
import io.github.dsheirer.spectrum.ShowTunerMenuItem;
|
||||
import io.github.dsheirer.spectrum.SpectralDisplayPanel;
|
||||
import io.github.dsheirer.util.ThreadPool;
|
||||
import io.github.dsheirer.util.TimeStamp;
|
||||
import io.github.dsheirer.vector.calibrate.CalibrationManager;
|
||||
import java.awt.AWTException;
|
||||
import java.awt.Desktop;
|
||||
import java.awt.Dimension;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.PreDestroy;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.Point;
|
||||
import java.awt.Robot;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import java.util.prefs.Preferences;
|
||||
import javafx.application.Platform;
|
||||
import javafx.embed.swing.JFXPanel;
|
||||
import javafx.scene.control.ButtonType;
|
||||
import jiconfont.icons.font_awesome.FontAwesome;
|
||||
import jiconfont.swing.IconFontSwing;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.Banner;
|
||||
import org.springframework.boot.WebApplicationType;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.domain.EntityScan;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.JCheckBoxMenuItem;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuBar;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JSeparator;
|
||||
import javax.swing.KeyStroke;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.event.MenuEvent;
|
||||
import javax.swing.event.MenuListener;
|
||||
import javax.swing.plaf.metal.MetalLookAndFeel;
|
||||
|
||||
public class SDRTrunk implements Listener<TunerEvent>
|
||||
@SpringBootApplication(scanBasePackages = {"io.github.dsheirer"})
|
||||
@EnableJpaRepositories("io.github.dsheirer.audio.call")
|
||||
@EntityScan("io.github.dsheirer.audio.call")
|
||||
public class SDRTrunk
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(SDRTrunk.class);
|
||||
private Preferences mPreferences = Preferences.userNodeForPackage(SDRTrunk.class);
|
||||
|
||||
private static final String PREFERENCE_BROADCAST_STATUS_VISIBLE = "sdrtrunk.broadcast.status.visible";
|
||||
private static final String PREFERENCE_NOW_PLAYING_DETAILS_VISIBLE = "sdrtrunk.now.playing.details.visible";
|
||||
private static final String PREFERENCE_RESOURCE_STATUS_VISIBLE = "sdrtrunk.resource.status.visible";
|
||||
private static final String BASE_WINDOW_NAME = "sdrtrunk.main.window";
|
||||
private static final String CONTROLLER_PANEL_IDENTIFIER = BASE_WINDOW_NAME + ".control.panel";
|
||||
private static final String SPECTRAL_PANEL_IDENTIFIER = BASE_WINDOW_NAME + ".spectral.panel";
|
||||
private static final String WINDOW_FRAME_IDENTIFIER = BASE_WINDOW_NAME + ".frame";
|
||||
|
||||
private boolean mBroadcastStatusVisible;
|
||||
private boolean mResourceStatusVisible;
|
||||
private boolean mNowPlayingDetailsVisible;
|
||||
private AudioRecordingManager mAudioRecordingManager;
|
||||
private AudioStreamingManager mAudioStreamingManager;
|
||||
private BroadcastStatusPanel mBroadcastStatusPanel;
|
||||
private ControllerPanel mControllerPanel;
|
||||
private IconModel mIconModel = new IconModel();
|
||||
private PlaylistManager mPlaylistManager;
|
||||
private SettingsManager mSettingsManager;
|
||||
private SpectralDisplayPanel mSpectralPanel;
|
||||
private JFrame mMainGui;
|
||||
private JideSplitPane mSplitPane;
|
||||
private JavaFxWindowManager mJavaFxWindowManager;
|
||||
private UserPreferences mUserPreferences = new UserPreferences();
|
||||
private TunerManager mTunerManager;
|
||||
@Resource
|
||||
private ApplicationLog mApplicationLog;
|
||||
private ResourceMonitor mResourceMonitor;
|
||||
private JFXPanel mResourceStatusPanel;
|
||||
|
||||
private String mTitle;
|
||||
@Resource
|
||||
private AudioRecordingManager mAudioRecordingManager;
|
||||
@Resource
|
||||
private ChannelModel mChannelModel;
|
||||
@Resource
|
||||
private ChannelProcessingManager mChannelProcessingManager;
|
||||
@Resource
|
||||
private TunerManager mTunerManager;
|
||||
@Resource
|
||||
private UserPreferences mUserPreferences;
|
||||
@Resource //SpringUiFactory does not instantiate this instance when headless=true
|
||||
private SDRTrunkUI mSDRTrunkUI;
|
||||
|
||||
/**
|
||||
* Constructs an instance of the SDRTrunk application
|
||||
*/
|
||||
public SDRTrunk()
|
||||
{
|
||||
if(!GraphicsEnvironment.isHeadless())
|
||||
{
|
||||
mMainGui = new JFrame();
|
||||
}
|
||||
}
|
||||
|
||||
mApplicationLog = new ApplicationLog(mUserPreferences);
|
||||
mApplicationLog.start();
|
||||
|
||||
mResourceMonitor = new ResourceMonitor(mUserPreferences);
|
||||
|
||||
String operatingSystem = System.getProperty("os.name", "generic").toLowerCase(Locale.ENGLISH);
|
||||
|
||||
if(operatingSystem.contains("mac") || operatingSystem.contains("nux"))
|
||||
{
|
||||
try
|
||||
{
|
||||
UIManager.setLookAndFeel(MetalLookAndFeel.class.getName());
|
||||
LookAndFeelFactory.installJideExtension();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
mLog.error("Error trying to set Metal look and feel for OS [" + operatingSystem + "]");
|
||||
}
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
ThreadPool.logSettings();
|
||||
|
||||
//Load properties file
|
||||
loadProperties();
|
||||
|
||||
//Log current properties setting
|
||||
SystemProperties.getInstance().logCurrentSettings();
|
||||
|
||||
//Register FontAwesome so we can use the fonts in Swing windows
|
||||
IconFontSwing.register(FontAwesome.getIconFont());
|
||||
|
||||
mTunerManager = new TunerManager(mUserPreferences);
|
||||
mTunerManager.start();
|
||||
|
||||
mSettingsManager = new SettingsManager();
|
||||
|
||||
AliasModel aliasModel = new AliasModel();
|
||||
EventLogManager eventLogManager = new EventLogManager(aliasModel, mUserPreferences);
|
||||
mPlaylistManager = new PlaylistManager(mUserPreferences, mTunerManager, aliasModel, eventLogManager, mIconModel);
|
||||
|
||||
if(!GraphicsEnvironment.isHeadless())
|
||||
{
|
||||
mJavaFxWindowManager = new JavaFxWindowManager(mUserPreferences, mTunerManager, mPlaylistManager);
|
||||
}
|
||||
|
||||
CalibrationManager calibrationManager = CalibrationManager.getInstance(mUserPreferences);
|
||||
final boolean calibrating = !calibrationManager.isCalibrated() &&
|
||||
!mUserPreferences.getVectorCalibrationPreference().isHideCalibrationDialog();
|
||||
|
||||
new ChannelSelectionManager(mPlaylistManager.getChannelModel());
|
||||
|
||||
AudioPlaybackManager audioPlaybackManager = new AudioPlaybackManager(mUserPreferences);
|
||||
|
||||
mAudioRecordingManager = new AudioRecordingManager(mUserPreferences);
|
||||
mAudioRecordingManager.start();
|
||||
|
||||
mAudioStreamingManager = new AudioStreamingManager(mPlaylistManager.getBroadcastModel(), BroadcastFormat.MP3,
|
||||
mUserPreferences);
|
||||
mAudioStreamingManager.start();
|
||||
|
||||
DuplicateCallDetector duplicateCallDetector = new DuplicateCallDetector(mUserPreferences);
|
||||
|
||||
mPlaylistManager.getChannelProcessingManager().addAudioSegmentListener(duplicateCallDetector);
|
||||
mPlaylistManager.getChannelProcessingManager().addAudioSegmentListener(audioPlaybackManager);
|
||||
mPlaylistManager.getChannelProcessingManager().addAudioSegmentListener(mAudioRecordingManager);
|
||||
mPlaylistManager.getChannelProcessingManager().addAudioSegmentListener(mAudioStreamingManager);
|
||||
|
||||
MapService mapService = new MapService(mIconModel);
|
||||
mPlaylistManager.getChannelProcessingManager().addDecodeEventListener(mapService);
|
||||
|
||||
mNowPlayingDetailsVisible = mPreferences.getBoolean(PREFERENCE_NOW_PLAYING_DETAILS_VISIBLE, true);
|
||||
|
||||
if(!GraphicsEnvironment.isHeadless())
|
||||
{
|
||||
mControllerPanel = new ControllerPanel(mPlaylistManager, audioPlaybackManager, mIconModel, mapService,
|
||||
mSettingsManager, mTunerManager, mUserPreferences, mNowPlayingDetailsVisible);
|
||||
}
|
||||
|
||||
mSpectralPanel = new SpectralDisplayPanel(mPlaylistManager, mSettingsManager, mTunerManager.getDiscoveredTunerModel());
|
||||
|
||||
TunerSpectralDisplayManager tunerSpectralDisplayManager = new TunerSpectralDisplayManager(mSpectralPanel,
|
||||
mPlaylistManager, mSettingsManager, mTunerManager.getDiscoveredTunerModel());
|
||||
mTunerManager.getDiscoveredTunerModel().addListener(tunerSpectralDisplayManager);
|
||||
mTunerManager.getDiscoveredTunerModel().addListener(this);
|
||||
|
||||
mPlaylistManager.init();
|
||||
|
||||
if(GraphicsEnvironment.isHeadless())
|
||||
{
|
||||
mLog.info("starting main application headless");
|
||||
mLog.info("starting main application in headless mode");
|
||||
autoStartChannels();
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.info("starting main application gui");
|
||||
|
||||
//Initialize the GUI
|
||||
initGUI();
|
||||
}
|
||||
|
||||
//Start the gui
|
||||
EventQueue.invokeLater(() -> {
|
||||
try
|
||||
mLog.info("starting main application with gui");
|
||||
if(mSDRTrunkUI != null)
|
||||
{
|
||||
if(!GraphicsEnvironment.isHeadless())
|
||||
{
|
||||
mMainGui.setVisible(true);
|
||||
Tuner tuner = tunerSpectralDisplayManager.showFirstTuner();
|
||||
|
||||
if(tuner != null)
|
||||
{
|
||||
updateTitle(tuner.getPreferredName());
|
||||
}
|
||||
}
|
||||
|
||||
if(calibrating && !GraphicsEnvironment.isHeadless())
|
||||
{
|
||||
Platform.runLater(() ->
|
||||
{
|
||||
CalibrationDialog calibrationDialog = mJavaFxWindowManager.getCalibrationDialog(mUserPreferences);
|
||||
Optional<ButtonType> calibrate = calibrationDialog.showAndWait();
|
||||
if(calibrate.isPresent() && calibrate.get().getText().equals("Calibrate"))
|
||||
{
|
||||
//Request focus and execute calibration
|
||||
MyEventBus.getGlobalEventBus().post(new ViewUserPreferenceEditorRequest(PreferenceEditorType.VECTOR_CALIBRATION));
|
||||
MyEventBus.getGlobalEventBus().post(new CalibrateRequest());
|
||||
}
|
||||
else
|
||||
{
|
||||
autoStartChannels();
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
autoStartChannels();
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a dialog that lists the channels that have been designated for auto-start, sorted by auto-start order and
|
||||
* allows the user to start now, cancel, or allow the timer to expire and then start the channels. The dialog will
|
||||
* only show if there are one ore more channels designated for auto-start.
|
||||
*/
|
||||
private void autoStartChannels()
|
||||
{
|
||||
List<Channel> channels = mPlaylistManager.getChannelModel().getAutoStartChannels();
|
||||
|
||||
if(channels.size() > 0)
|
||||
{
|
||||
if(GraphicsEnvironment.isHeadless())
|
||||
{
|
||||
for(Channel channel: channels)
|
||||
{
|
||||
try
|
||||
{
|
||||
mLog.info("Auto-starting channel " + channel.getName());
|
||||
mPlaylistManager.getChannelProcessingManager().start(channel);
|
||||
}
|
||||
catch(ChannelException ce)
|
||||
{
|
||||
mLog.error("Channel: " + channel.getName() + " auto-start failed: " + ce.getMessage());
|
||||
}
|
||||
}
|
||||
EventQueue.invokeLater(() -> mSDRTrunkUI.setVisible(true));
|
||||
}
|
||||
else
|
||||
{
|
||||
new ChannelAutoStartFrame(mPlaylistManager.getChannelProcessingManager(), channels, mUserPreferences);
|
||||
mLog.error("SDRTrunk user interface is null - can't start UI");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the contents of the frame.
|
||||
* Starts processing any channel configurations that are designated to auto-start
|
||||
*/
|
||||
private void initGUI()
|
||||
private void autoStartChannels()
|
||||
{
|
||||
mMainGui.setLayout(new MigLayout("insets 0 0 0 0 ", "[grow,fill]", "[grow,fill]0[shrink 0]"));
|
||||
|
||||
/**
|
||||
* Setup main JFrame window
|
||||
*/
|
||||
mTitle = SystemProperties.getInstance().getApplicationName();
|
||||
mMainGui.setTitle(mTitle);
|
||||
|
||||
Point location = mUserPreferences.getSwingPreference().getLocation(WINDOW_FRAME_IDENTIFIER);
|
||||
if(location != null)
|
||||
List<Channel> channels = mChannelModel.getAutoStartChannels();
|
||||
for(Channel channel: channels)
|
||||
{
|
||||
mMainGui.setLocation(location);
|
||||
}
|
||||
else
|
||||
{
|
||||
mMainGui.setLocationRelativeTo(null);
|
||||
}
|
||||
mMainGui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
mMainGui.addWindowListener(new ShutdownMonitor());
|
||||
|
||||
Dimension dimension = mUserPreferences.getSwingPreference().getDimension(WINDOW_FRAME_IDENTIFIER);
|
||||
|
||||
mSpectralPanel.setPreferredSize(new Dimension(1280, 300));
|
||||
mControllerPanel.setPreferredSize(new Dimension(1280, 500));
|
||||
|
||||
if(dimension != null)
|
||||
{
|
||||
Dimension spectral = mUserPreferences.getSwingPreference().getDimension(SPECTRAL_PANEL_IDENTIFIER);
|
||||
if(spectral != null)
|
||||
{
|
||||
mSpectralPanel.setSize(spectral);
|
||||
}
|
||||
|
||||
Dimension controller = mUserPreferences.getSwingPreference().getDimension(CONTROLLER_PANEL_IDENTIFIER);
|
||||
if(controller != null)
|
||||
{
|
||||
mControllerPanel.setSize(controller);
|
||||
}
|
||||
|
||||
mMainGui.setSize(dimension);
|
||||
|
||||
if(mUserPreferences.getSwingPreference().getMaximized(WINDOW_FRAME_IDENTIFIER, false))
|
||||
{
|
||||
mMainGui.setExtendedState(JFrame.MAXIMIZED_BOTH);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mMainGui.setSize(new Dimension(1280, 800));
|
||||
}
|
||||
|
||||
mSplitPane = new JideSplitPane(JideSplitPane.VERTICAL_SPLIT);
|
||||
mSplitPane.setDividerSize(5);
|
||||
mSplitPane.add(mSpectralPanel);
|
||||
mSplitPane.add(mControllerPanel);
|
||||
|
||||
mBroadcastStatusVisible = mPreferences.getBoolean(PREFERENCE_BROADCAST_STATUS_VISIBLE, false);
|
||||
|
||||
//Show broadcast status panel when user requests - disabled by default
|
||||
if(mBroadcastStatusVisible)
|
||||
{
|
||||
mSplitPane.add(getBroadcastStatusPanel());
|
||||
}
|
||||
|
||||
mMainGui.add(mSplitPane, "cell 0 0,span,grow");
|
||||
|
||||
mResourceMonitor.start();
|
||||
mResourceStatusVisible = mPreferences.getBoolean(PREFERENCE_RESOURCE_STATUS_VISIBLE, true);
|
||||
if(mResourceStatusVisible)
|
||||
{
|
||||
mMainGui.add(getResourceStatusPanel(), "span,growx");
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu items
|
||||
*/
|
||||
JMenuBar menuBar = new JMenuBar();
|
||||
mMainGui.setJMenuBar(menuBar);
|
||||
|
||||
JMenu fileMenu = new JMenu("File");
|
||||
menuBar.add(fileMenu);
|
||||
|
||||
JMenuItem exitMenu = new JMenuItem("Exit");
|
||||
exitMenu.addActionListener(event -> {
|
||||
processShutdown();
|
||||
System.exit(0);
|
||||
}
|
||||
);
|
||||
|
||||
fileMenu.add(exitMenu);
|
||||
|
||||
JMenu viewMenu = new JMenu("View");
|
||||
|
||||
JMenuItem viewPlaylistItem = new JMenuItem("Playlist Editor");
|
||||
viewPlaylistItem.setIcon(IconFontSwing.buildIcon(FontAwesome.PLAY_CIRCLE_O, 12));
|
||||
viewPlaylistItem.addActionListener(e -> MyEventBus.getGlobalEventBus().post(new ViewPlaylistRequest()));
|
||||
viewMenu.add(viewPlaylistItem);
|
||||
|
||||
viewMenu.add(new JSeparator());
|
||||
|
||||
JMenuItem viewApplicationLogsMenu = new JMenuItem("Application Log Files");
|
||||
viewApplicationLogsMenu.setIcon(IconFontSwing.buildIcon(FontAwesome.FOLDER_OPEN_O, 12));
|
||||
viewApplicationLogsMenu.addActionListener(arg0 -> {
|
||||
File logsDirectory = mUserPreferences.getDirectoryPreference().getDirectoryApplicationLog().toFile();
|
||||
try
|
||||
{
|
||||
Desktop.getDesktop().open(logsDirectory);
|
||||
mLog.info("Auto-starting channel " + channel.getName());
|
||||
mChannelProcessingManager.start(channel);
|
||||
}
|
||||
catch(Exception e)
|
||||
catch(ChannelException ce)
|
||||
{
|
||||
mLog.error("Couldn't open file explorer");
|
||||
|
||||
JOptionPane.showMessageDialog(mMainGui,
|
||||
"Can't launch file explorer - files are located at: " + logsDirectory,
|
||||
"Can't launch file explorer",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
mLog.error("Channel: " + channel.getName() + " auto-start failed: " + ce.getMessage());
|
||||
}
|
||||
});
|
||||
viewMenu.add(viewApplicationLogsMenu);
|
||||
|
||||
JMenuItem viewRecordingsMenuItem = new JMenuItem("Audio Recordings");
|
||||
viewRecordingsMenuItem.setIcon(IconFontSwing.buildIcon(FontAwesome.FOLDER_OPEN_O, 12));
|
||||
viewRecordingsMenuItem.addActionListener(arg0 -> {
|
||||
File recordingsDirectory = mUserPreferences.getDirectoryPreference().getDirectoryRecording().toFile();
|
||||
|
||||
try
|
||||
{
|
||||
Desktop.getDesktop().open(recordingsDirectory);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
mLog.error("Couldn't open file explorer");
|
||||
|
||||
JOptionPane.showMessageDialog(mMainGui,
|
||||
"Can't launch file explorer - files are located at: " +
|
||||
recordingsDirectory,
|
||||
"Can't launch file explorer",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
});
|
||||
viewMenu.add(viewRecordingsMenuItem);
|
||||
|
||||
JMenuItem viewEventLogsMenu = new JMenuItem("Channel Event Log Files");
|
||||
viewEventLogsMenu.setIcon(IconFontSwing.buildIcon(FontAwesome.FOLDER_OPEN_O, 12));
|
||||
viewEventLogsMenu.addActionListener(arg0 -> {
|
||||
File eventLogsDirectory = mUserPreferences.getDirectoryPreference().getDirectoryEventLog().toFile();
|
||||
try
|
||||
{
|
||||
Desktop.getDesktop().open(eventLogsDirectory);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
mLog.error("Couldn't open file explorer");
|
||||
|
||||
JOptionPane.showMessageDialog(mMainGui,
|
||||
"Can't launch file explorer - files are located at: " + eventLogsDirectory,
|
||||
"Can't launch file explorer",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
});
|
||||
viewMenu.add(viewEventLogsMenu);
|
||||
|
||||
JMenuItem iconManagerMenu = new JMenuItem("Icon Manager");
|
||||
iconManagerMenu.setIcon(IconFontSwing.buildIcon(FontAwesome.PICTURE_O, 12));
|
||||
iconManagerMenu.addActionListener(arg0 -> MyEventBus.getGlobalEventBus().post(new ViewIconManagerRequest()));
|
||||
viewMenu.add(iconManagerMenu);
|
||||
|
||||
JMenuItem recordingViewerMenu = new JMenuItem("Message Recording Viewer (.bits)");
|
||||
recordingViewerMenu.setIcon(IconFontSwing.buildIcon(FontAwesome.BRAILLE, 12));
|
||||
recordingViewerMenu.addActionListener(e -> MyEventBus.getGlobalEventBus().post(new ViewRecordingViewerRequest()));
|
||||
viewMenu.add(recordingViewerMenu);
|
||||
|
||||
JMenuItem viewScreenCapturesMenu = new JMenuItem("Screen Captures");
|
||||
viewScreenCapturesMenu.setIcon(IconFontSwing.buildIcon(FontAwesome.FOLDER_OPEN_O, 12));
|
||||
viewScreenCapturesMenu.addActionListener(arg0 -> {
|
||||
File screenCapturesDirectory = mUserPreferences.getDirectoryPreference().getDirectoryScreenCapture().toFile();
|
||||
try
|
||||
{
|
||||
Desktop.getDesktop().open(screenCapturesDirectory);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
mLog.error("Couldn't open file explorer");
|
||||
|
||||
JOptionPane.showMessageDialog(mMainGui,
|
||||
"Can't launch file explorer - files are located at: " + screenCapturesDirectory,
|
||||
"Can't launch file explorer",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
});
|
||||
viewMenu.add(viewScreenCapturesMenu);
|
||||
|
||||
JMenuItem preferencesItem = new JMenuItem("User Preferences");
|
||||
preferencesItem.setIcon(IconFontSwing.buildIcon(FontAwesome.COG, 12));
|
||||
preferencesItem.addActionListener(e -> MyEventBus.getGlobalEventBus().post(new ViewUserPreferenceEditorRequest()));
|
||||
viewMenu.add(preferencesItem);
|
||||
|
||||
viewMenu.add(new JSeparator());
|
||||
viewMenu.add(new TunersMenu());
|
||||
viewMenu.add(new JSeparator());
|
||||
viewMenu.add(new DisableSpectrumWaterfallMenuItem(mSpectralPanel));
|
||||
viewMenu.add(new NowPlayingChannelDetailsVisibleMenuItem());
|
||||
viewMenu.add(new BroadcastStatusVisibleMenuItem());
|
||||
viewMenu.add(new ResourceStatusVisibleMenuItem());
|
||||
|
||||
menuBar.add(viewMenu);
|
||||
|
||||
JMenuItem screenCaptureItem = new JMenuItem("Screen Capture");
|
||||
screenCaptureItem.setIcon(IconFontSwing.buildIcon(FontAwesome.CAMERA, 12));
|
||||
screenCaptureItem.setMnemonic(KeyEvent.VK_C);
|
||||
screenCaptureItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, ActionEvent.ALT_MASK));
|
||||
screenCaptureItem.setMaximumSize(screenCaptureItem.getPreferredSize());
|
||||
screenCaptureItem.addActionListener(arg0 -> {
|
||||
try
|
||||
{
|
||||
Robot robot = new Robot();
|
||||
|
||||
final BufferedImage image = robot.createScreenCapture(mMainGui.getBounds());
|
||||
|
||||
String filename = TimeStamp.getTimeStamp("_") + "_screen_capture.png";
|
||||
|
||||
final Path captureFile = mUserPreferences.getDirectoryPreference().getDirectoryScreenCapture().resolve(filename);
|
||||
|
||||
EventQueue.invokeLater(() -> {
|
||||
try
|
||||
{
|
||||
ImageIO.write(image, "png", captureFile.toFile());
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
mLog.error("Couldn't write screen capture to file [" + captureFile.toString() + "]", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch(AWTException e)
|
||||
{
|
||||
mLog.error("Exception while taking screen capture", e);
|
||||
}
|
||||
});
|
||||
|
||||
menuBar.add(screenCaptureItem);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs shutdown operations
|
||||
*/
|
||||
private void processShutdown()
|
||||
@PreDestroy
|
||||
public void preDestroy()
|
||||
{
|
||||
mLog.info("Application shutdown started ...");
|
||||
mUserPreferences.getSwingPreference().setLocation(WINDOW_FRAME_IDENTIFIER, mMainGui.getLocation());
|
||||
mUserPreferences.getSwingPreference().setDimension(WINDOW_FRAME_IDENTIFIER, mMainGui.getSize());
|
||||
mUserPreferences.getSwingPreference().setMaximized(WINDOW_FRAME_IDENTIFIER,
|
||||
(mMainGui.getExtendedState() & JFrame.MAXIMIZED_BOTH) == JFrame.MAXIMIZED_BOTH);
|
||||
mUserPreferences.getSwingPreference().setDimension(SPECTRAL_PANEL_IDENTIFIER, mSpectralPanel.getSize());
|
||||
mUserPreferences.getSwingPreference().setDimension(CONTROLLER_PANEL_IDENTIFIER, mControllerPanel.getSize());
|
||||
mJavaFxWindowManager.shutdown();
|
||||
mLog.info("Stopping channels ...");
|
||||
mPlaylistManager.getChannelProcessingManager().shutdown();
|
||||
mChannelProcessingManager.shutdown();
|
||||
mAudioRecordingManager.stop();
|
||||
mResourceMonitor.stop();
|
||||
|
||||
mLog.info("Stopping spectral display ...");
|
||||
mSpectralPanel.clearTuner();
|
||||
mLog.info("Stopping tuners ...");
|
||||
mTunerManager.stop();
|
||||
mLog.info("Shutdown complete.");
|
||||
mApplicationLog.stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazy constructor for broadcast status panel
|
||||
* Monitors the SDRTrunkUI window for shutdown so that we can terminate the overall SDRTrunk application.
|
||||
*/
|
||||
private BroadcastStatusPanel getBroadcastStatusPanel()
|
||||
{
|
||||
if(mBroadcastStatusPanel == null)
|
||||
{
|
||||
mBroadcastStatusPanel = new BroadcastStatusPanel(mPlaylistManager.getBroadcastModel(), mUserPreferences,
|
||||
"application.broadcast.status.panel");
|
||||
mBroadcastStatusPanel.setPreferredSize(new Dimension(880, 70));
|
||||
mBroadcastStatusPanel.getTable().setEnabled(false);
|
||||
}
|
||||
|
||||
return mBroadcastStatusPanel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles visibility of the broadcast channels status panel at the bottom of the controller panel
|
||||
*/
|
||||
private void toggleBroadcastStatusPanelVisibility()
|
||||
{
|
||||
mBroadcastStatusVisible = !mBroadcastStatusVisible;
|
||||
|
||||
EventQueue.invokeLater(() -> {
|
||||
if(mBroadcastStatusVisible)
|
||||
{
|
||||
mSplitPane.add(getBroadcastStatusPanel());
|
||||
}
|
||||
else
|
||||
{
|
||||
mSplitPane.remove(getBroadcastStatusPanel());
|
||||
}
|
||||
|
||||
mMainGui.revalidate();
|
||||
});
|
||||
|
||||
mPreferences.putBoolean(PREFERENCE_BROADCAST_STATUS_VISIBLE, mBroadcastStatusVisible);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazy constructor for resource status panel
|
||||
*/
|
||||
private JFXPanel getResourceStatusPanel()
|
||||
{
|
||||
|
||||
if(mResourceStatusPanel == null)
|
||||
{
|
||||
mResourceStatusPanel = mJavaFxWindowManager.getStatusPanel(mResourceMonitor);
|
||||
}
|
||||
|
||||
return mResourceStatusPanel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles visibility of the resource status panel at the bottom of the main UI window
|
||||
*/
|
||||
private void toggleResourceStatusPanelVisibility()
|
||||
{
|
||||
mResourceStatusVisible = !mResourceStatusVisible;
|
||||
|
||||
EventQueue.invokeLater(() -> {
|
||||
if(mResourceStatusVisible)
|
||||
{
|
||||
mMainGui.add(getResourceStatusPanel(), "span,growx");
|
||||
}
|
||||
else
|
||||
{
|
||||
mMainGui.remove(getResourceStatusPanel());
|
||||
}
|
||||
|
||||
mMainGui.revalidate();
|
||||
});
|
||||
|
||||
mPreferences.putBoolean(PREFERENCE_RESOURCE_STATUS_VISIBLE, mResourceStatusVisible);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles visibility of the Now Playing channel details panel
|
||||
*/
|
||||
private void toggleNowPlayingDetailsPanelVisibility()
|
||||
{
|
||||
mNowPlayingDetailsVisible = !mNowPlayingDetailsVisible;
|
||||
mControllerPanel.getNowPlayingPanel().setDetailTabsVisible(mNowPlayingDetailsVisible);
|
||||
mPreferences.putBoolean(PREFERENCE_NOW_PLAYING_DETAILS_VISIBLE, mNowPlayingDetailsVisible);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Loads the application properties file from the user's home directory,
|
||||
* creating the properties file for the first-time, if necessary
|
||||
*/
|
||||
private void loadProperties()
|
||||
{
|
||||
Path propertiesPath = mUserPreferences.getDirectoryPreference().getDirectoryApplicationRoot().resolve("SDRTrunk.properties");
|
||||
|
||||
if(!Files.exists(propertiesPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
mLog.info("SDRTrunk - creating application properties file [" + propertiesPath.toAbsolutePath() + "]");
|
||||
Files.createFile(propertiesPath);
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
mLog.error("SDRTrunk - couldn't create application properties file [" + propertiesPath.toAbsolutePath(), e);
|
||||
}
|
||||
}
|
||||
|
||||
if(Files.exists(propertiesPath))
|
||||
{
|
||||
SystemProperties.getInstance().load(propertiesPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.error("SDRTrunk - couldn't find or recreate the SDRTrunk application properties file");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets (or creates) the SDRTRunk application home directory.
|
||||
*
|
||||
* Note: the user can change this setting to allow log files and other
|
||||
* files to reside elsewhere on the file system.
|
||||
*/
|
||||
private Path getHomePath()
|
||||
{
|
||||
Path homePath = FileSystems.getDefault()
|
||||
.getPath(System.getProperty("user.home"), "SDRTrunk");
|
||||
|
||||
if(!Files.exists(homePath))
|
||||
{
|
||||
try
|
||||
{
|
||||
Files.createDirectory(homePath);
|
||||
|
||||
mLog.info("SDRTrunk - created application home directory [" +
|
||||
homePath.toString() + "]");
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
homePath = null;
|
||||
|
||||
mLog.error("SDRTrunk: exception while creating SDRTrunk home " +
|
||||
"directory in the user's home directory", e);
|
||||
}
|
||||
}
|
||||
|
||||
return homePath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(TunerEvent event)
|
||||
{
|
||||
switch(event.getEvent())
|
||||
{
|
||||
case REQUEST_MAIN_SPECTRAL_DISPLAY:
|
||||
updateTitle(event.getTuner().getPreferredName());
|
||||
break;
|
||||
case REQUEST_CLEAR_MAIN_SPECTRAL_DISPLAY:
|
||||
updateTitle(null);
|
||||
break;
|
||||
case NOTIFICATION_SHUTTING_DOWN:
|
||||
Tuner currentTuner = mSpectralPanel.getTuner();
|
||||
|
||||
if(event.hasTuner() && event.getTuner().equals(currentTuner) || currentTuner == null)
|
||||
{
|
||||
updateTitle(null);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the title bar with the tuner name
|
||||
* @param tunerName optional
|
||||
*/
|
||||
private void updateTitle(String tunerName)
|
||||
{
|
||||
if(tunerName != null)
|
||||
{
|
||||
mMainGui.setTitle(mTitle + " - " + tunerName);
|
||||
}
|
||||
else
|
||||
{
|
||||
mMainGui.setTitle(mTitle);
|
||||
}
|
||||
}
|
||||
|
||||
public class ShutdownMonitor extends WindowAdapter
|
||||
{
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e)
|
||||
{
|
||||
processShutdown();
|
||||
preDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcast status panel visible toggle menu item
|
||||
*/
|
||||
public class BroadcastStatusVisibleMenuItem extends JCheckBoxMenuItem
|
||||
{
|
||||
public BroadcastStatusVisibleMenuItem()
|
||||
{
|
||||
super("Show Streaming Status");
|
||||
setSelected(mBroadcastStatusVisible);
|
||||
addActionListener(e -> {
|
||||
toggleBroadcastStatusPanelVisibility();
|
||||
setSelected(mBroadcastStatusVisible);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resource status panel visible toggle menu item
|
||||
*/
|
||||
public class ResourceStatusVisibleMenuItem extends JCheckBoxMenuItem
|
||||
{
|
||||
public ResourceStatusVisibleMenuItem()
|
||||
{
|
||||
super("Show Resource Status");
|
||||
setSelected(mResourceStatusVisible);
|
||||
addActionListener(e -> {
|
||||
toggleResourceStatusPanelVisibility();
|
||||
setSelected(mResourceStatusVisible);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Now Playing channel details visible toggle menu item
|
||||
*/
|
||||
public class NowPlayingChannelDetailsVisibleMenuItem extends JCheckBoxMenuItem
|
||||
{
|
||||
public NowPlayingChannelDetailsVisibleMenuItem()
|
||||
{
|
||||
super("Show Now Playing Channel Details");
|
||||
setSelected(mNowPlayingDetailsVisible);
|
||||
addActionListener(e -> {
|
||||
toggleNowPlayingDetailsPanelVisibility();
|
||||
setSelected(mNowPlayingDetailsVisible);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public class TunersMenu extends JMenu
|
||||
{
|
||||
public TunersMenu()
|
||||
{
|
||||
super("Tuners");
|
||||
|
||||
addMenuListener(new MenuListener()
|
||||
{
|
||||
@Override
|
||||
public void menuSelected(MenuEvent e)
|
||||
{
|
||||
removeAll();
|
||||
|
||||
for(DiscoveredTuner discoveredTuner: mTunerManager.getAvailableTuners())
|
||||
{
|
||||
add(new ShowTunerMenuItem(mTunerManager.getDiscoveredTunerModel(), discoveredTuner.getTuner()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void menuDeselected(MenuEvent e) { }
|
||||
@Override
|
||||
public void menuCanceled(MenuEvent e) { }
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch the application.
|
||||
*/
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new SDRTrunk();
|
||||
boolean headless = GraphicsEnvironment.isHeadless();
|
||||
|
||||
//Set the user's preferred location for the database prior to starting the application
|
||||
String dbpath = new UserPreferences().getDirectoryPreference().getDirectoryApplicationRoot().toString();
|
||||
System.setProperty("derby.system.home", dbpath);
|
||||
|
||||
ConfigurableApplicationContext context = new SpringApplicationBuilder(SDRTrunk.class)
|
||||
.bannerMode(Banner.Mode.OFF)
|
||||
.headless(headless)
|
||||
.web(WebApplicationType.NONE)
|
||||
.registerShutdownHook(true)
|
||||
.run(args);
|
||||
}
|
||||
}
|
||||
|
||||
709
src/main/java/io/github/dsheirer/gui/SDRTrunkUI.java
Normal file
709
src/main/java/io/github/dsheirer/gui/SDRTrunkUI.java
Normal file
@@ -0,0 +1,709 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.gui;
|
||||
|
||||
import com.jidesoft.plaf.LookAndFeelFactory;
|
||||
import com.jidesoft.swing.JideSplitPane;
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastStatusPanel;
|
||||
import io.github.dsheirer.controller.ControllerPanel;
|
||||
import io.github.dsheirer.controller.channel.Channel;
|
||||
import io.github.dsheirer.controller.channel.ChannelAutoStartFrame;
|
||||
import io.github.dsheirer.controller.channel.ChannelModel;
|
||||
import io.github.dsheirer.controller.channel.ChannelProcessingManager;
|
||||
import io.github.dsheirer.controller.channel.ChannelSelectionManager;
|
||||
import io.github.dsheirer.eventbus.MyEventBus;
|
||||
import io.github.dsheirer.gui.icon.ViewIconManagerRequest;
|
||||
import io.github.dsheirer.gui.playlist.ViewPlaylistRequest;
|
||||
import io.github.dsheirer.gui.preference.CalibrateRequest;
|
||||
import io.github.dsheirer.gui.preference.PreferenceEditorType;
|
||||
import io.github.dsheirer.gui.preference.ViewUserPreferenceEditorRequest;
|
||||
import io.github.dsheirer.gui.preference.calibration.CalibrationDialog;
|
||||
import io.github.dsheirer.gui.viewer.ViewRecordingViewerRequest;
|
||||
import io.github.dsheirer.monitor.ResourceMonitor;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.properties.SystemProperties;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.source.tuner.Tuner;
|
||||
import io.github.dsheirer.source.tuner.TunerEvent;
|
||||
import io.github.dsheirer.source.tuner.manager.DiscoveredTuner;
|
||||
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||
import io.github.dsheirer.source.tuner.ui.DiscoveredTunerModel;
|
||||
import io.github.dsheirer.source.tuner.ui.TunerSpectralDisplayManager;
|
||||
import io.github.dsheirer.spectrum.DisableSpectrumWaterfallMenuItem;
|
||||
import io.github.dsheirer.spectrum.ShowTunerMenuItem;
|
||||
import io.github.dsheirer.spectrum.SpectralDisplayPanel;
|
||||
import io.github.dsheirer.util.TimeStamp;
|
||||
import io.github.dsheirer.vector.calibrate.CalibrationManager;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.awt.AWTException;
|
||||
import java.awt.Desktop;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.Point;
|
||||
import java.awt.Robot;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import java.util.prefs.Preferences;
|
||||
import javafx.application.Platform;
|
||||
import javafx.embed.swing.JFXPanel;
|
||||
import javafx.scene.control.ButtonType;
|
||||
import jiconfont.icons.font_awesome.FontAwesome;
|
||||
import jiconfont.swing.IconFontSwing;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.JCheckBoxMenuItem;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuBar;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JSeparator;
|
||||
import javax.swing.KeyStroke;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.event.MenuEvent;
|
||||
import javax.swing.event.MenuListener;
|
||||
import javax.swing.plaf.metal.MetalLookAndFeel;
|
||||
|
||||
/**
|
||||
* SDRTrunk primary user interface frame/window
|
||||
*/
|
||||
public class SDRTrunkUI extends JFrame implements Listener<TunerEvent>
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger(SDRTrunkUI.class);
|
||||
private final Preferences mPreferences = Preferences.userNodeForPackage(SDRTrunkUI.class);
|
||||
|
||||
private static final String PREFERENCE_BROADCAST_STATUS_VISIBLE = "sdrtrunk.broadcast.status.visible";
|
||||
private static final String PREFERENCE_NOW_PLAYING_DETAILS_VISIBLE = "sdrtrunk.now.playing.details.visible";
|
||||
private static final String PREFERENCE_RESOURCE_STATUS_VISIBLE = "sdrtrunk.resource.status.visible";
|
||||
private static final String BASE_WINDOW_NAME = "sdrtrunk.main.window";
|
||||
private static final String CONTROLLER_PANEL_IDENTIFIER = BASE_WINDOW_NAME + ".control.panel";
|
||||
private static final String SPECTRAL_PANEL_IDENTIFIER = BASE_WINDOW_NAME + ".spectral.panel";
|
||||
private static final String WINDOW_FRAME_IDENTIFIER = BASE_WINDOW_NAME + ".frame";
|
||||
|
||||
@Resource
|
||||
private BroadcastStatusPanel mBroadcastStatusPanel;
|
||||
@Resource
|
||||
private ChannelModel mChannelModel;
|
||||
@Resource
|
||||
private ChannelProcessingManager mChannelProcessingManager;
|
||||
@Resource
|
||||
private ControllerPanel mControllerPanel;
|
||||
@Resource
|
||||
private DiscoveredTunerModel mDiscoveredTunerModel;
|
||||
@Resource
|
||||
private JavaFxWindowManager mJavaFxWindowManager;
|
||||
@Resource
|
||||
private ResourceMonitor mResourceMonitor;
|
||||
@Resource
|
||||
private SpectralDisplayPanel mSpectralPanel;
|
||||
@Resource
|
||||
private TunerSpectralDisplayManager mTunerSpectralDisplayManager;
|
||||
@Resource
|
||||
private TunerManager mTunerManager;
|
||||
|
||||
private JFXPanel mResourceStatusPanel;
|
||||
private JideSplitPane mSplitPane;
|
||||
private boolean mBroadcastStatusVisible;
|
||||
private boolean mResourceStatusVisible;
|
||||
private boolean mNowPlayingDetailsVisible;
|
||||
|
||||
@Resource
|
||||
private UserPreferences mUserPreferences;
|
||||
|
||||
private String mTitle;
|
||||
|
||||
/**
|
||||
* Constructs an instance of the SDRTrunk user interface
|
||||
*/
|
||||
public SDRTrunkUI()
|
||||
{
|
||||
//Register FontAwesome so we can use the fonts in Swing windows
|
||||
IconFontSwing.register(FontAwesome.getIconFont());
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook into this visible method so that we can show the auto-start channels dialog on window show.
|
||||
*/
|
||||
@Override
|
||||
public void setVisible(boolean b)
|
||||
{
|
||||
super.setVisible(b);
|
||||
|
||||
CalibrationManager calibrationManager = CalibrationManager.getInstance(mUserPreferences);
|
||||
final boolean calibrating = !calibrationManager.isCalibrated() &&
|
||||
!mUserPreferences.getVectorCalibrationPreference().isHideCalibrationDialog();
|
||||
|
||||
if(calibrating)
|
||||
{
|
||||
Platform.runLater(() ->
|
||||
{
|
||||
CalibrationDialog calibrationDialog = mJavaFxWindowManager.getCalibrationDialog(mUserPreferences);
|
||||
Optional<ButtonType> calibrate = calibrationDialog.showAndWait();
|
||||
if(calibrate.isPresent() && calibrate.get().getText().equals("Calibrate"))
|
||||
{
|
||||
//Request focus and execute calibration
|
||||
MyEventBus.getGlobalEventBus().post(new ViewUserPreferenceEditorRequest(PreferenceEditorType.VECTOR_CALIBRATION));
|
||||
MyEventBus.getGlobalEventBus().post(new CalibrateRequest());
|
||||
}
|
||||
else
|
||||
{
|
||||
autoStartChannels();
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
autoStartChannels();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the auto-start channels dialog
|
||||
*/
|
||||
private void autoStartChannels()
|
||||
{
|
||||
List<Channel> channels = mChannelModel.getAutoStartChannels();
|
||||
|
||||
if(channels.size() > 0)
|
||||
{
|
||||
new ChannelAutoStartFrame(mChannelProcessingManager, channels, mUserPreferences);
|
||||
}
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
String operatingSystem = System.getProperty("os.name", "generic").toLowerCase(Locale.ENGLISH);
|
||||
|
||||
if(operatingSystem.contains("mac") || operatingSystem.contains("nux"))
|
||||
{
|
||||
try
|
||||
{
|
||||
UIManager.setLookAndFeel(MetalLookAndFeel.class.getName());
|
||||
LookAndFeelFactory.installJideExtension();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
mLog.error("Error trying to set Metal look and feel for OS [" + operatingSystem + "]");
|
||||
}
|
||||
}
|
||||
|
||||
new ChannelSelectionManager();
|
||||
|
||||
mNowPlayingDetailsVisible = mPreferences.getBoolean(PREFERENCE_NOW_PLAYING_DETAILS_VISIBLE, true);
|
||||
mTunerSpectralDisplayManager.setSpectralDisplayPanel(mSpectralPanel);
|
||||
mDiscoveredTunerModel.addListener(mTunerSpectralDisplayManager);
|
||||
mDiscoveredTunerModel.addListener(this);
|
||||
|
||||
initGUI();
|
||||
|
||||
Tuner tuner = mTunerSpectralDisplayManager.showFirstTuner();
|
||||
|
||||
if(tuner != null)
|
||||
{
|
||||
updateTitle(tuner.getPreferredName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the contents of the frame.
|
||||
*/
|
||||
private void initGUI()
|
||||
{
|
||||
setLayout(new MigLayout("insets 0 0 0 0 ", "[grow,fill]", "[grow,fill]0[shrink 0]"));
|
||||
|
||||
/**
|
||||
* Setup main JFrame window
|
||||
*/
|
||||
mTitle = SystemProperties.getInstance().getApplicationName();
|
||||
setTitle(mTitle);
|
||||
|
||||
Point location = mUserPreferences.getSwingPreference().getLocation(WINDOW_FRAME_IDENTIFIER);
|
||||
if(location != null)
|
||||
{
|
||||
setLocation(location);
|
||||
}
|
||||
else
|
||||
{
|
||||
setLocationRelativeTo(null);
|
||||
}
|
||||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
addWindowListener(new ShutdownMonitor());
|
||||
|
||||
Dimension dimension = mUserPreferences.getSwingPreference().getDimension(WINDOW_FRAME_IDENTIFIER);
|
||||
|
||||
mSpectralPanel.setPreferredSize(new Dimension(1280, 300));
|
||||
mControllerPanel.setPreferredSize(new Dimension(1280, 500));
|
||||
|
||||
if(dimension != null)
|
||||
{
|
||||
Dimension spectral = mUserPreferences.getSwingPreference().getDimension(SPECTRAL_PANEL_IDENTIFIER);
|
||||
if(spectral != null)
|
||||
{
|
||||
mSpectralPanel.setSize(spectral);
|
||||
}
|
||||
|
||||
Dimension controller = mUserPreferences.getSwingPreference().getDimension(CONTROLLER_PANEL_IDENTIFIER);
|
||||
if(controller != null)
|
||||
{
|
||||
mControllerPanel.setSize(controller);
|
||||
}
|
||||
|
||||
setSize(dimension);
|
||||
|
||||
if(mUserPreferences.getSwingPreference().getMaximized(WINDOW_FRAME_IDENTIFIER, false))
|
||||
{
|
||||
setExtendedState(JFrame.MAXIMIZED_BOTH);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setSize(new Dimension(1280, 800));
|
||||
}
|
||||
|
||||
mSplitPane = new JideSplitPane(JideSplitPane.VERTICAL_SPLIT);
|
||||
mSplitPane.setDividerSize(5);
|
||||
mSplitPane.add(mSpectralPanel);
|
||||
mSplitPane.add(mControllerPanel);
|
||||
|
||||
mBroadcastStatusVisible = mPreferences.getBoolean(PREFERENCE_BROADCAST_STATUS_VISIBLE, false);
|
||||
|
||||
//Show broadcast status panel when user requests - disabled by default
|
||||
if(mBroadcastStatusVisible)
|
||||
{
|
||||
mSplitPane.add(getBroadcastStatusPanel());
|
||||
}
|
||||
|
||||
add(mSplitPane, "cell 0 0,span,grow");
|
||||
|
||||
mResourceMonitor.start();
|
||||
mResourceStatusVisible = mPreferences.getBoolean(PREFERENCE_RESOURCE_STATUS_VISIBLE, true);
|
||||
if(mResourceStatusVisible)
|
||||
{
|
||||
add(getResourceStatusPanel(), "span,growx");
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu items
|
||||
*/
|
||||
JMenuBar menuBar = new JMenuBar();
|
||||
setJMenuBar(menuBar);
|
||||
|
||||
JMenu fileMenu = new JMenu("File");
|
||||
menuBar.add(fileMenu);
|
||||
|
||||
JMenuItem exitMenu = new JMenuItem("Exit");
|
||||
exitMenu.addActionListener(event -> {
|
||||
shutdown();
|
||||
System.exit(0);
|
||||
}
|
||||
);
|
||||
|
||||
fileMenu.add(exitMenu);
|
||||
|
||||
JMenu viewMenu = new JMenu("View");
|
||||
|
||||
JMenuItem viewPlaylistItem = new JMenuItem("Playlist Editor");
|
||||
viewPlaylistItem.setIcon(IconFontSwing.buildIcon(FontAwesome.PLAY_CIRCLE_O, 12));
|
||||
viewPlaylistItem.addActionListener(e -> MyEventBus.getGlobalEventBus().post(new ViewPlaylistRequest()));
|
||||
viewMenu.add(viewPlaylistItem);
|
||||
|
||||
viewMenu.add(new JSeparator());
|
||||
|
||||
JMenuItem viewApplicationLogsMenu = new JMenuItem("Application Log Files");
|
||||
viewApplicationLogsMenu.setIcon(IconFontSwing.buildIcon(FontAwesome.FOLDER_OPEN_O, 12));
|
||||
viewApplicationLogsMenu.addActionListener(arg0 -> {
|
||||
File logsDirectory = mUserPreferences.getDirectoryPreference().getDirectoryApplicationLog().toFile();
|
||||
try
|
||||
{
|
||||
Desktop.getDesktop().open(logsDirectory);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
mLog.error("Couldn't open file explorer");
|
||||
|
||||
JOptionPane.showMessageDialog(this,
|
||||
"Can't launch file explorer - files are located at: " + logsDirectory,
|
||||
"Can't launch file explorer",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
});
|
||||
viewMenu.add(viewApplicationLogsMenu);
|
||||
|
||||
JMenuItem viewRecordingsMenuItem = new JMenuItem("Audio Recordings");
|
||||
viewRecordingsMenuItem.setIcon(IconFontSwing.buildIcon(FontAwesome.FOLDER_OPEN_O, 12));
|
||||
viewRecordingsMenuItem.addActionListener(arg0 -> {
|
||||
File recordingsDirectory = mUserPreferences.getDirectoryPreference().getDirectoryRecording().toFile();
|
||||
|
||||
try
|
||||
{
|
||||
Desktop.getDesktop().open(recordingsDirectory);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
mLog.error("Couldn't open file explorer");
|
||||
|
||||
JOptionPane.showMessageDialog(this,
|
||||
"Can't launch file explorer - files are located at: " +
|
||||
recordingsDirectory,
|
||||
"Can't launch file explorer",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
});
|
||||
viewMenu.add(viewRecordingsMenuItem);
|
||||
|
||||
JMenuItem viewEventLogsMenu = new JMenuItem("Channel Event Log Files");
|
||||
viewEventLogsMenu.setIcon(IconFontSwing.buildIcon(FontAwesome.FOLDER_OPEN_O, 12));
|
||||
viewEventLogsMenu.addActionListener(arg0 -> {
|
||||
File eventLogsDirectory = mUserPreferences.getDirectoryPreference().getDirectoryEventLog().toFile();
|
||||
try
|
||||
{
|
||||
Desktop.getDesktop().open(eventLogsDirectory);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
mLog.error("Couldn't open file explorer");
|
||||
|
||||
JOptionPane.showMessageDialog(this, "Can't launch file explorer - files are located at: " + eventLogsDirectory,
|
||||
"Can't launch file explorer", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
});
|
||||
viewMenu.add(viewEventLogsMenu);
|
||||
|
||||
JMenuItem iconManagerMenu = new JMenuItem("Icon Manager");
|
||||
iconManagerMenu.setIcon(IconFontSwing.buildIcon(FontAwesome.PICTURE_O, 12));
|
||||
iconManagerMenu.addActionListener(arg0 -> MyEventBus.getGlobalEventBus().post(new ViewIconManagerRequest()));
|
||||
viewMenu.add(iconManagerMenu);
|
||||
|
||||
JMenuItem recordingViewerMenu = new JMenuItem("Message Recording Viewer (.bits)");
|
||||
recordingViewerMenu.setIcon(IconFontSwing.buildIcon(FontAwesome.BRAILLE, 12));
|
||||
recordingViewerMenu.addActionListener(e -> MyEventBus.getGlobalEventBus().post(new ViewRecordingViewerRequest()));
|
||||
viewMenu.add(recordingViewerMenu);
|
||||
|
||||
JMenuItem viewScreenCapturesMenu = new JMenuItem("Screen Captures");
|
||||
viewScreenCapturesMenu.setIcon(IconFontSwing.buildIcon(FontAwesome.FOLDER_OPEN_O, 12));
|
||||
viewScreenCapturesMenu.addActionListener(arg0 -> {
|
||||
File screenCapturesDirectory = mUserPreferences.getDirectoryPreference().getDirectoryScreenCapture().toFile();
|
||||
try
|
||||
{
|
||||
Desktop.getDesktop().open(screenCapturesDirectory);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
mLog.error("Couldn't open file explorer");
|
||||
|
||||
JOptionPane.showMessageDialog(this, "Can't launch file explorer - files are located at: " + screenCapturesDirectory,
|
||||
"Can't launch file explorer", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
});
|
||||
viewMenu.add(viewScreenCapturesMenu);
|
||||
|
||||
JMenuItem preferencesItem = new JMenuItem("User Preferences");
|
||||
preferencesItem.setIcon(IconFontSwing.buildIcon(FontAwesome.COG, 12));
|
||||
preferencesItem.addActionListener(e -> MyEventBus.getGlobalEventBus().post(new ViewUserPreferenceEditorRequest()));
|
||||
viewMenu.add(preferencesItem);
|
||||
|
||||
viewMenu.add(new JSeparator());
|
||||
viewMenu.add(new TunersMenu());
|
||||
viewMenu.add(new JSeparator());
|
||||
viewMenu.add(new DisableSpectrumWaterfallMenuItem(mSpectralPanel, mUserPreferences));
|
||||
viewMenu.add(new NowPlayingChannelDetailsVisibleMenuItem());
|
||||
viewMenu.add(new BroadcastStatusVisibleMenuItem());
|
||||
viewMenu.add(new ResourceStatusVisibleMenuItem());
|
||||
|
||||
menuBar.add(viewMenu);
|
||||
|
||||
JMenuItem screenCaptureItem = new JMenuItem("Screen Capture");
|
||||
screenCaptureItem.setIcon(IconFontSwing.buildIcon(FontAwesome.CAMERA, 12));
|
||||
screenCaptureItem.setMnemonic(KeyEvent.VK_C);
|
||||
screenCaptureItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, ActionEvent.ALT_MASK));
|
||||
screenCaptureItem.setMaximumSize(screenCaptureItem.getPreferredSize());
|
||||
screenCaptureItem.addActionListener(arg0 -> {
|
||||
try
|
||||
{
|
||||
Robot robot = new Robot();
|
||||
|
||||
final BufferedImage image = robot.createScreenCapture(getBounds());
|
||||
|
||||
String filename = TimeStamp.getTimeStamp("_") + "_screen_capture.png";
|
||||
|
||||
final Path captureFile = mUserPreferences.getDirectoryPreference().getDirectoryScreenCapture().resolve(filename);
|
||||
|
||||
EventQueue.invokeLater(() -> {
|
||||
try
|
||||
{
|
||||
ImageIO.write(image, "png", captureFile.toFile());
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
mLog.error("Couldn't write screen capture to file [" + captureFile.toString() + "]", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch(AWTException e)
|
||||
{
|
||||
mLog.error("Exception while taking screen capture", e);
|
||||
}
|
||||
});
|
||||
|
||||
menuBar.add(screenCaptureItem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the title bar with the tuner name
|
||||
* @param tunerName optional
|
||||
*/
|
||||
private void updateTitle(String tunerName)
|
||||
{
|
||||
if(tunerName != null)
|
||||
{
|
||||
setTitle(mTitle + " - " + tunerName);
|
||||
}
|
||||
else
|
||||
{
|
||||
setTitle(mTitle);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(TunerEvent event)
|
||||
{
|
||||
switch(event.getEvent())
|
||||
{
|
||||
case REQUEST_MAIN_SPECTRAL_DISPLAY:
|
||||
updateTitle(event.getTuner().getPreferredName());
|
||||
break;
|
||||
case REQUEST_CLEAR_MAIN_SPECTRAL_DISPLAY:
|
||||
updateTitle(null);
|
||||
break;
|
||||
case NOTIFICATION_SHUTTING_DOWN:
|
||||
Tuner currentTuner = mSpectralPanel.getTuner();
|
||||
|
||||
if(event.hasTuner() && event.getTuner().equals(currentTuner) || currentTuner == null)
|
||||
{
|
||||
updateTitle(null);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazy constructor for broadcast status panel
|
||||
*/
|
||||
private BroadcastStatusPanel getBroadcastStatusPanel()
|
||||
{
|
||||
return mBroadcastStatusPanel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles visibility of the broadcast channels status panel at the bottom of the controller panel
|
||||
*/
|
||||
private void toggleBroadcastStatusPanelVisibility()
|
||||
{
|
||||
mBroadcastStatusVisible = !mBroadcastStatusVisible;
|
||||
|
||||
EventQueue.invokeLater(() -> {
|
||||
if(mBroadcastStatusVisible)
|
||||
{
|
||||
mSplitPane.add(getBroadcastStatusPanel());
|
||||
}
|
||||
else
|
||||
{
|
||||
mSplitPane.remove(getBroadcastStatusPanel());
|
||||
}
|
||||
|
||||
revalidate();
|
||||
});
|
||||
|
||||
mPreferences.putBoolean(PREFERENCE_BROADCAST_STATUS_VISIBLE, mBroadcastStatusVisible);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazy constructor for resource status panel
|
||||
*/
|
||||
private JFXPanel getResourceStatusPanel()
|
||||
{
|
||||
|
||||
if(mResourceStatusPanel == null)
|
||||
{
|
||||
mResourceStatusPanel = mJavaFxWindowManager.getStatusPanel(mResourceMonitor);
|
||||
}
|
||||
|
||||
return mResourceStatusPanel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles visibility of the resource status panel at the bottom of the main UI window
|
||||
*/
|
||||
private void toggleResourceStatusPanelVisibility()
|
||||
{
|
||||
mResourceStatusVisible = !mResourceStatusVisible;
|
||||
|
||||
EventQueue.invokeLater(() -> {
|
||||
if(mResourceStatusVisible)
|
||||
{
|
||||
add(getResourceStatusPanel(), "span,growx");
|
||||
}
|
||||
else
|
||||
{
|
||||
remove(getResourceStatusPanel());
|
||||
}
|
||||
|
||||
revalidate();
|
||||
});
|
||||
|
||||
mPreferences.putBoolean(PREFERENCE_RESOURCE_STATUS_VISIBLE, mResourceStatusVisible);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles visibility of the Now Playing channel details panel
|
||||
*/
|
||||
private void toggleNowPlayingDetailsPanelVisibility()
|
||||
{
|
||||
mNowPlayingDetailsVisible = !mNowPlayingDetailsVisible;
|
||||
mControllerPanel.getNowPlayingPanel().setDetailTabsVisible(mNowPlayingDetailsVisible);
|
||||
mPreferences.putBoolean(PREFERENCE_NOW_PLAYING_DETAILS_VISIBLE, mNowPlayingDetailsVisible);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Performs shutdown operations. This is triggered by the shutdown monitor's windowClosing() method
|
||||
*/
|
||||
private void shutdown()
|
||||
{
|
||||
mLog.info("SDRTrunk UI shutdown started ...");
|
||||
mUserPreferences.getSwingPreference().setLocation(WINDOW_FRAME_IDENTIFIER, getLocation());
|
||||
mUserPreferences.getSwingPreference().setDimension(WINDOW_FRAME_IDENTIFIER, getSize());
|
||||
mUserPreferences.getSwingPreference().setMaximized(WINDOW_FRAME_IDENTIFIER,
|
||||
(getExtendedState() & JFrame.MAXIMIZED_BOTH) == JFrame.MAXIMIZED_BOTH);
|
||||
mUserPreferences.getSwingPreference().setDimension(SPECTRAL_PANEL_IDENTIFIER, mSpectralPanel.getSize());
|
||||
mUserPreferences.getSwingPreference().setDimension(CONTROLLER_PANEL_IDENTIFIER, mControllerPanel.getSize());
|
||||
mLog.info("Stopping JavaFX window manager ...");
|
||||
mJavaFxWindowManager.shutdown();
|
||||
mLog.info("Stopping resource monitor ...");
|
||||
mResourceMonitor.stop();
|
||||
mLog.info("Stopping spectral display ...");
|
||||
mSpectralPanel.clearTuner();
|
||||
}
|
||||
|
||||
/**
|
||||
* Window adapter to receive window closing event to initiate shutdown.
|
||||
*/
|
||||
public class ShutdownMonitor extends WindowAdapter
|
||||
{
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e)
|
||||
{
|
||||
shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcast status panel visible toggle menu item
|
||||
*/
|
||||
public class BroadcastStatusVisibleMenuItem extends JCheckBoxMenuItem
|
||||
{
|
||||
public BroadcastStatusVisibleMenuItem()
|
||||
{
|
||||
super("Show Streaming Status");
|
||||
setSelected(mBroadcastStatusVisible);
|
||||
addActionListener(e -> {
|
||||
toggleBroadcastStatusPanelVisibility();
|
||||
setSelected(mBroadcastStatusVisible);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resource status panel visible toggle menu item
|
||||
*/
|
||||
public class ResourceStatusVisibleMenuItem extends JCheckBoxMenuItem
|
||||
{
|
||||
public ResourceStatusVisibleMenuItem()
|
||||
{
|
||||
super("Show Resource Status");
|
||||
setSelected(mResourceStatusVisible);
|
||||
addActionListener(e -> {
|
||||
toggleResourceStatusPanelVisibility();
|
||||
setSelected(mResourceStatusVisible);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Now Playing channel details visible toggle menu item
|
||||
*/
|
||||
public class NowPlayingChannelDetailsVisibleMenuItem extends JCheckBoxMenuItem
|
||||
{
|
||||
public NowPlayingChannelDetailsVisibleMenuItem()
|
||||
{
|
||||
super("Show Now Playing Channel Details");
|
||||
setSelected(mNowPlayingDetailsVisible);
|
||||
addActionListener(e -> {
|
||||
toggleNowPlayingDetailsPanelVisibility();
|
||||
setSelected(mNowPlayingDetailsVisible);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu for selecting tuners for display.
|
||||
*/
|
||||
public class TunersMenu extends JMenu
|
||||
{
|
||||
public TunersMenu()
|
||||
{
|
||||
super("Tuners");
|
||||
|
||||
addMenuListener(new MenuListener()
|
||||
{
|
||||
@Override
|
||||
public void menuSelected(MenuEvent e)
|
||||
{
|
||||
removeAll();
|
||||
|
||||
for(DiscoveredTuner discoveredTuner: mTunerManager.getAvailableTuners())
|
||||
{
|
||||
add(new ShowTunerMenuItem(discoveredTuner.getTuner(), mDiscoveredTunerModel, mUserPreferences));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void menuDeselected(MenuEvent e) { }
|
||||
@Override
|
||||
public void menuCanceled(MenuEvent e) { }
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,710 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* 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
|
||||
* 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.gui;
|
||||
|
||||
import io.github.dsheirer.audio.broadcast.openmhz.OpenMHzEditor;
|
||||
import io.github.dsheirer.audio.call.CallView;
|
||||
import io.github.dsheirer.audio.playbackfx.AudioPlaybackChannelsView;
|
||||
import io.github.dsheirer.gui.icon.IconManager;
|
||||
import io.github.dsheirer.gui.playlist.PlaylistEditor;
|
||||
import io.github.dsheirer.gui.playlist.alias.AliasBulkEditor;
|
||||
import io.github.dsheirer.gui.playlist.alias.AliasConfigurationEditor;
|
||||
import io.github.dsheirer.gui.playlist.alias.AliasEditor;
|
||||
import io.github.dsheirer.gui.playlist.alias.AliasItemEditor;
|
||||
import io.github.dsheirer.gui.playlist.alias.AliasViewByIdentifierEditor;
|
||||
import io.github.dsheirer.gui.playlist.alias.AliasViewByRecordingEditor;
|
||||
import io.github.dsheirer.gui.playlist.channel.AMConfigurationEditor;
|
||||
import io.github.dsheirer.gui.playlist.channel.ChannelEditor;
|
||||
import io.github.dsheirer.gui.playlist.channel.DMRConfigurationEditor;
|
||||
import io.github.dsheirer.gui.playlist.channel.LTRConfigurationEditor;
|
||||
import io.github.dsheirer.gui.playlist.channel.LTRNetConfigurationEditor;
|
||||
import io.github.dsheirer.gui.playlist.channel.MPT1327ConfigurationEditor;
|
||||
import io.github.dsheirer.gui.playlist.channel.NBFMConfigurationEditor;
|
||||
import io.github.dsheirer.gui.playlist.channel.P25P1ConfigurationEditor;
|
||||
import io.github.dsheirer.gui.playlist.channel.P25P2ConfigurationEditor;
|
||||
import io.github.dsheirer.gui.playlist.channel.PassportConfigurationEditor;
|
||||
import io.github.dsheirer.gui.playlist.channel.UnknownConfigurationEditor;
|
||||
import io.github.dsheirer.gui.playlist.channelMap.ChannelMapEditor;
|
||||
import io.github.dsheirer.gui.playlist.manager.PlaylistManagerEditor;
|
||||
import io.github.dsheirer.gui.playlist.radioreference.CountyAgencyEditor;
|
||||
import io.github.dsheirer.gui.playlist.radioreference.CountySystemEditor;
|
||||
import io.github.dsheirer.gui.playlist.radioreference.NationalAgencyEditor;
|
||||
import io.github.dsheirer.gui.playlist.radioreference.RadioReferenceEditor;
|
||||
import io.github.dsheirer.gui.playlist.radioreference.SiteEditor;
|
||||
import io.github.dsheirer.gui.playlist.radioreference.StateAgencyEditor;
|
||||
import io.github.dsheirer.gui.playlist.radioreference.StateSystemEditor;
|
||||
import io.github.dsheirer.gui.playlist.radioreference.SystemSiteSelectionEditor;
|
||||
import io.github.dsheirer.gui.playlist.radioreference.SystemTalkgroupSelectionEditor;
|
||||
import io.github.dsheirer.gui.playlist.radioreference.TalkgroupEditor;
|
||||
import io.github.dsheirer.gui.playlist.streaming.BroadcastifyCallEditor;
|
||||
import io.github.dsheirer.gui.playlist.streaming.BroadcastifyStreamEditor;
|
||||
import io.github.dsheirer.gui.playlist.streaming.IcecastHTTPStreamEditor;
|
||||
import io.github.dsheirer.gui.playlist.streaming.IcecastTCPStreamEditor;
|
||||
import io.github.dsheirer.gui.playlist.streaming.RdioScannerEditor;
|
||||
import io.github.dsheirer.gui.playlist.streaming.ShoutcastV1StreamEditor;
|
||||
import io.github.dsheirer.gui.playlist.streaming.ShoutcastV2StreamEditor;
|
||||
import io.github.dsheirer.gui.playlist.streaming.StreamAliasSelectionEditor;
|
||||
import io.github.dsheirer.gui.playlist.streaming.StreamingEditor;
|
||||
import io.github.dsheirer.gui.playlist.streaming.UnknownStreamEditor;
|
||||
import io.github.dsheirer.gui.preference.DecodeEventViewPreferenceEditor;
|
||||
import io.github.dsheirer.gui.preference.TalkgroupFormatPreferenceEditor;
|
||||
import io.github.dsheirer.gui.preference.UserPreferencesEditor;
|
||||
import io.github.dsheirer.gui.preference.application.ApplicationPreferenceEditor;
|
||||
import io.github.dsheirer.gui.preference.calibration.VectorCalibrationPreferenceEditor;
|
||||
import io.github.dsheirer.gui.preference.call.CallManagementPreferenceEditor;
|
||||
import io.github.dsheirer.gui.preference.decoder.JmbeLibraryPreferenceEditor;
|
||||
import io.github.dsheirer.gui.preference.directory.DirectoryPreferenceEditor;
|
||||
import io.github.dsheirer.gui.preference.mp3.MP3PreferenceEditor;
|
||||
import io.github.dsheirer.gui.preference.playback.PlaybackPreferenceEditor;
|
||||
import io.github.dsheirer.gui.preference.record.RecordPreferenceEditor;
|
||||
import io.github.dsheirer.gui.preference.tuner.TunerPreferenceEditor;
|
||||
import io.github.dsheirer.jmbe.JmbeEditor;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import javafx.application.Platform;
|
||||
import javafx.embed.swing.JFXPanel;
|
||||
import jiconfont.javafx.IconFontFX;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
|
||||
/**
|
||||
* Spring configuration factory for JavaFX UI components that require dependency injection (@Resource)
|
||||
*
|
||||
* Note: all bean creator methods are also annotated as @Lazy so that Spring doesn't auto-instantiate these beans when
|
||||
* we're running in a headless environment.
|
||||
*/
|
||||
@Configuration
|
||||
public class SpringJavaFxBeanFactory
|
||||
{
|
||||
private JFXPanel mJFXPanel;
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
*/
|
||||
public SpringJavaFxBeanFactory()
|
||||
{
|
||||
if(!GraphicsEnvironment.isHeadless())
|
||||
{
|
||||
//Initialize the JavafX platform by creating a JFXPanel.
|
||||
createJFXPanel();
|
||||
|
||||
//Register JavaFX icon fonts
|
||||
IconFontFX.register(jiconfont.icons.font_awesome.FontAwesome.getIconFont());
|
||||
IconFontFX.register(jiconfont.icons.elusive.Elusive.getIconFont());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the JavaFX platform by creating a JavaFX panel for Swing application compatibility
|
||||
*/
|
||||
private void createJFXPanel()
|
||||
{
|
||||
if(mJFXPanel == null)
|
||||
{
|
||||
mJFXPanel = new JFXPanel();
|
||||
Platform.setImplicitExit(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call view Panel
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public CallView getCallViewPanel()
|
||||
{
|
||||
return new CallView();
|
||||
}
|
||||
|
||||
/**
|
||||
* Audio playback channels view
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public AudioPlaybackChannelsView getAudioPlaybackChannelsView()
|
||||
{
|
||||
return new AudioPlaybackChannelsView();
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias Item Editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public AliasItemEditor getAliasItemEditor()
|
||||
{
|
||||
return new AliasItemEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias Bulk Editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public AliasBulkEditor getAliasBulkEditor()
|
||||
{
|
||||
return new AliasBulkEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias Configuration Editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public AliasConfigurationEditor getAliasConfigurationEditor()
|
||||
{
|
||||
return new AliasConfigurationEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias Editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public AliasEditor getAliasEditor()
|
||||
{
|
||||
return new AliasEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias View By Identifier Editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public AliasViewByIdentifierEditor getAliasViewByIdentifierEditor()
|
||||
{
|
||||
return new AliasViewByIdentifierEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Channel Editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public ChannelEditor getChannelEditor()
|
||||
{
|
||||
return new ChannelEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Playlist Editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public PlaylistEditor getPlaylistEditor()
|
||||
{
|
||||
return new PlaylistEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Playlist Manager Editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public PlaylistManagerEditor getPlaylistManagerEditor()
|
||||
{
|
||||
return new PlaylistManagerEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Radio Reference Editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public RadioReferenceEditor getRadioReferenceEditor()
|
||||
{
|
||||
return new RadioReferenceEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stream alias selection editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public StreamAliasSelectionEditor getStreamAliasSelectionEditor()
|
||||
{
|
||||
return new StreamAliasSelectionEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Streaming editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public StreamingEditor getStreamingEditor()
|
||||
{
|
||||
return new StreamingEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* AM channel configuration editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public AMConfigurationEditor getAMConfigurationEditor()
|
||||
{
|
||||
return new AMConfigurationEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* NBFM channel configuration editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public NBFMConfigurationEditor getNBFMConfigurationEditor()
|
||||
{
|
||||
return new NBFMConfigurationEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* DMR channel configuration editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public DMRConfigurationEditor getDMRConfigurationEditor()
|
||||
{
|
||||
return new DMRConfigurationEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* LTR channel configuration editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public LTRConfigurationEditor getLTRConfigurationEditor()
|
||||
{
|
||||
return new LTRConfigurationEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* LTR-Net channel configuration editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public LTRNetConfigurationEditor getLTRNetConfigurationEditor()
|
||||
{
|
||||
return new LTRNetConfigurationEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* MPT-1327 channel configuration editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public MPT1327ConfigurationEditor getMPT1327ConfigurationEditor()
|
||||
{
|
||||
return new MPT1327ConfigurationEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* P25 Phase 1 channel configuration editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public P25P1ConfigurationEditor getP25P1ConfigurationEditor()
|
||||
{
|
||||
return new P25P1ConfigurationEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* P25 Phase 2 channel configuration editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public P25P2ConfigurationEditor getP25P2ConfigurationEditor()
|
||||
{
|
||||
return new P25P2ConfigurationEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Passport channel configuration editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public PassportConfigurationEditor getPassportConfigurationEditor()
|
||||
{
|
||||
return new PassportConfigurationEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unknown channel configuration editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public UnknownConfigurationEditor getUnknownConfigurationEditor()
|
||||
{
|
||||
return new UnknownConfigurationEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcastify stream editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public BroadcastifyStreamEditor getBroadcastifyStreamEditor()
|
||||
{
|
||||
return new BroadcastifyStreamEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcastify calls stream editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public BroadcastifyCallEditor getBroadcastifyCallEditor()
|
||||
{
|
||||
return new BroadcastifyCallEditor();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* OpenMHZ stream editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public OpenMHzEditor getOpenMhzEditor()
|
||||
{
|
||||
return new OpenMHzEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Rdio scanner stream editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public RdioScannerEditor getRdioScannerEditor()
|
||||
{
|
||||
return new RdioScannerEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Icecast TCP stream editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public IcecastTCPStreamEditor getIcecastTcpStreamEditor()
|
||||
{
|
||||
return new IcecastTCPStreamEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Icecast HTTP stream editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public IcecastHTTPStreamEditor getIcecastHTTPStreamEditor()
|
||||
{
|
||||
return new IcecastHTTPStreamEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shoutcast V1 stream editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public ShoutcastV1StreamEditor getShoutcastV1StreamEditor()
|
||||
{
|
||||
return new ShoutcastV1StreamEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shoutcast V1 stream editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public ShoutcastV2StreamEditor getShoutcastV2StreamEditor()
|
||||
{
|
||||
return new ShoutcastV2StreamEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unknown stream editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public UnknownStreamEditor getUnknownStreamEditor()
|
||||
{
|
||||
return new UnknownStreamEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* County agency editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public CountyAgencyEditor getCountyAgencyEditor()
|
||||
{
|
||||
return new CountyAgencyEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* County system editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public CountySystemEditor getCountySystemEditor()
|
||||
{
|
||||
return new CountySystemEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* State agency editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public StateAgencyEditor getStateAgencyEditor()
|
||||
{
|
||||
return new StateAgencyEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* State system editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public StateSystemEditor getStateSystemEditor()
|
||||
{
|
||||
return new StateSystemEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* National agency editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public NationalAgencyEditor getNationalAgencyEditor()
|
||||
{
|
||||
return new NationalAgencyEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* System talkgroup selection editor
|
||||
*
|
||||
* Note: editor is used in multiple places so we create a new instance for each (ie scope=prototype)
|
||||
*/
|
||||
@Bean
|
||||
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
@Lazy
|
||||
public SystemTalkgroupSelectionEditor getSystemTalkgroupSelectionEditor()
|
||||
{
|
||||
return new SystemTalkgroupSelectionEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Site editor
|
||||
*
|
||||
* Note: editor is used in multiple places so we create a new instance for each (ie scope=prototype)
|
||||
*/
|
||||
@Bean
|
||||
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
@Lazy
|
||||
public SiteEditor getSiteEditor()
|
||||
{
|
||||
return new SiteEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Talkgroup editor
|
||||
*
|
||||
* Note: editor is used in multiple places so we create a new instance for each (ie scope=prototype)
|
||||
*/
|
||||
@Bean
|
||||
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
@Lazy
|
||||
public TalkgroupEditor getTalkgroupEditor()
|
||||
{
|
||||
return new TalkgroupEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* System site selection editor
|
||||
*
|
||||
* Note: editor is used in multiple places so we create a new instance for each (ie scope=prototype)
|
||||
*/
|
||||
@Bean
|
||||
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
@Lazy
|
||||
public SystemSiteSelectionEditor getSystemSiteSelectionEditor()
|
||||
{
|
||||
return new SystemSiteSelectionEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Channel map editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public ChannelMapEditor getChannelMapEditor()
|
||||
{
|
||||
return new ChannelMapEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Channel map editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public IconManager getIconManager()
|
||||
{
|
||||
return new IconManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* User preferences editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public UserPreferencesEditor getUserPreferencesEditor()
|
||||
{
|
||||
return new UserPreferencesEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Jmbe editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public JmbeEditor getJmbeEditor()
|
||||
{
|
||||
return new JmbeEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias view-by recording editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public AliasViewByRecordingEditor getAliasViewByRecordingEditor()
|
||||
{
|
||||
return new AliasViewByRecordingEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Application preference editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public ApplicationPreferenceEditor getApplicationPreferenceEditor()
|
||||
{
|
||||
return new ApplicationPreferenceEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Call management preference editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public CallManagementPreferenceEditor getCallManagementPreferenceEditor()
|
||||
{
|
||||
return new CallManagementPreferenceEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Application preference editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public MP3PreferenceEditor getMp3PreferenceEditor()
|
||||
{
|
||||
return new MP3PreferenceEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Playback preference editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public PlaybackPreferenceEditor getPlaybackPreferenceEditor()
|
||||
{
|
||||
return new PlaybackPreferenceEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Record preference editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public RecordPreferenceEditor getRecordPreferenceEditor()
|
||||
{
|
||||
return new RecordPreferenceEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode event view preference editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public DecodeEventViewPreferenceEditor getDecodeEventViewPreferenceEditor()
|
||||
{
|
||||
return new DecodeEventViewPreferenceEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Directory preference editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public DirectoryPreferenceEditor getDirectoryPreferenceEditor()
|
||||
{
|
||||
return new DirectoryPreferenceEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Playback preference editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public JmbeLibraryPreferenceEditor getJmbeLibraryPreferenceEditor()
|
||||
{
|
||||
return new JmbeLibraryPreferenceEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tuner preference editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public TunerPreferenceEditor getTunerPreferenceEditor()
|
||||
{
|
||||
return new TunerPreferenceEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Talkgroup format preference editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public TalkgroupFormatPreferenceEditor getTalkgroupFormatPreferenceEditor()
|
||||
{
|
||||
return new TalkgroupFormatPreferenceEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Vector calibration preference editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public VectorCalibrationPreferenceEditor getVectorCalibrationPreferenceEditor()
|
||||
{
|
||||
return new VectorCalibrationPreferenceEditor();
|
||||
}
|
||||
}
|
||||
249
src/main/java/io/github/dsheirer/gui/SpringSwingBeanFactory.java
Normal file
249
src/main/java/io/github/dsheirer/gui/SpringSwingBeanFactory.java
Normal file
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.gui;
|
||||
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastStatusPanel;
|
||||
import io.github.dsheirer.audio.playback.AudioPanel;
|
||||
import io.github.dsheirer.channel.details.ChannelDetailPanel;
|
||||
import io.github.dsheirer.channel.metadata.ChannelMetadataPanel;
|
||||
import io.github.dsheirer.channel.metadata.NowPlayingPanel;
|
||||
import io.github.dsheirer.controller.ControllerPanel;
|
||||
import io.github.dsheirer.gui.power.ChannelPowerPanel;
|
||||
import io.github.dsheirer.module.decode.event.DecodeEventPanel;
|
||||
import io.github.dsheirer.source.tuner.ui.DiscoveredTunerEditor;
|
||||
import io.github.dsheirer.source.tuner.ui.TunerViewPanel;
|
||||
import io.github.dsheirer.spectrum.FrequencyOverlayPanel;
|
||||
import io.github.dsheirer.spectrum.OverlayPanel;
|
||||
import io.github.dsheirer.spectrum.SpectralDisplayPanel;
|
||||
import io.github.dsheirer.spectrum.SpectrumFrame;
|
||||
import io.github.dsheirer.spectrum.SpectrumPanel;
|
||||
import io.github.dsheirer.spectrum.WaterfallPanel;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
|
||||
/**
|
||||
* Spring configuration factory for Swing UI components that require dependency injection (@Resource)
|
||||
*
|
||||
* Note: all bean creator methods are also annotated as @Lazy so that Spring doesn't auto-instantiate these beans when
|
||||
* we're running in a headless environment.
|
||||
*/
|
||||
@Configuration
|
||||
public class SpringSwingBeanFactory
|
||||
{
|
||||
/**
|
||||
* Constructs an instance
|
||||
*/
|
||||
public SpringSwingBeanFactory()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the primary UI instance when running in non-headless mode.
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public SDRTrunkUI getSDRTrunkUI()
|
||||
{
|
||||
if(GraphicsEnvironment.isHeadless())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new SDRTrunkUI();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new spectrum frame
|
||||
*/
|
||||
@Bean
|
||||
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
@Lazy
|
||||
public SpectrumFrame createSpectrumFrame()
|
||||
{
|
||||
return new SpectrumFrame();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the spectral display panel
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
public SpectralDisplayPanel getSpectralDisplayPanel()
|
||||
{
|
||||
return new SpectralDisplayPanel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the spectrum panel
|
||||
*
|
||||
* Note: editor is used in multiple places so we create a new instance for each (ie scope=prototype)
|
||||
*/
|
||||
@Bean
|
||||
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
@Lazy
|
||||
public SpectrumPanel getSpectrumPanel()
|
||||
{
|
||||
return new SpectrumPanel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the waterfall panel
|
||||
*
|
||||
* Note: editor is used in multiple places so we create a new instance for each (ie scope=prototype)
|
||||
*/
|
||||
@Bean
|
||||
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
@Lazy
|
||||
public WaterfallPanel getWaterfallPanel()
|
||||
{
|
||||
return new WaterfallPanel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the overlay panel
|
||||
*
|
||||
* Note: editor is used in multiple places so we create a new instance for each (ie scope=prototype)
|
||||
*/
|
||||
@Bean
|
||||
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
@Lazy
|
||||
public OverlayPanel getOverlayPanel()
|
||||
{
|
||||
return new OverlayPanel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the frequency overlay panel
|
||||
*
|
||||
* Note: editor is used in multiple places so we create a new instance for each (ie scope=prototype)
|
||||
*/
|
||||
@Bean
|
||||
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
@Lazy
|
||||
public FrequencyOverlayPanel getFrequencyOverlayPanel()
|
||||
{
|
||||
return new FrequencyOverlayPanel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a broadcast (ie streaming) status panel
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public BroadcastStatusPanel getBroadcastStatusPanel()
|
||||
{
|
||||
return new BroadcastStatusPanel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the controller panel
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public ControllerPanel controllerPanel()
|
||||
{
|
||||
return new ControllerPanel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the now playing panel
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public NowPlayingPanel getNowPlayingPanel()
|
||||
{
|
||||
return new NowPlayingPanel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the channel metadata panel
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public ChannelMetadataPanel getChannelMetadataPanel()
|
||||
{
|
||||
return new ChannelMetadataPanel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the channel detail panel
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public ChannelDetailPanel getChannelDetailPanel()
|
||||
{
|
||||
return new ChannelDetailPanel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the channel power panel
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public ChannelPowerPanel getChannelPowerPanel()
|
||||
{
|
||||
return new ChannelPowerPanel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the decode event panel
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public DecodeEventPanel getDecodeEventPanel()
|
||||
{
|
||||
return new DecodeEventPanel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an audio panel
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public AudioPanel getAudioPanel()
|
||||
{
|
||||
return new AudioPanel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates discovered tuner editor
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public DiscoveredTunerEditor getDiscoveredTunerEditor()
|
||||
{
|
||||
return new DiscoveredTunerEditor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates tuner view panel
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public TunerViewPanel getTunerViewPanel()
|
||||
{
|
||||
return new TunerViewPanel();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.gui.calls;
|
||||
|
||||
import javafx.scene.layout.VBox;
|
||||
|
||||
/**
|
||||
* Call audio panel for managing call audio playback.
|
||||
*/
|
||||
public class CallAudioPanel extends VBox
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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
|
||||
@@ -35,6 +35,13 @@ import io.github.dsheirer.spectrum.ComplexDftProcessor;
|
||||
import io.github.dsheirer.spectrum.DFTSize;
|
||||
import io.github.dsheirer.spectrum.SpectrumPanel;
|
||||
import io.github.dsheirer.spectrum.converter.ComplexDecibelConverter;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -47,13 +54,6 @@ import javax.swing.JToggleButton;
|
||||
import javax.swing.SpinnerNumberModel;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class ChannelizerViewer extends JFrame
|
||||
{
|
||||
@@ -316,7 +316,7 @@ public class ChannelizerViewer extends JFrame
|
||||
public PrimarySpectrumPanel(SettingsManager settingsManager, double sampleRate)
|
||||
{
|
||||
setLayout(new MigLayout("insets 0 0 0 0", "[grow,fill]", "[grow,fill]"));
|
||||
mSpectrumPanel = new SpectrumPanel(settingsManager);
|
||||
mSpectrumPanel = new SpectrumPanel();
|
||||
mSpectrumPanel.setSampleSize(28);
|
||||
add(mSpectrumPanel);
|
||||
|
||||
@@ -354,7 +354,7 @@ public class ChannelizerViewer extends JFrame
|
||||
public ChannelPanel(SettingsManager settingsManager, double sampleRate, long frequency, int bandwidth, boolean enableLogging)
|
||||
{
|
||||
setLayout(new MigLayout("insets 0 0 0 0", "[center,grow,fill][]", "[grow,fill][]"));
|
||||
mSpectrumPanel = new SpectrumPanel(settingsManager);
|
||||
mSpectrumPanel = new SpectrumPanel();
|
||||
mSpectrumPanel.setSampleSize(32);
|
||||
add(mSpectrumPanel, "span");
|
||||
|
||||
@@ -435,7 +435,7 @@ public class ChannelizerViewer extends JFrame
|
||||
{
|
||||
mSource = source;
|
||||
setLayout(new MigLayout("insets 0 0 0 0", "[center,grow,fill][]", "[grow,fill][]"));
|
||||
mSpectrumPanel = new SpectrumPanel(settingsManager);
|
||||
mSpectrumPanel = new SpectrumPanel();
|
||||
mSpectrumPanel.setSampleSize(32);
|
||||
add(mSpectrumPanel, "span");
|
||||
add(new JLabel("Index:" + index));
|
||||
|
||||
@@ -333,7 +333,7 @@ public class ChannelizerViewer2 extends JFrame
|
||||
public PrimarySpectrumPanel(SettingsManager settingsManager, double sampleRate)
|
||||
{
|
||||
setLayout(new MigLayout("insets 0 0 0 0", "[grow,fill]", "[grow,fill]"));
|
||||
mSpectrumPanel = new SpectrumPanel(settingsManager);
|
||||
mSpectrumPanel = new SpectrumPanel();
|
||||
mSpectrumPanel.setSampleSize(16);
|
||||
add(mSpectrumPanel);
|
||||
|
||||
@@ -371,7 +371,7 @@ public class ChannelizerViewer2 extends JFrame
|
||||
public ChannelPanel(SettingsManager settingsManager, double sampleRate, long frequency, int bandwidth)
|
||||
{
|
||||
setLayout(new MigLayout("insets 0 0 0 0", "[grow,fill][grow,fill][grow,fill]", "[grow,fill][]"));
|
||||
mSpectrumPanel = new SpectrumPanel(settingsManager);
|
||||
mSpectrumPanel = new SpectrumPanel();
|
||||
mSpectrumPanel.setSampleSize(16);
|
||||
add(mSpectrumPanel, "span");
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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,6 +36,13 @@ import io.github.dsheirer.spectrum.ComplexDftProcessor;
|
||||
import io.github.dsheirer.spectrum.DFTSize;
|
||||
import io.github.dsheirer.spectrum.SpectrumPanel;
|
||||
import io.github.dsheirer.spectrum.converter.ComplexDecibelConverter;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -48,13 +55,6 @@ import javax.swing.JToggleButton;
|
||||
import javax.swing.SpinnerNumberModel;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class HeterodyneChannelizerViewer extends JFrame
|
||||
{
|
||||
@@ -315,7 +315,7 @@ public class HeterodyneChannelizerViewer extends JFrame
|
||||
public PrimarySpectrumPanel(SettingsManager settingsManager, double sampleRate)
|
||||
{
|
||||
setLayout(new MigLayout("insets 0 0 0 0", "[grow,fill]", "[grow,fill]"));
|
||||
mSpectrumPanel = new SpectrumPanel(settingsManager);
|
||||
mSpectrumPanel = new SpectrumPanel();
|
||||
mSpectrumPanel.setSampleSize(28);
|
||||
add(mSpectrumPanel);
|
||||
|
||||
@@ -353,7 +353,7 @@ public class HeterodyneChannelizerViewer extends JFrame
|
||||
public ChannelPanel(SettingsManager settingsManager, double sampleRate, long frequency, int bandwidth, boolean enableLogging)
|
||||
{
|
||||
setLayout(new MigLayout("insets 0 0 0 0", "[center,grow,fill][]", "[grow,fill][]"));
|
||||
mSpectrumPanel = new SpectrumPanel(settingsManager);
|
||||
mSpectrumPanel = new SpectrumPanel();
|
||||
mSpectrumPanel.setSampleSize(32);
|
||||
add(mSpectrumPanel, "span");
|
||||
|
||||
@@ -435,7 +435,7 @@ public class HeterodyneChannelizerViewer extends JFrame
|
||||
{
|
||||
mSource = source;
|
||||
setLayout(new MigLayout("insets 0 0 0 0", "[center,grow,fill][]", "[grow,fill][]"));
|
||||
mSpectrumPanel = new SpectrumPanel(settingsManager);
|
||||
mSpectrumPanel = new SpectrumPanel();
|
||||
mSpectrumPanel.setSampleSize(32);
|
||||
add(mSpectrumPanel, "span");
|
||||
add(new JLabel("Index:" + index));
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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
|
||||
@@ -150,7 +150,7 @@ public class SynthesizerViewer extends JFrame
|
||||
public PrimarySpectrumPanel(SettingsManager settingsManager)
|
||||
{
|
||||
setLayout(new MigLayout("insets 0 0 0 0", "[grow,fill]", "[grow,fill]"));
|
||||
mSpectrumPanel = new SpectrumPanel(settingsManager);
|
||||
mSpectrumPanel = new SpectrumPanel();
|
||||
mSpectrumPanel.setSampleSize(16);
|
||||
add(mSpectrumPanel);
|
||||
|
||||
@@ -181,7 +181,7 @@ public class SynthesizerViewer extends JFrame
|
||||
public ChannelPanel(SettingsManager settingsManager, ChannelControlPanel channelControlPanel)
|
||||
{
|
||||
setLayout(new MigLayout("insets 0 0 0 0", "[grow,fill]", "[grow,fill][]"));
|
||||
mSpectrumPanel = new SpectrumPanel(settingsManager);
|
||||
mSpectrumPanel = new SpectrumPanel();
|
||||
mSpectrumPanel.setSampleSize(16);
|
||||
add(mSpectrumPanel, "wrap");
|
||||
add(channelControlPanel);
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.gui.control;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import javafx.scene.control.TableCell;
|
||||
import javafx.scene.control.TableColumn;
|
||||
import javafx.util.Callback;
|
||||
|
||||
/**
|
||||
* Table cell factory that formats a long timestamp column value as a formatted date/time stamp.
|
||||
* @param <T> is the table row entity type
|
||||
*/
|
||||
public class TimestampTableCellFactory<T> implements Callback<TableColumn<T, Long>, TableCell<T, Long>>
|
||||
{
|
||||
private SimpleDateFormat mSDF = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
|
||||
|
||||
@Override
|
||||
public TableCell<T, Long> call(TableColumn<T, Long> param)
|
||||
{
|
||||
return new TableCell<>()
|
||||
{
|
||||
@Override
|
||||
protected void updateItem(Long item, boolean empty)
|
||||
{
|
||||
super.updateItem(item, empty);
|
||||
|
||||
if(empty)
|
||||
{
|
||||
setText(null);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(item instanceof Long l)
|
||||
{
|
||||
String a = mSDF.format(l);
|
||||
setText(a);
|
||||
}
|
||||
else
|
||||
{
|
||||
setText("Not a Long: " + item.getClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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,6 +22,11 @@ package io.github.dsheirer.gui.icon;
|
||||
import io.github.dsheirer.gui.playlist.Editor;
|
||||
import io.github.dsheirer.icon.Icon;
|
||||
import io.github.dsheirer.icon.IconModel;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.collections.transformation.SortedList;
|
||||
import javafx.geometry.HPos;
|
||||
@@ -48,17 +53,16 @@ import javafx.util.Callback;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
* GUI manager/editor for standard and custom icons used in sdrtrunk
|
||||
*/
|
||||
public class IconManager extends Editor<Icon>
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger(IconManager.class);
|
||||
|
||||
@Resource
|
||||
private IconModel mIconModel;
|
||||
|
||||
private TableView<Icon> mIconTableView;
|
||||
private Button mAddButton;
|
||||
private Button mEditButton;
|
||||
@@ -78,9 +82,13 @@ public class IconManager extends Editor<Icon>
|
||||
/**
|
||||
* Constructs an instance
|
||||
*/
|
||||
public IconManager(IconModel iconModel)
|
||||
public IconManager()
|
||||
{
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
mIconModel = iconModel;
|
||||
getChildren().addAll(getAccordion());
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* 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
|
||||
* 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.gui.javafx.table;
|
||||
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TableColumn;
|
||||
import javafx.scene.control.TableView;
|
||||
import javafx.scene.control.cell.CheckBoxTableCell;
|
||||
import javafx.scene.control.cell.PropertyValueFactory;
|
||||
import javafx.scene.layout.ColumnConstraints;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.Priority;
|
||||
import javafx.scene.layout.VBox;
|
||||
|
||||
/**
|
||||
* Editor for managing table column ordering and visibility.
|
||||
*/
|
||||
public class TableColumnEditor extends VBox
|
||||
{
|
||||
private TableView mTableView;
|
||||
private TableViewColumnController mTableViewColumnController;
|
||||
private TableView mColumnsTableView;
|
||||
private Button mCloseButton;
|
||||
private Button mOrderUpButton;
|
||||
private Button mOrderDownButton;
|
||||
private Button mResetColumnsButton;
|
||||
private BooleanProperty mClosed = new SimpleBooleanProperty();
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param tableView to be configured/managed
|
||||
*/
|
||||
public TableColumnEditor(TableView tableView, TableViewColumnController monitor)
|
||||
{
|
||||
mTableView = tableView;
|
||||
mTableViewColumnController = monitor;
|
||||
setPadding(new Insets(10));
|
||||
GridPane gridPane = new GridPane();
|
||||
gridPane.setHgap(10);
|
||||
gridPane.setVgap(5);
|
||||
int row = 0;
|
||||
|
||||
Label infoLabel = new Label("Configure Columns");
|
||||
GridPane.setConstraints(infoLabel, 0, row);
|
||||
gridPane.getChildren().add(infoLabel);
|
||||
|
||||
GridPane.setConstraints(getCloseButton(), 1, row);
|
||||
gridPane.getChildren().add(getCloseButton());
|
||||
|
||||
row++;
|
||||
|
||||
GridPane.setConstraints(getColumnsTableView(), 0, row, 1, 6);
|
||||
gridPane.getChildren().add(getColumnsTableView());
|
||||
|
||||
row += 2;
|
||||
|
||||
GridPane.setConstraints(getOrderUpButton(), 1, row);
|
||||
gridPane.getChildren().add(getOrderUpButton());
|
||||
|
||||
row++;
|
||||
|
||||
GridPane.setConstraints(getOrderDownButton(), 1, row);
|
||||
gridPane.getChildren().add(getOrderDownButton());
|
||||
|
||||
row++;
|
||||
GridPane.setConstraints(getResetColumnsButton(), 1, row);
|
||||
gridPane.getChildren().add(getResetColumnsButton());
|
||||
|
||||
ColumnConstraints cc1 = new ColumnConstraints();
|
||||
cc1.setHgrow(Priority.ALWAYS);
|
||||
ColumnConstraints cc2 = new ColumnConstraints();
|
||||
cc2.setHgrow(Priority.NEVER);
|
||||
cc2.setPrefWidth(60);
|
||||
cc2.setMinWidth(60);
|
||||
gridPane.getColumnConstraints().addAll(cc1, cc2);
|
||||
|
||||
VBox.setVgrow(gridPane, Priority.ALWAYS);
|
||||
getChildren().add(gridPane);
|
||||
}
|
||||
|
||||
private TableView<TableColumn> getColumnsTableView()
|
||||
{
|
||||
if(mColumnsTableView == null)
|
||||
{
|
||||
mColumnsTableView = new TableView(mTableView.getColumns());
|
||||
mColumnsTableView.setEditable(true);
|
||||
|
||||
TableColumn textColumn = new TableColumn("Column");
|
||||
textColumn.setEditable(false);
|
||||
textColumn.setCellValueFactory(new PropertyValueFactory<>("text"));
|
||||
mColumnsTableView.getColumns().add(textColumn);
|
||||
|
||||
TableColumn<TableColumn,Boolean> visibleColumn = new TableColumn("Visible");
|
||||
visibleColumn.setCellValueFactory(new PropertyValueFactory<>("visible"));
|
||||
visibleColumn.setCellFactory(CheckBoxTableCell.forTableColumn(visibleColumn));
|
||||
visibleColumn.setEditable(true);
|
||||
mColumnsTableView.getColumns().add(visibleColumn);
|
||||
|
||||
mColumnsTableView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void changed(ObservableValue observable, Object oldValue, Object newValue)
|
||||
{
|
||||
//If monitored table has only a single column keep both buttons disabled.
|
||||
if(mTableView.getColumns().size() <= 1)
|
||||
{
|
||||
getOrderDownButton().setDisable(true);
|
||||
getOrderUpButton().setDisable(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if(newValue == null)
|
||||
{
|
||||
getOrderDownButton().setDisable(true);
|
||||
getOrderUpButton().setDisable(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(mColumnsTableView.getSelectionModel().isSelected(0))
|
||||
{
|
||||
getOrderDownButton().setDisable(false);
|
||||
getOrderUpButton().setDisable(true);
|
||||
}
|
||||
else if(mColumnsTableView.getSelectionModel().isSelected(mTableView.getColumns().size() - 1))
|
||||
{
|
||||
getOrderDownButton().setDisable(true);
|
||||
getOrderUpButton().setDisable(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
getOrderDownButton().setDisable(false);
|
||||
getOrderUpButton().setDisable(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return mColumnsTableView;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close button
|
||||
* @return button
|
||||
*/
|
||||
private Button getCloseButton()
|
||||
{
|
||||
if(mCloseButton == null)
|
||||
{
|
||||
mCloseButton = new Button("Close");
|
||||
mCloseButton.setMaxWidth(Double.MAX_VALUE);
|
||||
mCloseButton.setOnAction(event -> closedProperty().set(true));
|
||||
}
|
||||
|
||||
return mCloseButton;
|
||||
}
|
||||
|
||||
private Button getOrderUpButton()
|
||||
{
|
||||
if(mOrderUpButton == null)
|
||||
{
|
||||
mOrderUpButton = new Button("Up");
|
||||
mOrderUpButton.setDisable(true);
|
||||
mOrderUpButton.setMaxWidth(Double.MAX_VALUE);
|
||||
mOrderUpButton.setOnAction(event -> {
|
||||
if(mColumnsTableView.getSelectionModel().selectedItemProperty().get() != null)
|
||||
{
|
||||
TableColumn selected = (TableColumn)mColumnsTableView.getSelectionModel().getSelectedItem();
|
||||
int currentIndex = mTableView.getColumns().indexOf(selected);
|
||||
mTableView.getColumns().remove(selected);
|
||||
mTableView.getColumns().add(currentIndex - 1, selected);
|
||||
//Reselect the column since it moved and lost the selection
|
||||
mColumnsTableView.getSelectionModel().select(selected);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return mOrderUpButton;
|
||||
}
|
||||
|
||||
private Button getOrderDownButton()
|
||||
{
|
||||
if(mOrderDownButton == null)
|
||||
{
|
||||
mOrderDownButton = new Button("Down");
|
||||
mOrderDownButton.setDisable(true);
|
||||
mOrderDownButton.setMaxWidth(Double.MAX_VALUE);
|
||||
mOrderDownButton.setOnAction(event -> {
|
||||
if(mColumnsTableView.getSelectionModel().selectedItemProperty().get() != null)
|
||||
{
|
||||
TableColumn selected = (TableColumn)mColumnsTableView.getSelectionModel().getSelectedItem();
|
||||
int currentIndex = mTableView.getColumns().indexOf(selected);
|
||||
mTableView.getColumns().remove(selected);
|
||||
mTableView.getColumns().add(currentIndex + 1, selected);
|
||||
//Reselect the column since it moved and lost the selection
|
||||
mColumnsTableView.getSelectionModel().select(selected);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return mOrderDownButton;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the columns to default state.
|
||||
* @return button to reset
|
||||
*/
|
||||
private Button getResetColumnsButton()
|
||||
{
|
||||
if(mResetColumnsButton == null)
|
||||
{
|
||||
mResetColumnsButton = new Button("Reset");
|
||||
mResetColumnsButton.setMaxWidth(Double.MAX_VALUE);
|
||||
mResetColumnsButton.setOnAction(event -> mTableViewColumnController.reset());
|
||||
}
|
||||
|
||||
return mResetColumnsButton;
|
||||
}
|
||||
|
||||
/**
|
||||
* Observable property to monitor for when the user clicks the close button.
|
||||
*/
|
||||
public BooleanProperty closedProperty()
|
||||
{
|
||||
return mClosed;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* 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
|
||||
* 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.gui.javafx.table;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javafx.scene.control.TableColumn;
|
||||
import javafx.scene.control.TableView;
|
||||
|
||||
/**
|
||||
* Captures the state of table columns.
|
||||
*/
|
||||
public class TableState
|
||||
{
|
||||
private List<ColumnState> mColumns = new ArrayList<>();
|
||||
private List<SortedColumn> mSort = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
*/
|
||||
public TableState()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to create a table state from a list of table columns
|
||||
* @param columns to capture state
|
||||
* @return table state instance
|
||||
*/
|
||||
public static TableState create(TableView tableView)
|
||||
{
|
||||
TableState tableState = new TableState();
|
||||
|
||||
List<TableColumn> columns = tableView.getColumns();
|
||||
for(TableColumn column: columns)
|
||||
{
|
||||
if(column.getId() == null || column.getId().isEmpty())
|
||||
{
|
||||
throw new IllegalArgumentException("TableColumns must have a non-null, non-empty ID value.");
|
||||
}
|
||||
|
||||
tableState.addColumn(new ColumnState(column.getId(), column.isVisible(), (int)column.getWidth()));
|
||||
}
|
||||
|
||||
List<TableColumn> sortedColumns = tableView.getSortOrder();
|
||||
for(TableColumn sortedColumn: sortedColumns)
|
||||
{
|
||||
if(sortedColumn.getId() == null || sortedColumn.getId().isEmpty())
|
||||
{
|
||||
throw new IllegalArgumentException("TableColumns must have a non-null, non-empty ID value.");
|
||||
}
|
||||
|
||||
tableState.addSort(new SortedColumn(sortedColumn.getId(), sortedColumn.getSortType()));
|
||||
}
|
||||
|
||||
return tableState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Column states.
|
||||
* @return column states
|
||||
*/
|
||||
public List<ColumnState> getColumns()
|
||||
{
|
||||
return mColumns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a column state
|
||||
* @param columnState to add
|
||||
*/
|
||||
public void addColumn(ColumnState columnState)
|
||||
{
|
||||
mColumns.add(columnState);
|
||||
}
|
||||
|
||||
/**
|
||||
* List of sorted columns
|
||||
* @return sorted columns
|
||||
*/
|
||||
public List<SortedColumn> getSort()
|
||||
{
|
||||
return mSort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the sorted column
|
||||
* @param sortedColumn to add
|
||||
*/
|
||||
public void addSort(SortedColumn sortedColumn)
|
||||
{
|
||||
mSort.add(sortedColumn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Column state. Note: arg/variable names are abbreviated for brevity in json representation.
|
||||
* @param id for the column
|
||||
* @param v visible status
|
||||
* @param w width of the column
|
||||
*/
|
||||
public record ColumnState(String id, boolean v, int w) {};
|
||||
|
||||
/**
|
||||
* Sorted column
|
||||
* @param id of the column
|
||||
* @param sortType ascending or descending
|
||||
*/
|
||||
public record SortedColumn(String id, TableColumn.SortType sortType) {};
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* 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
|
||||
* 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.gui.javafx.table;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.prefs.Preferences;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.scene.control.TableColumn;
|
||||
import javafx.scene.control.TableView;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Utility to monitor a JavaFX TableView's column ordering, sizes and visibiltiy and restore those settings on startup.
|
||||
*/
|
||||
public class TableViewColumnController implements ListChangeListener
|
||||
{
|
||||
private static final Logger LOG = LoggerFactory.getLogger(TableViewColumnController.class);
|
||||
private final Preferences mPreferences = Preferences.userNodeForPackage(TableViewColumnController.class);
|
||||
private static final String PREFERENCE_KEY_TABLE_STATE = ".table.state";
|
||||
private String mPreferencePrefix;
|
||||
private TableView mTableView;
|
||||
private TableState mDefaultTableState;
|
||||
private ColumnVisibilityMonitor mVisibilityMonitor = new ColumnVisibilityMonitor();
|
||||
private ColumnWidthMonitor mWidthMonitor = new ColumnWidthMonitor();
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param tableView to be monitor and control the column settings
|
||||
* @param preferencePrefix to use for storing the table state in preferences, must be non-null/non-empty/unique.
|
||||
*/
|
||||
public TableViewColumnController(TableView tableView, String preferencePrefix)
|
||||
{
|
||||
if(preferencePrefix == null || preferencePrefix.isEmpty())
|
||||
{
|
||||
throw new IllegalArgumentException("Preference prefix [" + preferencePrefix + "] must be non-null & non-empty");
|
||||
}
|
||||
|
||||
mTableView = tableView;
|
||||
mPreferencePrefix = preferencePrefix;
|
||||
mDefaultTableState = TableState.create(mTableView);
|
||||
|
||||
TableState storedTableState = getStoredTableState();
|
||||
|
||||
if(storedTableState != null)
|
||||
{
|
||||
apply(storedTableState);
|
||||
}
|
||||
|
||||
//Register listeners on the table and the individual columns
|
||||
mTableView.getColumns().addListener(this);
|
||||
mTableView.getSortOrder().addListener(this);
|
||||
|
||||
ObservableList<TableColumn> columns = mTableView.getColumns();
|
||||
for(TableColumn tableColumn: columns)
|
||||
{
|
||||
tableColumn.visibleProperty().addListener(mVisibilityMonitor);
|
||||
tableColumn.widthProperty().addListener(mWidthMonitor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the table columns to the default state
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
apply(mDefaultTableState);
|
||||
//Clear the preference since we're at default state
|
||||
mPreferences.put(mPreferencePrefix + PREFERENCE_KEY_TABLE_STATE, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the table state to the currently monitored table view.
|
||||
* @param tableState to apply.
|
||||
*/
|
||||
private void apply(TableState tableState)
|
||||
{
|
||||
if(tableState != null)
|
||||
{
|
||||
if(tableState.getColumns().size() != mTableView.getColumns().size())
|
||||
{
|
||||
LOG.error("Unable to restore tableview column state - column size mismatch");
|
||||
return;
|
||||
}
|
||||
|
||||
//Remove the columns from the table and re-add them according to the stored ordering.
|
||||
List<TableColumn> columns = new ArrayList<>(mTableView.getColumns());
|
||||
mTableView.getColumns().clear();
|
||||
|
||||
for(TableState.ColumnState columnState: tableState.getColumns())
|
||||
{
|
||||
TableColumn match = null;
|
||||
for(TableColumn tableColumn: columns)
|
||||
{
|
||||
if(tableColumn.getId() != null && tableColumn.getId().equals(columnState.id()))
|
||||
{
|
||||
match = tableColumn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(match != null)
|
||||
{
|
||||
match.setVisible(columnState.v());
|
||||
match.setPrefWidth(columnState.w());
|
||||
mTableView.getColumns().add(match);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG.warn("Unable to find matching table column for id [" + columnState.id() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
//Clear and restore the sort ordering
|
||||
mTableView.getSortOrder().clear();
|
||||
for(TableState.SortedColumn sortedColumn: tableState.getSort())
|
||||
{
|
||||
List<TableColumn> tableColumns = mTableView.getColumns();
|
||||
|
||||
for(TableColumn column: tableColumns)
|
||||
{
|
||||
if(sortedColumn.id().equals(column.getId()))
|
||||
{
|
||||
column.setSortType(sortedColumn.sortType());
|
||||
mTableView.getSortOrder().add(column);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores current table state
|
||||
*/
|
||||
private void storeTableState()
|
||||
{
|
||||
TableState tableState = TableState.create(mTableView);
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
try
|
||||
{
|
||||
String json = objectMapper.writeValueAsString(tableState);
|
||||
mPreferences.put(mPreferencePrefix + PREFERENCE_KEY_TABLE_STATE, json);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
LOG.error("Error creating table state json for table [" + mPreferencePrefix + "]", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the stored table state
|
||||
* @return stored table state or null if this is the first usage or the state has been reset to default.
|
||||
*/
|
||||
private TableState getStoredTableState()
|
||||
{
|
||||
String json = mPreferences.get(mPreferencePrefix + PREFERENCE_KEY_TABLE_STATE, null);
|
||||
|
||||
if(json != null)
|
||||
{
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
try
|
||||
{
|
||||
return objectMapper.readValue(json.getBytes(), TableState.class);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
LOG.error("Error deserializing table state from json [" + json + "] " + e.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements the ListChangeListener interface to monitor the table columns for ordering changes.
|
||||
* @param c an object representing the change that was done
|
||||
*/
|
||||
@Override
|
||||
public void onChanged(Change c)
|
||||
{
|
||||
boolean changed = false;
|
||||
|
||||
while(c.next())
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if(changed)
|
||||
{
|
||||
storeTableState();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Column visibility monitor
|
||||
*/
|
||||
private class ColumnVisibilityMonitor implements ChangeListener<Boolean>
|
||||
{
|
||||
@Override
|
||||
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue)
|
||||
{
|
||||
storeTableState();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Column width monitor
|
||||
*/
|
||||
private class ColumnWidthMonitor implements ChangeListener<Number>
|
||||
{
|
||||
@Override
|
||||
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue)
|
||||
{
|
||||
storeTableState();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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
|
||||
@@ -30,11 +30,14 @@ import io.github.dsheirer.gui.playlist.radioreference.RadioReferenceEditor;
|
||||
import io.github.dsheirer.gui.playlist.streaming.StreamingEditor;
|
||||
import io.github.dsheirer.gui.preference.PreferenceEditorType;
|
||||
import io.github.dsheirer.gui.preference.ViewUserPreferenceEditorRequest;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||
import io.github.dsheirer.util.ThreadPool;
|
||||
import io.github.dsheirer.util.TimeStamp;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import javafx.application.Platform;
|
||||
import javafx.embed.swing.SwingFXUtils;
|
||||
import javafx.scene.control.Menu;
|
||||
@@ -54,9 +57,6 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
* JavaFX playlist, channels, aliases, streaming and radioreference.com import editor
|
||||
@@ -64,9 +64,17 @@ import java.nio.file.Path;
|
||||
public class PlaylistEditor extends BorderPane
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger(PlaylistEditor.class);
|
||||
|
||||
private PlaylistManager mPlaylistManager;
|
||||
private TunerManager mTunerManager;
|
||||
@Resource
|
||||
private AliasEditor mAliasEditor;
|
||||
@Resource
|
||||
private ChannelEditor mChannelEditor;
|
||||
@Resource
|
||||
private PlaylistManagerEditor mPlaylistManagerEditor;
|
||||
@Resource
|
||||
private RadioReferenceEditor mRadioReferenceEditor;
|
||||
@Resource
|
||||
private StreamingEditor mStreamingEditor;
|
||||
@Resource
|
||||
private UserPreferences mUserPreferences;
|
||||
private MenuBar mMenuBar;
|
||||
private TabPane mTabPane;
|
||||
@@ -75,21 +83,17 @@ public class PlaylistEditor extends BorderPane
|
||||
private Tab mAliasesTab;
|
||||
private Tab mRadioReferenceTab;
|
||||
private Tab mStreamingTab;
|
||||
private AliasEditor mAliasEditor;
|
||||
private ChannelEditor mChannelEditor;
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param playlistManager for alias and channel models
|
||||
* @param tunerManager for tuners
|
||||
* @param userPreferences for settings
|
||||
*/
|
||||
public PlaylistEditor(PlaylistManager playlistManager, TunerManager tunerManager, UserPreferences userPreferences)
|
||||
public PlaylistEditor()
|
||||
{
|
||||
mPlaylistManager = playlistManager;
|
||||
mTunerManager = tunerManager;
|
||||
mUserPreferences = userPreferences;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
//Throw a new runnable back onto the FX thread to lazy load the editor content after the editor has been
|
||||
//constructed and shown.
|
||||
Platform.runLater(() -> {
|
||||
@@ -221,11 +225,6 @@ public class PlaylistEditor extends BorderPane
|
||||
|
||||
private AliasEditor getAliasEditor()
|
||||
{
|
||||
if(mAliasEditor == null)
|
||||
{
|
||||
mAliasEditor = new AliasEditor(mPlaylistManager, mUserPreferences);
|
||||
}
|
||||
|
||||
return mAliasEditor;
|
||||
}
|
||||
|
||||
@@ -242,11 +241,6 @@ public class PlaylistEditor extends BorderPane
|
||||
|
||||
private ChannelEditor getChannelEditor()
|
||||
{
|
||||
if(mChannelEditor == null)
|
||||
{
|
||||
mChannelEditor = new ChannelEditor(mPlaylistManager, mTunerManager, mUserPreferences);
|
||||
}
|
||||
|
||||
return mChannelEditor;
|
||||
}
|
||||
|
||||
@@ -255,7 +249,7 @@ public class PlaylistEditor extends BorderPane
|
||||
if(mPlaylistsTab == null)
|
||||
{
|
||||
mPlaylistsTab = new Tab("Playlists");
|
||||
mPlaylistsTab.setContent(new PlaylistManagerEditor(mPlaylistManager, mUserPreferences));
|
||||
mPlaylistsTab.setContent(mPlaylistManagerEditor);
|
||||
}
|
||||
|
||||
return mPlaylistsTab;
|
||||
@@ -266,7 +260,15 @@ public class PlaylistEditor extends BorderPane
|
||||
if(mRadioReferenceTab == null)
|
||||
{
|
||||
mRadioReferenceTab = new Tab("Radio Reference");
|
||||
mRadioReferenceTab.setContent(new RadioReferenceEditor(mUserPreferences, mPlaylistManager));
|
||||
mRadioReferenceTab.setContent(mRadioReferenceEditor);
|
||||
|
||||
//Only login once/if the user selects the radio reference tab
|
||||
mRadioReferenceTab.selectedProperty().addListener((observable, oldValue, selected) -> {
|
||||
if(selected)
|
||||
{
|
||||
mRadioReferenceEditor.login();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return mRadioReferenceTab;
|
||||
@@ -277,7 +279,7 @@ public class PlaylistEditor extends BorderPane
|
||||
if(mStreamingTab == null)
|
||||
{
|
||||
mStreamingTab = new Tab("Streaming");
|
||||
mStreamingTab.setContent(new StreamingEditor(mPlaylistManager));
|
||||
mStreamingTab.setContent(mStreamingEditor);
|
||||
}
|
||||
|
||||
return mStreamingTab;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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
|
||||
@@ -19,13 +19,12 @@
|
||||
|
||||
package io.github.dsheirer.gui.playlist;
|
||||
|
||||
import io.github.dsheirer.alias.AliasModel;
|
||||
import io.github.dsheirer.gui.JavaFxWindowManager;
|
||||
import io.github.dsheirer.icon.IconModel;
|
||||
import io.github.dsheirer.module.log.EventLogManager;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import javafx.application.Application;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.Scene;
|
||||
@@ -45,14 +44,16 @@ public class PlaylistEditorApplication extends Application
|
||||
|
||||
public PlaylistEditorApplication()
|
||||
{
|
||||
AliasModel aliasModel = new AliasModel();
|
||||
EventLogManager eventLogManager = new EventLogManager(aliasModel, mUserPreferences);
|
||||
mTunerManager = new TunerManager(mUserPreferences);
|
||||
mTunerManager.start();
|
||||
mPlaylistManager = new PlaylistManager(mUserPreferences, mTunerManager, aliasModel, eventLogManager, new IconModel());
|
||||
}
|
||||
|
||||
mPlaylistManager.init();
|
||||
mJavaFxWindowManager = new JavaFxWindowManager(mUserPreferences, mTunerManager, mPlaylistManager);
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
EventLogManager eventLogManager = new EventLogManager();
|
||||
mTunerManager = new TunerManager();
|
||||
mTunerManager.start();
|
||||
mPlaylistManager = new PlaylistManager();
|
||||
mJavaFxWindowManager = new JavaFxWindowManager();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -69,7 +70,7 @@ public class PlaylistEditorApplication extends Application
|
||||
{
|
||||
if(mPlaylistEditor == null)
|
||||
{
|
||||
mPlaylistEditor = new PlaylistEditor(mPlaylistManager, mTunerManager, mUserPreferences);
|
||||
mPlaylistEditor = new PlaylistEditor();
|
||||
}
|
||||
|
||||
return mPlaylistEditor;
|
||||
|
||||
@@ -23,7 +23,9 @@ import com.google.common.collect.Ordering;
|
||||
import io.github.dsheirer.alias.Alias;
|
||||
import io.github.dsheirer.gui.playlist.Editor;
|
||||
import io.github.dsheirer.icon.Icon;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.icon.IconModel;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.List;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.ReadOnlyBooleanProperty;
|
||||
@@ -52,7 +54,8 @@ import org.controlsfx.control.ToggleSwitch;
|
||||
*/
|
||||
public class AliasBulkEditor extends Editor<List<Alias>>
|
||||
{
|
||||
private PlaylistManager mPlaylistManager;
|
||||
@Resource
|
||||
private IconModel mIconModel;
|
||||
private Label mEditingLabel;
|
||||
private ColorPicker mColorPicker;
|
||||
private Button mApplyColorButton;
|
||||
@@ -65,20 +68,19 @@ public class AliasBulkEditor extends Editor<List<Alias>>
|
||||
private ToggleSwitch mRecordToggleSwitch;
|
||||
private Button mApplyRecordButton;
|
||||
|
||||
private BooleanProperty mChangeInProgressProperty;
|
||||
private BooleanProperty mChangeInProgressProperty = new SimpleBooleanProperty();
|
||||
private ReadOnlyBooleanProperty mChangeInProgressROProperty;
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
*
|
||||
* @param playlistManager for accessing icon manager
|
||||
*/
|
||||
public AliasBulkEditor(PlaylistManager playlistManager)
|
||||
public AliasBulkEditor()
|
||||
{
|
||||
mPlaylistManager = playlistManager;
|
||||
|
||||
mChangeInProgressProperty = new SimpleBooleanProperty();
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
GridPane gridPane = new GridPane();
|
||||
gridPane.setPadding(new Insets(10, 10, 10, 10));
|
||||
gridPane.setHgap(10);
|
||||
@@ -280,7 +282,7 @@ public class AliasBulkEditor extends Editor<List<Alias>>
|
||||
{
|
||||
mIconNodeComboBox = new ComboBox<>();
|
||||
mIconNodeComboBox.setMaxWidth(Double.MAX_VALUE);
|
||||
mIconNodeComboBox.setItems(new SortedList(mPlaylistManager.getIconModel().iconsProperty(), Ordering.natural()));
|
||||
mIconNodeComboBox.setItems(new SortedList(mIconModel.iconsProperty(), Ordering.natural()));
|
||||
mIconNodeComboBox.setCellFactory(new IconCellFactory());
|
||||
mIconNodeComboBox.getSelectionModel().selectedItemProperty()
|
||||
.addListener((observable, oldValue, newValue) ->
|
||||
@@ -298,25 +300,20 @@ public class AliasBulkEditor extends Editor<List<Alias>>
|
||||
{
|
||||
mApplyIconButton = new Button("Apply");
|
||||
mApplyIconButton.setDisable(true);
|
||||
mApplyIconButton.setOnAction(new EventHandler<ActionEvent>()
|
||||
{
|
||||
@Override
|
||||
public void handle(ActionEvent event)
|
||||
mApplyIconButton.setOnAction(event -> {
|
||||
startChange();
|
||||
|
||||
Icon icon = getIconNodeComboBox().getSelectionModel().getSelectedItem();
|
||||
|
||||
if(icon != null)
|
||||
{
|
||||
startChange();
|
||||
|
||||
Icon icon = getIconNodeComboBox().getSelectionModel().getSelectedItem();
|
||||
|
||||
if(icon != null)
|
||||
for(Alias alias : getItem())
|
||||
{
|
||||
for(Alias alias : getItem())
|
||||
{
|
||||
alias.setIconName(icon.getName());
|
||||
}
|
||||
alias.setIconName(icon.getName());
|
||||
}
|
||||
|
||||
endChange();
|
||||
}
|
||||
|
||||
endChange();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -26,8 +26,9 @@ import io.github.dsheirer.alias.AliasModel;
|
||||
import io.github.dsheirer.gui.control.MaxLengthUnaryOperator;
|
||||
import io.github.dsheirer.gui.playlist.Editor;
|
||||
import io.github.dsheirer.icon.Icon;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.icon.IconModel;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@@ -80,9 +81,13 @@ public class AliasConfigurationEditor extends SplitPane
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger(AliasConfigurationEditor.class);
|
||||
|
||||
private PlaylistManager mPlaylistManager;
|
||||
private UserPreferences mUserPreferences;
|
||||
@Resource
|
||||
private AliasModel mAliasModel;
|
||||
@Resource
|
||||
private IconModel mIconModel;
|
||||
@Resource
|
||||
private AliasItemEditor mAliasItemEditor;
|
||||
@Resource
|
||||
private AliasBulkEditor mAliasBulkEditor;
|
||||
private Editor mCurrentEditor;
|
||||
private TableView<Alias> mAliasTableView;
|
||||
@@ -100,11 +105,13 @@ public class AliasConfigurationEditor extends SplitPane
|
||||
private SortedList<Alias> mAliasSortedList;
|
||||
private AliasPredicate mAliasPredicate;
|
||||
|
||||
public AliasConfigurationEditor(PlaylistManager playlistManager, UserPreferences userPreferences)
|
||||
public AliasConfigurationEditor()
|
||||
{
|
||||
mPlaylistManager = playlistManager;
|
||||
mUserPreferences = userPreferences;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
VBox leftBox = new VBox();
|
||||
VBox.setVgrow(getAliasTableView(), Priority.ALWAYS);
|
||||
leftBox.getChildren().addAll(getSearchAndListSelectionBox(), getAliasTableView());
|
||||
@@ -209,21 +216,11 @@ public class AliasConfigurationEditor extends SplitPane
|
||||
|
||||
private AliasItemEditor getAliasItemEditor()
|
||||
{
|
||||
if(mAliasItemEditor == null)
|
||||
{
|
||||
mAliasItemEditor = new AliasItemEditor(mPlaylistManager, mUserPreferences);
|
||||
}
|
||||
|
||||
return mAliasItemEditor;
|
||||
}
|
||||
|
||||
private AliasBulkEditor getAliasBulkEditor()
|
||||
{
|
||||
if(mAliasBulkEditor == null)
|
||||
{
|
||||
mAliasBulkEditor = new AliasBulkEditor(mPlaylistManager);
|
||||
}
|
||||
|
||||
return mAliasBulkEditor;
|
||||
}
|
||||
|
||||
@@ -288,7 +285,7 @@ public class AliasConfigurationEditor extends SplitPane
|
||||
{
|
||||
if(mAliasListNameComboBox == null)
|
||||
{
|
||||
mAliasListNameComboBox = new ComboBox<>(mPlaylistManager.getAliasModel().aliasListNames());
|
||||
mAliasListNameComboBox = new ComboBox<>(mAliasModel.aliasListNames());
|
||||
mAliasListNameComboBox.getSelectionModel().selectedItemProperty()
|
||||
.addListener((ObservableValue<? extends String> observable, String oldValue, String newValue) ->
|
||||
{
|
||||
@@ -337,7 +334,7 @@ public class AliasConfigurationEditor extends SplitPane
|
||||
if(name != null && !name.isEmpty())
|
||||
{
|
||||
name = name.trim();
|
||||
mPlaylistManager.getAliasModel().addAliasList(name);
|
||||
mAliasModel.addAliasList(name);
|
||||
getAliasListNameComboBox().getSelectionModel().select(name);
|
||||
}
|
||||
});
|
||||
@@ -436,7 +433,7 @@ public class AliasConfigurationEditor extends SplitPane
|
||||
{
|
||||
if(mAliasFilteredList == null)
|
||||
{
|
||||
mAliasFilteredList = new FilteredList<>(mPlaylistManager.getAliasModel().aliasList(), getAliasPredicate());
|
||||
mAliasFilteredList = new FilteredList<>(mAliasModel.aliasList(), getAliasPredicate());
|
||||
}
|
||||
|
||||
return mAliasFilteredList;
|
||||
@@ -506,7 +503,7 @@ public class AliasConfigurationEditor extends SplitPane
|
||||
{
|
||||
Alias alias = new Alias("New Alias");
|
||||
alias.setAliasListName(getAliasListNameComboBox().getSelectionModel().getSelectedItem());
|
||||
mPlaylistManager.getAliasModel().addAlias(alias);
|
||||
mAliasModel.addAlias(alias);
|
||||
|
||||
//Queue a select alias action to allow table to update filter predicate and display the alias
|
||||
Platform.runLater(() ->
|
||||
@@ -544,7 +541,7 @@ public class AliasConfigurationEditor extends SplitPane
|
||||
if(result.get() == ButtonType.YES)
|
||||
{
|
||||
List<Alias> selectedAliases = new ArrayList<>(getAliasTableView().getSelectionModel().getSelectedItems());
|
||||
mPlaylistManager.getAliasModel().removeAliases(selectedAliases);
|
||||
mAliasModel.removeAliases(selectedAliases);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -563,7 +560,7 @@ public class AliasConfigurationEditor extends SplitPane
|
||||
{
|
||||
Alias original = getAliasTableView().getSelectionModel().getSelectedItem();
|
||||
Alias copy = AliasFactory.shallowCopyOf(original);
|
||||
mPlaylistManager.getAliasModel().addAlias(copy);
|
||||
mAliasModel.addAlias(copy);
|
||||
getAliasTableView().getSelectionModel().clearSelection();
|
||||
getAliasTableView().getSelectionModel().select(copy);
|
||||
getAliasTableView().scrollTo(copy);
|
||||
@@ -587,7 +584,7 @@ public class AliasConfigurationEditor extends SplitPane
|
||||
emptyItem.setDisable(true);
|
||||
mMoveToAliasButton.getItems().addAll(emptyItem, new SeparatorMenuItem());
|
||||
|
||||
List<String> aliasLists = mPlaylistManager.getAliasModel().getListNames();
|
||||
List<String> aliasLists = mAliasModel.getListNames();
|
||||
|
||||
for(String aliasList : aliasLists)
|
||||
{
|
||||
@@ -614,11 +611,11 @@ public class AliasConfigurationEditor extends SplitPane
|
||||
List<Alias> selectedAliases = new ArrayList<>(getAliasTableView().getSelectionModel().getSelectedItems());
|
||||
for(Alias selected : selectedAliases)
|
||||
{
|
||||
AliasList existing = mPlaylistManager.getAliasModel().getAliasList(selected.getAliasListName());
|
||||
AliasList existing = mAliasModel.getAliasList(selected.getAliasListName());
|
||||
existing.removeAlias(selected);
|
||||
|
||||
selected.setAliasListName(getText());
|
||||
AliasList moveToList = mPlaylistManager.getAliasModel().getAliasList(selected.getAliasListName());
|
||||
AliasList moveToList = mAliasModel.getAliasList(selected.getAliasListName());
|
||||
moveToList.addAlias(selected);
|
||||
}
|
||||
});
|
||||
@@ -830,7 +827,7 @@ public class AliasConfigurationEditor extends SplitPane
|
||||
|
||||
if(alias != null)
|
||||
{
|
||||
Icon icon = mPlaylistManager.getIconModel().getIcon(alias.getIconName());
|
||||
Icon icon = mIconModel.getIcon(alias.getIconName());
|
||||
|
||||
if(icon != null && icon.getFxImage() != null)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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,11 @@
|
||||
package io.github.dsheirer.gui.playlist.alias;
|
||||
|
||||
import io.github.dsheirer.alias.Alias;
|
||||
import io.github.dsheirer.alias.AliasModel;
|
||||
import io.github.dsheirer.alias.id.AliasID;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
import javafx.beans.InvalidationListener;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.control.Tab;
|
||||
import javafx.scene.control.TabPane;
|
||||
@@ -32,29 +34,49 @@ import javafx.scene.control.TabPane;
|
||||
*/
|
||||
public class AliasEditor extends TabPane
|
||||
{
|
||||
private PlaylistManager mPlaylistManager;
|
||||
private UserPreferences mUserPreferences;
|
||||
@Resource
|
||||
private AliasConfigurationEditor mAliasConfigurationEditor;
|
||||
@Resource
|
||||
private AliasModel mAliasModel;
|
||||
@Resource
|
||||
private AliasViewByIdentifierEditor mAliasViewByIdentifierEditor;
|
||||
@Resource
|
||||
private AliasViewByRecordingEditor mAliasViewByRecordingEditor;
|
||||
private Tab mAliasConfigurationTab;
|
||||
private Tab mAliasIdentifierTab;
|
||||
private Tab mAliasRecordingTab;
|
||||
private boolean mAliasListInvalidated = false;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param playlistManager for alias model access
|
||||
* @param userPreferences for settings
|
||||
*/
|
||||
public AliasEditor(PlaylistManager playlistManager, UserPreferences userPreferences)
|
||||
public AliasEditor()
|
||||
{
|
||||
mPlaylistManager = playlistManager;
|
||||
mUserPreferences = userPreferences;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
setPadding(new Insets(4,0,0,0));
|
||||
setTabClosingPolicy(TabPane.TabClosingPolicy.UNAVAILABLE);
|
||||
Tab viewByTab = new Tab("View By:");
|
||||
viewByTab.setDisable(true);
|
||||
getTabs().addAll(viewByTab, getAliasConfigurationTab(), getAliasIdentifierTab(), getAliasRecordingTab());
|
||||
|
||||
//Note if aliases change since we're using a static snapshot
|
||||
mAliasModel.aliasList().addListener((InvalidationListener)observable -> mAliasListInvalidated = true);
|
||||
|
||||
//Only update the alias list when this tab is selected to avoid many slow updates in the background
|
||||
getAliasIdentifierTab().selectedProperty().addListener(observable ->
|
||||
{
|
||||
if (mAliasListInvalidated)
|
||||
{
|
||||
getAliasViewByIdentifierEditor().updateList();
|
||||
mAliasListInvalidated = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,11 +123,6 @@ public class AliasEditor extends TabPane
|
||||
|
||||
private AliasConfigurationEditor getAliasConfigurationEditor()
|
||||
{
|
||||
if(mAliasConfigurationEditor == null)
|
||||
{
|
||||
mAliasConfigurationEditor = new AliasConfigurationEditor(mPlaylistManager, mUserPreferences);
|
||||
}
|
||||
|
||||
return mAliasConfigurationEditor;
|
||||
}
|
||||
|
||||
@@ -122,20 +139,20 @@ public class AliasEditor extends TabPane
|
||||
|
||||
private AliasViewByIdentifierEditor getAliasViewByIdentifierEditor()
|
||||
{
|
||||
if(mAliasViewByIdentifierEditor == null)
|
||||
{
|
||||
mAliasViewByIdentifierEditor = new AliasViewByIdentifierEditor(mPlaylistManager, getAliasIdentifierTab().selectedProperty());
|
||||
}
|
||||
|
||||
return mAliasViewByIdentifierEditor;
|
||||
}
|
||||
|
||||
private AliasViewByRecordingEditor getAliasViewByRecordingEditor()
|
||||
{
|
||||
return mAliasViewByRecordingEditor;
|
||||
}
|
||||
|
||||
private Tab getAliasRecordingTab()
|
||||
{
|
||||
if(mAliasRecordingTab == null)
|
||||
{
|
||||
mAliasRecordingTab = new Tab("Record");
|
||||
mAliasRecordingTab.setContent(new AliasViewByRecordingEditor(mPlaylistManager));
|
||||
mAliasRecordingTab.setContent(getAliasViewByRecordingEditor());
|
||||
}
|
||||
|
||||
return mAliasRecordingTab;
|
||||
|
||||
@@ -20,12 +20,12 @@
|
||||
package io.github.dsheirer.gui.playlist.alias;
|
||||
|
||||
import com.google.common.collect.Ordering;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import impl.org.controlsfx.autocompletion.AutoCompletionTextFieldBinding;
|
||||
import impl.org.controlsfx.autocompletion.SuggestionProvider;
|
||||
import io.github.dsheirer.alias.Alias;
|
||||
import io.github.dsheirer.alias.AliasFactory;
|
||||
import io.github.dsheirer.alias.AliasList;
|
||||
import io.github.dsheirer.alias.AliasModel;
|
||||
import io.github.dsheirer.alias.action.AliasAction;
|
||||
import io.github.dsheirer.alias.action.AliasActionType;
|
||||
import io.github.dsheirer.alias.action.beep.BeepAction;
|
||||
@@ -48,6 +48,7 @@ import io.github.dsheirer.alias.id.talkgroup.Talkgroup;
|
||||
import io.github.dsheirer.alias.id.talkgroup.TalkgroupFormatter;
|
||||
import io.github.dsheirer.alias.id.talkgroup.TalkgroupRange;
|
||||
import io.github.dsheirer.alias.id.tone.TonesID;
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastModel;
|
||||
import io.github.dsheirer.audio.broadcast.ConfiguredBroadcast;
|
||||
import io.github.dsheirer.eventbus.MyEventBus;
|
||||
import io.github.dsheirer.gui.playlist.Editor;
|
||||
@@ -58,11 +59,15 @@ import io.github.dsheirer.gui.playlist.alias.identifier.EmptyIdentifierEditor;
|
||||
import io.github.dsheirer.gui.playlist.alias.identifier.IdentifierEditor;
|
||||
import io.github.dsheirer.gui.playlist.alias.identifier.IdentifierEditorFactory;
|
||||
import io.github.dsheirer.icon.Icon;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.icon.IconModel;
|
||||
import io.github.dsheirer.preference.IPreferenceUpdateListener;
|
||||
import io.github.dsheirer.preference.PreferenceType;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.preference.identifier.IntegerFormat;
|
||||
import io.github.dsheirer.protocol.Protocol;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.PreDestroy;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -114,11 +119,17 @@ import org.slf4j.LoggerFactory;
|
||||
/**
|
||||
* Editor for configuring individual aliases
|
||||
*/
|
||||
public class AliasItemEditor extends Editor<Alias>
|
||||
public class AliasItemEditor extends Editor<Alias> implements IPreferenceUpdateListener
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger(AliasItemEditor.class);
|
||||
|
||||
private PlaylistManager mPlaylistManager;
|
||||
@Resource
|
||||
private AliasModel mAliasModel;
|
||||
@Resource
|
||||
private BroadcastModel mBroadcastModel;
|
||||
@Resource
|
||||
private IconModel mIconModel;
|
||||
@Resource
|
||||
private UserPreferences mUserPreferences;
|
||||
private EditorModificationListener mEditorModificationListener = new EditorModificationListener();
|
||||
private IdentifierEditorModificationListener mIdentifierEditorModificationListener = new IdentifierEditorModificationListener();
|
||||
@@ -161,15 +172,16 @@ public class AliasItemEditor extends Editor<Alias>
|
||||
private EmptyActionEditor mEmptyActionEditor = new EmptyActionEditor();
|
||||
private ActionEditor mActionEditor;
|
||||
|
||||
|
||||
public AliasItemEditor(PlaylistManager playlistManager, UserPreferences userPreferences)
|
||||
public AliasItemEditor()
|
||||
{
|
||||
mPlaylistManager = playlistManager;
|
||||
mUserPreferences = userPreferences;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
mUserPreferences.addUpdateListener(this);
|
||||
//Listen for changes to the stream configurations and refresh the stream lists
|
||||
mPlaylistManager.getBroadcastModel().getConfiguredBroadcasts()
|
||||
.addListener((ListChangeListener<ConfiguredBroadcast>)c -> updateStreamViews());
|
||||
mBroadcastModel.getConfiguredBroadcasts().addListener((ListChangeListener<ConfiguredBroadcast>)c -> updateStreamViews());
|
||||
|
||||
MyEventBus.getGlobalEventBus().register(this);
|
||||
|
||||
@@ -192,8 +204,13 @@ public class AliasItemEditor extends Editor<Alias>
|
||||
getChildren().add(hbox);
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void dispose()
|
||||
{
|
||||
mUserPreferences.removeUpdateListener(this);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@Override
|
||||
public void preferenceUpdated(PreferenceType preferenceType)
|
||||
{
|
||||
if(preferenceType == PreferenceType.TALKGROUP_FORMAT)
|
||||
@@ -251,7 +268,7 @@ public class AliasItemEditor extends Editor<Alias>
|
||||
String iconName = alias.getIconName();
|
||||
if(iconName != null)
|
||||
{
|
||||
icon = mPlaylistManager.getIconModel().getIcon(iconName);
|
||||
icon = mIconModel.getIcon(iconName);
|
||||
}
|
||||
getIconNodeComboBox().getSelectionModel().select(icon);
|
||||
|
||||
@@ -399,7 +416,7 @@ public class AliasItemEditor extends Editor<Alias>
|
||||
}
|
||||
}
|
||||
|
||||
AliasList aliasList = mPlaylistManager.getAliasModel().getAliasList(alias.getAliasListName());
|
||||
AliasList aliasList = mAliasModel.getAliasList(alias.getAliasListName());
|
||||
aliasList.updateAlias(alias);
|
||||
|
||||
//Reset the alias to refresh the editor.
|
||||
@@ -409,12 +426,6 @@ public class AliasItemEditor extends Editor<Alias>
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose()
|
||||
{
|
||||
MyEventBus.getGlobalEventBus().unregister(this);
|
||||
}
|
||||
|
||||
private VBox getTitledPanesBox()
|
||||
{
|
||||
if(mTitledPanesBox == null)
|
||||
@@ -819,7 +830,7 @@ public class AliasItemEditor extends Editor<Alias>
|
||||
|
||||
if(getItem() != null)
|
||||
{
|
||||
List<String> availableStreams = mPlaylistManager.getBroadcastModel().getBroadcastConfigurationNames();
|
||||
List<String> availableStreams = mBroadcastModel.getBroadcastConfigurationNames();
|
||||
|
||||
Set<BroadcastChannel> selectedChannels = getItem().getBroadcastChannels();
|
||||
|
||||
@@ -1088,7 +1099,7 @@ public class AliasItemEditor extends Editor<Alias>
|
||||
mIconNodeComboBox = new ComboBox<>();
|
||||
mIconNodeComboBox.setMaxWidth(Double.MAX_VALUE);
|
||||
mIconNodeComboBox.setDisable(true);
|
||||
mIconNodeComboBox.setItems(new SortedList(mPlaylistManager.getIconModel().iconsProperty(), Ordering.natural()));
|
||||
mIconNodeComboBox.setItems(new SortedList(mIconModel.iconsProperty(), Ordering.natural()));
|
||||
mIconNodeComboBox.setCellFactory(new IconCellFactory());
|
||||
mIconNodeComboBox.getSelectionModel().selectedItemProperty()
|
||||
.addListener((observable, oldValue, newValue) -> modifiedProperty().set(true));
|
||||
@@ -1103,14 +1114,14 @@ public class AliasItemEditor extends Editor<Alias>
|
||||
private void refreshAutoCompleteBindings()
|
||||
{
|
||||
getGroupSuggestionProvider().clearSuggestions();
|
||||
getGroupSuggestionProvider().addPossibleSuggestions(mPlaylistManager.getAliasModel().getGroupNames());
|
||||
getGroupSuggestionProvider().addPossibleSuggestions(mAliasModel.getGroupNames());
|
||||
}
|
||||
|
||||
private SuggestionProvider<String> getGroupSuggestionProvider()
|
||||
{
|
||||
if(mGroupSuggestionProvider == null)
|
||||
{
|
||||
mGroupSuggestionProvider = SuggestionProvider.create(mPlaylistManager.getAliasModel().getGroupNames());
|
||||
mGroupSuggestionProvider = SuggestionProvider.create(mAliasModel.getGroupNames());
|
||||
}
|
||||
|
||||
return mGroupSuggestionProvider;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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,10 +24,13 @@ import io.github.dsheirer.alias.AliasModel;
|
||||
import io.github.dsheirer.alias.id.AliasID;
|
||||
import io.github.dsheirer.alias.id.AliasIDType;
|
||||
import io.github.dsheirer.eventbus.MyEventBus;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import javafx.beans.InvalidationListener;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import javafx.beans.Observable;
|
||||
import javafx.beans.property.ReadOnlyBooleanProperty;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
import javafx.collections.FXCollections;
|
||||
@@ -50,35 +53,24 @@ import javafx.util.Callback;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class AliasViewByIdentifierEditor extends VBox
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger(AliasViewByIdentifierEditor.class);
|
||||
private PlaylistManager mPlaylistManager;
|
||||
@Resource
|
||||
private AliasModel mAliasModel;
|
||||
private ComboBox<String> mAliasListNameComboBox;
|
||||
private ComboBox<AliasIDType> mAliasIDTypeComboBox;
|
||||
private TableView<AliasAndIdentifier> mAliasAndIdentifierTableView;
|
||||
private TableColumn<AliasAndIdentifier,String> mIdentifierColumn;
|
||||
private Button mViewAliasButton;
|
||||
private boolean aliasListInvalidated;
|
||||
|
||||
public AliasViewByIdentifierEditor(PlaylistManager playlistManager, ReadOnlyBooleanProperty tabSelectedProperty)
|
||||
public AliasViewByIdentifierEditor()
|
||||
{
|
||||
aliasListInvalidated = false;
|
||||
mPlaylistManager = playlistManager;
|
||||
//Note if aliases change since we're using a static snapshot
|
||||
mPlaylistManager.getAliasModel().aliasList().addListener((InvalidationListener)observable -> aliasListInvalidated = true);
|
||||
|
||||
//Only update the list when this tab is selected to avoid many slow updates in the background
|
||||
tabSelectedProperty.addListener(observable -> {
|
||||
if (aliasListInvalidated)
|
||||
updateList();
|
||||
});
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
GridPane gridPane = new GridPane();
|
||||
gridPane.setPadding(new Insets(10,10,10,10));
|
||||
gridPane.setVgap(10);
|
||||
@@ -115,14 +107,14 @@ public class AliasViewByIdentifierEditor extends VBox
|
||||
updateList();
|
||||
}
|
||||
|
||||
private void updateList()
|
||||
public void updateList()
|
||||
{
|
||||
getAliasAndIdentifierTableView().getItems().clear();
|
||||
|
||||
String aliasList = getAliasListNameComboBox().getSelectionModel().getSelectedItem();
|
||||
AliasIDType type = getAliasIDTypeComboBox().getSelectionModel().getSelectedItem();
|
||||
|
||||
List<Alias> aliases = mPlaylistManager.getAliasModel().getAliases(aliasList, type);
|
||||
List<Alias> aliases = mAliasModel.getAliases(aliasList, type);
|
||||
|
||||
for(Alias alias: aliases)
|
||||
{
|
||||
@@ -136,8 +128,6 @@ public class AliasViewByIdentifierEditor extends VBox
|
||||
}
|
||||
|
||||
getAliasAndIdentifierTableView().getSortOrder().setAll(mIdentifierColumn);
|
||||
|
||||
aliasListInvalidated = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -230,8 +220,7 @@ public class AliasViewByIdentifierEditor extends VBox
|
||||
if(mAliasListNameComboBox == null)
|
||||
{
|
||||
Predicate<String> filterPredicate = s -> !s.contentEquals(AliasModel.NO_ALIAS_LIST);
|
||||
FilteredList<String> filteredChannelList =
|
||||
new FilteredList<>(mPlaylistManager.getAliasModel().aliasListNames(), filterPredicate);
|
||||
FilteredList<String> filteredChannelList = new FilteredList<>(mAliasModel.aliasListNames(), filterPredicate);
|
||||
mAliasListNameComboBox = new ComboBox<>(filteredChannelList);
|
||||
mAliasListNameComboBox.setPadding(new Insets(0,10,0,0));
|
||||
if(mAliasListNameComboBox.getItems().size() > 0)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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
|
||||
@@ -21,7 +21,11 @@ package io.github.dsheirer.gui.playlist.alias;
|
||||
|
||||
import io.github.dsheirer.alias.Alias;
|
||||
import io.github.dsheirer.alias.AliasModel;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import javafx.collections.transformation.FilteredList;
|
||||
import javafx.collections.transformation.SortedList;
|
||||
@@ -44,15 +48,11 @@ import org.controlsfx.control.textfield.TextFields;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class AliasViewByRecordingEditor extends VBox
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(AliasViewByRecordingEditor.class);
|
||||
|
||||
private PlaylistManager mPlaylistManager;
|
||||
@Resource
|
||||
private AliasModel mAliasModel;
|
||||
private ComboBox<String> mAliasListNameComboBox;
|
||||
private HBox mTopBox;
|
||||
private TextField mSearchField;
|
||||
@@ -67,10 +67,13 @@ public class AliasViewByRecordingEditor extends VBox
|
||||
private AvailablePredicate mNoRecordPredicate;
|
||||
private SelectedPredicate mRecordPredicate;
|
||||
|
||||
public AliasViewByRecordingEditor(PlaylistManager playlistManager)
|
||||
public AliasViewByRecordingEditor()
|
||||
{
|
||||
mPlaylistManager = playlistManager;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
VBox buttonBox = new VBox();
|
||||
buttonBox.setMaxHeight(Double.MAX_VALUE);
|
||||
buttonBox.setAlignment(Pos.CENTER);
|
||||
@@ -105,8 +108,7 @@ public class AliasViewByRecordingEditor extends VBox
|
||||
if(mAliasListNameComboBox == null)
|
||||
{
|
||||
Predicate<String> filterPredicate = s -> !s.contentEquals(AliasModel.NO_ALIAS_LIST);
|
||||
FilteredList<String> filteredChannelList =
|
||||
new FilteredList<>(mPlaylistManager.getAliasModel().aliasListNames(), filterPredicate);
|
||||
FilteredList<String> filteredChannelList = new FilteredList<>(mAliasModel.aliasListNames(), filterPredicate);
|
||||
mAliasListNameComboBox = new ComboBox<>(filteredChannelList);
|
||||
mAliasListNameComboBox.setPadding(new Insets(0,10,0,0));
|
||||
mAliasListNameComboBox.getSelectionModel().selectedItemProperty()
|
||||
@@ -126,8 +128,7 @@ public class AliasViewByRecordingEditor extends VBox
|
||||
{
|
||||
if(mNoRecordFilteredList == null)
|
||||
{
|
||||
mNoRecordFilteredList = new FilteredList<>(mPlaylistManager.getAliasModel().aliasList(),
|
||||
getNoRecordPredicate());
|
||||
mNoRecordFilteredList = new FilteredList<>(mAliasModel.aliasList(), getNoRecordPredicate());
|
||||
}
|
||||
|
||||
return mNoRecordFilteredList;
|
||||
@@ -137,8 +138,7 @@ public class AliasViewByRecordingEditor extends VBox
|
||||
{
|
||||
if(mRecordFilteredList == null)
|
||||
{
|
||||
mRecordFilteredList = new FilteredList<>(mPlaylistManager.getAliasModel().aliasList(),
|
||||
getRecordPredicate());
|
||||
mRecordFilteredList = new FilteredList<>(mAliasModel.aliasList(), getRecordPredicate());
|
||||
}
|
||||
|
||||
return mRecordFilteredList;
|
||||
|
||||
@@ -32,14 +32,12 @@ import io.github.dsheirer.module.decode.config.DecodeConfiguration;
|
||||
import io.github.dsheirer.module.decode.nbfm.DecodeConfigNBFM;
|
||||
import io.github.dsheirer.module.log.EventLogType;
|
||||
import io.github.dsheirer.module.log.config.EventLogConfiguration;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.preference.identifier.IntegerFormat;
|
||||
import io.github.dsheirer.protocol.Protocol;
|
||||
import io.github.dsheirer.record.RecorderType;
|
||||
import io.github.dsheirer.record.config.RecordConfiguration;
|
||||
import io.github.dsheirer.source.config.SourceConfiguration;
|
||||
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
@@ -87,14 +85,15 @@ public class AMConfigurationEditor extends ChannelConfigurationEditor
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param playlistManager for playlists
|
||||
* @param tunerManager for tuners
|
||||
* @param userPreferences for preferences
|
||||
*/
|
||||
public AMConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
||||
UserPreferences userPreferences, IFilterProcessor filterProcessor)
|
||||
public AMConfigurationEditor()
|
||||
{
|
||||
super(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
super.postConstruct();
|
||||
getTitledPanesBox().getChildren().add(getSourcePane());
|
||||
getTitledPanesBox().getChildren().add(getDecoderPane());
|
||||
getTitledPanesBox().getChildren().add(getEventLogPane());
|
||||
|
||||
@@ -22,6 +22,7 @@ package io.github.dsheirer.gui.playlist.channel;
|
||||
import io.github.dsheirer.alias.AliasModel;
|
||||
import io.github.dsheirer.controller.channel.Channel;
|
||||
import io.github.dsheirer.controller.channel.ChannelException;
|
||||
import io.github.dsheirer.controller.channel.ChannelProcessingManager;
|
||||
import io.github.dsheirer.eventbus.MyEventBus;
|
||||
import io.github.dsheirer.gui.control.MaxLengthUnaryOperator;
|
||||
import io.github.dsheirer.gui.playlist.Editor;
|
||||
@@ -31,13 +32,13 @@ import io.github.dsheirer.module.decode.DecoderType;
|
||||
import io.github.dsheirer.module.decode.config.AuxDecodeConfiguration;
|
||||
import io.github.dsheirer.module.decode.config.DecodeConfiguration;
|
||||
import io.github.dsheirer.module.log.config.EventLogConfiguration;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.record.config.RecordConfiguration;
|
||||
import io.github.dsheirer.source.config.SourceConfigTuner;
|
||||
import io.github.dsheirer.source.config.SourceConfiguration;
|
||||
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||
import io.github.dsheirer.util.ThreadPool;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
import javafx.application.Platform;
|
||||
@@ -78,8 +79,13 @@ public abstract class ChannelConfigurationEditor extends Editor<Channel>
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(ChannelConfigurationEditor.class);
|
||||
|
||||
private PlaylistManager mPlaylistManager;
|
||||
@Resource
|
||||
private AliasModel mAliasModel;
|
||||
@Resource
|
||||
private ChannelProcessingManager mChannelProcessingManager;
|
||||
@Resource
|
||||
protected TunerManager mTunerManager;
|
||||
@Resource
|
||||
protected UserPreferences mUserPreferences;
|
||||
protected EditorModificationListener mEditorModificationListener = new EditorModificationListener();
|
||||
private Button mPlayButton;
|
||||
@@ -103,20 +109,20 @@ public abstract class ChannelConfigurationEditor extends Editor<Channel>
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param playlistManager for playlists
|
||||
* @param tunerManager for tuners
|
||||
* @param userPreferences for preferences
|
||||
*/
|
||||
public ChannelConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
||||
UserPreferences userPreferences, IFilterProcessor filterProcessor)
|
||||
public ChannelConfigurationEditor()
|
||||
{
|
||||
mPlaylistManager = playlistManager;
|
||||
mTunerManager = tunerManager;
|
||||
mUserPreferences = userPreferences;
|
||||
mFilterProcessor = filterProcessor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Spring post-construct setup that is common for all sub-class implementations.
|
||||
*
|
||||
* Note: this method is not annotated with @PostConstruct because the subclass method would mask it. So, we
|
||||
* invoke this method from the subclass.
|
||||
*/
|
||||
public void postConstruct()
|
||||
{
|
||||
setMaxWidth(Double.MAX_VALUE);
|
||||
|
||||
HBox hbox = new HBox();
|
||||
hbox.setSpacing(10);
|
||||
hbox.setPadding(new Insets(10,10,10,10));
|
||||
@@ -125,16 +131,16 @@ public abstract class ChannelConfigurationEditor extends Editor<Channel>
|
||||
HBox.setHgrow(getButtonBox(), Priority.NEVER);
|
||||
hbox.getChildren().addAll(getTextFieldPane(), getButtonBox());
|
||||
VBox.setVgrow(getTitledPanesScrollPane(), Priority.ALWAYS);
|
||||
|
||||
getChildren().addAll(hbox, getTitledPanesScrollPane());
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides subclass access to the playlist manager and related components
|
||||
* Sets the filter processor to be controlled by this instance
|
||||
* @param filterProcessor to be controlled.
|
||||
*/
|
||||
protected PlaylistManager getPlaylistManager()
|
||||
public void setFilterProcessor(IFilterProcessor filterProcessor)
|
||||
{
|
||||
return mPlaylistManager;
|
||||
mFilterProcessor = filterProcessor;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -181,7 +187,7 @@ public abstract class ChannelConfigurationEditor extends Editor<Channel>
|
||||
{
|
||||
if(!getAliasListComboBox().getItems().contains(aliasListName))
|
||||
{
|
||||
mPlaylistManager.getAliasModel().addAliasList(aliasListName);
|
||||
mAliasModel.addAliasList(aliasListName);
|
||||
}
|
||||
|
||||
getAliasListComboBox().getSelectionModel().select(aliasListName);
|
||||
@@ -370,7 +376,7 @@ public abstract class ChannelConfigurationEditor extends Editor<Channel>
|
||||
ThreadPool.CACHED.execute(() -> {
|
||||
try
|
||||
{
|
||||
mPlaylistManager.getChannelProcessingManager().start(getItem());
|
||||
mChannelProcessingManager.start(getItem());
|
||||
}
|
||||
catch(ChannelException ce)
|
||||
{
|
||||
@@ -391,7 +397,7 @@ public abstract class ChannelConfigurationEditor extends Editor<Channel>
|
||||
ThreadPool.CACHED.execute(() -> {
|
||||
try
|
||||
{
|
||||
mPlaylistManager.getChannelProcessingManager().stop(getItem());
|
||||
mChannelProcessingManager.stop(getItem());
|
||||
}
|
||||
catch(ChannelException ce)
|
||||
{
|
||||
@@ -623,7 +629,7 @@ public abstract class ChannelConfigurationEditor extends Editor<Channel>
|
||||
{
|
||||
Predicate<String> filterPredicate = s -> !s.contentEquals(AliasModel.NO_ALIAS_LIST);
|
||||
FilteredList<String> filteredChannelList =
|
||||
new FilteredList<>(mPlaylistManager.getAliasModel().aliasListNames(), filterPredicate);
|
||||
new FilteredList<>(mAliasModel.aliasListNames(), filterPredicate);
|
||||
mAliasListComboBox = new ComboBox<>(filteredChannelList);
|
||||
mAliasListComboBox.setPrefWidth(150);
|
||||
mAliasListComboBox.setDisable(true);
|
||||
@@ -659,7 +665,7 @@ public abstract class ChannelConfigurationEditor extends Editor<Channel>
|
||||
if(name != null && !name.isEmpty())
|
||||
{
|
||||
name = name.trim();
|
||||
mPlaylistManager.getAliasModel().addAliasList(name);
|
||||
mAliasModel.addAliasList(name);
|
||||
getAliasListComboBox().getSelectionModel().select(name);
|
||||
}
|
||||
});
|
||||
@@ -713,8 +719,8 @@ public abstract class ChannelConfigurationEditor extends Editor<Channel>
|
||||
{
|
||||
try
|
||||
{
|
||||
mPlaylistManager.getChannelProcessingManager().stop(getItem());
|
||||
mPlaylistManager.getChannelProcessingManager().start(getItem());
|
||||
mChannelProcessingManager.stop(getItem());
|
||||
mChannelProcessingManager.start(getItem());
|
||||
}
|
||||
catch(ChannelException se)
|
||||
{
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.gui.playlist.channel;
|
||||
|
||||
import io.github.dsheirer.module.decode.DecoderType;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Provides access to channel configuration editors for various decoder types.
|
||||
*/
|
||||
public class ChannelConfigurationEditorFactory
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(ChannelConfigurationEditorFactory.class);
|
||||
private static List<DecoderType> mLoggedUnrecognizedTypes = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Constructs an editor for the specified decoder type
|
||||
* @param decoderType to create
|
||||
* @param playlistManager for the editor
|
||||
* @param tunerManager for tuners
|
||||
* @param userPreferences for preferences
|
||||
* @param filterProcessor to be notified to clear and restore any applied filters.
|
||||
* @return constructed editor
|
||||
*/
|
||||
public static ChannelConfigurationEditor getEditor(DecoderType decoderType, PlaylistManager playlistManager,
|
||||
TunerManager tunerManager, UserPreferences userPreferences,
|
||||
IFilterProcessor filterProcessor)
|
||||
{
|
||||
switch(decoderType)
|
||||
{
|
||||
case AM:
|
||||
return new AMConfigurationEditor(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||
case DMR:
|
||||
return new DMRConfigurationEditor(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||
case NBFM:
|
||||
return new NBFMConfigurationEditor(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||
case LTR_NET:
|
||||
return new LTRNetConfigurationEditor(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||
case LTR:
|
||||
return new LTRConfigurationEditor(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||
case MPT1327:
|
||||
return new MPT1327ConfigurationEditor(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||
case PASSPORT:
|
||||
return new PassportConfigurationEditor(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||
case P25_PHASE1:
|
||||
return new P25P1ConfigurationEditor(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||
case P25_PHASE2:
|
||||
return new P25P2ConfigurationEditor(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||
default:
|
||||
if(decoderType != null && !mLoggedUnrecognizedTypes.contains(decoderType))
|
||||
{
|
||||
mLog.warn("Can't create channel configuration editor - unrecognized decoder type: " + decoderType);
|
||||
mLoggedUnrecognizedTypes.add(decoderType);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,11 +21,12 @@ package io.github.dsheirer.gui.playlist.channel;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import io.github.dsheirer.controller.channel.Channel;
|
||||
import io.github.dsheirer.controller.channel.ChannelModel;
|
||||
import io.github.dsheirer.controller.channel.ChannelProcessingManager;
|
||||
import io.github.dsheirer.module.decode.DecoderFactory;
|
||||
import io.github.dsheirer.module.decode.DecoderType;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -75,9 +76,13 @@ import org.slf4j.LoggerFactory;
|
||||
public class ChannelEditor extends SplitPane implements IFilterProcessor
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(ChannelEditor.class);
|
||||
private PlaylistManager mPlaylistManager;
|
||||
private TunerManager mTunerManager;
|
||||
private UserPreferences mUserPreferences;
|
||||
@Resource
|
||||
private ChannelModel mChannelModel;
|
||||
@Resource
|
||||
private ChannelProcessingManager mChannelProcessingManager;
|
||||
@Resource
|
||||
private List<ChannelConfigurationEditor> mChannelConfigurationEditors;
|
||||
|
||||
private TableView<Channel> mChannelTableView;
|
||||
private Label mPlaceholderLabel;
|
||||
private MenuButton mNewButton;
|
||||
@@ -91,22 +96,32 @@ public class ChannelEditor extends SplitPane implements IFilterProcessor
|
||||
private ToggleButton mAutoStartToggleButton;
|
||||
private ToggleButton mPlayingToggleButton;
|
||||
private ChannelConfigurationEditor mChannelConfigurationEditor;
|
||||
private UnknownConfigurationEditor mUnknownConfigurationEditor;
|
||||
private ChannelConfigurationEditor mUnknownConfigurationEditor;
|
||||
private Map<DecoderType,ChannelConfigurationEditor> mChannelConfigurationEditorMap = new HashMap();
|
||||
private FilteredList<Channel> mChannelFilteredList;
|
||||
private ChannelListFilter mChannelListFilter = new ChannelListFilter();
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param playlistManager containing playlists and channel configurations
|
||||
*/
|
||||
public ChannelEditor(PlaylistManager playlistManager, TunerManager tunerManager, UserPreferences userPreferences)
|
||||
public ChannelEditor()
|
||||
{
|
||||
mPlaylistManager = playlistManager;
|
||||
mTunerManager = tunerManager;
|
||||
mUserPreferences = userPreferences;
|
||||
mUnknownConfigurationEditor = new UnknownConfigurationEditor(mPlaylistManager, mTunerManager,
|
||||
userPreferences, this);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
//Spring instantiates all editors so place them into a lookup map
|
||||
for(ChannelConfigurationEditor editor: mChannelConfigurationEditors)
|
||||
{
|
||||
mChannelConfigurationEditorMap.put(editor.getDecoderType(), editor);
|
||||
editor.setFilterProcessor(this);
|
||||
|
||||
if(editor instanceof UnknownConfigurationEditor unknown)
|
||||
{
|
||||
mUnknownConfigurationEditor = unknown;
|
||||
}
|
||||
}
|
||||
|
||||
HBox channelsBox = new HBox();
|
||||
channelsBox.setSpacing(10.0);
|
||||
@@ -202,17 +217,12 @@ public class ChannelEditor extends SplitPane implements IFilterProcessor
|
||||
|
||||
if(editor == null)
|
||||
{
|
||||
editor = ChannelConfigurationEditorFactory.getEditor(channelDecoderType, mPlaylistManager,
|
||||
mTunerManager, mUserPreferences, this);
|
||||
mLog.warn("Unable to find channel configuration editor for " + channelDecoderType);
|
||||
|
||||
if(editor != null)
|
||||
for(Map.Entry<DecoderType,ChannelConfigurationEditor> entry: mChannelConfigurationEditorMap.entrySet())
|
||||
{
|
||||
mChannelConfigurationEditorMap.put(channelDecoderType, editor);
|
||||
System.out.println("Type: " + entry.getKey() + " Editor: " + entry.getValue().getClass());
|
||||
}
|
||||
}
|
||||
|
||||
if(editor == null)
|
||||
{
|
||||
editor = mUnknownConfigurationEditor;
|
||||
}
|
||||
|
||||
@@ -228,7 +238,7 @@ public class ChannelEditor extends SplitPane implements IFilterProcessor
|
||||
{
|
||||
Channel channel = new Channel();
|
||||
channel.setDecodeConfiguration(DecoderFactory.getDecodeConfiguration(decoderType));
|
||||
mPlaylistManager.getChannelModel().addChannel(channel);
|
||||
mChannelModel.addChannel(channel);
|
||||
getChannelTableView().getSelectionModel().select(channel);
|
||||
getChannelTableView().scrollTo(channel);
|
||||
}
|
||||
@@ -498,7 +508,7 @@ public class ChannelEditor extends SplitPane implements IFilterProcessor
|
||||
mChannelTableView.setPlaceholder(getPlaceholderLabel());
|
||||
|
||||
//Sorting and filtering for the table
|
||||
mChannelFilteredList = new FilteredList<>(mPlaylistManager.getChannelModel().channelList(), mChannelListFilter);
|
||||
mChannelFilteredList = new FilteredList<>(mChannelModel.channelList(), mChannelListFilter);
|
||||
SortedList<Channel> sortedList = new SortedList<>(mChannelFilteredList);
|
||||
sortedList.comparatorProperty().bind(mChannelTableView.comparatorProperty());
|
||||
mChannelTableView.setItems(sortedList);
|
||||
@@ -585,7 +595,7 @@ public class ChannelEditor extends SplitPane implements IFilterProcessor
|
||||
{
|
||||
try
|
||||
{
|
||||
mPlaylistManager.getChannelProcessingManager().stop(selected);
|
||||
mChannelProcessingManager.stop(selected);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
@@ -593,7 +603,7 @@ public class ChannelEditor extends SplitPane implements IFilterProcessor
|
||||
}
|
||||
}
|
||||
|
||||
mPlaylistManager.getChannelModel().removeChannel(selected);
|
||||
mChannelModel.removeChannel(selected);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -612,7 +622,7 @@ public class ChannelEditor extends SplitPane implements IFilterProcessor
|
||||
mCloneButton.setOnAction(event -> {
|
||||
Channel selected = getChannelTableView().getSelectionModel().getSelectedItem();
|
||||
Channel copy = selected.copyOf();
|
||||
mPlaylistManager.getChannelModel().addChannel(copy);
|
||||
mChannelModel.addChannel(copy);
|
||||
getChannelTableView().getSelectionModel().select(copy);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -32,12 +32,10 @@ import io.github.dsheirer.module.decode.dmr.DecodeConfigDMR;
|
||||
import io.github.dsheirer.module.decode.dmr.channel.TimeslotFrequency;
|
||||
import io.github.dsheirer.module.log.EventLogType;
|
||||
import io.github.dsheirer.module.log.config.EventLogConfiguration;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.record.RecorderType;
|
||||
import io.github.dsheirer.record.config.RecordConfiguration;
|
||||
import io.github.dsheirer.source.config.SourceConfiguration;
|
||||
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
@@ -94,14 +92,15 @@ public class DMRConfigurationEditor extends ChannelConfigurationEditor
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param playlistManager for playlists
|
||||
* @param tunerManager for tuners
|
||||
* @param userPreferences for preferences
|
||||
*/
|
||||
public DMRConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
||||
UserPreferences userPreferences, IFilterProcessor filterProcessor)
|
||||
public DMRConfigurationEditor()
|
||||
{
|
||||
super(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
super.postConstruct();
|
||||
getTitledPanesBox().getChildren().add(getSourcePane());
|
||||
getTitledPanesBox().getChildren().add(getDecoderPane());
|
||||
getTitledPanesBox().getChildren().add(getEventLogPane());
|
||||
|
||||
@@ -31,12 +31,10 @@ import io.github.dsheirer.module.decode.config.DecodeConfiguration;
|
||||
import io.github.dsheirer.module.decode.ltrstandard.DecodeConfigLTRStandard;
|
||||
import io.github.dsheirer.module.log.EventLogType;
|
||||
import io.github.dsheirer.module.log.config.EventLogConfiguration;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.record.RecorderType;
|
||||
import io.github.dsheirer.record.config.RecordConfiguration;
|
||||
import io.github.dsheirer.source.config.SourceConfiguration;
|
||||
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javafx.geometry.HPos;
|
||||
@@ -71,14 +69,15 @@ public class LTRConfigurationEditor extends ChannelConfigurationEditor
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param playlistManager for playlists
|
||||
* @param tunerManager for tuners
|
||||
* @param userPreferences for preferences
|
||||
*/
|
||||
public LTRConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
||||
UserPreferences userPreferences, IFilterProcessor filterProcessor)
|
||||
public LTRConfigurationEditor()
|
||||
{
|
||||
super(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
super.postConstruct();
|
||||
getTitledPanesBox().getChildren().add(getSourcePane());
|
||||
getTitledPanesBox().getChildren().add(getDecoderPane());
|
||||
getTitledPanesBox().getChildren().add(getAuxDecoderPane());
|
||||
|
||||
@@ -31,12 +31,10 @@ import io.github.dsheirer.module.decode.config.DecodeConfiguration;
|
||||
import io.github.dsheirer.module.decode.ltrnet.DecodeConfigLTRNet;
|
||||
import io.github.dsheirer.module.log.EventLogType;
|
||||
import io.github.dsheirer.module.log.config.EventLogConfiguration;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.record.RecorderType;
|
||||
import io.github.dsheirer.record.config.RecordConfiguration;
|
||||
import io.github.dsheirer.source.config.SourceConfiguration;
|
||||
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javafx.geometry.HPos;
|
||||
@@ -71,14 +69,15 @@ public class LTRNetConfigurationEditor extends ChannelConfigurationEditor
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param playlistManager for playlists
|
||||
* @param tunerManager for tuners
|
||||
* @param userPreferences for preferences
|
||||
*/
|
||||
public LTRNetConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
||||
UserPreferences userPreferences, IFilterProcessor filterProcessor)
|
||||
public LTRNetConfigurationEditor()
|
||||
{
|
||||
super(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
super.postConstruct();
|
||||
getTitledPanesBox().getChildren().add(getSourcePane());
|
||||
getTitledPanesBox().getChildren().add(getDecoderPane());
|
||||
getTitledPanesBox().getChildren().add(getAuxDecoderPane());
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
package io.github.dsheirer.gui.playlist.channel;
|
||||
|
||||
import io.github.dsheirer.controller.channel.map.ChannelMap;
|
||||
import io.github.dsheirer.controller.channel.map.ChannelMapModel;
|
||||
import io.github.dsheirer.eventbus.MyEventBus;
|
||||
import io.github.dsheirer.gui.playlist.channelMap.ViewChannelMapEditorRequest;
|
||||
import io.github.dsheirer.gui.playlist.eventlog.EventLogConfigurationEditor;
|
||||
@@ -32,12 +33,11 @@ import io.github.dsheirer.module.decode.config.DecodeConfiguration;
|
||||
import io.github.dsheirer.module.decode.mpt1327.DecodeConfigMPT1327;
|
||||
import io.github.dsheirer.module.log.EventLogType;
|
||||
import io.github.dsheirer.module.log.config.EventLogConfiguration;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.record.RecorderType;
|
||||
import io.github.dsheirer.record.config.RecordConfiguration;
|
||||
import io.github.dsheirer.source.config.SourceConfiguration;
|
||||
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javafx.event.ActionEvent;
|
||||
@@ -67,6 +67,8 @@ import static io.github.dsheirer.module.decode.config.DecodeConfiguration.CALL_T
|
||||
public class MPT1327ConfigurationEditor extends ChannelConfigurationEditor
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(MPT1327ConfigurationEditor.class);
|
||||
@Resource
|
||||
private ChannelMapModel mChannelMapModel;
|
||||
private TitledPane mDecoderPane;
|
||||
private TitledPane mEventLogPane;
|
||||
private TitledPane mRecordPane;
|
||||
@@ -81,14 +83,15 @@ public class MPT1327ConfigurationEditor extends ChannelConfigurationEditor
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param playlistManager for playlists
|
||||
* @param tunerManager for tuners
|
||||
* @param userPreferences for preferences
|
||||
*/
|
||||
public MPT1327ConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
||||
UserPreferences userPreferences, IFilterProcessor filterProcessor)
|
||||
public MPT1327ConfigurationEditor()
|
||||
{
|
||||
super(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
super.postConstruct();
|
||||
getTitledPanesBox().getChildren().add(getSourcePane());
|
||||
getTitledPanesBox().getChildren().add(getDecoderPane());
|
||||
getTitledPanesBox().getChildren().add(getEventLogPane());
|
||||
@@ -251,7 +254,7 @@ public class MPT1327ConfigurationEditor extends ChannelConfigurationEditor
|
||||
mChannelMapComboBox.setMaxWidth(Double.MAX_VALUE);
|
||||
mChannelMapComboBox.setDisable(true);
|
||||
mChannelMapComboBox.setTooltip(new Tooltip("Select a channel map to use for this system"));
|
||||
mChannelMapComboBox.setItems(getPlaylistManager().getChannelMapModel().getChannelMaps());
|
||||
mChannelMapComboBox.setItems(mChannelMapModel.getChannelMaps());
|
||||
mChannelMapComboBox.setDisable(true);
|
||||
mChannelMapComboBox.getSelectionModel().selectedItemProperty()
|
||||
.addListener((observable, oldValue, newValue) -> modifiedProperty().set(true));
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
package io.github.dsheirer.gui.playlist.channel;
|
||||
|
||||
import io.github.dsheirer.gui.control.DbPowerMeter;
|
||||
import io.github.dsheirer.gui.control.HexFormatter;
|
||||
import io.github.dsheirer.gui.control.IntegerFormatter;
|
||||
import io.github.dsheirer.gui.playlist.decoder.AuxDecoderConfigurationEditor;
|
||||
import io.github.dsheirer.gui.playlist.eventlog.EventLogConfigurationEditor;
|
||||
@@ -32,14 +31,12 @@ import io.github.dsheirer.module.decode.config.DecodeConfiguration;
|
||||
import io.github.dsheirer.module.decode.nbfm.DecodeConfigNBFM;
|
||||
import io.github.dsheirer.module.log.EventLogType;
|
||||
import io.github.dsheirer.module.log.config.EventLogConfiguration;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.preference.identifier.IntegerFormat;
|
||||
import io.github.dsheirer.protocol.Protocol;
|
||||
import io.github.dsheirer.record.RecorderType;
|
||||
import io.github.dsheirer.record.config.RecordConfiguration;
|
||||
import io.github.dsheirer.source.config.SourceConfiguration;
|
||||
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
@@ -84,18 +81,18 @@ public class NBFMConfigurationEditor extends ChannelConfigurationEditor
|
||||
private EventLogConfigurationEditor mEventLogConfigurationEditor;
|
||||
private final TalkgroupValueChangeListener mTalkgroupValueChangeListener = new TalkgroupValueChangeListener();
|
||||
private final IntegerFormatter mDecimalFormatter = new IntegerFormatter(1, 65535);
|
||||
private final HexFormatter mHexFormatter = new HexFormatter(1, 65535);
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param playlistManager for playlists
|
||||
* @param tunerManager for tuners
|
||||
* @param userPreferences for preferences
|
||||
*/
|
||||
public NBFMConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
||||
UserPreferences userPreferences, IFilterProcessor filterProcessor)
|
||||
public NBFMConfigurationEditor()
|
||||
{
|
||||
super(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
super.postConstruct();
|
||||
getTitledPanesBox().getChildren().add(getSourcePane());
|
||||
getTitledPanesBox().getChildren().add(getDecoderPane());
|
||||
getTitledPanesBox().getChildren().add(getAuxDecoderPane());
|
||||
|
||||
@@ -30,12 +30,10 @@ import io.github.dsheirer.module.decode.p25.phase1.DecodeConfigP25Phase1;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.P25P1Decoder;
|
||||
import io.github.dsheirer.module.log.EventLogType;
|
||||
import io.github.dsheirer.module.log.config.EventLogConfiguration;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.record.RecorderType;
|
||||
import io.github.dsheirer.record.config.RecordConfiguration;
|
||||
import io.github.dsheirer.source.config.SourceConfiguration;
|
||||
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
@@ -77,14 +75,15 @@ public class P25P1ConfigurationEditor extends ChannelConfigurationEditor
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param playlistManager for playlists
|
||||
* @param tunerManager for tuners
|
||||
* @param userPreferences for preferences
|
||||
*/
|
||||
public P25P1ConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
||||
UserPreferences userPreferences, IFilterProcessor filterProcessor)
|
||||
public P25P1ConfigurationEditor()
|
||||
{
|
||||
super(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
super.postConstruct();
|
||||
getTitledPanesBox().getChildren().add(getSourcePane());
|
||||
getTitledPanesBox().getChildren().add(getDecoderPane());
|
||||
getTitledPanesBox().getChildren().add(getEventLogPane());
|
||||
|
||||
@@ -31,12 +31,10 @@ import io.github.dsheirer.module.decode.p25.phase2.DecodeConfigP25Phase2;
|
||||
import io.github.dsheirer.module.decode.p25.phase2.enumeration.ScrambleParameters;
|
||||
import io.github.dsheirer.module.log.EventLogType;
|
||||
import io.github.dsheirer.module.log.config.EventLogConfiguration;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.record.RecorderType;
|
||||
import io.github.dsheirer.record.config.RecordConfiguration;
|
||||
import io.github.dsheirer.source.config.SourceConfiguration;
|
||||
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javafx.geometry.HPos;
|
||||
@@ -67,13 +65,15 @@ public class P25P2ConfigurationEditor extends ChannelConfigurationEditor
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param playlistManager
|
||||
* @param userPreferences
|
||||
*/
|
||||
public P25P2ConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
||||
UserPreferences userPreferences, IFilterProcessor filterProcessor)
|
||||
public P25P2ConfigurationEditor()
|
||||
{
|
||||
super(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
super.postConstruct();
|
||||
getTitledPanesBox().getChildren().add(getSourcePane());
|
||||
getTitledPanesBox().getChildren().add(getDecoderPane());
|
||||
getTitledPanesBox().getChildren().add(getEventLogPane());
|
||||
|
||||
@@ -30,12 +30,10 @@ import io.github.dsheirer.module.decode.config.DecodeConfiguration;
|
||||
import io.github.dsheirer.module.decode.passport.DecodeConfigPassport;
|
||||
import io.github.dsheirer.module.log.EventLogType;
|
||||
import io.github.dsheirer.module.log.config.EventLogConfiguration;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.record.RecorderType;
|
||||
import io.github.dsheirer.record.config.RecordConfiguration;
|
||||
import io.github.dsheirer.source.config.SourceConfiguration;
|
||||
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javafx.geometry.Insets;
|
||||
@@ -63,13 +61,15 @@ public class PassportConfigurationEditor extends ChannelConfigurationEditor
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param playlistManager
|
||||
* @param userPreferences
|
||||
*/
|
||||
public PassportConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
||||
UserPreferences userPreferences, IFilterProcessor filterProcessor)
|
||||
public PassportConfigurationEditor()
|
||||
{
|
||||
super(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
super.postConstruct();
|
||||
getTitledPanesBox().getChildren().add(getSourcePane());
|
||||
getTitledPanesBox().getChildren().add(getDecoderPane());
|
||||
getTitledPanesBox().getChildren().add(getAuxDecoderPane());
|
||||
|
||||
@@ -23,11 +23,9 @@ import io.github.dsheirer.module.decode.DecoderType;
|
||||
import io.github.dsheirer.module.decode.config.AuxDecodeConfiguration;
|
||||
import io.github.dsheirer.module.decode.config.DecodeConfiguration;
|
||||
import io.github.dsheirer.module.log.config.EventLogConfiguration;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.record.config.RecordConfiguration;
|
||||
import io.github.dsheirer.source.config.SourceConfiguration;
|
||||
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import javafx.scene.control.TitledPane;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -42,12 +40,15 @@ public class UnknownConfigurationEditor extends ChannelConfigurationEditor
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param aliasModel
|
||||
*/
|
||||
public UnknownConfigurationEditor(PlaylistManager playlistManager, TunerManager tunerManager,
|
||||
UserPreferences userPreferences, IFilterProcessor filterProcessor)
|
||||
public UnknownConfigurationEditor()
|
||||
{
|
||||
super(playlistManager, tunerManager, userPreferences, filterProcessor);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
super.postConstruct();
|
||||
getTitledPanesBox().getChildren().add(getDecoderPane());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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,6 +24,9 @@ import io.github.dsheirer.controller.channel.map.ChannelMapModel;
|
||||
import io.github.dsheirer.controller.channel.map.ChannelRange;
|
||||
import io.github.dsheirer.gui.control.IntegerTextField;
|
||||
import io.github.dsheirer.gui.playlist.Editor;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.Optional;
|
||||
import javafx.application.Platform;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
@@ -52,16 +55,14 @@ import javafx.scene.layout.VBox;
|
||||
import javafx.scene.text.Text;
|
||||
import javafx.util.Callback;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* JavaFX editor for channel maps
|
||||
*/
|
||||
public class ChannelMapEditor extends SplitPane
|
||||
{
|
||||
private static final String COPY_NAME = " (copy)";
|
||||
@Resource
|
||||
private ChannelMapModel mChannelMapModel;
|
||||
private SplitPane mSplitPane;
|
||||
private MapEditor mMapEditor;
|
||||
private HBox mChannelMapManagerBox;
|
||||
private VBox mMapButtonsBox;
|
||||
@@ -78,12 +79,14 @@ public class ChannelMapEditor extends SplitPane
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
*
|
||||
* @param channelMapModel for accessing channel maps
|
||||
*/
|
||||
public ChannelMapEditor(ChannelMapModel channelMapModel)
|
||||
public ChannelMapEditor()
|
||||
{
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
mChannelMapModel = channelMapModel;
|
||||
setOrientation(Orientation.VERTICAL);
|
||||
getItems().addAll(getChannelMapManagerBox(), getMapEditor(), getChannelRangePane());
|
||||
}
|
||||
@@ -123,15 +126,10 @@ public class ChannelMapEditor extends SplitPane
|
||||
mNewMapButton = new Button("New Map");
|
||||
mNewMapButton.setTooltip(new Tooltip("Create a new channel map"));
|
||||
mNewMapButton.setMaxWidth(Double.MAX_VALUE);
|
||||
mNewMapButton.setOnAction(new EventHandler<ActionEvent>()
|
||||
{
|
||||
@Override
|
||||
public void handle(ActionEvent event)
|
||||
{
|
||||
ChannelMap channelMap = new ChannelMap("New Channel Map");
|
||||
mChannelMapModel.addChannelMap(channelMap);
|
||||
getChannelMapListView().getSelectionModel().select(channelMap);
|
||||
}
|
||||
mNewMapButton.setOnAction(event -> {
|
||||
ChannelMap channelMap = new ChannelMap("New Channel Map");
|
||||
mChannelMapModel.addChannelMap(channelMap);
|
||||
getChannelMapListView().getSelectionModel().select(channelMap);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -146,32 +144,27 @@ public class ChannelMapEditor extends SplitPane
|
||||
mCloneMapButton.setTooltip(new Tooltip("Create a copy of the selected channel map"));
|
||||
mCloneMapButton.setDisable(true);
|
||||
mCloneMapButton.setMaxWidth(Double.MAX_VALUE);
|
||||
mCloneMapButton.setOnAction(new EventHandler<ActionEvent>()
|
||||
{
|
||||
@Override
|
||||
public void handle(ActionEvent event)
|
||||
mCloneMapButton.setOnAction(event -> {
|
||||
ChannelMap selected = getChannelMapListView().getSelectionModel().getSelectedItem();
|
||||
|
||||
if(selected != null)
|
||||
{
|
||||
ChannelMap selected = getChannelMapListView().getSelectionModel().getSelectedItem();
|
||||
ChannelMap copy = selected.copyOf();
|
||||
|
||||
if(selected != null)
|
||||
String name = selected.getName();
|
||||
|
||||
if(name == null)
|
||||
{
|
||||
ChannelMap copy = selected.copyOf();
|
||||
|
||||
String name = selected.getName();
|
||||
|
||||
if(name == null)
|
||||
{
|
||||
name = COPY_NAME;
|
||||
}
|
||||
else if(!name.toLowerCase().endsWith(COPY_NAME))
|
||||
{
|
||||
name = name + COPY_NAME;
|
||||
}
|
||||
|
||||
copy.setName(name);
|
||||
mChannelMapModel.addChannelMap(copy);
|
||||
getChannelMapListView().getSelectionModel().select(copy);
|
||||
name = COPY_NAME;
|
||||
}
|
||||
else if(!name.toLowerCase().endsWith(COPY_NAME))
|
||||
{
|
||||
name = name + COPY_NAME;
|
||||
}
|
||||
|
||||
copy.setName(name);
|
||||
mChannelMapModel.addChannelMap(copy);
|
||||
getChannelMapListView().getSelectionModel().select(copy);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,35 +1,42 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 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.gui.playlist.manager;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import com.google.common.io.Files;
|
||||
import io.github.dsheirer.controller.channel.Channel;
|
||||
import io.github.dsheirer.controller.channel.ChannelException;
|
||||
import io.github.dsheirer.eventbus.MyEventBus;
|
||||
import io.github.dsheirer.controller.channel.ChannelModel;
|
||||
import io.github.dsheirer.controller.channel.ChannelProcessingManager;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.preference.IPreferenceUpdateListener;
|
||||
import io.github.dsheirer.preference.PreferenceType;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.PreDestroy;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import javafx.application.Platform;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
@@ -53,17 +60,10 @@ import jiconfont.javafx.IconNode;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Editor for managing playlists via the playlist manager
|
||||
*/
|
||||
public class PlaylistManagerEditor extends HBox
|
||||
public class PlaylistManagerEditor extends HBox implements IPreferenceUpdateListener
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger(PlaylistManagerEditor.class);
|
||||
|
||||
@@ -72,7 +72,13 @@ public class PlaylistManagerEditor extends HBox
|
||||
private static final FileChooser.ExtensionFilter ALL_FILES_FILE_FILTER =
|
||||
new FileChooser.ExtensionFilter("All Files (*.*)", "*.*");
|
||||
|
||||
@Resource
|
||||
private ChannelModel mChannelModel;
|
||||
@Resource
|
||||
private ChannelProcessingManager mChannelProcessingManager;
|
||||
@Resource
|
||||
private PlaylistManager mPlaylistManager;
|
||||
@Resource
|
||||
private UserPreferences mUserPreferences;
|
||||
private TableView<Path> mPlaylistTableView;
|
||||
private VBox mButtonBox;
|
||||
@@ -86,25 +92,25 @@ public class PlaylistManagerEditor extends HBox
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param playlistManager for managing playlist
|
||||
* @param userPreferences for accessing preferences
|
||||
*/
|
||||
public PlaylistManagerEditor(PlaylistManager playlistManager, UserPreferences userPreferences)
|
||||
public PlaylistManagerEditor()
|
||||
{
|
||||
mPlaylistManager = playlistManager;
|
||||
mUserPreferences = userPreferences;
|
||||
|
||||
//Register to receive preferences updates
|
||||
MyEventBus.getGlobalEventBus().register(this);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
mUserPreferences.addUpdateListener(this);
|
||||
setPadding(new Insets(5, 5, 5, 5));
|
||||
HBox.setHgrow(getPlaylistTableView(), Priority.ALWAYS);
|
||||
getChildren().addAll(getPlaylistTableView(), getButtonBox());
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void dispose()
|
||||
{
|
||||
MyEventBus.getGlobalEventBus().unregister(this);
|
||||
mUserPreferences.removeUpdateListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -272,7 +278,7 @@ public class PlaylistManagerEditor extends HBox
|
||||
}
|
||||
}
|
||||
|
||||
final List<Channel> autoStartChannels = mPlaylistManager.getChannelModel().getAutoStartChannels();
|
||||
final List<Channel> autoStartChannels = mChannelModel.getAutoStartChannels();
|
||||
|
||||
if(autoStartChannels.size() > 0)
|
||||
{
|
||||
@@ -290,7 +296,7 @@ public class PlaylistManagerEditor extends HBox
|
||||
{
|
||||
try
|
||||
{
|
||||
mPlaylistManager.getChannelProcessingManager().start(channel);
|
||||
mChannelProcessingManager.start(channel);
|
||||
}
|
||||
catch(ChannelException ce)
|
||||
{
|
||||
@@ -526,7 +532,7 @@ public class PlaylistManagerEditor extends HBox
|
||||
* to the playlist list view so that we can reflect changes to the current playlist.
|
||||
* @param preferenceType that was updated
|
||||
*/
|
||||
@Subscribe
|
||||
@Override
|
||||
public void preferenceUpdated(PreferenceType preferenceType)
|
||||
{
|
||||
if(preferenceType == PreferenceType.PLAYLIST)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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
|
||||
@@ -19,13 +19,17 @@
|
||||
|
||||
package io.github.dsheirer.gui.playlist.radioreference;
|
||||
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.controller.channel.ChannelModel;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.rrapi.type.Agency;
|
||||
import io.github.dsheirer.rrapi.type.AgencyInfo;
|
||||
import io.github.dsheirer.rrapi.type.CountyInfo;
|
||||
import io.github.dsheirer.service.radioreference.RadioReference;
|
||||
import io.github.dsheirer.util.ThreadPool;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.property.IntegerProperty;
|
||||
@@ -39,19 +43,18 @@ import javafx.scene.layout.VBox;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Editor for displaying a list of agencies and viewing frequency lists for each agency
|
||||
*/
|
||||
public class AgencyEditor extends VBox
|
||||
public abstract class AgencyEditor extends VBox
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger(AgencyEditor.class);
|
||||
@Resource
|
||||
private UserPreferences mUserPreferences;
|
||||
@Resource
|
||||
private ChannelModel mChannelModel;
|
||||
@Resource
|
||||
private RadioReference mRadioReference;
|
||||
private PlaylistManager mPlaylistManager;
|
||||
private Level mLevel;
|
||||
private ListView<Agency> mAgencyListView;
|
||||
private AgencyFrequencyEditor mAgencyFrequencyEditor;
|
||||
@@ -59,19 +62,19 @@ public class AgencyEditor extends VBox
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param userPreferences
|
||||
* @param radioReference
|
||||
* @param level
|
||||
*/
|
||||
public AgencyEditor(UserPreferences userPreferences, RadioReference radioReference,
|
||||
PlaylistManager playlistManager, Level level)
|
||||
public AgencyEditor(Level level)
|
||||
{
|
||||
mUserPreferences = userPreferences;
|
||||
mRadioReference = radioReference;
|
||||
mPlaylistManager = playlistManager;
|
||||
mLevel = level;
|
||||
mAgencyCountProperty.bind(Bindings.size(getAgencyListView().getItems()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Not annotated. Sub-class must implement the annotation and invoke this method.
|
||||
*/
|
||||
public void postConstruct()
|
||||
{
|
||||
mAgencyCountProperty.bind(Bindings.size(getAgencyListView().getItems()));
|
||||
setPadding(new Insets(10,10,10,10));
|
||||
setSpacing(10);
|
||||
VBox.setVgrow(getAgencyFrequencyEditor(), Priority.ALWAYS);
|
||||
@@ -127,7 +130,7 @@ public class AgencyEditor extends VBox
|
||||
{
|
||||
if(mAgencyFrequencyEditor == null)
|
||||
{
|
||||
mAgencyFrequencyEditor = new AgencyFrequencyEditor(mUserPreferences, mRadioReference, mPlaylistManager, mLevel);
|
||||
mAgencyFrequencyEditor = new AgencyFrequencyEditor(mUserPreferences, mRadioReference, mChannelModel, mLevel);
|
||||
}
|
||||
|
||||
return mAgencyFrequencyEditor;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
package io.github.dsheirer.gui.playlist.radioreference;
|
||||
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.controller.channel.ChannelModel;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.rrapi.type.Category;
|
||||
import io.github.dsheirer.rrapi.type.Frequency;
|
||||
@@ -27,6 +27,11 @@ import io.github.dsheirer.rrapi.type.Mode;
|
||||
import io.github.dsheirer.rrapi.type.SubCategory;
|
||||
import io.github.dsheirer.service.radioreference.RadioReference;
|
||||
import io.github.dsheirer.util.ThreadPool;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
@@ -46,12 +51,6 @@ import javafx.util.StringConverter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Grid pane with components for visualizing and selecting categories of frequencies for an agency
|
||||
*/
|
||||
@@ -62,8 +61,8 @@ public class AgencyFrequencyEditor extends GridPane
|
||||
private static final SubCategory ALL_SUB_CATEGORIES = new AllSubCategories();
|
||||
|
||||
private UserPreferences mUserPreferences;
|
||||
private ChannelModel mChannelModel;
|
||||
private RadioReference mRadioReference;
|
||||
private PlaylistManager mPlaylistManager;
|
||||
private Level mLevel;
|
||||
private ComboBox<Category> mCategoryComboBox;
|
||||
private ComboBox<SubCategory> mSubCategoryComboBox;
|
||||
@@ -72,12 +71,17 @@ public class AgencyFrequencyEditor extends GridPane
|
||||
private ProgressIndicator mProgressIndicator;
|
||||
private FrequencyEditor mFrequencyEditor;
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param radioReference to use for lookups
|
||||
* @param level for this editor.
|
||||
*/
|
||||
public AgencyFrequencyEditor(UserPreferences userPreferences, RadioReference radioReference,
|
||||
PlaylistManager playlistManager, Level level)
|
||||
ChannelModel channelModel, Level level)
|
||||
{
|
||||
mUserPreferences = userPreferences;
|
||||
mChannelModel = channelModel;
|
||||
mRadioReference = radioReference;
|
||||
mPlaylistManager = playlistManager;
|
||||
mLevel = level;
|
||||
|
||||
setPadding(new Insets(5, 5, 5,5));
|
||||
@@ -175,7 +179,7 @@ public class AgencyFrequencyEditor extends GridPane
|
||||
{
|
||||
if(mFrequencyEditor == null)
|
||||
{
|
||||
mFrequencyEditor = new FrequencyEditor(mUserPreferences, mRadioReference, mPlaylistManager, mLevel);
|
||||
mFrequencyEditor = new FrequencyEditor(mUserPreferences, mRadioReference, mChannelModel, mLevel);
|
||||
}
|
||||
|
||||
return mFrequencyEditor;
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.gui.playlist.radioreference;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
|
||||
public class CountyAgencyEditor extends AgencyEditor
|
||||
{
|
||||
/**
|
||||
* Constructs an instance
|
||||
*/
|
||||
public CountyAgencyEditor()
|
||||
{
|
||||
super(Level.COUNTY);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
super.postConstruct();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.gui.playlist.radioreference;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
|
||||
public class CountySystemEditor extends SystemEditor
|
||||
{
|
||||
/**
|
||||
* Constructs an instance
|
||||
*/
|
||||
public CountySystemEditor()
|
||||
{
|
||||
super(Level.COUNTY);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
super.postConstruct();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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,6 +20,7 @@
|
||||
package io.github.dsheirer.gui.playlist.radioreference;
|
||||
|
||||
import io.github.dsheirer.controller.channel.Channel;
|
||||
import io.github.dsheirer.controller.channel.ChannelModel;
|
||||
import io.github.dsheirer.eventbus.MyEventBus;
|
||||
import io.github.dsheirer.gui.playlist.channel.ViewChannelRequest;
|
||||
import io.github.dsheirer.module.decode.DecoderFactory;
|
||||
@@ -27,7 +28,6 @@ import io.github.dsheirer.module.decode.config.DecodeConfiguration;
|
||||
import io.github.dsheirer.module.decode.nbfm.DecodeConfigNBFM;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.DecodeConfigP25Phase1;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.P25P1Decoder;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.rrapi.type.Category;
|
||||
import io.github.dsheirer.rrapi.type.Frequency;
|
||||
@@ -36,6 +36,7 @@ import io.github.dsheirer.rrapi.type.SubCategory;
|
||||
import io.github.dsheirer.service.radioreference.RadioReference;
|
||||
import io.github.dsheirer.source.config.SourceConfigTuner;
|
||||
import io.github.dsheirer.util.ThreadPool;
|
||||
import java.text.DecimalFormat;
|
||||
import javafx.animation.FadeTransition;
|
||||
import javafx.application.Platform;
|
||||
import javafx.geometry.HPos;
|
||||
@@ -53,15 +54,13 @@ import javafx.util.Duration;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
public class FrequencyEditor extends VBox
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger(FrequencyEditor.class);
|
||||
private final DecimalFormat FREQUENCY_FORMATTER = new DecimalFormat("0.00000");
|
||||
private UserPreferences mUserPreferences;
|
||||
private ChannelModel mChannelModel;
|
||||
private RadioReference mRadioReference;
|
||||
private PlaylistManager mPlaylistManager;
|
||||
private UserPreferences mUserPreferences;
|
||||
private Level mLevel;
|
||||
private TextField mAlphaTagTextField;
|
||||
private TextField mFrequencyTextField;
|
||||
@@ -77,12 +76,18 @@ public class FrequencyEditor extends VBox
|
||||
private ModeDecoderType mModeDecoderType;
|
||||
private long mFrequency;
|
||||
|
||||
public FrequencyEditor(UserPreferences userPreferences, RadioReference radioReference,
|
||||
PlaylistManager playlistManager, Level level)
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param userPreferences for preferences lookups
|
||||
* @param radioReference for data lookups
|
||||
* @param channelModel for channels
|
||||
* @param level for this editor.
|
||||
*/
|
||||
public FrequencyEditor(UserPreferences userPreferences, RadioReference radioReference, ChannelModel channelModel, Level level)
|
||||
{
|
||||
mUserPreferences = userPreferences;
|
||||
mRadioReference = radioReference;
|
||||
mPlaylistManager = playlistManager;
|
||||
mChannelModel = channelModel;
|
||||
mLevel = level;
|
||||
|
||||
GridPane gridPane = new GridPane();
|
||||
@@ -372,7 +377,7 @@ public class FrequencyEditor extends VBox
|
||||
if(channel != null)
|
||||
{
|
||||
getCreateButton().setDisable(true);
|
||||
mPlaylistManager.getChannelModel().addChannel(channel);
|
||||
mChannelModel.addChannel(channel);
|
||||
|
||||
if(getShowCreatedChannelCheckBox().selectedProperty().get())
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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,6 +24,7 @@ import io.github.dsheirer.rrapi.RadioReferenceException;
|
||||
import io.github.dsheirer.rrapi.response.Fault;
|
||||
import io.github.dsheirer.rrapi.type.AuthorizationInformation;
|
||||
import io.github.dsheirer.service.radioreference.RadioReference;
|
||||
import java.net.ConnectException;
|
||||
import javafx.application.Platform;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
@@ -48,11 +49,6 @@ import jiconfont.javafx.IconNode;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.net.ConnectException;
|
||||
import java.text.ParseException;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Login dialog for radioreference.com with support for testing connection to the service.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.gui.playlist.radioreference;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
|
||||
public class NationalAgencyEditor extends AgencyEditor
|
||||
{
|
||||
/**
|
||||
* Constructs an instance
|
||||
*/
|
||||
public NationalAgencyEditor()
|
||||
{
|
||||
super(Level.NATIONAL);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
super.postConstruct();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
package io.github.dsheirer.gui.playlist.radioreference;
|
||||
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.rrapi.RadioReferenceException;
|
||||
import io.github.dsheirer.rrapi.type.Agency;
|
||||
@@ -32,6 +31,12 @@ import io.github.dsheirer.rrapi.type.State;
|
||||
import io.github.dsheirer.rrapi.type.StateInfo;
|
||||
import io.github.dsheirer.service.radioreference.RadioReference;
|
||||
import io.github.dsheirer.util.ThreadPool;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.PreDestroy;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.geometry.Insets;
|
||||
@@ -56,16 +61,23 @@ import jiconfont.javafx.IconNode;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class RadioReferenceEditor extends BorderPane implements Consumer<AuthorizationInformation>
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger(RadioReferenceEditor.class);
|
||||
private UserPreferences mUserPreferences;
|
||||
@Resource
|
||||
private CountyAgencyEditor mCountyAgencyEditor;
|
||||
@Resource
|
||||
private CountySystemEditor mCountySystemEditor;
|
||||
@Resource
|
||||
private NationalAgencyEditor mNationalAgencyEditor;
|
||||
@Resource
|
||||
private RadioReference mRadioReference;
|
||||
private PlaylistManager mPlaylistManager;
|
||||
@Resource
|
||||
private StateAgencyEditor mStateAgencyEditor;
|
||||
@Resource
|
||||
private StateSystemEditor mStateSystemEditor;
|
||||
@Resource
|
||||
private UserPreferences mUserPreferences;
|
||||
private VBox mTopBox;
|
||||
private HBox mCredentialsBox;
|
||||
private Label mRRStatusText;
|
||||
@@ -79,11 +91,6 @@ public class RadioReferenceEditor extends BorderPane implements Consumer<Authori
|
||||
private ComboBox<Country> mCountryComboBox;
|
||||
private ComboBox<State> mStateComboBox;
|
||||
private ComboBox<County> mCountyComboBox;
|
||||
private AgencyEditor mNationalAgencyEditor;
|
||||
private AgencyEditor mStateAgencyEditor;
|
||||
private AgencyEditor mCountyAgencyEditor;
|
||||
private SystemEditor mStateSystemEditor;
|
||||
private SystemEditor mCountySystemEditor;
|
||||
private TabPane mTabPane;
|
||||
private Tab mNationalAgencyTab;
|
||||
private Tab mStateAgencyTab;
|
||||
@@ -91,34 +98,42 @@ public class RadioReferenceEditor extends BorderPane implements Consumer<Authori
|
||||
private Tab mStateSystemTab;
|
||||
private Tab mCountySystemTab;
|
||||
|
||||
public RadioReferenceEditor(UserPreferences userPreferences, PlaylistManager playlistManager)
|
||||
/**
|
||||
* Constructs an instance
|
||||
*/
|
||||
public RadioReferenceEditor()
|
||||
{
|
||||
mUserPreferences = userPreferences;
|
||||
mRadioReference = playlistManager.getRadioReference();
|
||||
mPlaylistManager = playlistManager;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
setTop(getTopBox());
|
||||
setCenter(getTabPane());
|
||||
|
||||
login();
|
||||
|
||||
if(mRadioReference.premiumAccountProperty().get())
|
||||
{
|
||||
refreshCountries();
|
||||
}
|
||||
|
||||
//Refresh the countries combo box once we're logged on, if not already
|
||||
mRadioReference.premiumAccountProperty().addListener((observable, oldValue, newValue) -> {
|
||||
if(newValue)
|
||||
//Only refresh the countries if we're now logged in and we weren't previously logged in.
|
||||
if(newValue && oldValue ^ newValue)
|
||||
{
|
||||
refreshCountries();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void login()
|
||||
@PreDestroy
|
||||
public void preDestroy()
|
||||
{
|
||||
if(mUserPreferences.getRadioReferencePreference().hasStoredCredentials())
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs radio reference login and sets the state of the premiumAccountProperty and if the login is good, it
|
||||
* triggers a refresh on the countries list box.
|
||||
*/
|
||||
public void login()
|
||||
{
|
||||
if(mUserPreferences.getRadioReferencePreference().hasStoredCredentials() &&
|
||||
!mRadioReference.premiumAccountProperty().get())
|
||||
{
|
||||
AuthorizationInformation credentials = mUserPreferences.getRadioReferencePreference().getAuthorizationInformation();
|
||||
|
||||
@@ -139,6 +154,7 @@ public class RadioReferenceEditor extends BorderPane implements Consumer<Authori
|
||||
|
||||
final int preferredCountryId = mUserPreferences.getRadioReferencePreference().getPreferredCountryId();
|
||||
|
||||
//Retrieve the countries off of the JavaFX event thread and load the UI on the JavaFX platform thread
|
||||
ThreadPool.CACHED.execute(() -> {
|
||||
try
|
||||
{
|
||||
@@ -297,56 +313,31 @@ public class RadioReferenceEditor extends BorderPane implements Consumer<Authori
|
||||
return mCountySystemTab;
|
||||
}
|
||||
|
||||
private AgencyEditor getNationalAgencyEditor()
|
||||
private AgencyEditor getCountyAgencyEditor()
|
||||
{
|
||||
if(mNationalAgencyEditor == null)
|
||||
{
|
||||
mNationalAgencyEditor = new AgencyEditor(mUserPreferences, mRadioReference, mPlaylistManager, Level.NATIONAL);
|
||||
}
|
||||
|
||||
return mNationalAgencyEditor;
|
||||
return mCountyAgencyEditor;
|
||||
}
|
||||
|
||||
private AgencyEditor getStateAgencyEditor()
|
||||
{
|
||||
if(mStateAgencyEditor == null)
|
||||
{
|
||||
mStateAgencyEditor = new AgencyEditor(mUserPreferences, mRadioReference, mPlaylistManager, Level.STATE);
|
||||
}
|
||||
|
||||
return mStateAgencyEditor;
|
||||
}
|
||||
|
||||
private AgencyEditor getCountyAgencyEditor()
|
||||
private AgencyEditor getNationalAgencyEditor()
|
||||
{
|
||||
if(mCountyAgencyEditor == null)
|
||||
{
|
||||
mCountyAgencyEditor = new AgencyEditor(mUserPreferences, mRadioReference, mPlaylistManager, Level.COUNTY);
|
||||
}
|
||||
|
||||
return mCountyAgencyEditor;
|
||||
}
|
||||
|
||||
private SystemEditor getStateSystemEditor()
|
||||
{
|
||||
if(mStateSystemEditor == null)
|
||||
{
|
||||
mStateSystemEditor = new SystemEditor(mUserPreferences, mRadioReference, mPlaylistManager, Level.STATE);
|
||||
}
|
||||
|
||||
return mStateSystemEditor;
|
||||
return mNationalAgencyEditor;
|
||||
}
|
||||
|
||||
private SystemEditor getCountySystemEditor()
|
||||
{
|
||||
if(mCountySystemEditor == null)
|
||||
{
|
||||
mCountySystemEditor = new SystemEditor(mUserPreferences, mRadioReference, mPlaylistManager, Level.COUNTY);
|
||||
}
|
||||
|
||||
return mCountySystemEditor;
|
||||
}
|
||||
|
||||
private SystemEditor getStateSystemEditor()
|
||||
{
|
||||
return mStateSystemEditor;
|
||||
}
|
||||
|
||||
private VBox getTopBox()
|
||||
{
|
||||
if(mTopBox == null)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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
|
||||
@@ -21,6 +21,7 @@ package io.github.dsheirer.gui.playlist.radioreference;
|
||||
|
||||
import io.github.dsheirer.alias.AliasModel;
|
||||
import io.github.dsheirer.controller.channel.Channel;
|
||||
import io.github.dsheirer.controller.channel.ChannelModel;
|
||||
import io.github.dsheirer.eventbus.MyEventBus;
|
||||
import io.github.dsheirer.gui.control.MaxLengthUnaryOperator;
|
||||
import io.github.dsheirer.gui.playlist.channel.ViewChannelRequest;
|
||||
@@ -33,7 +34,6 @@ import io.github.dsheirer.module.decode.p25.phase1.DecodeConfigP25Phase1;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.P25P1Decoder;
|
||||
import io.github.dsheirer.module.decode.p25.phase2.DecodeConfigP25Phase2;
|
||||
import io.github.dsheirer.module.decode.p25.phase2.enumeration.ScrambleParameters;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.rrapi.type.RadioNetwork;
|
||||
import io.github.dsheirer.rrapi.type.Site;
|
||||
@@ -42,6 +42,15 @@ import io.github.dsheirer.rrapi.type.System;
|
||||
import io.github.dsheirer.rrapi.type.SystemInformation;
|
||||
import io.github.dsheirer.source.config.SourceConfigTuner;
|
||||
import io.github.dsheirer.source.config.SourceConfigTunerMultipleFrequency;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
import javafx.animation.RotateTransition;
|
||||
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
@@ -74,14 +83,6 @@ import org.controlsfx.control.SegmentedButton;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class SiteEditor extends GridPane
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger(SiteEditor.class);
|
||||
@@ -90,9 +91,12 @@ public class SiteEditor extends GridPane
|
||||
private static final String PRIMARY_CONTROL_CHANNEL = "d";
|
||||
private static final String TOGGLE_BUTTON_CONTROL = "Control";
|
||||
private static final String TOGGLE_BUTTON_P25_VOICE = "All P25 Voice";
|
||||
|
||||
@Resource
|
||||
private AliasModel mAliasModel;
|
||||
@Resource
|
||||
private ChannelModel mChannelModel;
|
||||
@Resource
|
||||
private UserPreferences mUserPreferences;
|
||||
private PlaylistManager mPlaylistManager;
|
||||
private TableView<SiteFrequency> mSiteFrequencyTableView;
|
||||
private TableColumn<SiteFrequency,String> mTypeColumn;
|
||||
private SegmentedButton mFrequenciesSegmentedButton;
|
||||
@@ -116,11 +120,13 @@ public class SiteEditor extends GridPane
|
||||
private ComboBox mAliasListNameComboBox;
|
||||
private Button mNewAliasListButton;
|
||||
|
||||
public SiteEditor(UserPreferences userPreferences, PlaylistManager playlistManager)
|
||||
public SiteEditor()
|
||||
{
|
||||
mUserPreferences = userPreferences;
|
||||
mPlaylistManager = playlistManager;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
setMaxHeight(Double.MAX_VALUE);
|
||||
setHgap(5.0);
|
||||
setVgap(5.0);
|
||||
@@ -476,7 +482,7 @@ public class SiteEditor extends GridPane
|
||||
gotoChannel = channel;
|
||||
}
|
||||
|
||||
mPlaylistManager.getChannelModel().addChannel(channel);
|
||||
mChannelModel.addChannel(channel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -540,7 +546,7 @@ public class SiteEditor extends GridPane
|
||||
channel.setSourceConfiguration(sourceConfig);
|
||||
}
|
||||
|
||||
mPlaylistManager.getChannelModel().addChannel(channel);
|
||||
mChannelModel.addChannel(channel);
|
||||
|
||||
if(getGoToChannelEditorCheckBox().isSelected())
|
||||
{
|
||||
@@ -614,7 +620,7 @@ public class SiteEditor extends GridPane
|
||||
channel.setSourceConfiguration(sourceConfig);
|
||||
}
|
||||
|
||||
mPlaylistManager.getChannelModel().addChannel(channel);
|
||||
mChannelModel.addChannel(channel);
|
||||
|
||||
if(getGoToChannelEditorCheckBox().isSelected())
|
||||
{
|
||||
@@ -641,7 +647,7 @@ public class SiteEditor extends GridPane
|
||||
gotoChannel = channel;
|
||||
}
|
||||
|
||||
mPlaylistManager.getChannelModel().addChannel(channel);
|
||||
mChannelModel.addChannel(channel);
|
||||
}
|
||||
|
||||
if(getGoToChannelEditorCheckBox().isSelected() && gotoChannel != null)
|
||||
@@ -706,7 +712,7 @@ public class SiteEditor extends GridPane
|
||||
channel.setSourceConfiguration(sourceConfig);
|
||||
}
|
||||
|
||||
mPlaylistManager.getChannelModel().addChannel(channel);
|
||||
mChannelModel.addChannel(channel);
|
||||
|
||||
if(getGoToChannelEditorCheckBox().isSelected())
|
||||
{
|
||||
@@ -734,7 +740,7 @@ public class SiteEditor extends GridPane
|
||||
gotoChannel = channel;
|
||||
}
|
||||
|
||||
mPlaylistManager.getChannelModel().addChannel(channel);
|
||||
mChannelModel.addChannel(channel);
|
||||
}
|
||||
|
||||
if(getGoToChannelEditorCheckBox().isSelected() && gotoChannel != null)
|
||||
@@ -768,7 +774,7 @@ public class SiteEditor extends GridPane
|
||||
{
|
||||
Predicate<String> filterPredicate = s -> !s.contentEquals(AliasModel.NO_ALIAS_LIST);
|
||||
FilteredList<String> filteredChannelList =
|
||||
new FilteredList<>(mPlaylistManager.getAliasModel().aliasListNames(), filterPredicate);
|
||||
new FilteredList<>(mAliasModel.aliasListNames(), filterPredicate);
|
||||
mAliasListNameComboBox = new ComboBox<>(filteredChannelList);
|
||||
mAliasListNameComboBox.setDisable(true);
|
||||
mAliasListNameComboBox.setMaxWidth(Double.MAX_VALUE);
|
||||
@@ -806,7 +812,7 @@ public class SiteEditor extends GridPane
|
||||
if(name != null && !name.isEmpty())
|
||||
{
|
||||
name = name.trim();
|
||||
mPlaylistManager.getAliasModel().addAliasList(name);
|
||||
mAliasModel.addAliasList(name);
|
||||
getAliasListNameComboBox().getSelectionModel().select(name);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.gui.playlist.radioreference;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
|
||||
public class StateAgencyEditor extends AgencyEditor
|
||||
{
|
||||
/**
|
||||
* Constructs an instance
|
||||
*/
|
||||
public StateAgencyEditor()
|
||||
{
|
||||
super(Level.STATE);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
super.postConstruct();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.gui.playlist.radioreference;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
|
||||
public class StateSystemEditor extends SystemEditor
|
||||
{
|
||||
/**
|
||||
* Constructs an instance
|
||||
*/
|
||||
public StateSystemEditor()
|
||||
{
|
||||
super(Level.STATE);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
super.postConstruct();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
package io.github.dsheirer.gui.playlist.radioreference;
|
||||
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.rrapi.RadioReferenceException;
|
||||
import io.github.dsheirer.rrapi.type.CountyInfo;
|
||||
@@ -34,6 +33,7 @@ import io.github.dsheirer.rrapi.type.Type;
|
||||
import io.github.dsheirer.rrapi.type.Voice;
|
||||
import io.github.dsheirer.service.radioreference.RadioReference;
|
||||
import io.github.dsheirer.util.ThreadPool;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
@@ -63,37 +63,40 @@ import org.slf4j.LoggerFactory;
|
||||
/**
|
||||
* Radio Reference editor for trunked radio systems
|
||||
*/
|
||||
public class SystemEditor extends VBox
|
||||
public abstract class SystemEditor extends VBox
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger(SystemEditor.class);
|
||||
|
||||
private UserPreferences mUserPreferences;
|
||||
@Resource
|
||||
private RadioReference mRadioReference;
|
||||
private PlaylistManager mPlaylistManager;
|
||||
@Resource
|
||||
private SystemTalkgroupSelectionEditor mSystemTalkgroupSelectionEditor;
|
||||
@Resource
|
||||
private UserPreferences mUserPreferences;
|
||||
private Level mLevel;
|
||||
private ComboBox<System> mSystemComboBox;
|
||||
private IntegerProperty mSystemCountProperty = new SimpleIntegerProperty();
|
||||
private TabPane mTabPane;
|
||||
private Tab mSystemTab;
|
||||
private Tab mTalkgroupTab;
|
||||
@Resource
|
||||
private SystemSiteSelectionEditor mSystemSiteSelectionEditor;
|
||||
private SystemTalkgroupSelectionEditor mSystemTalkgroupSelectionEditor;
|
||||
private RadioReferenceDecoder mRadioReferenceDecoder;
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param userPreferences for preferences
|
||||
* @param radioReference to access radio reference
|
||||
* @param playlistManager
|
||||
* @param level STATE or COUNTY
|
||||
*/
|
||||
public SystemEditor(UserPreferences userPreferences, RadioReference radioReference,
|
||||
PlaylistManager playlistManager, Level level)
|
||||
public SystemEditor(Level level)
|
||||
{
|
||||
mUserPreferences = userPreferences;
|
||||
mRadioReference = radioReference;
|
||||
mPlaylistManager = playlistManager;
|
||||
mLevel = level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Not annotated. Sub-class implementation must be annotated.
|
||||
*/
|
||||
public void postConstruct()
|
||||
{
|
||||
mSystemCountProperty.bind(Bindings.size(getSystemComboBox().getItems()));
|
||||
|
||||
setPadding(new Insets(20,10,10,10));
|
||||
@@ -168,11 +171,6 @@ public class SystemEditor extends VBox
|
||||
|
||||
private SystemSiteSelectionEditor getSystemSiteSelectionEditor()
|
||||
{
|
||||
if(mSystemSiteSelectionEditor == null)
|
||||
{
|
||||
mSystemSiteSelectionEditor = new SystemSiteSelectionEditor(mUserPreferences, mPlaylistManager);
|
||||
}
|
||||
|
||||
return mSystemSiteSelectionEditor;
|
||||
}
|
||||
|
||||
@@ -189,11 +187,6 @@ public class SystemEditor extends VBox
|
||||
|
||||
private SystemTalkgroupSelectionEditor getSystemTalkgroupSelectionEditor()
|
||||
{
|
||||
if(mSystemTalkgroupSelectionEditor == null)
|
||||
{
|
||||
mSystemTalkgroupSelectionEditor = new SystemTalkgroupSelectionEditor(mUserPreferences, mPlaylistManager);
|
||||
}
|
||||
|
||||
return mSystemTalkgroupSelectionEditor;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,34 +1,32 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 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
|
||||
* * 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.gui.playlist.radioreference;
|
||||
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.rrapi.type.Flavor;
|
||||
import io.github.dsheirer.rrapi.type.System;
|
||||
import io.github.dsheirer.rrapi.type.SystemInformation;
|
||||
import io.github.dsheirer.rrapi.type.Type;
|
||||
import io.github.dsheirer.rrapi.type.Voice;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.List;
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.control.Label;
|
||||
@@ -42,8 +40,6 @@ import javafx.scene.layout.Priority;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* View for a radio reference trunked mobile radio system
|
||||
@@ -51,30 +47,28 @@ import java.util.List;
|
||||
public class SystemSiteSelectionEditor extends GridPane
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger(SystemSiteSelectionEditor.class);
|
||||
|
||||
private UserPreferences mUserPreferences;
|
||||
private PlaylistManager mPlaylistManager;
|
||||
@Resource
|
||||
private SiteEditor mSiteEditor;
|
||||
private ProgressIndicator mProgressIndicator;
|
||||
private Label mPlaceholderLabel;
|
||||
private Label mProtocolLabel;
|
||||
private Label mFlavorLabel;
|
||||
private Label mVoiceLabel;
|
||||
private TableView<EnrichedSite> mSiteTableView;
|
||||
private SiteEditor mSiteEditor;
|
||||
private RadioReferenceDecoder mRadioReferenceDecoder;
|
||||
private System mCurrentSystem;
|
||||
private SystemInformation mCurrentSystemInformation;
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param userPreferences for settings
|
||||
* @param playlistManager to access radio reference
|
||||
*/
|
||||
public SystemSiteSelectionEditor(UserPreferences userPreferences, PlaylistManager playlistManager)
|
||||
public SystemSiteSelectionEditor()
|
||||
{
|
||||
mUserPreferences = userPreferences;
|
||||
mPlaylistManager = playlistManager;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
setPadding(new Insets(10,0,0,0));
|
||||
setHgap(10);
|
||||
setVgap(10);
|
||||
@@ -146,11 +140,6 @@ public class SystemSiteSelectionEditor extends GridPane
|
||||
|
||||
private SiteEditor getSiteEditor()
|
||||
{
|
||||
if(mSiteEditor == null)
|
||||
{
|
||||
mSiteEditor = new SiteEditor(mUserPreferences, mPlaylistManager);
|
||||
}
|
||||
|
||||
return mSiteEditor;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,12 +28,13 @@ import io.github.dsheirer.alias.id.talkgroup.TalkgroupRange;
|
||||
import io.github.dsheirer.eventbus.MyEventBus;
|
||||
import io.github.dsheirer.gui.control.MaxLengthUnaryOperator;
|
||||
import io.github.dsheirer.identifier.talkgroup.TalkgroupIdentifier;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.protocol.Protocol;
|
||||
import io.github.dsheirer.rrapi.type.System;
|
||||
import io.github.dsheirer.rrapi.type.Talkgroup;
|
||||
import io.github.dsheirer.rrapi.type.TalkgroupCategory;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
@@ -82,12 +83,15 @@ public class SystemTalkgroupSelectionEditor extends GridPane
|
||||
private static final Logger mLog = LoggerFactory.getLogger(SystemTalkgroupSelectionEditor.class);
|
||||
|
||||
private final TalkgroupCategory ALL_TALKGROUPS = new TalkgroupCategory();
|
||||
@Resource
|
||||
private AliasModel mAliasModel;
|
||||
@Resource
|
||||
private TalkgroupEditor mTalkgroupEditor;
|
||||
@Resource
|
||||
private UserPreferences mUserPreferences;
|
||||
private PlaylistManager mPlaylistManager;
|
||||
private TableView<AliasedTalkgroup> mTalkgroupTableView;
|
||||
private ComboBox<TalkgroupCategory> mTalkgroupCategoryComboBox;
|
||||
private TextField mSearchField;
|
||||
private TalkgroupEditor mTalkgroupEditor;
|
||||
private ComboBox<String> mAliasListNameComboBox;
|
||||
private Button mNewAliasListButton;
|
||||
private TalkgroupFilter mTalkgroupFilter = new TalkgroupFilter();
|
||||
@@ -102,14 +106,16 @@ public class SystemTalkgroupSelectionEditor extends GridPane
|
||||
private ProgressIndicator mProgressIndicator;
|
||||
private CheckBox mEncryptedAsDoNotMonitorCheckBox;
|
||||
|
||||
public SystemTalkgroupSelectionEditor(UserPreferences userPreferences, PlaylistManager playlistManager)
|
||||
public SystemTalkgroupSelectionEditor()
|
||||
{
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
//Register to receive flash alias box requests
|
||||
MyEventBus.getGlobalEventBus().register(this);
|
||||
|
||||
mUserPreferences = userPreferences;
|
||||
mPlaylistManager = playlistManager;
|
||||
|
||||
ALL_TALKGROUPS.setName("(All Talkgroups)");
|
||||
|
||||
setPadding(new Insets(10,0,0,0));
|
||||
@@ -369,7 +375,7 @@ public class SystemTalkgroupSelectionEditor extends GridPane
|
||||
createdAliases.add(alias);
|
||||
}
|
||||
|
||||
mPlaylistManager.getAliasModel().addAliases(createdAliases);
|
||||
mAliasModel.addAliases(createdAliases);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -433,11 +439,6 @@ public class SystemTalkgroupSelectionEditor extends GridPane
|
||||
|
||||
private TalkgroupEditor getTalkgroupEditor()
|
||||
{
|
||||
if(mTalkgroupEditor == null)
|
||||
{
|
||||
mTalkgroupEditor = new TalkgroupEditor(mUserPreferences, mPlaylistManager);
|
||||
}
|
||||
|
||||
return mTalkgroupEditor;
|
||||
}
|
||||
|
||||
@@ -458,7 +459,7 @@ public class SystemTalkgroupSelectionEditor extends GridPane
|
||||
{
|
||||
Predicate<String> filterPredicate = s -> !s.contentEquals(AliasModel.NO_ALIAS_LIST);
|
||||
FilteredList<String> filteredChannelList =
|
||||
new FilteredList<>(mPlaylistManager.getAliasModel().aliasListNames(), filterPredicate);
|
||||
new FilteredList<>(mAliasModel.aliasListNames(), filterPredicate);
|
||||
mAliasListNameComboBox = new ComboBox<>(filteredChannelList);
|
||||
mAliasListNameComboBox.setPrefWidth(150);
|
||||
mAliasListNameComboBox.setOnAction(event -> updateAliasList(getAliasListNameComboBox()
|
||||
@@ -487,7 +488,7 @@ public class SystemTalkgroupSelectionEditor extends GridPane
|
||||
mAliasList.aliases().removeListener(mAliasListChangeListener);
|
||||
}
|
||||
|
||||
mAliasList = mPlaylistManager.getAliasModel().getAliasList(aliasListName);
|
||||
mAliasList = mAliasModel.getAliasList(aliasListName);
|
||||
|
||||
if(mAliasList != null)
|
||||
{
|
||||
@@ -583,7 +584,7 @@ public class SystemTalkgroupSelectionEditor extends GridPane
|
||||
if(name != null && !name.isEmpty())
|
||||
{
|
||||
name = name.trim();
|
||||
mPlaylistManager.getAliasModel().addAliasList(name);
|
||||
mAliasModel.addAliasList(name);
|
||||
getAliasListNameComboBox().getSelectionModel().select(name);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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,12 +20,13 @@
|
||||
package io.github.dsheirer.gui.playlist.radioreference;
|
||||
|
||||
import io.github.dsheirer.alias.Alias;
|
||||
import io.github.dsheirer.alias.AliasModel;
|
||||
import io.github.dsheirer.eventbus.MyEventBus;
|
||||
import io.github.dsheirer.gui.playlist.alias.ViewAliasRequest;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.rrapi.type.System;
|
||||
import io.github.dsheirer.rrapi.type.Talkgroup;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.geometry.Orientation;
|
||||
import javafx.scene.control.Alert;
|
||||
@@ -42,8 +43,8 @@ import org.slf4j.LoggerFactory;
|
||||
public class TalkgroupEditor extends GridPane
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger(TalkgroupEditor.class);
|
||||
private UserPreferences mUserPreferences;
|
||||
private PlaylistManager mPlaylistManager;
|
||||
@Resource
|
||||
private AliasModel mAliasModel;
|
||||
private TextField mAlphaTagTextField;
|
||||
private TextField mDescriptionTextField;
|
||||
private TextField mTalkgroupTextField;
|
||||
@@ -64,11 +65,13 @@ public class TalkgroupEditor extends GridPane
|
||||
private Alias mAlias;
|
||||
private boolean mSetEncryptedDoNotMonitor;
|
||||
|
||||
public TalkgroupEditor(UserPreferences userPreferences, PlaylistManager playlistManager)
|
||||
public TalkgroupEditor()
|
||||
{
|
||||
mUserPreferences = userPreferences;
|
||||
mPlaylistManager = playlistManager;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
setHgap(5);
|
||||
setVgap(5);
|
||||
|
||||
@@ -150,7 +153,6 @@ public class TalkgroupEditor extends GridPane
|
||||
getChildren().add(getCreateAliasButton());
|
||||
}
|
||||
|
||||
|
||||
public void setTalkgroup(Talkgroup talkgroup, System system, RadioReferenceDecoder decoder, Alias alias,
|
||||
String aliasListName, String group, boolean setEncryptedDoNotMonitor)
|
||||
{
|
||||
@@ -292,7 +294,7 @@ public class TalkgroupEditor extends GridPane
|
||||
alias.addAliasID(new io.github.dsheirer.alias.id.priority.Priority(priority));
|
||||
}
|
||||
|
||||
mPlaylistManager.getAliasModel().addAlias(alias);
|
||||
mAliasModel.addAlias(alias);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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
|
||||
@@ -19,11 +19,14 @@
|
||||
|
||||
package io.github.dsheirer.gui.playlist.streaming;
|
||||
|
||||
import io.github.dsheirer.alias.AliasModel;
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastConfiguration;
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastEvent;
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastModel;
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastServerType;
|
||||
import io.github.dsheirer.gui.playlist.Editor;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
@@ -45,7 +48,10 @@ import org.controlsfx.control.ToggleSwitch;
|
||||
*/
|
||||
public abstract class AbstractBroadcastEditor<T extends BroadcastConfiguration> extends Editor<T>
|
||||
{
|
||||
private PlaylistManager mPlaylistManager;
|
||||
@Resource
|
||||
private AliasModel mAliasModel;
|
||||
@Resource
|
||||
private BroadcastModel mBroadcastModel;
|
||||
private Button mSaveButton;
|
||||
private Button mResetButton;
|
||||
private TextField mFormatField;
|
||||
@@ -55,11 +61,14 @@ public abstract class AbstractBroadcastEditor<T extends BroadcastConfiguration>
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param playlistManager for access the stream manager
|
||||
*/
|
||||
public AbstractBroadcastEditor(PlaylistManager playlistManager)
|
||||
public AbstractBroadcastEditor()
|
||||
{
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
mPlaylistManager = playlistManager;
|
||||
getFormatField().setText(getBroadcastServerType().toString());
|
||||
|
||||
VBox buttonBox = new VBox();
|
||||
@@ -73,11 +82,6 @@ public abstract class AbstractBroadcastEditor<T extends BroadcastConfiguration>
|
||||
getChildren().addAll(editorBox);
|
||||
}
|
||||
|
||||
protected PlaylistManager getPlaylistManager()
|
||||
{
|
||||
return mPlaylistManager;
|
||||
}
|
||||
|
||||
protected abstract GridPane getEditorPane();
|
||||
|
||||
public abstract BroadcastServerType getBroadcastServerType();
|
||||
@@ -117,7 +121,7 @@ public abstract class AbstractBroadcastEditor<T extends BroadcastConfiguration>
|
||||
|
||||
if(previousName != null && !previousName.isEmpty() && !updatedName.contentEquals(previousName))
|
||||
{
|
||||
if(getPlaylistManager().getAliasModel().hasAliasesWithBroadcastChannel(previousName))
|
||||
if(mAliasModel.hasAliasesWithBroadcastChannel(previousName))
|
||||
{
|
||||
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
|
||||
alert.getButtonTypes().clear();
|
||||
@@ -136,15 +140,14 @@ public abstract class AbstractBroadcastEditor<T extends BroadcastConfiguration>
|
||||
alert.showAndWait().ifPresent(buttonType -> {
|
||||
if(buttonType == ButtonType.YES)
|
||||
{
|
||||
getPlaylistManager().getAliasModel().updateBroadcastChannel(previousName, updatedName);
|
||||
mAliasModel.updateBroadcastChannel(previousName, updatedName);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: remove this after we get rid of Swing tables so that we don't have to announce these changes.
|
||||
mPlaylistManager.getBroadcastModel().process(new BroadcastEvent(configuration,
|
||||
BroadcastEvent.Event.CONFIGURATION_CHANGE));
|
||||
mBroadcastModel.process(new BroadcastEvent(configuration, BroadcastEvent.Event.CONFIGURATION_CHANGE));
|
||||
}
|
||||
|
||||
modifiedProperty().set(false);
|
||||
|
||||
@@ -1,30 +1,26 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 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.gui.playlist.streaming;
|
||||
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastConfiguration;
|
||||
import io.github.dsheirer.gui.control.IntegerTextField;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import javafx.scene.control.CheckBox;
|
||||
import javafx.scene.control.PasswordField;
|
||||
import javafx.scene.control.TextField;
|
||||
@@ -46,9 +42,8 @@ public abstract class AbstractStreamEditor<T extends BroadcastConfiguration> ext
|
||||
/**
|
||||
* Constructs an instance
|
||||
*/
|
||||
public AbstractStreamEditor(PlaylistManager playlistManager)
|
||||
public AbstractStreamEditor()
|
||||
{
|
||||
super(playlistManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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
|
||||
@@ -23,7 +23,6 @@ import io.github.dsheirer.audio.broadcast.BroadcastServerType;
|
||||
import io.github.dsheirer.audio.broadcast.broadcastify.BroadcastifyCallBroadcaster;
|
||||
import io.github.dsheirer.audio.broadcast.broadcastify.BroadcastifyCallConfiguration;
|
||||
import io.github.dsheirer.gui.control.IntegerTextField;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.control.Alert;
|
||||
@@ -32,9 +31,9 @@ import javafx.scene.control.ButtonType;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import org.controlsfx.control.ToggleSwitch;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.controlsfx.control.ToggleSwitch;
|
||||
|
||||
/**
|
||||
* Broadcastify calls API configuration editor
|
||||
@@ -53,11 +52,9 @@ public class BroadcastifyCallEditor extends AbstractBroadcastEditor<Broadcastify
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param playlistManager for accessing the broadcast model
|
||||
*/
|
||||
public BroadcastifyCallEditor(PlaylistManager playlistManager)
|
||||
public BroadcastifyCallEditor()
|
||||
{
|
||||
super(playlistManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,23 +1,20 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 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.gui.playlist.streaming;
|
||||
@@ -26,7 +23,6 @@ package io.github.dsheirer.gui.playlist.streaming;
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastServerType;
|
||||
import io.github.dsheirer.audio.broadcast.broadcastify.BroadcastifyFeedConfiguration;
|
||||
import io.github.dsheirer.gui.control.IntegerTextField;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.control.Label;
|
||||
@@ -42,9 +38,8 @@ public class BroadcastifyStreamEditor extends AbstractStreamEditor<BroadcastifyF
|
||||
private TextField mMountPointTextField;
|
||||
private IntegerTextField mFeedIdTextField;
|
||||
|
||||
public BroadcastifyStreamEditor(PlaylistManager playlistManager)
|
||||
public BroadcastifyStreamEditor()
|
||||
{
|
||||
super(playlistManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,40 +1,31 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 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.gui.playlist.streaming;
|
||||
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastServerType;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
|
||||
/**
|
||||
* Stream configuration editor for Icecast 2.4+ HTTP broadcast
|
||||
*/
|
||||
public class IcecastHTTPStreamEditor extends IcecastStreamEditor
|
||||
{
|
||||
public IcecastHTTPStreamEditor(PlaylistManager playlistManager)
|
||||
{
|
||||
super(playlistManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BroadcastServerType getBroadcastServerType()
|
||||
{
|
||||
|
||||
@@ -1,30 +1,26 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 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.gui.playlist.streaming;
|
||||
|
||||
|
||||
import io.github.dsheirer.audio.broadcast.icecast.IcecastConfiguration;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.control.Label;
|
||||
@@ -45,9 +41,8 @@ public abstract class IcecastStreamEditor extends AbstractStreamEditor<IcecastCo
|
||||
private TextField mGenreTextField;
|
||||
private TextField mURLTextField;
|
||||
|
||||
public IcecastStreamEditor(PlaylistManager playlistManager)
|
||||
public IcecastStreamEditor()
|
||||
{
|
||||
super(playlistManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,40 +1,31 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 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.gui.playlist.streaming;
|
||||
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastServerType;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
|
||||
/**
|
||||
* Stream configuration editor for Icecast 2.3 TCP broadcast
|
||||
*/
|
||||
public class IcecastTCPStreamEditor extends IcecastStreamEditor
|
||||
{
|
||||
public IcecastTCPStreamEditor(PlaylistManager playlistManager)
|
||||
{
|
||||
super(playlistManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BroadcastServerType getBroadcastServerType()
|
||||
{
|
||||
|
||||
@@ -22,7 +22,6 @@ package io.github.dsheirer.gui.playlist.streaming;
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastServerType;
|
||||
import io.github.dsheirer.audio.broadcast.rdioscanner.RdioScannerConfiguration;
|
||||
import io.github.dsheirer.gui.control.IntegerTextField;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.control.Label;
|
||||
@@ -46,11 +45,9 @@ public class RdioScannerEditor extends AbstractBroadcastEditor<RdioScannerConfig
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param playlistManager for accessing the broadcast model
|
||||
*/
|
||||
public RdioScannerEditor(PlaylistManager playlistManager)
|
||||
public RdioScannerEditor()
|
||||
{
|
||||
super(playlistManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,23 +1,20 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 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.gui.playlist.streaming;
|
||||
@@ -25,7 +22,6 @@ package io.github.dsheirer.gui.playlist.streaming;
|
||||
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastServerType;
|
||||
import io.github.dsheirer.audio.broadcast.shoutcast.v1.ShoutcastV1Configuration;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.control.Label;
|
||||
@@ -43,11 +39,6 @@ public class ShoutcastV1StreamEditor extends AbstractStreamEditor<ShoutcastV1Con
|
||||
private TextField mGenreTextField;
|
||||
private ToggleSwitch mPublicToggleSwitch;
|
||||
|
||||
public ShoutcastV1StreamEditor(PlaylistManager playlistManager)
|
||||
{
|
||||
super(playlistManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BroadcastServerType getBroadcastServerType()
|
||||
{
|
||||
|
||||
@@ -1,23 +1,20 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 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.gui.playlist.streaming;
|
||||
@@ -26,7 +23,6 @@ package io.github.dsheirer.gui.playlist.streaming;
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastServerType;
|
||||
import io.github.dsheirer.audio.broadcast.shoutcast.v2.ShoutcastV2Configuration;
|
||||
import io.github.dsheirer.gui.control.IntegerTextField;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.control.Label;
|
||||
@@ -46,11 +42,6 @@ public class ShoutcastV2StreamEditor extends AbstractStreamEditor<ShoutcastV2Con
|
||||
private TextField mGenreTextField;
|
||||
private ToggleSwitch mPublicToggleSwitch;
|
||||
|
||||
public ShoutcastV2StreamEditor(PlaylistManager playlistManager)
|
||||
{
|
||||
super(playlistManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BroadcastServerType getBroadcastServerType()
|
||||
{
|
||||
|
||||
@@ -1,31 +1,33 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 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.gui.playlist.streaming;
|
||||
|
||||
import io.github.dsheirer.alias.Alias;
|
||||
import io.github.dsheirer.alias.AliasModel;
|
||||
import io.github.dsheirer.alias.id.broadcast.BroadcastChannel;
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastConfiguration;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import javafx.collections.transformation.FilteredList;
|
||||
import javafx.collections.transformation.SortedList;
|
||||
@@ -49,17 +51,14 @@ import org.controlsfx.control.textfield.TextFields;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Editor for managing which aliases are configured for a specific broadcast configuration audio stream
|
||||
*/
|
||||
public class StreamAliasSelectionEditor extends VBox
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(StreamAliasSelectionEditor.class);
|
||||
private PlaylistManager mPlaylistManager;
|
||||
@Resource
|
||||
private AliasModel mAliasModel;
|
||||
private BroadcastConfiguration mSelectedBroadcastConfiguration;
|
||||
private HBox mSearchBox;
|
||||
private TextField mSearchField;
|
||||
@@ -76,12 +75,14 @@ public class StreamAliasSelectionEditor extends VBox
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param playlistManager for access to alias model
|
||||
*/
|
||||
public StreamAliasSelectionEditor(PlaylistManager playlistManager)
|
||||
public StreamAliasSelectionEditor()
|
||||
{
|
||||
mPlaylistManager = playlistManager;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
VBox buttonBox = new VBox();
|
||||
buttonBox.setMaxHeight(Double.MAX_VALUE);
|
||||
buttonBox.setAlignment(Pos.CENTER);
|
||||
@@ -125,8 +126,7 @@ public class StreamAliasSelectionEditor extends VBox
|
||||
{
|
||||
if(mAvailableFilteredList == null)
|
||||
{
|
||||
mAvailableFilteredList = new FilteredList<>(mPlaylistManager.getAliasModel().aliasList(),
|
||||
mAvailableAliasPredicate);
|
||||
mAvailableFilteredList = new FilteredList<>(mAliasModel.aliasList(), mAvailableAliasPredicate);
|
||||
}
|
||||
|
||||
return mAvailableFilteredList;
|
||||
@@ -136,8 +136,7 @@ public class StreamAliasSelectionEditor extends VBox
|
||||
{
|
||||
if(mSelectedFilteredList == null)
|
||||
{
|
||||
mSelectedFilteredList = new FilteredList<>(mPlaylistManager.getAliasModel().aliasList(),
|
||||
mSelectedAliasPredicate);
|
||||
mSelectedFilteredList = new FilteredList<>(mAliasModel.aliasList(), mSelectedAliasPredicate);
|
||||
}
|
||||
|
||||
return mSelectedFilteredList;
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.gui.playlist.streaming;
|
||||
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastServerType;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
|
||||
/**
|
||||
* Factory for creating broadcast configuration editors
|
||||
*/
|
||||
public class StreamEditorFactory
|
||||
{
|
||||
/**
|
||||
* Creates a new editor for the specified broadcast server type
|
||||
* @param broadcastServerType to edit
|
||||
* @return editor or the default unknown editor
|
||||
*/
|
||||
public static AbstractBroadcastEditor getEditor(BroadcastServerType broadcastServerType, PlaylistManager playlistManager)
|
||||
{
|
||||
switch(broadcastServerType)
|
||||
{
|
||||
case BROADCASTIFY:
|
||||
return new BroadcastifyStreamEditor(playlistManager);
|
||||
case RDIOSCANNER_CALL:
|
||||
return new RdioScannerEditor(playlistManager);
|
||||
case OPENMHZ:
|
||||
return new OpenMHzEditor(playlistManager);
|
||||
case BROADCASTIFY_CALL:
|
||||
return new BroadcastifyCallEditor(playlistManager);
|
||||
case ICECAST_HTTP:
|
||||
return new IcecastHTTPStreamEditor(playlistManager);
|
||||
case ICECAST_TCP:
|
||||
return new IcecastTCPStreamEditor(playlistManager);
|
||||
case SHOUTCAST_V1:
|
||||
return new ShoutcastV1StreamEditor(playlistManager);
|
||||
case SHOUTCAST_V2:
|
||||
return new ShoutcastV2StreamEditor(playlistManager);
|
||||
default:
|
||||
return new UnknownStreamEditor(playlistManager);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,12 +22,15 @@ package io.github.dsheirer.gui.playlist.streaming;
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastConfiguration;
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastFactory;
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastFormat;
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastModel;
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastServerType;
|
||||
import io.github.dsheirer.audio.broadcast.ConfiguredBroadcast;
|
||||
import io.github.dsheirer.audio.broadcast.broadcastify.BroadcastifyFeedConfiguration;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.rrapi.type.UserFeedBroadcast;
|
||||
import io.github.dsheirer.service.radioreference.RadioReference;
|
||||
import io.github.dsheirer.util.ThreadPool;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
@@ -71,7 +74,15 @@ public class StreamingEditor extends SplitPane
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(StreamingEditor.class);
|
||||
|
||||
private final PlaylistManager mPlaylistManager;
|
||||
@Resource
|
||||
private BroadcastModel mBroadcastModel;
|
||||
@Resource
|
||||
private RadioReference mRadioReference;
|
||||
@Resource
|
||||
private StreamAliasSelectionEditor mStreamAliasSelectionEditor;
|
||||
@Resource
|
||||
private List<AbstractBroadcastEditor> mBroadcastEditors;
|
||||
|
||||
private TableView<ConfiguredBroadcast> mConfiguredBroadcastTableView;
|
||||
private MenuButton mNewButton;
|
||||
private Button mDeleteButton;
|
||||
@@ -81,24 +92,35 @@ public class StreamingEditor extends SplitPane
|
||||
private Tab mAliasTab;
|
||||
private Label mRadioReferenceLoginLabel;
|
||||
private AbstractBroadcastEditor<?> mCurrentEditor;
|
||||
private final UnknownStreamEditor mUnknownEditor;
|
||||
private UnknownStreamEditor mUnknownEditor;
|
||||
private Map<BroadcastServerType, AbstractBroadcastEditor<?>> mEditorMap = new EnumMap<>(BroadcastServerType.class);
|
||||
private final List<UserFeedBroadcast> mBroadcastifyFeeds = new ArrayList<>();
|
||||
private ScrollPane mEditorScrollPane;
|
||||
private StreamAliasSelectionEditor mStreamAliasSelectionEditor;
|
||||
private final StreamConfigurationEditorModificationListener mStreamConfigurationEditorModificationListener =
|
||||
new StreamConfigurationEditorModificationListener();
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param playlistManager for accessing streaming model
|
||||
*/
|
||||
public StreamingEditor(PlaylistManager playlistManager)
|
||||
public StreamingEditor()
|
||||
{
|
||||
mPlaylistManager = playlistManager;
|
||||
mUnknownEditor = new UnknownStreamEditor(mPlaylistManager);
|
||||
mPlaylistManager.getRadioReference().availableProperty()
|
||||
.addListener((observable, oldValue, newValue) -> refreshBroadcastifyStreams());
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
//Spring instantiates stream editors and we load them into a lookup map
|
||||
for(AbstractBroadcastEditor editor: mBroadcastEditors)
|
||||
{
|
||||
mEditorMap.put(editor.getBroadcastServerType(), editor);
|
||||
|
||||
if(editor instanceof UnknownStreamEditor unknown)
|
||||
{
|
||||
mUnknownEditor = unknown;
|
||||
}
|
||||
}
|
||||
|
||||
mRadioReference.availableProperty().addListener((observable, oldValue, newValue) -> refreshBroadcastifyStreams());
|
||||
refreshBroadcastifyStreams();
|
||||
|
||||
VBox buttonsBox = new VBox();
|
||||
@@ -200,16 +222,7 @@ public class StreamingEditor extends SplitPane
|
||||
|
||||
if(editor == null)
|
||||
{
|
||||
editor = StreamEditorFactory.getEditor(configType, mPlaylistManager);
|
||||
|
||||
if(editor != null)
|
||||
{
|
||||
mEditorMap.put(configType, editor);
|
||||
}
|
||||
}
|
||||
|
||||
if(editor == null)
|
||||
{
|
||||
mLog.warn("Unable to find streaming editor for server type: " + editorType);
|
||||
editor = mUnknownEditor;
|
||||
}
|
||||
|
||||
@@ -230,12 +243,12 @@ public class StreamingEditor extends SplitPane
|
||||
*/
|
||||
private void refreshBroadcastifyStreams()
|
||||
{
|
||||
if(mPlaylistManager.getRadioReference().availableProperty().get())
|
||||
if(mRadioReference.availableProperty().get())
|
||||
{
|
||||
ThreadPool.CACHED.submit(() -> {
|
||||
try
|
||||
{
|
||||
List<UserFeedBroadcast> feeds = mPlaylistManager.getRadioReference().getService().getUserFeeds();
|
||||
List<UserFeedBroadcast> feeds = mRadioReference.getService().getUserFeeds();
|
||||
mBroadcastifyFeeds.clear();
|
||||
mBroadcastifyFeeds.addAll(feeds);
|
||||
}
|
||||
@@ -249,11 +262,6 @@ public class StreamingEditor extends SplitPane
|
||||
|
||||
private StreamAliasSelectionEditor getStreamAliasSelectionEditor()
|
||||
{
|
||||
if(mStreamAliasSelectionEditor == null)
|
||||
{
|
||||
mStreamAliasSelectionEditor = new StreamAliasSelectionEditor(mPlaylistManager);
|
||||
}
|
||||
|
||||
return mStreamAliasSelectionEditor;
|
||||
}
|
||||
|
||||
@@ -262,7 +270,7 @@ public class StreamingEditor extends SplitPane
|
||||
if(mRadioReferenceLoginLabel == null)
|
||||
{
|
||||
mRadioReferenceLoginLabel = new Label("Note: use Radio Reference tab to login and access Broadcastify stream configuration(s)");
|
||||
mRadioReferenceLoginLabel.visibleProperty().bind(mPlaylistManager.getRadioReference().availableProperty().not());
|
||||
mRadioReferenceLoginLabel.visibleProperty().bind(mRadioReference.availableProperty().not());
|
||||
}
|
||||
|
||||
return mRadioReferenceLoginLabel;
|
||||
@@ -325,7 +333,7 @@ public class StreamingEditor extends SplitPane
|
||||
for(UserFeedBroadcast feed: mBroadcastifyFeeds)
|
||||
{
|
||||
//Only show a menu item for the feed if it's not already defined
|
||||
if(mPlaylistManager.getBroadcastModel().getBroadcastConfiguration(feed.getDescription()) == null)
|
||||
if(mBroadcastModel.getBroadcastConfiguration(feed.getDescription()) == null)
|
||||
{
|
||||
mNewButton.getItems().add(new CreateBroadcastifyMenuItem(feed));
|
||||
}
|
||||
@@ -382,7 +390,7 @@ public class StreamingEditor extends SplitPane
|
||||
|
||||
if(result.get() == ButtonType.YES)
|
||||
{
|
||||
mPlaylistManager.getBroadcastModel().removeBroadcastConfiguration(config);
|
||||
mBroadcastModel.removeBroadcastConfiguration(config);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -398,7 +406,7 @@ public class StreamingEditor extends SplitPane
|
||||
mConfiguredBroadcastTableView = new TableView<>();
|
||||
mConfiguredBroadcastTableView.setPlaceholder(new Label("Click the New button to create a new " +
|
||||
"audio streaming configuration"));
|
||||
mConfiguredBroadcastTableView.setItems(mPlaylistManager.getBroadcastModel().getConfiguredBroadcasts());
|
||||
mConfiguredBroadcastTableView.setItems(mBroadcastModel.getConfiguredBroadcasts());
|
||||
|
||||
TableColumn<ConfiguredBroadcast,Boolean> enabledColumn = new TableColumn("Enabled");
|
||||
enabledColumn.setCellValueFactory(new PropertyValueFactory<>("enabled"));
|
||||
@@ -465,8 +473,7 @@ public class StreamingEditor extends SplitPane
|
||||
|
||||
if(configuration != null)
|
||||
{
|
||||
ConfiguredBroadcast configuredBroadcast = mPlaylistManager.getBroadcastModel()
|
||||
.addBroadcastConfiguration(configuration);
|
||||
ConfiguredBroadcast configuredBroadcast = mBroadcastModel.addBroadcastConfiguration(configuration);
|
||||
getConfiguredBroadcastTableView().getSelectionModel().select(configuredBroadcast);
|
||||
}
|
||||
});
|
||||
@@ -487,8 +494,7 @@ public class StreamingEditor extends SplitPane
|
||||
|
||||
setOnAction(event -> {
|
||||
BroadcastConfiguration config = BroadcastFactory.getConfiguration(mBroadcastServerType, BroadcastFormat.MP3);
|
||||
ConfiguredBroadcast configuredBroadcast = mPlaylistManager.getBroadcastModel()
|
||||
.addBroadcastConfiguration(config);
|
||||
ConfiguredBroadcast configuredBroadcast = mBroadcastModel.addBroadcastConfiguration(config);
|
||||
getConfiguredBroadcastTableView().getSelectionModel().select(configuredBroadcast);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,23 +1,20 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 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.gui.playlist.streaming;
|
||||
@@ -25,7 +22,6 @@ package io.github.dsheirer.gui.playlist.streaming;
|
||||
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastConfiguration;
|
||||
import io.github.dsheirer.audio.broadcast.BroadcastServerType;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.control.Label;
|
||||
@@ -38,11 +34,6 @@ public class UnknownStreamEditor extends AbstractStreamEditor<BroadcastConfigura
|
||||
{
|
||||
private GridPane mEditorPane;
|
||||
|
||||
public UnknownStreamEditor(PlaylistManager playlistManager)
|
||||
{
|
||||
super(playlistManager);
|
||||
}
|
||||
|
||||
public BroadcastServerType getBroadcastServerType()
|
||||
{
|
||||
return BroadcastServerType.UNKNOWN;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
package io.github.dsheirer.gui.power;
|
||||
|
||||
import io.github.dsheirer.controller.channel.Channel;
|
||||
import io.github.dsheirer.controller.channel.ChannelProcessingManager;
|
||||
import io.github.dsheirer.dsp.filter.channelizer.PolyphaseChannelSource;
|
||||
import io.github.dsheirer.dsp.squelch.ISquelchConfiguration;
|
||||
import io.github.dsheirer.gui.control.DbPowerMeter;
|
||||
@@ -27,7 +28,6 @@ import io.github.dsheirer.module.ProcessingChain;
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.sample.complex.ComplexSamplesToNativeBufferModule;
|
||||
import io.github.dsheirer.settings.SettingsManager;
|
||||
import io.github.dsheirer.source.Source;
|
||||
import io.github.dsheirer.source.SourceEvent;
|
||||
import io.github.dsheirer.source.tuner.channel.HalfBandTunerChannelSource;
|
||||
@@ -38,6 +38,8 @@ import io.github.dsheirer.spectrum.FrequencyOverlayPanel;
|
||||
import io.github.dsheirer.spectrum.SpectrumPanel;
|
||||
import io.github.dsheirer.spectrum.converter.ComplexDecibelConverter;
|
||||
import io.github.dsheirer.spectrum.converter.DFTResultsConverter;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.awt.Component;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.event.ComponentEvent;
|
||||
@@ -73,14 +75,19 @@ public class ChannelPowerPanel extends JPanel implements Listener<ProcessingChai
|
||||
private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("0.0");
|
||||
private static final DecimalFormat FREQUENCY_FORMAT = new DecimalFormat("0.00000");
|
||||
private static final String NOT_AVAILABLE = "Not Available";
|
||||
@Resource
|
||||
private ChannelProcessingManager mChannelProcessingManager;
|
||||
@Resource
|
||||
private FrequencyOverlayPanel mFrequencyOverlayPanel;
|
||||
@Resource
|
||||
private PlaylistManager mPlaylistManager;
|
||||
@Resource
|
||||
private SpectrumPanel mSpectrumPanel;
|
||||
private ProcessingChain mProcessingChain;
|
||||
private ComplexSamplesToNativeBufferModule mSampleStreamTapModule = new ComplexSamplesToNativeBufferModule();
|
||||
private ComplexDftProcessor mComplexDftProcessor = new ComplexDftProcessor();
|
||||
private DFTResultsConverter mDFTResultsConverter = new ComplexDecibelConverter();
|
||||
private JLayeredPane mLayeredPanel;
|
||||
private SpectrumPanel mSpectrumPanel;
|
||||
private FrequencyOverlayPanel mFrequencyOverlayPanel;
|
||||
private JLayeredPane mLayeredPanel = new JLayeredPane();
|
||||
private DbPowerMeter mPowerMeter = new DbPowerMeter();
|
||||
private PeakMonitor mPeakMonitor = new PeakMonitor(DbPowerMeter.DEFAULT_MINIMUM_POWER);
|
||||
private SourceEventProcessor mSourceEventProcessor = new SourceEventProcessor();
|
||||
@@ -103,10 +110,13 @@ public class ChannelPowerPanel extends JPanel implements Listener<ProcessingChai
|
||||
/**
|
||||
* Constructs an instance.
|
||||
*/
|
||||
public ChannelPowerPanel(PlaylistManager playlistManager, SettingsManager settingsManager)
|
||||
public ChannelPowerPanel()
|
||||
{
|
||||
mPlaylistManager = playlistManager;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
setLayout(new MigLayout("", "[][][][grow,fill]", "[grow,fill]"));
|
||||
mPowerMeter.setPeakVisible(true);
|
||||
mPowerMeter.setSquelchThresholdVisible(true);
|
||||
@@ -227,16 +237,12 @@ public class ChannelPowerPanel extends JPanel implements Listener<ProcessingChai
|
||||
|
||||
fftPanel.add(labelPanel, "wrap");
|
||||
|
||||
mFrequencyOverlayPanel = new FrequencyOverlayPanel(settingsManager);
|
||||
|
||||
mSpectrumPanel = new SpectrumPanel(settingsManager);
|
||||
mSpectrumPanel.setSampleSize(18.0);
|
||||
|
||||
/**
|
||||
* The layered pane holds the overlapping spectrum and channel panels
|
||||
* and manages the sizing of each panel with the resize listener
|
||||
*/
|
||||
mLayeredPanel = new JLayeredPane();
|
||||
mLayeredPanel.addComponentListener(new ResizeListener());
|
||||
|
||||
/**
|
||||
@@ -346,7 +352,7 @@ public class ChannelPowerPanel extends JPanel implements Listener<ProcessingChai
|
||||
{
|
||||
if(mProcessingChain != null)
|
||||
{
|
||||
Channel channel = mPlaylistManager.getChannelProcessingManager().getChannel(mProcessingChain);
|
||||
Channel channel = mChannelProcessingManager.getChannel(mProcessingChain);
|
||||
|
||||
if(channel != null && channel.getDecodeConfiguration() instanceof ISquelchConfiguration)
|
||||
{
|
||||
@@ -363,7 +369,7 @@ public class ChannelPowerPanel extends JPanel implements Listener<ProcessingChai
|
||||
*/
|
||||
private void setConfigSquelchAutoTrack(boolean autoTrack)
|
||||
{
|
||||
Channel channel = mPlaylistManager.getChannelProcessingManager().getChannel(mProcessingChain);
|
||||
Channel channel = mChannelProcessingManager.getChannel(mProcessingChain);
|
||||
|
||||
if(channel != null && channel.getDecodeConfiguration() instanceof ISquelchConfiguration)
|
||||
{
|
||||
@@ -440,7 +446,7 @@ public class ChannelPowerPanel extends JPanel implements Listener<ProcessingChai
|
||||
mFrequencyOverlayPanel.process(SourceEvent.sampleRateChange(tcs.getSampleRate()));
|
||||
}
|
||||
|
||||
Channel channel = mPlaylistManager.getChannelProcessingManager().getChannel(mProcessingChain);
|
||||
Channel channel = mChannelProcessingManager.getChannel(mProcessingChain);
|
||||
|
||||
if(channel != null)
|
||||
{
|
||||
|
||||
@@ -1,50 +1,62 @@
|
||||
/*******************************************************************************
|
||||
* sdr-trunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 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 <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
* 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.gui.preference;
|
||||
|
||||
import io.github.dsheirer.preference.TimestampFormat;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.preference.event.DecodeEventPreference;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import java.util.Date;
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.control.ChoiceBox;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
/**
|
||||
* Preference settings for channel event view
|
||||
*/
|
||||
public class DecodeEventViewPreferenceEditor extends HBox
|
||||
public class DecodeEventViewPreferenceEditor extends PreferenceEditor
|
||||
{
|
||||
private DecodeEventPreference mDecodeEventPreference;
|
||||
private GridPane mEditorPane;
|
||||
private ChoiceBox<DisplayableTimestamp> mTimestampFormatChoiceBox;
|
||||
private Label mTimestampFormatLabel;
|
||||
|
||||
public DecodeEventViewPreferenceEditor(UserPreferences userPreferences)
|
||||
public DecodeEventViewPreferenceEditor()
|
||||
{
|
||||
mDecodeEventPreference = userPreferences.getDecodeEventPreference();
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
mDecodeEventPreference = getUserPreferences().getDecodeEventPreference();
|
||||
getChildren().add(getEditorPane());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreferenceEditorType getPreferenceEditorType()
|
||||
{
|
||||
return PreferenceEditorType.CHANNEL_EVENT;
|
||||
}
|
||||
|
||||
private GridPane getEditorPane()
|
||||
{
|
||||
if(mEditorPane == null)
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.gui.preference;
|
||||
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import jakarta.annotation.Resource;
|
||||
import javafx.scene.layout.VBox;
|
||||
|
||||
/**
|
||||
* Preference editor base class.
|
||||
*/
|
||||
public abstract class PreferenceEditor extends VBox
|
||||
{
|
||||
@Resource
|
||||
private UserPreferences mUserPreferences;
|
||||
|
||||
protected UserPreferences getUserPreferences()
|
||||
{
|
||||
return mUserPreferences;
|
||||
}
|
||||
|
||||
public abstract PreferenceEditorType getPreferenceEditorType();
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.gui.preference;
|
||||
|
||||
import io.github.dsheirer.gui.preference.application.ApplicationPreferenceEditor;
|
||||
import io.github.dsheirer.gui.preference.calibration.VectorCalibrationPreferenceEditor;
|
||||
import io.github.dsheirer.gui.preference.call.CallManagementPreferenceEditor;
|
||||
import io.github.dsheirer.gui.preference.decoder.JmbeLibraryPreferenceEditor;
|
||||
import io.github.dsheirer.gui.preference.directory.DirectoryPreferenceEditor;
|
||||
import io.github.dsheirer.gui.preference.mp3.MP3PreferenceEditor;
|
||||
import io.github.dsheirer.gui.preference.playback.PlaybackPreferenceEditor;
|
||||
import io.github.dsheirer.gui.preference.record.RecordPreferenceEditor;
|
||||
import io.github.dsheirer.gui.preference.tuner.TunerPreferenceEditor;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import javafx.scene.Node;
|
||||
|
||||
/**
|
||||
* Creates an editor for the specified preference editor type
|
||||
*/
|
||||
public class PreferenceEditorFactory
|
||||
{
|
||||
public static Node getEditor(PreferenceEditorType preferenceEditorType, UserPreferences userPreferences)
|
||||
{
|
||||
switch(preferenceEditorType)
|
||||
{
|
||||
case APPLICATION:
|
||||
return new ApplicationPreferenceEditor(userPreferences);
|
||||
case AUDIO_CALL_MANAGEMENT:
|
||||
return new CallManagementPreferenceEditor(userPreferences);
|
||||
case AUDIO_MP3:
|
||||
return new MP3PreferenceEditor(userPreferences);
|
||||
case AUDIO_OUTPUT:
|
||||
return new PlaybackPreferenceEditor(userPreferences);
|
||||
case AUDIO_RECORD:
|
||||
return new RecordPreferenceEditor(userPreferences);
|
||||
case CHANNEL_EVENT:
|
||||
return new DecodeEventViewPreferenceEditor(userPreferences);
|
||||
case DIRECTORY:
|
||||
return new DirectoryPreferenceEditor(userPreferences);
|
||||
case JMBE_LIBRARY:
|
||||
return new JmbeLibraryPreferenceEditor(userPreferences);
|
||||
case SOURCE_TUNERS:
|
||||
return new TunerPreferenceEditor(userPreferences);
|
||||
case TALKGROUP_FORMAT:
|
||||
return new TalkgroupFormatPreferenceEditor(userPreferences);
|
||||
case VECTOR_CALIBRATION:
|
||||
return new VectorCalibrationPreferenceEditor(userPreferences);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -30,9 +30,9 @@ public enum PreferenceEditorType
|
||||
JMBE_LIBRARY("JMBE Audio Library"),
|
||||
AUDIO_MP3("MP3"),
|
||||
AUDIO_RECORD("Record"),
|
||||
AUDIO_OUTPUT("Output/Tones"),
|
||||
AUDIO_PLAYBACK("Playback/Tones"),
|
||||
AUDIO_CALL_MANAGEMENT("Call Management"),
|
||||
SOURCE_TUNERS("Tuners"),
|
||||
TUNERS("Tuners"),
|
||||
TALKGROUP_FORMAT("Talkgroup & Radio ID"),
|
||||
VECTOR_CALIBRATION("Vector Calibration"),
|
||||
DEFAULT("Default");
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 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,15 +14,16 @@
|
||||
*
|
||||
* 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.gui.preference;
|
||||
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.preference.identifier.IntegerFormat;
|
||||
import io.github.dsheirer.preference.identifier.TalkgroupFormatPreference;
|
||||
import io.github.dsheirer.protocol.Protocol;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import java.util.Set;
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Orientation;
|
||||
@@ -32,25 +32,33 @@ import javafx.scene.control.ChoiceBox;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.Separator;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/**
|
||||
* Preference settings for channel event view
|
||||
*/
|
||||
public class TalkgroupFormatPreferenceEditor extends HBox
|
||||
public class TalkgroupFormatPreferenceEditor extends PreferenceEditor
|
||||
{
|
||||
private TalkgroupFormatPreference mTalkgroupFormatPreference;
|
||||
private GridPane mEditorPane;
|
||||
|
||||
public TalkgroupFormatPreferenceEditor(UserPreferences userPreferences)
|
||||
public TalkgroupFormatPreferenceEditor()
|
||||
{
|
||||
mTalkgroupFormatPreference = userPreferences.getTalkgroupFormatPreference();
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
mTalkgroupFormatPreference = getUserPreferences().getTalkgroupFormatPreference();
|
||||
getChildren().add(getEditorPane());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreferenceEditorType getPreferenceEditorType()
|
||||
{
|
||||
return PreferenceEditorType.TALKGROUP_FORMAT;
|
||||
}
|
||||
|
||||
private GridPane getEditorPane()
|
||||
{
|
||||
if(mEditorPane == null)
|
||||
|
||||
@@ -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
|
||||
@@ -21,8 +21,10 @@ package io.github.dsheirer.gui.preference;
|
||||
|
||||
import io.github.dsheirer.eventbus.MyEventBus;
|
||||
import io.github.dsheirer.gui.playlist.ViewPlaylistRequest;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
@@ -53,8 +55,9 @@ public class UserPreferencesEditor extends BorderPane
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(UserPreferencesEditor.class);
|
||||
|
||||
private Map<PreferenceEditorType,Node> mEditors = new EnumMap<>(PreferenceEditorType.class);
|
||||
private UserPreferences mUserPreferences;
|
||||
@Resource
|
||||
private List<PreferenceEditor> mPreferenceEditors;
|
||||
private Map<PreferenceEditorType,Node> mEditorMap = new EnumMap<>(PreferenceEditorType.class);
|
||||
private MenuBar mMenuBar;
|
||||
private TreeView mEditorSelectionTreeView;
|
||||
private VBox mEditorAndButtonsBox;
|
||||
@@ -63,31 +66,29 @@ public class UserPreferencesEditor extends BorderPane
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
*
|
||||
* @param userPreferences to edit
|
||||
*/
|
||||
public UserPreferencesEditor(UserPreferences userPreferences)
|
||||
public UserPreferencesEditor()
|
||||
{
|
||||
mUserPreferences = userPreferences;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
//Spring auto-constructs all of our editors for us with the @Resource tagged member variable.
|
||||
for(PreferenceEditor editor: mPreferenceEditors)
|
||||
{
|
||||
mEditorMap.put(editor.getPreferenceEditorType(), editor);
|
||||
}
|
||||
|
||||
mEditorMap.put(PreferenceEditorType.DEFAULT, getDefaultEditor());
|
||||
|
||||
setTop(getMenuBar());
|
||||
|
||||
HBox contentBox = new HBox();
|
||||
HBox.setHgrow(getEditorAndButtonsBox(), Priority.ALWAYS);
|
||||
contentBox.getChildren().addAll(getEditorSelectionTreeView(), getEditorAndButtonsBox());
|
||||
setCenter(contentBox);
|
||||
}
|
||||
|
||||
private UserPreferences getUserPreferences()
|
||||
{
|
||||
if(mUserPreferences == null)
|
||||
{
|
||||
mUserPreferences = new UserPreferences();
|
||||
}
|
||||
|
||||
return mUserPreferences;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the editor specified in the request by scrolling the editor view tree to the selected item.
|
||||
*/
|
||||
@@ -141,7 +142,7 @@ public class UserPreferencesEditor extends BorderPane
|
||||
|
||||
private Node getDefaultEditor()
|
||||
{
|
||||
Node editor = mEditors.get(PreferenceEditorType.DEFAULT);
|
||||
Node editor = mEditorMap.get(PreferenceEditorType.DEFAULT);
|
||||
|
||||
if(editor == null)
|
||||
{
|
||||
@@ -149,7 +150,7 @@ public class UserPreferencesEditor extends BorderPane
|
||||
defaultEditor.setPadding(new Insets(10, 10, 10, 10));
|
||||
Label label = new Label("Please select a preference ...");
|
||||
defaultEditor.getChildren().add(label);
|
||||
mEditors.put(PreferenceEditorType.DEFAULT, defaultEditor);
|
||||
mEditorMap.put(PreferenceEditorType.DEFAULT, defaultEditor);
|
||||
editor = defaultEditor;
|
||||
}
|
||||
|
||||
@@ -173,7 +174,7 @@ public class UserPreferencesEditor extends BorderPane
|
||||
TreeItem<String> audioItem = new TreeItem<>("Audio");
|
||||
audioItem.getChildren().add(new TreeItem(PreferenceEditorType.AUDIO_CALL_MANAGEMENT));
|
||||
audioItem.getChildren().add(new TreeItem(PreferenceEditorType.AUDIO_MP3));
|
||||
audioItem.getChildren().add(new TreeItem(PreferenceEditorType.AUDIO_OUTPUT));
|
||||
audioItem.getChildren().add(new TreeItem(PreferenceEditorType.AUDIO_PLAYBACK));
|
||||
audioItem.getChildren().add(new TreeItem(PreferenceEditorType.AUDIO_RECORD));
|
||||
treeRoot.getChildren().add(audioItem);
|
||||
audioItem.setExpanded(true);
|
||||
@@ -200,7 +201,7 @@ public class UserPreferencesEditor extends BorderPane
|
||||
storageItem.setExpanded(true);
|
||||
|
||||
TreeItem<String> sourceItem = new TreeItem<>("Source");
|
||||
sourceItem.getChildren().add(new TreeItem(PreferenceEditorType.SOURCE_TUNERS));
|
||||
sourceItem.getChildren().add(new TreeItem(PreferenceEditorType.TUNERS));
|
||||
treeRoot.getChildren().add(sourceItem);
|
||||
sourceItem.setExpanded(true);
|
||||
|
||||
@@ -266,19 +267,11 @@ public class UserPreferencesEditor extends BorderPane
|
||||
|
||||
private void setEditor(PreferenceEditorType type)
|
||||
{
|
||||
Node editor = mEditors.get(type);
|
||||
Node editor = mEditorMap.get(type);
|
||||
|
||||
if(editor == null)
|
||||
{
|
||||
if(type == PreferenceEditorType.DEFAULT)
|
||||
{
|
||||
editor = getDefaultEditor();
|
||||
}
|
||||
else
|
||||
{
|
||||
editor = PreferenceEditorFactory.getEditor(type, getUserPreferences());
|
||||
mEditors.put(type, editor);
|
||||
}
|
||||
editor = mEditorMap.get(PreferenceEditorType.DEFAULT);
|
||||
}
|
||||
|
||||
getEditorAndButtonsBox().getChildren().remove(mEditor);
|
||||
|
||||
@@ -19,20 +19,21 @@
|
||||
|
||||
package io.github.dsheirer.gui.preference.application;
|
||||
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.gui.preference.PreferenceEditor;
|
||||
import io.github.dsheirer.gui.preference.PreferenceEditorType;
|
||||
import io.github.dsheirer.preference.application.ApplicationPreference;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.Spinner;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
|
||||
|
||||
/**
|
||||
* Preference settings for application
|
||||
*/
|
||||
public class ApplicationPreferenceEditor extends HBox
|
||||
public class ApplicationPreferenceEditor extends PreferenceEditor
|
||||
{
|
||||
private ApplicationPreference mApplicationPreference;
|
||||
private GridPane mEditorPane;
|
||||
@@ -41,14 +42,24 @@ public class ApplicationPreferenceEditor extends HBox
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param userPreferences for obtaining reference to preference.
|
||||
*/
|
||||
public ApplicationPreferenceEditor(UserPreferences userPreferences)
|
||||
public ApplicationPreferenceEditor()
|
||||
{
|
||||
mApplicationPreference = userPreferences.getApplicationPreference();
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
mApplicationPreference = getUserPreferences().getApplicationPreference();
|
||||
getChildren().add(getEditorPane());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreferenceEditorType getPreferenceEditorType()
|
||||
{
|
||||
return PreferenceEditorType.APPLICATION;
|
||||
}
|
||||
|
||||
private GridPane getEditorPane()
|
||||
{
|
||||
if(mEditorPane == null)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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,13 +24,16 @@ import ch.qos.logback.classic.LoggerContext;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import io.github.dsheirer.eventbus.MyEventBus;
|
||||
import io.github.dsheirer.gui.preference.CalibrateRequest;
|
||||
import io.github.dsheirer.gui.preference.PreferenceEditor;
|
||||
import io.github.dsheirer.gui.preference.PreferenceEditorType;
|
||||
import io.github.dsheirer.log.TextAreaLogAppender;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.preference.calibration.VectorCalibrationPreference;
|
||||
import io.github.dsheirer.util.ThreadPool;
|
||||
import io.github.dsheirer.vector.calibrate.Calibration;
|
||||
import io.github.dsheirer.vector.calibrate.CalibrationException;
|
||||
import io.github.dsheirer.vector.calibrate.CalibrationManager;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import java.util.List;
|
||||
import javafx.application.Platform;
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.geometry.Insets;
|
||||
@@ -48,12 +51,10 @@ import org.controlsfx.control.ToggleSwitch;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Preference settings for duplicate call audio handling
|
||||
*/
|
||||
public class VectorCalibrationPreferenceEditor extends HBox
|
||||
public class VectorCalibrationPreferenceEditor extends PreferenceEditor
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(VectorCalibrationPreferenceEditor.class);
|
||||
private VectorCalibrationPreference mPreference;
|
||||
@@ -71,10 +72,15 @@ public class VectorCalibrationPreferenceEditor extends HBox
|
||||
/**
|
||||
* Constructs an instance
|
||||
*/
|
||||
public VectorCalibrationPreferenceEditor(UserPreferences userPreferences)
|
||||
public VectorCalibrationPreferenceEditor()
|
||||
{
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
MyEventBus.getGlobalEventBus().register(this);
|
||||
mPreference = userPreferences.getVectorCalibrationPreference();
|
||||
mPreference = getUserPreferences().getVectorCalibrationPreference();
|
||||
setMaxHeight(Double.MAX_VALUE);
|
||||
setMaxWidth(Double.MAX_VALUE);
|
||||
|
||||
@@ -95,6 +101,12 @@ public class VectorCalibrationPreferenceEditor extends HBox
|
||||
getChildren().add(vbox);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreferenceEditorType getPreferenceEditorType()
|
||||
{
|
||||
return PreferenceEditorType.VECTOR_CALIBRATION;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void process(CalibrateRequest request)
|
||||
{
|
||||
|
||||
@@ -20,8 +20,10 @@
|
||||
package io.github.dsheirer.gui.preference.call;
|
||||
|
||||
import io.github.dsheirer.audio.broadcast.PatchGroupStreamingOption;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.gui.preference.PreferenceEditor;
|
||||
import io.github.dsheirer.gui.preference.PreferenceEditorType;
|
||||
import io.github.dsheirer.preference.duplicate.CallManagementPreference;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
@@ -39,7 +41,7 @@ import org.slf4j.LoggerFactory;
|
||||
/**
|
||||
* Preference settings for audio call management for duplicate calls and patch group streaming.
|
||||
*/
|
||||
public class CallManagementPreferenceEditor extends HBox
|
||||
public class CallManagementPreferenceEditor extends PreferenceEditor
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(CallManagementPreferenceEditor.class);
|
||||
private CallManagementPreference mPreference;
|
||||
@@ -54,14 +56,24 @@ public class CallManagementPreferenceEditor extends HBox
|
||||
/**
|
||||
* Constructs an instance
|
||||
*/
|
||||
public CallManagementPreferenceEditor(UserPreferences userPreferences)
|
||||
public CallManagementPreferenceEditor()
|
||||
{
|
||||
mPreference = userPreferences.getDuplicateCallDetectionPreference();
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
mPreference = getUserPreferences().getCallManagementPreference();
|
||||
HBox.setHgrow(getEditorPane(), Priority.ALWAYS);
|
||||
getChildren().add(getEditorPane());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreferenceEditorType getPreferenceEditorType()
|
||||
{
|
||||
return PreferenceEditorType.AUDIO_CALL_MANAGEMENT;
|
||||
}
|
||||
|
||||
private GridPane getEditorPane()
|
||||
{
|
||||
if(mEditorPane == null)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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
|
||||
@@ -21,14 +21,19 @@ package io.github.dsheirer.gui.preference.decoder;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import io.github.dsheirer.eventbus.MyEventBus;
|
||||
import io.github.dsheirer.gui.preference.PreferenceEditor;
|
||||
import io.github.dsheirer.gui.preference.PreferenceEditorType;
|
||||
import io.github.dsheirer.jmbe.JmbeCreator;
|
||||
import io.github.dsheirer.jmbe.JmbeEditorRequest;
|
||||
import io.github.dsheirer.jmbe.github.GitHub;
|
||||
import io.github.dsheirer.jmbe.github.Release;
|
||||
import io.github.dsheirer.jmbe.github.Version;
|
||||
import io.github.dsheirer.preference.PreferenceType;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.util.ThreadPool;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import javafx.application.Platform;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
@@ -42,21 +47,16 @@ import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Region;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.stage.FileChooser;
|
||||
import javafx.stage.Stage;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
|
||||
/**
|
||||
* Preference settings for decoders
|
||||
*/
|
||||
public class JmbeLibraryPreferenceEditor extends VBox
|
||||
public class JmbeLibraryPreferenceEditor extends PreferenceEditor
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(JmbeLibraryPreferenceEditor.class);
|
||||
|
||||
@@ -64,8 +64,6 @@ public class JmbeLibraryPreferenceEditor extends VBox
|
||||
private static final String CREATE_LIBRARY = "Create Library";
|
||||
private static final String CHECK_FOR_UPDATE = "Check For Library Update";
|
||||
private static final String LIBRARY_NOT_SETUP = "None. Click Select or Create Library button to setup.";
|
||||
|
||||
private UserPreferences mUserPreferences;
|
||||
private GridPane mEditorPane;
|
||||
private Label mJmbeLibraryLabel;
|
||||
private Label mJmbeVersionLabel;
|
||||
@@ -76,18 +74,26 @@ public class JmbeLibraryPreferenceEditor extends VBox
|
||||
private HBox mButtonsBox;
|
||||
private CheckBox mAlertUserWhenMissingCheckBox;
|
||||
|
||||
public JmbeLibraryPreferenceEditor(UserPreferences userPreferences)
|
||||
public JmbeLibraryPreferenceEditor()
|
||||
{
|
||||
mUserPreferences = userPreferences;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
//Register to receive directory preference update notifications so we can update the path labels
|
||||
MyEventBus.getGlobalEventBus().register(this);
|
||||
|
||||
setPadding(new Insets(10,10,10,10));
|
||||
setSpacing(10);
|
||||
getChildren().addAll(getEditorPane(), getButtonsBox(), getAlertUserWhenMissingCheckBox());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreferenceEditorType getPreferenceEditorType()
|
||||
{
|
||||
return PreferenceEditorType.JMBE_LIBRARY;
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
MyEventBus.getGlobalEventBus().unregister(this);
|
||||
@@ -98,11 +104,11 @@ public class JmbeLibraryPreferenceEditor extends VBox
|
||||
if(mAlertUserWhenMissingCheckBox == null)
|
||||
{
|
||||
mAlertUserWhenMissingCheckBox = new CheckBox("Alert when decoder requires missing JMBE library");
|
||||
mAlertUserWhenMissingCheckBox.setSelected(mUserPreferences.getJmbeLibraryPreference()
|
||||
mAlertUserWhenMissingCheckBox.setSelected(getUserPreferences().getJmbeLibraryPreference()
|
||||
.getAlertIfMissingLibraryRequired());
|
||||
mAlertUserWhenMissingCheckBox.setOnAction(event -> {
|
||||
boolean alert = mAlertUserWhenMissingCheckBox.isSelected();
|
||||
mUserPreferences.getJmbeLibraryPreference().setAlertIfMissingLibraryRequired(alert);
|
||||
getUserPreferences().getJmbeLibraryPreference().setAlertIfMissingLibraryRequired(alert);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -154,7 +160,7 @@ public class JmbeLibraryPreferenceEditor extends VBox
|
||||
if(mCreateButton == null)
|
||||
{
|
||||
mCreateButton = new Button();
|
||||
mCreateButton.setText(mUserPreferences.getJmbeLibraryPreference()
|
||||
mCreateButton.setText(getUserPreferences().getJmbeLibraryPreference()
|
||||
.getPathJmbeLibrary() != null ? CHECK_FOR_UPDATE : CREATE_LIBRARY);
|
||||
mCreateButton.setOnAction(event -> checkForUpdatedLibrary());
|
||||
}
|
||||
@@ -170,7 +176,7 @@ public class JmbeLibraryPreferenceEditor extends VBox
|
||||
ThreadPool.CACHED.execute(() -> {
|
||||
try
|
||||
{
|
||||
Version current = mUserPreferences.getJmbeLibraryPreference().getCurrentVersion();
|
||||
Version current = getUserPreferences().getJmbeLibraryPreference().getCurrentVersion();
|
||||
final Release release = GitHub.getLatestRelease(JmbeCreator.GITHUB_JMBE_RELEASES_URL);
|
||||
|
||||
mLog.info("Checking for JMBE Library Updates ...");
|
||||
@@ -268,7 +274,7 @@ public class JmbeLibraryPreferenceEditor extends VBox
|
||||
if(mJmbeVersionLabel == null)
|
||||
{
|
||||
mJmbeVersionLabel = new Label();
|
||||
Version version = mUserPreferences.getJmbeLibraryPreference().getCurrentVersion();
|
||||
Version version = getUserPreferences().getJmbeLibraryPreference().getCurrentVersion();
|
||||
|
||||
if(version != null)
|
||||
{
|
||||
@@ -296,7 +302,7 @@ public class JmbeLibraryPreferenceEditor extends VBox
|
||||
FileChooser fileChooser = new FileChooser();
|
||||
fileChooser.setTitle("Select JMBE Audio Library Location");
|
||||
|
||||
Path path = mUserPreferences.getDirectoryPreference().getDefaultJmbeDirectory();
|
||||
Path path = getUserPreferences().getDirectoryPreference().getDefaultJmbeDirectory();
|
||||
|
||||
if(Files.exists(path))
|
||||
{
|
||||
@@ -308,7 +314,7 @@ public class JmbeLibraryPreferenceEditor extends VBox
|
||||
|
||||
if(selected != null)
|
||||
{
|
||||
mUserPreferences.getJmbeLibraryPreference().setPathJmbeLibrary(selected.toPath());
|
||||
getUserPreferences().getJmbeLibraryPreference().setPathJmbeLibrary(selected.toPath());
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -322,7 +328,7 @@ public class JmbeLibraryPreferenceEditor extends VBox
|
||||
if(mResetButton == null)
|
||||
{
|
||||
mResetButton = new Button("Reset");
|
||||
mResetButton.setOnAction(event -> mUserPreferences.getJmbeLibraryPreference().resetPathJmbeLibrary());
|
||||
mResetButton.setOnAction(event -> getUserPreferences().getJmbeLibraryPreference().resetPathJmbeLibrary());
|
||||
}
|
||||
|
||||
return mResetButton;
|
||||
@@ -332,7 +338,7 @@ public class JmbeLibraryPreferenceEditor extends VBox
|
||||
{
|
||||
if(mPathToJmbeLibraryLabel == null)
|
||||
{
|
||||
Path path = mUserPreferences.getJmbeLibraryPreference().getPathJmbeLibrary();
|
||||
Path path = getUserPreferences().getJmbeLibraryPreference().getPathJmbeLibrary();
|
||||
mPathToJmbeLibraryLabel = new Label(path != null ? path.toString() : PATH_NOT_SET);
|
||||
}
|
||||
|
||||
@@ -344,13 +350,13 @@ public class JmbeLibraryPreferenceEditor extends VBox
|
||||
{
|
||||
if(preferenceType != null && preferenceType == PreferenceType.JMBE_LIBRARY)
|
||||
{
|
||||
Path path = mUserPreferences.getJmbeLibraryPreference().getPathJmbeLibrary();
|
||||
Path path = getUserPreferences().getJmbeLibraryPreference().getPathJmbeLibrary();
|
||||
getPathToJmbeLibraryLabel().setText(path != null ? path.toString() : PATH_NOT_SET);
|
||||
Version version = mUserPreferences.getJmbeLibraryPreference().getCurrentVersion();
|
||||
Version version = getUserPreferences().getJmbeLibraryPreference().getCurrentVersion();
|
||||
getJmbeVersionLabel().setText(version != null ? version.toString() : LIBRARY_NOT_SETUP);
|
||||
getCreateButton().setText(mUserPreferences.getJmbeLibraryPreference()
|
||||
getCreateButton().setText(getUserPreferences().getJmbeLibraryPreference()
|
||||
.getPathJmbeLibrary() != null ? CHECK_FOR_UPDATE : CREATE_LIBRARY);
|
||||
getAlertUserWhenMissingCheckBox().setSelected(mUserPreferences.getJmbeLibraryPreference()
|
||||
getAlertUserWhenMissingCheckBox().setSelected(getUserPreferences().getJmbeLibraryPreference()
|
||||
.getAlertIfMissingLibraryRequired());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,11 +19,13 @@
|
||||
|
||||
package io.github.dsheirer.gui.preference.directory;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import io.github.dsheirer.eventbus.MyEventBus;
|
||||
import io.github.dsheirer.gui.preference.PreferenceEditor;
|
||||
import io.github.dsheirer.gui.preference.PreferenceEditorType;
|
||||
import io.github.dsheirer.preference.IPreferenceUpdateListener;
|
||||
import io.github.dsheirer.preference.PreferenceType;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.preference.directory.DirectoryPreference;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.PreDestroy;
|
||||
import java.io.File;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
@@ -45,7 +47,7 @@ import org.slf4j.LoggerFactory;
|
||||
/**
|
||||
* Preference settings for channel event view
|
||||
*/
|
||||
public class DirectoryPreferenceEditor extends HBox
|
||||
public class DirectoryPreferenceEditor extends PreferenceEditor implements IPreferenceUpdateListener
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(DirectoryPreferenceEditor.class);
|
||||
|
||||
@@ -100,20 +102,29 @@ public class DirectoryPreferenceEditor extends HBox
|
||||
private Spinner<Integer> mRecordingSpinner;
|
||||
private Spinner<Integer> mEventLogSpinner;
|
||||
|
||||
public DirectoryPreferenceEditor(UserPreferences userPreferences)
|
||||
public DirectoryPreferenceEditor()
|
||||
{
|
||||
mDirectoryPreference = userPreferences.getDirectoryPreference();
|
||||
|
||||
//Register to receive directory preference update notifications so we can update the path labels
|
||||
MyEventBus.getGlobalEventBus().register(this);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
getUserPreferences().addUpdateListener(this);
|
||||
mDirectoryPreference = getUserPreferences().getDirectoryPreference();
|
||||
HBox.setHgrow(getEditorPane(), Priority.ALWAYS);
|
||||
getChildren().add(getEditorPane());
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void dispose()
|
||||
{
|
||||
MyEventBus.getGlobalEventBus().unregister(this);
|
||||
getUserPreferences().removeUpdateListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreferenceEditorType getPreferenceEditorType()
|
||||
{
|
||||
return PreferenceEditorType.DIRECTORY;
|
||||
}
|
||||
|
||||
private GridPane getEditorPane()
|
||||
@@ -886,7 +897,7 @@ public class DirectoryPreferenceEditor extends HBox
|
||||
return mStreamingPathLabel;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@Override
|
||||
public void preferenceUpdated(PreferenceType preferenceType)
|
||||
{
|
||||
if(preferenceType != null && preferenceType == PreferenceType.DIRECTORY)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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
|
||||
@@ -21,8 +21,10 @@ package io.github.dsheirer.gui.preference.mp3;
|
||||
|
||||
import io.github.dsheirer.audio.convert.InputAudioFormat;
|
||||
import io.github.dsheirer.audio.convert.MP3Setting;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.gui.preference.PreferenceEditor;
|
||||
import io.github.dsheirer.gui.preference.PreferenceEditorType;
|
||||
import io.github.dsheirer.preference.mp3.MP3Preference;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.control.Alert;
|
||||
@@ -39,7 +41,7 @@ import org.slf4j.LoggerFactory;
|
||||
/**
|
||||
* Preference settings for MP3
|
||||
*/
|
||||
public class MP3PreferenceEditor extends HBox
|
||||
public class MP3PreferenceEditor extends PreferenceEditor
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(MP3PreferenceEditor.class);
|
||||
private MP3Preference mMP3Preference;
|
||||
@@ -50,15 +52,25 @@ public class MP3PreferenceEditor extends HBox
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param userPreferences
|
||||
*/
|
||||
public MP3PreferenceEditor(UserPreferences userPreferences)
|
||||
public MP3PreferenceEditor()
|
||||
{
|
||||
mMP3Preference = userPreferences.getMP3Preference();
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
mMP3Preference = getUserPreferences().getMP3Preference();
|
||||
HBox.setHgrow(getEditorPane(), Priority.ALWAYS);
|
||||
getChildren().add(getEditorPane());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreferenceEditorType getPreferenceEditorType()
|
||||
{
|
||||
return PreferenceEditorType.AUDIO_MP3;
|
||||
}
|
||||
|
||||
private GridPane getEditorPane()
|
||||
{
|
||||
if(mEditorPane == null)
|
||||
|
||||
@@ -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
|
||||
@@ -20,10 +20,13 @@
|
||||
package io.github.dsheirer.gui.preference.playback;
|
||||
|
||||
import io.github.dsheirer.audio.AudioFormats;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.audio.playbackfx.PlaybackView;
|
||||
import io.github.dsheirer.gui.preference.PreferenceEditor;
|
||||
import io.github.dsheirer.gui.preference.PreferenceEditorType;
|
||||
import io.github.dsheirer.preference.playback.PlaybackPreference;
|
||||
import io.github.dsheirer.source.mixer.MixerChannelConfiguration;
|
||||
import io.github.dsheirer.source.mixer.MixerManager;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.ShortBuffer;
|
||||
@@ -35,6 +38,7 @@ import javafx.scene.control.Button;
|
||||
import javafx.scene.control.ComboBox;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.Separator;
|
||||
import javafx.scene.control.Tooltip;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Priority;
|
||||
@@ -53,10 +57,10 @@ import javax.sound.sampled.DataLine;
|
||||
/**
|
||||
* Preference settings for audio playback
|
||||
*/
|
||||
public class PlaybackPreferenceEditor extends HBox
|
||||
public class PlaybackPreferenceEditor extends PreferenceEditor
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(PlaybackPreferenceEditor.class);
|
||||
private final PlaybackPreference mPlaybackPreference;
|
||||
private PlaybackPreference mPlaybackPreference;
|
||||
private GridPane mEditorPane;
|
||||
private ComboBox<MixerChannelConfiguration> mMixerComboBox;
|
||||
private Button mMixerTestButton;
|
||||
@@ -68,27 +72,48 @@ public class PlaybackPreferenceEditor extends HBox
|
||||
private ComboBox<ToneVolume> mStartToneVolumeComboBox;
|
||||
private ComboBox<ToneFrequency> mDropToneFrequencyComboBox;
|
||||
private ComboBox<ToneVolume> mDropToneVolumeComboBox;
|
||||
private ComboBox<PlaybackView> mPlaybackViewComboBox;
|
||||
|
||||
public PlaybackPreferenceEditor(UserPreferences userPreferences)
|
||||
public PlaybackPreferenceEditor()
|
||||
{
|
||||
mPlaybackPreference = userPreferences.getPlaybackPreference();
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
mPlaybackPreference = getUserPreferences().getPlaybackPreference();
|
||||
HBox.setHgrow(getEditorPane(), Priority.ALWAYS);
|
||||
getChildren().add(getEditorPane());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreferenceEditorType getPreferenceEditorType()
|
||||
{
|
||||
return PreferenceEditorType.AUDIO_PLAYBACK;
|
||||
}
|
||||
|
||||
private GridPane getEditorPane()
|
||||
{
|
||||
if(mEditorPane == null)
|
||||
{
|
||||
int row = 0;
|
||||
mEditorPane = new GridPane();
|
||||
mEditorPane.setPadding(new Insets(10, 10, 10, 10));
|
||||
mEditorPane.setHgap(10);
|
||||
mEditorPane.setVgap(10);
|
||||
Label outputLabel = new Label("Audio Output Device");
|
||||
|
||||
int row = 0;
|
||||
|
||||
Label playbackLabel = new Label("Audio Playback (Left/Right) Channel View");
|
||||
mEditorPane.add(playbackLabel, 0, row, 3, 1);
|
||||
Label styleLabel = new Label("View Style:");
|
||||
GridPane.setHalignment(styleLabel, HPos.RIGHT);
|
||||
mEditorPane.add(styleLabel, 0, ++row, 2, 1);
|
||||
mEditorPane.add(getPlaybackViewComboBox(), 2, row, 3, 1);
|
||||
mEditorPane.add(new Separator(Orientation.HORIZONTAL), 0, ++row, 6, 1);
|
||||
|
||||
Label outputLabel = new Label("Audio Output Device:");
|
||||
GridPane.setHalignment(outputLabel, HPos.RIGHT);
|
||||
mEditorPane.add(outputLabel, 0, row, 2, 1);
|
||||
mEditorPane.add(outputLabel, 0, ++row, 2, 1);
|
||||
mEditorPane.add(getMixerComboBox(), 2, row, 3, 1);
|
||||
mEditorPane.add(getMixerTestButton(), 5, row);
|
||||
mEditorPane.add(new Separator(Orientation.HORIZONTAL), 0, ++row, 6, 1);
|
||||
@@ -269,6 +294,24 @@ public class PlaybackPreferenceEditor extends HBox
|
||||
return mStartToneVolumeComboBox;
|
||||
}
|
||||
|
||||
/**
|
||||
* Playback view style selection box.
|
||||
*/
|
||||
public ComboBox<PlaybackView> getPlaybackViewComboBox()
|
||||
{
|
||||
if(mPlaybackViewComboBox == null)
|
||||
{
|
||||
mPlaybackViewComboBox = new ComboBox<>();
|
||||
mPlaybackViewComboBox.setTooltip(new Tooltip("Determines the styling of the audio playback left/right channel views"));
|
||||
mPlaybackViewComboBox.getItems().addAll(PlaybackView.values());
|
||||
mPlaybackViewComboBox.getSelectionModel().select(mPlaybackPreference.getPlaybackView());
|
||||
mPlaybackViewComboBox.getSelectionModel().selectedItemProperty()
|
||||
.addListener((observable, oldValue, newValue) -> mPlaybackPreference.setPlaybackView(newValue));
|
||||
}
|
||||
|
||||
return mPlaybackViewComboBox;
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays the audio buffer over the default mono playback device
|
||||
* @param audioSamples with 8 kHz mono PCM samples
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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
|
||||
@@ -19,9 +19,11 @@
|
||||
|
||||
package io.github.dsheirer.gui.preference.record;
|
||||
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.gui.preference.PreferenceEditor;
|
||||
import io.github.dsheirer.gui.preference.PreferenceEditorType;
|
||||
import io.github.dsheirer.preference.record.RecordPreference;
|
||||
import io.github.dsheirer.record.RecordFormat;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.geometry.Insets;
|
||||
@@ -37,20 +39,31 @@ import org.slf4j.LoggerFactory;
|
||||
/**
|
||||
* Preference settings for recording
|
||||
*/
|
||||
public class RecordPreferenceEditor extends HBox
|
||||
public class RecordPreferenceEditor extends PreferenceEditor
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(RecordPreferenceEditor.class);
|
||||
private RecordPreference mRecordPreference;
|
||||
private GridPane mEditorPane;
|
||||
private ComboBox<RecordFormat> mRecordFormatComboBox;
|
||||
|
||||
public RecordPreferenceEditor(UserPreferences userPreferences)
|
||||
public RecordPreferenceEditor()
|
||||
{
|
||||
mRecordPreference = userPreferences.getRecordPreference();
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
mRecordPreference = getUserPreferences().getRecordPreference();
|
||||
HBox.setHgrow(getEditorPane(), Priority.ALWAYS);
|
||||
getChildren().add(getEditorPane());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreferenceEditorType getPreferenceEditorType()
|
||||
{
|
||||
return PreferenceEditorType.AUDIO_RECORD;
|
||||
}
|
||||
|
||||
private GridPane getEditorPane()
|
||||
{
|
||||
if(mEditorPane == null)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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
|
||||
@@ -19,25 +19,25 @@
|
||||
|
||||
package io.github.dsheirer.gui.preference.tuner;
|
||||
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.gui.preference.PreferenceEditor;
|
||||
import io.github.dsheirer.gui.preference.PreferenceEditorType;
|
||||
import io.github.dsheirer.preference.source.ChannelizerType;
|
||||
import io.github.dsheirer.preference.source.TunerPreference;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Orientation;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.Alert;
|
||||
import javafx.scene.control.ChoiceBox;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.Separator;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
|
||||
|
||||
/**
|
||||
* Preference settings for channel event view
|
||||
*/
|
||||
public class TunerPreferenceEditor extends HBox
|
||||
public class TunerPreferenceEditor extends PreferenceEditor
|
||||
{
|
||||
private static final String HELP_TEXT_POLYPHASE = "Processes all channels from tuner. This " +
|
||||
"channelizer is more efficient when decoding 3 or more channels.";
|
||||
@@ -55,12 +55,26 @@ public class TunerPreferenceEditor extends HBox
|
||||
private ChoiceBox<RspDuoSelectionMode> mRspDuoTunerModeChoiceBox;
|
||||
private Label mRspDuoModeLabel;
|
||||
|
||||
public TunerPreferenceEditor(UserPreferences userPreferences)
|
||||
/**
|
||||
* Constructs an instance
|
||||
*/
|
||||
public TunerPreferenceEditor()
|
||||
{
|
||||
mTunerPreference = userPreferences.getTunerPreference();
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct()
|
||||
{
|
||||
mTunerPreference = getUserPreferences().getTunerPreference();
|
||||
getChildren().add(getEditorPane());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreferenceEditorType getPreferenceEditorType()
|
||||
{
|
||||
return PreferenceEditorType.TUNERS;
|
||||
}
|
||||
|
||||
private GridPane getEditorPane()
|
||||
{
|
||||
if(mEditorPane == null)
|
||||
@@ -116,7 +130,7 @@ public class TunerPreferenceEditor extends HBox
|
||||
label.setWrapText(true);
|
||||
Alert alert = new Alert(Alert.AlertType.WARNING);
|
||||
alert.getDialogPane().setContent(label);
|
||||
alert.initOwner(((Node)getChannelizerTypeChoiceBox()).getScene().getWindow());
|
||||
alert.initOwner((getChannelizerTypeChoiceBox()).getScene().getWindow());
|
||||
alert.show();
|
||||
});
|
||||
}
|
||||
@@ -184,7 +198,7 @@ public class TunerPreferenceEditor extends HBox
|
||||
label.setWrapText(true);
|
||||
Alert alert = new Alert(Alert.AlertType.WARNING);
|
||||
alert.getDialogPane().setContent(label);
|
||||
alert.initOwner(((Node)getRspDuoTunerModeChoiceBox()).getScene().getWindow());
|
||||
alert.initOwner((getRspDuoTunerModeChoiceBox()).getScene().getWindow());
|
||||
alert.show();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
package io.github.dsheirer.gui.viewer;
|
||||
|
||||
import io.github.dsheirer.audio.call.Call;
|
||||
import io.github.dsheirer.gui.control.TimestampTableCellFactory;
|
||||
import io.github.dsheirer.message.IMessage;
|
||||
import io.github.dsheirer.module.decode.dmr.DMRMessageFramer;
|
||||
import io.github.dsheirer.module.decode.dmr.DMRMessageProcessor;
|
||||
@@ -339,6 +341,7 @@ public class DmrViewer extends VBox
|
||||
timestampColumn.setPrefWidth(110);
|
||||
timestampColumn.setText("Time");
|
||||
timestampColumn.setCellValueFactory(new PropertyValueFactory<>("timestamp"));
|
||||
timestampColumn.setCellFactory(new TimestampTableCellFactory<Call>());
|
||||
|
||||
TableColumn timeslotColumn = new TableColumn();
|
||||
timeslotColumn.setPrefWidth(35);
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
package io.github.dsheirer.gui.viewer;
|
||||
|
||||
import io.github.dsheirer.audio.call.Call;
|
||||
import io.github.dsheirer.gui.control.TimestampTableCellFactory;
|
||||
import io.github.dsheirer.message.IMessage;
|
||||
import io.github.dsheirer.message.StuffBitsMessage;
|
||||
import io.github.dsheirer.module.decode.p25.phase1.P25P1MessageFramer;
|
||||
@@ -307,6 +309,7 @@ public class P25P1Viewer extends VBox
|
||||
timestampColumn.setPrefWidth(110);
|
||||
timestampColumn.setText("Time");
|
||||
timestampColumn.setCellValueFactory(new PropertyValueFactory<>("timestamp"));
|
||||
timestampColumn.setCellFactory(new TimestampTableCellFactory<Call>());
|
||||
|
||||
TableColumn validColumn = new TableColumn();
|
||||
validColumn.setPrefWidth(50);
|
||||
|
||||
Reference in New Issue
Block a user