Skip to content

Commit

Permalink
#1725 WIP additional enhancements and resolves missing class from build.
Browse files Browse the repository at this point in the history
  • Loading branch information
sheirerd committed Dec 7, 2023
1 parent 8d33be8 commit ab0874f
Show file tree
Hide file tree
Showing 6 changed files with 194 additions and 41 deletions.
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ import java.text.SimpleDateFormat
* Instructions for building/compiling the sdrtrunk application.
*
* Prerequisites:
* Install and configure an OpenJDK version 19+ that includes the JavaFX modules (e.g. Bellsoft Liberica JDK)
* - Optional: install and configure Gradle 7.6+
* Install and configure an OpenJDK version 20 that includes the JavaFX modules (e.g. Bellsoft Liberica JDK)
* - Optional: install and configure Gradle 8.2+
*
* Scenario 1: run the application via gradle command line from the source code root directory:
* command: ./gradlew run
Expand Down Expand Up @@ -236,7 +236,7 @@ def configure(org.beryx.runtime.RuntimeZipTask rt, List<String> jvmArgs) {
//jdk.incubator.vector - needed for Project Panama foreign function and vector apis
//jdk.accessibility is used with assistive technologies like screen readers
//java.management for JVM resource monitoring
rt.extension.addModules('jdk.crypto.ec', 'jdk.incubator.vector', 'jdk.accessibility', 'java.management')
rt.extension.addModules('jdk.crypto.ec', 'jdk.incubator.vector', 'jdk.accessibility', 'java.management', 'java.instrument')

//Use auto-detected modules and 'add' any specified modules.
rt.extension.additive.set(true)
Expand Down
43 changes: 23 additions & 20 deletions src/main/java/io/github/dsheirer/audio/AbstractAudioModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,6 @@ protected void closeAudioSegment()
@Override
public void stop()
{
if(getAudioSegment().isDuplicate())
{
mLog.warn("Audio Module [" + getClass() + "] stop() invoked AND DUPLICATE=TRUE is detected");
}
closeAudioSegment();
}

Expand Down Expand Up @@ -140,26 +136,33 @@ public AudioSegment getAudioSegment()

public void addAudio(float[] audioBuffer)
{
AudioSegment audioSegment = getAudioSegment();

//If the current segment exceeds the max samples length, close it so that a new segment gets generated
//and then link the segments together
if(mAudioSampleCount >= mMaxSegmentAudioSampleLength)
if(audioBuffer != null)
{
AudioSegment previous = getAudioSegment();
closeAudioSegment();
audioSegment = getAudioSegment();
audioSegment.linkTo(previous);
}
AudioSegment audioSegment = getAudioSegment();

try
{
audioSegment.addAudio(audioBuffer);
mAudioSampleCount += audioBuffer.length;
//If the current segment exceeds the max samples length, close it so that a new segment gets generated
//and then link the segments together
if(mAudioSampleCount >= mMaxSegmentAudioSampleLength)
{
AudioSegment previous = getAudioSegment();
closeAudioSegment();
audioSegment = getAudioSegment();
audioSegment.linkTo(previous);
}

try
{
audioSegment.addAudio(audioBuffer);
mAudioSampleCount += audioBuffer.length;
}
catch(Exception e)
{
closeAudioSegment();
}
}
catch(Exception e)
else
{
closeAudioSegment();
mLog.info("Attempt to add null audio from " + getClass());
}
}

Expand Down
25 changes: 25 additions & 0 deletions src/main/java/io/github/dsheirer/audio/call/CallRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,37 @@

package io.github.dsheirer.audio.call;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

/**
* Calls database repository
*/
public interface CallRepository extends JpaRepository<Call,Long>
{
@Query("SELECT t FROM Call t WHERE t.mToId like ?1 OR t.mToAlias like ?1 OR t.mFromId like ?1 OR t.mFromAlias like ?1")
Page<Call> findByAnyIdWithPagination(String value, Pageable pageable);

@Query("SELECT t FROM Call t WHERE t.mToId like ?1 OR t.mToAlias like ?1")
Page<Call> findByToWithPagination(String value, Pageable pageable);

@Query("SELECT t FROM Call t WHERE t.mFromId like ?1 OR t.mFromAlias like ?1")
Page<Call> findByFromWithPagination(String value, Pageable pageable);

@Query("SELECT t FROM Call t WHERE t.mCallType like ?1")
Page<Call> findByCallTypeWithPagination(String value, Pageable pageable);

@Query("SELECT t FROM Call t WHERE t.mChannel like ?1")
Page<Call> findByChannelWithPagination(String value, Pageable pageable);

@Query("SELECT t FROM Call t WHERE t.mProtocol like ?1")
Page<Call> findByProtocolWithPagination(String value, Pageable pageable);

@Query("SELECT t FROM Call t WHERE t.mSite like ?1")
Page<Call> findBySiteWithPagination(String value, Pageable pageable);

@Query("SELECT t FROM Call t WHERE t.mSystem like ?1")
Page<Call> findBySystemWithPagination(String value, Pageable pageable);
}
121 changes: 103 additions & 18 deletions src/main/java/io/github/dsheirer/audio/call/CallViewPanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Alert;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressIndicator;
Expand Down Expand Up @@ -87,13 +88,14 @@ public class CallViewPanel extends VBox implements IPageRequestListener
private Label mCallsCountLabel;
private LongProperty mCallCount = new SimpleLongProperty();
private Sort mSort = DEFAULT_SORT;
private ComboBox<SearchColumn> mSearchColumnComboBox;
private CheckBox mSearchExactCheckBox;

/**
* Constructs an instance
*/
public CallViewPanel()
{
setSpacing(5);
mCallCount.addListener((observable, oldValue, newValue) -> {
getCallsCountLabel().setText("Calls: " + newValue);
int pageCount = (int)(mCallCount.get() / getPageSize());
Expand All @@ -111,8 +113,13 @@ public CallViewPanel()
@PostConstruct
public void postConstruct()
{
HBox controlBox = new HBox();
controlBox.setPadding(new Insets(2, 15, 2, 15));
HBox.setHgrow(getPagingBox(), Priority.ALWAYS);
controlBox.getChildren().addAll(getSearchBox(), getPagingBox());

VBox.setVgrow(getCallTableView(), Priority.ALWAYS);
getChildren().addAll(getSearchBox(), getCallTableView(), getPagingBox());
getChildren().addAll(controlBox, getCallTableView());

getPagingController().update(1, 20);

Expand All @@ -132,6 +139,14 @@ public void preDestroy()
mAudioManager.remove(mCallEventListener);
}

/**
* Shows first page of results.
*/
private void showFirstPage()
{
showPage(1);
}

/**
* Sets the page to view. This implements the IPageRequestListener interface.
* @param page number to display.
Expand All @@ -143,19 +158,52 @@ public void showPage(int page)
{
Platform.runLater(() -> getPlaceholderProgressIndicator().setVisible(true));

final String searchTerm = getSearchField().getText();
final SearchColumn searchColumn = getSearchColumnComboBox().getSelectionModel().getSelectedItem();
final boolean wildcard = !getSearchExactCheckBox().isSelected();

//Spin the query off onto a cached thread and then place the results back onto the FX thread.
ThreadPool.CACHED.submit(() -> {
ThreadPool.CACHED.submit(() ->
{
final PageRequest pageRequest = PageRequest.of(page - 1, getPageSize(), mSort);

try
{
Page<Call> callPage = mCallRepository.findAll(PageRequest.of(page - 1, getPageSize(), mSort));
Platform.runLater(() -> {
mCalls.clear();
mCalls.addAll(callPage.stream().toList());
getPlaceholderProgressIndicator().setVisible(false);
getPagingController().update(callPage.getNumber() + 1, callPage.getTotalPages());
mCallCount.set(callPage.getTotalElements());
});
Page<Call> callPage = null;

if(searchTerm != null && !searchTerm.isEmpty() && searchColumn != null)
{
final String wildcardSearch = (wildcard ? "%" : "") + searchTerm + (wildcard ? "%" : "");

switch(searchColumn)
{
case ANY_ID -> callPage = mCallRepository.findByAnyIdWithPagination(wildcardSearch, pageRequest);
case CALL_TYPE -> callPage = mCallRepository.findByCallTypeWithPagination(wildcardSearch, pageRequest);
case CHANNEL -> callPage = mCallRepository.findByChannelWithPagination(wildcardSearch, pageRequest);
case FROM -> callPage = mCallRepository.findByFromWithPagination(wildcardSearch, pageRequest);
case PROTOCOL -> callPage = mCallRepository.findByProtocolWithPagination(wildcardSearch, pageRequest);
case SITE -> callPage = mCallRepository.findBySiteWithPagination(wildcardSearch, pageRequest);
case SYSTEM -> callPage = mCallRepository.findBySystemWithPagination(wildcardSearch, pageRequest);
case TO -> callPage = mCallRepository.findByToWithPagination(wildcardSearch, pageRequest);
}
}
else
{
callPage = mCallRepository.findAll(pageRequest);
}

if(callPage != null)
{
final Page<Call> finalCallPage = callPage;

Platform.runLater(() -> {
mCalls.clear();
mCalls.addAll(finalCallPage.stream().toList());
getPlaceholderProgressIndicator().setVisible(false);
getPagingController().update(finalCallPage.getNumber() + 1, finalCallPage.getTotalPages());
mCallCount.set(finalCallPage.getTotalElements());
});
}
}
catch(Throwable t)
{
Expand All @@ -175,6 +223,10 @@ public void showPage(int page)
}
});
}
else
{
LOGGER.warn("Invalid page [" + page + "] number request");
}
}

/**
Expand Down Expand Up @@ -207,7 +259,7 @@ private void updateSortOrder()
mSort = DEFAULT_SORT;
}

showPage(0);
showFirstPage();
}

/**
Expand All @@ -231,6 +283,23 @@ private Label getCallsCountLabel()
return mCallsCountLabel;
}

/**
* Toggles wildcard searching
* @return true for exact match or false for wildcard/fuzzy matching.
*/
private CheckBox getSearchExactCheckBox()
{
if(mSearchExactCheckBox == null)
{
mSearchExactCheckBox = new CheckBox("Exact Match");
mSearchExactCheckBox.setTooltip(new Tooltip("Toggle exact matching (checked) or wildcard/fuzzy " +
"matching (unchecked)"));
mSearchExactCheckBox.selectedProperty().addListener((observable, oldValue, newValue) -> showFirstPage());
}

return mSearchExactCheckBox;
}

/**
* Page size selection combo box.
*
Expand All @@ -243,14 +312,31 @@ private ComboBox<Integer> getPageSizeComboBox()
ObservableList<Integer> pageSizes = FXCollections.observableArrayList();
pageSizes.addAll(25, 50, 100, 200);
mPageSizeComboBox = new ComboBox<>(pageSizes);
mPageSizeComboBox.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> showPage(1));
mPageSizeComboBox.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> showFirstPage());
mPageSizeComboBox.setTooltip(new Tooltip("Select the page size"));
mPageSizeComboBox.getSelectionModel().select(0);
}

return mPageSizeComboBox;
}

/**
* Page size selection combo box.
*
* Note: when the user changes the page size, we always request page 1 again.
*/
private ComboBox<SearchColumn> getSearchColumnComboBox()
{
if(mSearchColumnComboBox == null)
{
mSearchColumnComboBox = new ComboBox<>(FXCollections.observableArrayList(SearchColumn.values()));
mSearchColumnComboBox.getSelectionModel().select(SearchColumn.ANY_ID);
mSearchColumnComboBox.setTooltip(new Tooltip("Select the field(s) to search against"));
}

return mSearchColumnComboBox;
}

/**
* Paging controls panel
*/
Expand All @@ -259,7 +345,7 @@ private HBox getPagingBox()
if(mPagingBox == null)
{
mPagingBox = new HBox();
mPagingBox.setAlignment(Pos.CENTER_LEFT);
mPagingBox.setAlignment(Pos.CENTER_RIGHT);
mPagingBox.setSpacing(3);
Label pageSizeLabel = new Label("Page Size:");
getPagingController().setPadding(new Insets(2, 0, 6, 20));
Expand Down Expand Up @@ -442,12 +528,11 @@ private HBox getSearchBox()
{
mSearchBox = new HBox();
mSearchBox.setAlignment(Pos.CENTER_LEFT);
mSearchBox.setPadding(new Insets(5, 5, 0, 15));
mSearchBox.setSpacing(5);

Label searchLabel = new Label("Search:");
searchLabel.setAlignment(Pos.CENTER_RIGHT);
mSearchBox.getChildren().addAll(searchLabel, getSearchField());
mSearchBox.getChildren().addAll(searchLabel, getSearchField(), getSearchColumnComboBox(), getSearchExactCheckBox());
}

return mSearchBox;
Expand All @@ -458,9 +543,9 @@ private TextField getSearchField()
if(mSearchField == null)
{
mSearchField = TextFields.createClearableTextField();
mSearchField.setDisable(true);
mSearchField.setTooltip(new Tooltip("Type a value to search against the selected database field(s)"));
mSearchField.textProperty().addListener((observable, oldValue, newValue) -> {
// updateListFilters();
showFirstPage();
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ private Label getPageLabel()
if(mPageLabel == null)
{
mPageLabel = new Label("Page 1 of 1");
mPageLabel.setTooltip(new Tooltip("Current Page and Total Page Count"));
mPageLabel.setAlignment(Pos.CENTER);
mPageLabel.setMaxWidth(Double.MAX_VALUE);
mPageLabel.setPadding(new Insets(0, 20, 0, 20));
Expand All @@ -164,6 +165,7 @@ private Button getFirstButton()
if(mFirstButton == null)
{
mFirstButton = new Button();
mFirstButton.setTooltip(new Tooltip("Go To First Page"));
IconNode iconNode = new IconNode(FontAwesome.ANGLE_DOUBLE_LEFT);
iconNode.setIconSize(20);
iconNode.setFill(Color.BLACK);
Expand All @@ -182,6 +184,7 @@ private Button getLastButton()
if(mLastButton == null)
{
mLastButton = new Button();
mLastButton.setTooltip(new Tooltip("Go To Last Page"));
IconNode iconNode = new IconNode(FontAwesome.ANGLE_DOUBLE_RIGHT);
iconNode.setIconSize(20);
iconNode.setFill(Color.BLACK);
Expand All @@ -200,6 +203,7 @@ private Button getNextButton()
if(mNextButton == null)
{
mNextButton = new Button();
mNextButton.setTooltip(new Tooltip("Go To Next Page"));
IconNode iconNode = new IconNode(FontAwesome.ANGLE_RIGHT);
iconNode.setIconSize(20);
iconNode.setFill(Color.BLACK);
Expand All @@ -218,6 +222,7 @@ private Button getPreviousButton()
if(mPreviousButton == null)
{
mPreviousButton = new Button();
mPreviousButton.setTooltip(new Tooltip("Go To Previous Page"));
IconNode iconNode = new IconNode(FontAwesome.ANGLE_LEFT);
iconNode.setIconSize(20);
iconNode.setFill(Color.BLACK);
Expand Down
Loading

0 comments on commit ab0874f

Please sign in to comment.