Skip to content

Commit

Permalink
Merge pull request #9 from IdelsTak/8-add-metadata-fetch-and-selectio…
Browse files Browse the repository at this point in the history
…n-feature-with-undoredo-and-filename-rename-options

#8
  • Loading branch information
IdelsTak authored Jul 2, 2024
2 parents 76a236b + 5163fca commit a71847b
Show file tree
Hide file tree
Showing 34 changed files with 1,312 additions and 124 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/.idea/
/target/
/logs/
*.log
17 changes: 17 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,30 @@
<artifactId>ikonli-boxicons-pack</artifactId>
<version>${ikonli.version}</version>
</dependency>
<dependency>
<groupId>org.kordamp.ikonli</groupId>
<artifactId>ikonli-microns-pack</artifactId>
<version>${ikonli.version}</version>
</dependency>

<dependency>
<groupId>com.dlsc.gemsfx</groupId>
<artifactId>gemsfx</artifactId>
<version>2.32.0</version>
</dependency>

<!-- Web -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20240303</version>
</dependency>

<!-- AudioTagger -->
<dependency>
<groupId>org</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ public static List<File> findAllFilesRecursively(File directory) throws IOExcept
}

public static boolean isAudioFile(File file) {
return file.getName().toLowerCase().endsWith(".mp3");
String lowerCaseName = file.getName().toLowerCase();
return lowerCaseName.endsWith(".mp3") || lowerCaseName.endsWith(".flac");
}

