diff --git a/src/main/java/com/github/idelstak/metadata/filesystem/FileAccess.java b/src/main/java/com/github/idelstak/metadata/filesystem/FileAccess.java index 2d88974..881ab6c 100644 --- a/src/main/java/com/github/idelstak/metadata/filesystem/FileAccess.java +++ b/src/main/java/com/github/idelstak/metadata/filesystem/FileAccess.java @@ -25,7 +25,8 @@ public static List 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 { diff --git a/src/main/java/com/github/idelstak/metadata/views/Alert.java b/src/main/java/com/github/idelstak/metadata/views/Alert.java new file mode 100644 index 0000000..9758cff --- /dev/null +++ b/src/main/java/com/github/idelstak/metadata/views/Alert.java @@ -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(); + } +} \ No newline at end of file diff --git a/src/main/java/com/github/idelstak/metadata/views/FilesTableViewController.java b/src/main/java/com/github/idelstak/metadata/views/FilesTableViewController.java index c65fe91..6b91e9f 100644 --- a/src/main/java/com/github/idelstak/metadata/views/FilesTableViewController.java +++ b/src/main/java/com/github/idelstak/metadata/views/FilesTableViewController.java @@ -21,6 +21,7 @@ public class FilesTableViewController extends FxmlController { private final ObjectProperty rootDirectory; private final ObservableList taggedAudioFiles; private final IntegerProperty audioFilesCount; + private final BooleanProperty fileSelected; @FXML private TableView filesTableView; @FXML @@ -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); @@ -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 files = new ArrayList<>(filesTmp); runLater(() -> { @@ -65,19 +68,12 @@ protected void initialize() { }); Service> 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)); } }); @@ -87,7 +83,7 @@ protected void initialize() { resolveService.setOnSucceeded(event -> { @SuppressWarnings("unchecked") List tagged = (List) event.getSource().getValue(); - LOG.info("ResolveService successfully mapped {} tagged mixed", tagged.size()); + LOG.debug("ResolveService successfully mapped {} tagged mixed", tagged.size()); }); resolveService.start(); @@ -147,4 +143,8 @@ void updateView(TaggedAudioFile taggedAudioFile) { }).start(); })); } + + BooleanProperty fileSelected() { + return fileSelected; + } } \ No newline at end of file diff --git a/src/main/java/com/github/idelstak/metadata/views/FxmlController.java b/src/main/java/com/github/idelstak/metadata/views/FxmlController.java index d2a88ed..04bb1bc 100644 --- a/src/main/java/com/github/idelstak/metadata/views/FxmlController.java +++ b/src/main/java/com/github/idelstak/metadata/views/FxmlController.java @@ -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; } \ No newline at end of file diff --git a/src/main/java/com/github/idelstak/metadata/views/MainViewController.java b/src/main/java/com/github/idelstak/metadata/views/MainViewController.java index e4e41e0..6b89a58 100644 --- a/src/main/java/com/github/idelstak/metadata/views/MainViewController.java +++ b/src/main/java/com/github/idelstak/metadata/views/MainViewController.java @@ -1,5 +1,6 @@ package com.github.idelstak.metadata.views; +import javafx.beans.binding.*; import javafx.event.*; import javafx.fxml.*; import javafx.scene.*; @@ -23,15 +24,23 @@ 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); @@ -55,6 +64,15 @@ 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.updatedTaggedAudioFile(); + 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(); diff --git a/src/main/java/com/github/idelstak/metadata/views/MetadataFetchDialog.java b/src/main/java/com/github/idelstak/metadata/views/MetadataFetchDialog.java index 4d91078..90ad355 100644 --- a/src/main/java/com/github/idelstak/metadata/views/MetadataFetchDialog.java +++ b/src/main/java/com/github/idelstak/metadata/views/MetadataFetchDialog.java @@ -55,7 +55,7 @@ private static DialogPane dialogPane(MetadataQuery query, TaggedAudioFile tagged LOG.error("", e); Window owner = writeButton.getScene().getWindow(); String message = "Failed to write tags to " + taggedAudioFile.fileName(); - alertError(owner, message, e); + Alert.ERROR.show(owner, message, e); event.consume(); } }); @@ -64,14 +64,4 @@ private static DialogPane dialogPane(MetadataQuery query, TaggedAudioFile tagged return pane; } - private static void alertError(Window owner, String message, Exception e) { - Alert alert = new Alert(Alert.AlertType.ERROR); - alert.initOwner(owner); - alert.setHeaderText(message); - Label label = new Label(e.getMessage()); - label.getStyleClass().addAll("error", "expandable"); - DialogPane pane = alert.getDialogPane(); - pane.setExpandableContent(label); - pane.setExpanded(true); - } } \ No newline at end of file diff --git a/src/main/java/com/github/idelstak/metadata/views/SongInfoViewController.java b/src/main/java/com/github/idelstak/metadata/views/SongInfoViewController.java index c203c7a..bb6c345 100644 --- a/src/main/java/com/github/idelstak/metadata/views/SongInfoViewController.java +++ b/src/main/java/com/github/idelstak/metadata/views/SongInfoViewController.java @@ -59,6 +59,23 @@ void setTaggedAudioFile(TaggedAudioFile taggedAudioFile) { this.taggedAudioFile.set(taggedAudioFile); } + TaggedAudioFile taggedAudioFile() { + return taggedAudioFile.get(); + } + + TaggedAudioFile updatedTaggedAudioFile() { + TaggedAudioFile editedFile = new TaggedAudioFile(title(), + artist(), + album(), + track(), + year(), + art(), + fileName()); + TaggedAudioFile updatedFile = this.taggedAudioFile.get(); + updatedFile.copy(editedFile); + return updatedFile; + } + String title() { return titleField.getText(); } @@ -79,15 +96,11 @@ String year() { return yearField.getText(); } - String fileName() { - return fileNameField.getText(); - } - Image art() { return artView.getImage(); } - TaggedAudioFile taggedAudioFile() { - return taggedAudioFile.get(); + String fileName() { + return fileNameField.getText(); } } \ No newline at end of file diff --git a/src/main/java/com/github/idelstak/metadata/views/TaggedAudioFile.java b/src/main/java/com/github/idelstak/metadata/views/TaggedAudioFile.java index 4ab000e..f0198ff 100644 --- a/src/main/java/com/github/idelstak/metadata/views/TaggedAudioFile.java +++ b/src/main/java/com/github/idelstak/metadata/views/TaggedAudioFile.java @@ -117,11 +117,13 @@ public String toString() { } void writeFrom(TaggedAudioFile taggedAudioFile) throws IOException { - Tag tag = audioFile.getTag(); - LOG.info("Updating tags on: {}", audioFile); + if (audioFile == null) { + throw new IOException(new IllegalArgumentException("Attempt to use null TaggedAudioFile")); + } - if (audioFile == null || tag == null) { - return; + Tag tag = audioFile.getTag(); + if (tag == null) { + throw new IOException(new IllegalArgumentException("Attempt to use null Tag from AudioFile")); } try { @@ -197,7 +199,7 @@ String fileName() { return fileName.get(); } - private void copy(TaggedAudioFile taggedAudioFile) { + void copy(TaggedAudioFile taggedAudioFile) { title.set(taggedAudioFile.title()); artist.set(taggedAudioFile.artist()); album.set(taggedAudioFile.album()); @@ -215,31 +217,4 @@ private static byte[] imageData(Image art) throws IOException { } } - StringProperty titleProperty() { - return title; - } - - StringProperty artistProperty() { - return artist; - } - - StringProperty albumProperty() { - return album; - } - - StringProperty trackProperty() { - return track; - } - - StringProperty yearProperty() { - return year; - } - - StringProperty fileNameProperty() { - return fileName; - } - - ObjectProperty artProperty() { - return art; - } } \ No newline at end of file diff --git a/src/main/resources/com/github/idelstak/metadata/views/main-view.fxml b/src/main/resources/com/github/idelstak/metadata/views/main-view.fxml index f7774aa..6cd5dd5 100644 --- a/src/main/resources/com/github/idelstak/metadata/views/main-view.fxml +++ b/src/main/resources/com/github/idelstak/metadata/views/main-view.fxml @@ -25,13 +25,13 @@ - -