Skip to content

Commit

Permalink
Merge pull request #138 from CodeDead/feature/add-custom-sounds
Browse files Browse the repository at this point in the history
feat: added the ability to add custom sounds, refactoring
  • Loading branch information
CodeDead authored Jan 19, 2025
2 parents 63ceee8 + 87aa516 commit ba3b099
Show file tree
Hide file tree
Showing 20 changed files with 264 additions and 82 deletions.
120 changes: 109 additions & 11 deletions src/main/java/com/codedead/opal/controller/MainWindowController.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.RowConstraints;
import javafx.scene.media.MediaPlayer;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
Expand All @@ -38,6 +40,10 @@

public final class MainWindowController implements IAudioTimer, TrayIconListener {

@FXML
private GridPane grpCustom;
@FXML
private TitledPane pneCustom;
@FXML
private TitledPane pneOther;
@FXML
Expand Down Expand Up @@ -269,8 +275,8 @@ private List<SoundPane> getSoundPanes(final GridPane parent) {
private void openFile(final String path) {
if (path == null)
throw new NullPointerException("Path cannot be null!");
if (path.isEmpty())
throw new IllegalArgumentException("Path cannot be empty!");
if (path.isBlank())
throw new IllegalArgumentException("Path cannot be blank!");

try {
helpUtils.openFile(new RunnableFileOpener(path, new IRunnableHelper() {
Expand Down Expand Up @@ -319,6 +325,19 @@ private void initialize() {
e.setVisible(true);
e.setManaged(true);
});

final List<SoundPane> customSoundPanes = getSoundPanes(grpCustom);
if (!customSoundPanes.isEmpty()) {
pneCustom.setExpanded(true);
pneCustom.setVisible(true);
pneCustom.setManaged(true);

customSoundPanes.forEach(e -> {
e.setVisible(true);
e.setManaged(true);
});
}

btnClearSearch.setVisible(false);
btnClearSearch.setManaged(false);

Expand All @@ -344,15 +363,36 @@ private void initialize() {
});
return;
}

Platform.runLater(() -> {
getAllSoundPanes()
.forEach(e -> {
e.setVisible(e.getName().toLowerCase().contains(newValue.trim().toLowerCase()));
e.setManaged(e.isVisible());
});

getSoundPanes(grpCustom)
.forEach(e -> {
e.setVisible(e.getName().toLowerCase().contains(newValue.trim().toLowerCase()));
e.setManaged(e.isVisible());
});

// Check if there are still active sound panes on pneCustom
final List<SoundPane> customSoundPanes = getSoundPanes(grpCustom);
if (!customSoundPanes.isEmpty()) {
customSoundPanes.stream().filter(Node::isVisible).findFirst().ifPresentOrElse(_ -> {
pneCustom.setExpanded(true);
pneCustom.setVisible(true);
pneCustom.setManaged(true);
}, () -> {
pneCustom.setExpanded(false);
pneCustom.setVisible(false);
pneCustom.setManaged(false);
});
}

// Check if there are still active sound panes on pneNature
getSoundPanes(grpNature).stream().filter(Node::isVisible).findFirst().ifPresentOrElse(e -> {
getSoundPanes(grpNature).stream().filter(Node::isVisible).findFirst().ifPresentOrElse(_ -> {
pneNature.setExpanded(true);
pneNature.setVisible(true);
pneNature.setManaged(true);
Expand All @@ -363,7 +403,7 @@ private void initialize() {
});

// Check if there are still active sound panes on pneOffice
getSoundPanes(grpOffice).stream().filter(Node::isVisible).findFirst().ifPresentOrElse(e -> {
getSoundPanes(grpOffice).stream().filter(Node::isVisible).findFirst().ifPresentOrElse(_ -> {
pneOffice.setExpanded(true);
pneOffice.setVisible(true);
pneOffice.setManaged(true);
Expand All @@ -374,7 +414,7 @@ private void initialize() {
});

// Check if there are still active sound panes on pneAudiences
getSoundPanes(grpAudiences).stream().filter(Node::isVisible).findFirst().ifPresentOrElse(e -> {
getSoundPanes(grpAudiences).stream().filter(Node::isVisible).findFirst().ifPresentOrElse(_ -> {
pneAudiences.setExpanded(true);
pneAudiences.setVisible(true);
pneAudiences.setManaged(true);
Expand All @@ -385,7 +425,7 @@ private void initialize() {
});

// Check if there are still active sound panes on pneRadioFrequencyStatic
getSoundPanes(grpRadioFrequencyStatic).stream().filter(Node::isVisible).findFirst().ifPresentOrElse(e -> {
getSoundPanes(grpRadioFrequencyStatic).stream().filter(Node::isVisible).findFirst().ifPresentOrElse(_ -> {
pneRadioFrequencyStatic.setExpanded(true);
pneRadioFrequencyStatic.setVisible(true);
pneRadioFrequencyStatic.setManaged(true);
Expand All @@ -396,7 +436,7 @@ private void initialize() {
});

// Check if there are still active sound panes on pneOther
getSoundPanes(grpOther).stream().filter(Node::isVisible).findFirst().ifPresentOrElse(e -> {
getSoundPanes(grpOther).stream().filter(Node::isVisible).findFirst().ifPresentOrElse(_ -> {
pneOther.setExpanded(true);
pneOther.setVisible(true);
pneOther.setManaged(true);
Expand Down Expand Up @@ -442,6 +482,52 @@ private void openSoundPresetAction() {
}
}

/**
* Open a custom sound
*/
@FXML
private void addCustomSound() {
logger.info("Opening a custom sound");
final FileChooser chooser = new FileChooser();

final FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter("MP3 (*.mp3)", "*.mp3");
chooser.getExtensionFilters().add(extFilter);

final File file = chooser.showOpenDialog(new Stage());

if (file != null && file.exists()) {
if (file.getAbsolutePath().isBlank())
throw new IllegalArgumentException("Path cannot be blank!");

logger.info("Loading custom sound from {}", file.getAbsolutePath());

try {
final RowConstraints row = new RowConstraints();
row.setVgrow(Priority.ALWAYS);

grpCustom.getRowConstraints().add(row);

final SoundPane customSoundPane = new SoundPane();
final int count = getSoundPanes(grpCustom).size() + 1;

customSoundPane.setName(translationBundle.getString("CustomSound") + " #" + count);
customSoundPane.setMediaKey("custom" + count);
customSoundPane.setMediaPath(file.toURI().toURL().toString());
customSoundPane.setImage("/images/customsound.png");
customSoundPane.setResourceFile(false);

grpCustom.add(customSoundPane, 0, count - 1);

pneCustom.setExpanded(true);
pneCustom.setVisible(true);
pneCustom.setManaged(true);
} catch (final IOException ex) {
logger.error("Unable to open the custom sound from {}", file.getAbsolutePath(), ex);
FxUtils.showErrorAlert(translationBundle.getString("OpenCustomSoundError"), ex.toString(), getClass().getResourceAsStream(SharedVariables.ICON_URL));
}
}
}

/**
* Open a sound preset
*
Expand All @@ -450,17 +536,17 @@ private void openSoundPresetAction() {
private void openSoundPreset(final String path) {
if (path == null)
throw new NullPointerException("Path cannot be null!");
if (path.isEmpty())
throw new IllegalArgumentException("Path cannot be empty!");
if (path.isBlank())
throw new IllegalArgumentException("Path cannot be blank!");

logger.info("Loading sound preset from {}", path);

try {
final Path filePath = Path.of(path);
final String actual = Files.readString(filePath);

if (actual.isEmpty())
throw new IllegalArgumentException("Sound preset cannot be empty!");
if (actual.isBlank())
throw new IllegalArgumentException("Sound preset cannot be blank!");

final TypeReference<HashMap<String, Double>> typeRef = new TypeReference<>() {
};
Expand Down Expand Up @@ -518,6 +604,10 @@ private void playPauseAction() {
for (final SoundPane soundPane : getAllSoundPanes()) {
soundPane.playPause();
}

for (final SoundPane soundPane : getSoundPanes(grpCustom)) {
soundPane.playPause();
}
} catch (final MediaPlayerException ex) {
logger.error("Unable to play / pause MediaPlayer", ex);
FxUtils.showErrorAlert(translationBundle.getString("PlayPauseError"), ex.toString(), getClass().getResourceAsStream(SharedVariables.ICON_URL));
Expand All @@ -531,6 +621,13 @@ private void playPauseAction() {
private void resetAction() {
logger.info("Resetting all audio sliders");
getAllSoundPanes().forEach(e -> e.getSlider().setValue(0));

getSoundPanes(grpCustom).forEach(SoundPane::disposeMediaPlayer);
grpCustom.getChildren().clear();

pneCustom.setExpanded(false);
pneCustom.setVisible(false);
pneCustom.setManaged(false);
}

/**
Expand Down Expand Up @@ -684,6 +781,7 @@ private void clearSearchAction() {
public void fired() {
cancelTimer();
getAllSoundPanes().forEach(SoundPane::pause);
getSoundPanes(grpCustom).forEach(SoundPane::pause);

if (Boolean.parseBoolean(settingsController.getProperties().getProperty("timerComputerShutdown", "false"))) {
final String command = switch (platformName.toLowerCase()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,10 @@ public String getPropertiesResourceLocation() {
* @param propertiesResourceLocation The resource location of the default properties file
*/
public void setPropertiesResourceLocation(final String propertiesResourceLocation) {
if (propertiesResourceLocation == null || propertiesResourceLocation.isEmpty())
throw new IllegalArgumentException("Properties resource location cannot be null!");
if (propertiesResourceLocation == null)
throw new NullPointerException("Properties resource location cannot be null!");
if (propertiesResourceLocation.isBlank())
throw new IllegalArgumentException("Properties resource location cannot be blank!");

this.propertiesResourceLocation = propertiesResourceLocation;
}
Expand All @@ -107,8 +109,10 @@ public String getPropertiesFileLocation() {
* @param propertiesFileLocation The properties file location
*/
public void setPropertiesFileLocation(final String propertiesFileLocation) {
if (propertiesFileLocation == null || propertiesFileLocation.isEmpty())
throw new IllegalArgumentException("Properties file location cannot be null or empty!");
if (propertiesFileLocation == null)
throw new NullPointerException("Properties file location cannot be null!");
if (propertiesFileLocation.isBlank())
throw new IllegalArgumentException("Properties file location cannot be blank!");

this.propertiesFileLocation = propertiesFileLocation;
}
Expand Down
20 changes: 10 additions & 10 deletions src/main/java/com/codedead/opal/controller/UpdateController.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ public UpdateController(final String updateUrl, final String currentVersion) {
public Optional<PlatformUpdate> checkForUpdates(final String currentPlatform, final boolean isPortable) throws InterruptedException, InvalidHttpResponseCodeException, IOException {
if (currentPlatform == null)
throw new NullPointerException("Current platform cannot be null!");
if (currentPlatform.isEmpty())
throw new IllegalArgumentException("Current platform cannot be empty!");
if (currentPlatform.isBlank())
throw new IllegalArgumentException("Current platform cannot be blank!");

logger.info("Attempting to retrieve the latest PlatformUpdate objects");

Expand Down Expand Up @@ -151,12 +151,12 @@ public List<PlatformUpdate> getUpdates() throws IOException, InterruptedExceptio
public void downloadFile(final String url, final String path) throws IOException, URISyntaxException {
if (url == null)
throw new NullPointerException("URL cannot be null!");
if (url.isEmpty())
throw new IllegalArgumentException("URL cannot be empty!");
if (url.isBlank())
throw new IllegalArgumentException("URL cannot be blank!");
if (path == null)
throw new NullPointerException("Path cannot be null!");
if (path.isEmpty())
throw new IllegalArgumentException("Path cannot be empty!");
if (path.isBlank())
throw new IllegalArgumentException("Path cannot be blank!");

logger.info("Attempting to download file from {} and store it at {}", url, path);

Expand Down Expand Up @@ -187,8 +187,8 @@ public String getUpdateUrl() {
public void setUpdateUrl(final String updateUrl) {
if (updateUrl == null)
throw new NullPointerException("Update URL cannot be null!");
if (updateUrl.isEmpty())
throw new IllegalArgumentException("Update URL cannot be empty!");
if (updateUrl.isBlank())
throw new IllegalArgumentException("Update URL cannot be blank!");

this.updateUrl = updateUrl;
}
Expand All @@ -201,8 +201,8 @@ public void setUpdateUrl(final String updateUrl) {
public void setCurrentVersion(final String currentVersion) {
if (currentVersion == null)
throw new NullPointerException("currentVersion cannot be null!");
if (currentVersion.isEmpty())
throw new IllegalArgumentException("currentVersion cannot be empty!");
if (currentVersion.isBlank())
throw new IllegalArgumentException("currentVersion cannot be blank!");

this.currentVersion = currentVersion;
}
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/com/codedead/opal/domain/NumberTextField.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ public NumberTextField() {
this.setOnKeyPressed(e -> {
if (e.getCode() == KeyCode.UP) {
int currentValue = 0;
if (!this.getText().isEmpty()) {
if (!this.getText().isBlank()) {
currentValue = Integer.parseInt(this.getText());
}
currentValue++;
this.setText(Integer.toString(currentValue));
} else if (e.getCode() == KeyCode.DOWN) {
int currentValue = 0;
if (!this.getText().isEmpty()) {
if (!this.getText().isBlank()) {
currentValue = Integer.parseInt(this.getText());
}
if (currentValue - 1 >= getMin()) {
Expand Down
Loading

0 comments on commit ba3b099

Please sign in to comment.