static void deleteDirectoryRecursively(File directory) throws IOException {
Expand Down
35 changes: 35 additions & 0 deletions src/main/java/com/github/idelstak/metadata/views/Alert.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.github.idelstak.metadata.views;

import javafx.scene.control.*;
import javafx.stage.*;

public enum Alert {
ERROR(javafx.scene.control.Alert.AlertType.ERROR);

private final javafx.scene.control.Alert alert;
private final DialogPane dialogPane;

Alert(javafx.scene.control.Alert.AlertType type) {
alert = new javafx.scene.control.Alert(type);
dialogPane = alert.getDialogPane();
}

void show(Window owner, String message, Exception exception) {
show(owner, message, null, exception);
}

void show(Window owner, String header, String content, Exception exception) {
alert.initOwner(owner);
alert.setHeaderText(header);
if (exception != null) {
Label label = new Label(exception.getMessage());
label.getStyleClass().addAll("error", "expandable");
dialogPane.setExpandableContent(label);
dialogPane.setExpanded(true);
} else {
alert.setContentText(content);
}

alert.show();
}
}
17 changes: 17 additions & 0 deletions src/main/java/com/github/idelstak/metadata/views/Css.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.github.idelstak.metadata.views;

import java.net.*;

public enum Css {
STYLES("/com/github/idelstak/metadata/views/styles.css");

private final String path;

Css(String path) {this.path = path;}

String toExternalForm() {
URL resource = getClass().getResource(path);
assert resource != null;
return resource.toExternalForm();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public class FilesTableViewController extends FxmlController {
private final ObjectProperty<File> rootDirectory;
private final ObservableList<TaggedAudioFile> taggedAudioFiles;
private final IntegerProperty audioFilesCount;
private final BooleanProperty fileSelected;
@FXML
private TableView<TaggedAudioFile> filesTableView;
@FXML
Expand All @@ -38,10 +39,12 @@ public FilesTableViewController() {
rootDirectory = new SimpleObjectProperty<>();
taggedAudioFiles = FXCollections.observableArrayList();
audioFilesCount = new SimpleIntegerProperty();
fileSelected = new SimpleBooleanProperty();
}

@Override
protected void initialize() {
fileSelected.bind(filesTableView.getSelectionModel().selectedItemProperty().map(Objects::nonNull));
rootDirectory.addListener((_, _, directory) -> {
LOG.debug("root directory set to: {}", directory);

Expand All @@ -56,7 +59,7 @@ protected void initialize() {
LOG.error("", e);
}

LOG.info("Mapping {} audio mixed to tagged audio mixed...", filesTmp.size());
LOG.debug("Mapping {} audio mixed to tagged audio mixed...", filesTmp.size());

List<File> files = new ArrayList<>(filesTmp);
runLater(() -> {
Expand All @@ -65,19 +68,12 @@ protected void initialize() {
});

Service<List<TaggedAudioFile>> resolveService = new AudioFileResolveService(files);
resolveService.messageProperty().addListener((_, _, message) -> {
if (message == null) {
return;
}
LOG.info(message);
});
resolveService.progressProperty().addListener((_, _, progress) -> {
LOG.info("progress: {}", progress);
});
resolveService.messageProperty().addListener((_, _, message) -> LOG.debug(message));
resolveService.progressProperty().addListener((_, _, progress) -> LOG.debug("progress: {}", progress));
resolveService.valueProperty().addListener((_, _, latestTaggedAudioFiles) -> {
if (latestTaggedAudioFiles != null && latestTaggedAudioFiles.size() == 1) {
TaggedAudioFile latestResolvedFile = latestTaggedAudioFiles.getFirst();
LOG.info("Latest resolved file: {}", latestResolvedFile);
LOG.debug("Latest resolved file: {}", latestResolvedFile);
runLater(() -> taggedAudioFiles.add(latestResolvedFile));
}
});
Expand All @@ -87,7 +83,7 @@ protected void initialize() {
resolveService.setOnSucceeded(event -> {
@SuppressWarnings("unchecked")
List<TaggedAudioFile> tagged = (List<TaggedAudioFile>) event.getSource().getValue();
LOG.info("ResolveService successfully mapped {} tagged mixed", tagged.size());
LOG.debug("ResolveService successfully mapped {} tagged mixed", tagged.size());
});

resolveService.start();
Expand All @@ -104,20 +100,14 @@ protected void initialize() {
TableViewSelectionModel<TaggedAudioFile> selectionModel = filesTableView.getSelectionModel();
ReadOnlyObjectProperty<TaggedAudioFile> itemProperty = selectionModel.selectedItemProperty();
itemProperty.addListener((_, _, taggedAudioFile) -> {
if (taggedAudioFile == null) {
return;
}

SongInfoViewController controller;
try {
controller = (SongInfoViewController) SONG_INFO_VIEW.controller();
} catch (IOException e) {
LOG.error("", e);
throw new RuntimeException(e);
}

//runLater(() -> controller.setTaggedAudioFile(taggedAudioFile));
controller.setTaggedAudioFile(taggedAudioFile);
runLater(() -> {
try {
SongInfoViewController controller = (SongInfoViewController) SONG_INFO_VIEW.controller();
controller.setTaggedAudioFile(taggedAudioFile);
} catch (IOException e) {
LOG.error("", e);
}
});
});
}

Expand All @@ -133,4 +123,28 @@ <T> TableView<T> getFilesView() {
int audioFilesCount() {
return audioFilesCount.get();
}

void updateView(TaggedAudioFile taggedAudioFile) {
taggedAudioFiles.stream()
.filter(file -> Objects.equals(file.fileName(), taggedAudioFile.fileName()))
.map(taggedAudioFiles::indexOf)
.findFirst()
.ifPresent(index -> runLater(() -> {
taggedAudioFiles.set(index, taggedAudioFile);
TableViewSelectionModel<TaggedAudioFile> selection = filesTableView.getSelectionModel();
selection.clearSelection();
new Thread(() -> {
try {
Thread.sleep(500L);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
selection.select(taggedAudioFile);
}).start();
}));
}

BooleanProperty fileSelected() {
return fileSelected;
}
}
4 changes: 3 additions & 1 deletion src/main/java/com/github/idelstak/metadata/views/Fxml.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
public enum Fxml {
FILES_TABLE_VIEW("/com/github/idelstak/metadata/views/files-table-view.fxml"),
SONG_INFO_VIEW("/com/github/idelstak/metadata/views/song-info-view.fxml"),
MAIN_VIEW("/com/github/idelstak/metadata/views/main-view.fxml");
MAIN_VIEW("/com/github/idelstak/metadata/views/main-view.fxml"),
METADATA_FETCH_VIEW("/com/github/idelstak/metadata/views/metadata-fetch-view.fxml");

private final String path;
private Object controller;
Expand All @@ -35,4 +36,5 @@ Object controller() throws IOException {
}
return controller;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import javafx.fxml.*;

import java.io.*;

public abstract class FxmlController {

@FXML
protected abstract void initialize();
protected abstract void initialize() throws IOException;
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
package com.github.idelstak.metadata.views;

import javafx.beans.binding.*;
import javafx.event.*;
import javafx.fxml.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.*;
import javafx.util.*;
import org.slf4j.*;

import java.io.*;
import java.util.*;

import static com.github.idelstak.metadata.views.Fxml.*;
import static javafx.application.Platform.*;
import static javafx.scene.control.ButtonType.*;

public class MainViewController extends FxmlController {

Expand All @@ -20,24 +24,36 @@ public class MainViewController extends FxmlController {
private Label spacerLabel;
@FXML
private SplitPane mainSplitPane;
@FXML
private Button writeMetadataButton;
@FXML
private Button fetchMetadataButton;

@Override
protected void initialize() {
protected void initialize() throws IOException {
spacerLabel.skinProperty().addListener(_ -> runLater(() -> {
try {
loadViews();
FilesTableViewController controller = (FilesTableViewController) FILES_TABLE_VIEW.controller();
BooleanBinding noFileSelected = controller.fileSelected().not();
writeMetadataButton.disableProperty().bind(noFileSelected);
writeMetadataButton.disableProperty().bind(noFileSelected);
fetchMetadataButton.disableProperty().bind(noFileSelected);
} catch (IOException e) {
LOG.error("", e);
throw new RuntimeException(e);
}
}));
HBox.setHgrow(spacerLabel, Priority.ALWAYS);

mainSplitPane.heightProperty().addListener((_, _, _) -> runLater(this::updateDividerPosition));
}

private void loadViews() throws IOException {
mainSplitPane.getItems().addAll(filesTableView(), songInfoPane());
mainSplitPane.setDividerPosition(0, 0.6);
updateDividerPosition();
}

private void updateDividerPosition() {
mainSplitPane.setDividerPosition(0, 0.9);
}

private Node filesTableView() throws IOException {
Expand All @@ -48,6 +64,42 @@ private Node songInfoPane() throws IOException {
return SONG_INFO_VIEW.root();
}

@FXML
private void writeMetadata(ActionEvent actionEvent) throws IOException {
SongInfoViewController controller = (SongInfoViewController) SONG_INFO_VIEW.controller();
TaggedAudioFile updatedTaggedAudioFile = controller.updateTaggedAudioFile();
FilesTableViewController filesController = (FilesTableViewController) FILES_TABLE_VIEW.controller();
filesController.updateView(updatedTaggedAudioFile);
actionEvent.consume();
}

@FXML
private void fetchMetadata(ActionEvent actionEvent) throws IOException {
Window owner = ((Node) actionEvent.getSource()).getScene().getWindow();
SongInfoViewController controller = (SongInfoViewController) SONG_INFO_VIEW.controller();
Pair<String, String> titlePair = new QueryPair("TITLE", controller.title());
Pair<String, String> artistPair = new QueryPair("ARTIST", controller.artist());
Pair<String, String> albumPair = new QueryPair("ALBUM", controller.album());
Pair<String, String> yearPair = new QueryPair("YEAR", controller.year());
MetadataQuery query = new MetadataQuery(titlePair, artistPair, albumPair, yearPair);
TaggedAudioFile taggedAudioFile = controller.taggedAudioFile();
Optional<ButtonType> selection = new MetadataFetchDialog(owner, query, taggedAudioFile).showAndWait();
selection.stream().filter(type -> type == OK).findFirst().ifPresent(_ -> {
FilesTableViewController filesController = null;
try {
filesController = (FilesTableViewController) FILES_TABLE_VIEW.controller();
} catch (IOException e) {
LOG.error("", e);
}

if (filesController == null) {
return;
}

filesController.updateView(taggedAudioFile);
});
}

@FXML
private void openDirectory(ActionEvent actionEvent) throws IOException {
DirectoryChooser directoryChooser = new DirectoryChooser();
Expand Down
Loading

0 comments on commit a71847b

Please sign in to comment.