diff --git a/.idea/misc.xml b/.idea/misc.xml index 001e756..ffc6446 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -8,7 +8,7 @@ - + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index e45147d..8f8c679 100644 --- a/pom.xml +++ b/pom.xml @@ -19,24 +19,33 @@ javafx-controls 21 + org.openjfx javafx-fxml 21 - + org.junit.jupiter junit-jupiter-api ${junit.version} test + org.junit.jupiter junit-jupiter-engine ${junit.version} test - + + + + org.openjfx + javafx-media + 21 + + diff --git a/src/main/java/sbu/javafx/Launcher.java b/src/main/java/sbu/javafx/Launcher.java index c288d10..b203f3e 100644 --- a/src/main/java/sbu/javafx/Launcher.java +++ b/src/main/java/sbu/javafx/Launcher.java @@ -2,7 +2,10 @@ package sbu.javafx; import javafx.application.Application; -public class Launcher{ +public class Launcher { public static void main(String[] args) { - // TODO: Launch the JavaFX application by calling Application.launch(Main.class) } + // TODO: Launch the JavaFX application by calling Application.launch(Main.class) + Application.launch(MusicApp.class); + + } } diff --git a/src/main/java/sbu/javafx/MusicApp.java b/src/main/java/sbu/javafx/MusicApp.java index a50badc..34bd7f8 100644 --- a/src/main/java/sbu/javafx/MusicApp.java +++ b/src/main/java/sbu/javafx/MusicApp.java @@ -4,6 +4,7 @@ import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.Scene; import javafx.stage.Stage; +import javafx.scene.image.Image; import java.io.IOException; @@ -14,9 +15,13 @@ public class MusicApp extends Application { { FXMLLoader fxmlLoader = new FXMLLoader(MusicApp.class.getResource("App-view.fxml")); Scene scene = new Scene(fxmlLoader.load()); + scene.getStylesheets().add(getClass().getResource("style.css").toExternalForm()); stage.setTitle("Music Player"); + stage.setResizable(false); stage.setScene(scene); //TODO: add icon to the stage + Image icon = new Image(getClass().getResourceAsStream("MusicPlayerIcon.png")); + stage.getIcons().add(icon); stage.show(); } diff --git a/src/main/java/sbu/javafx/MusicController.java b/src/main/java/sbu/javafx/MusicController.java index 5da27a9..12b8212 100644 --- a/src/main/java/sbu/javafx/MusicController.java +++ b/src/main/java/sbu/javafx/MusicController.java @@ -2,30 +2,207 @@ package sbu.javafx; import javafx.fxml.FXML; import javafx.event.ActionEvent; +import javafx.scene.Scene; +import javafx.scene.control.Button; import javafx.scene.control.Label; +import javafx.scene.control.ListView; +import javafx.scene.image.Image; import javafx.scene.input.MouseEvent; import javafx.scene.layout.VBox; +import javafx.scene.media.Media; +import javafx.scene.media.MediaPlayer; +import javafx.stage.Stage; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; public class MusicController { + private List allSongs; + private List playList; + private Song currentlyPlaying; + private MediaPlayer mediaPlayer; + private boolean isPlaying = false; + private Button currentPlayButton; + @FXML private Label nowPlayingLabel; + @FXML private Button song01; + @FXML private Button song02; + @FXML private Button song03; + @FXML private Button song01P; + @FXML private Button song02P; + @FXML private Button song03P; // TODO: Define your UI components using the @FXML annotation. //TODO: Implement the logic to play a song. This method should update the UI to show which song is currently playing. @FXML - public void handlePlayAction() { + public void initialize() { + + allSongs = new ArrayList<>(); + playList = new ArrayList<>(); + + allSongs.add(new Song("Sing", "Travis", "3:48", "E:\\JavaProjects\\HW-07-JavaFX\\src\\main\\resources\\sbu\\songs\\Sing.mp3")); + allSongs.add(new Song("Akhare Ghesse", "Dang Show", "3:18", "E:\\JavaProjects\\HW-07-JavaFX\\src\\main\\resources\\sbu\\songs\\Akhare-Ghesse.mp3")); + allSongs.add(new Song("Married Life", "Michael Giacchino", "4:10", "E:\\JavaProjects\\HW-07-JavaFX\\src\\main\\resources\\sbu\\songs\\Married Life.mp3")); + + nowPlayingLabel.setText(""); + + addToPlaylist(); + } + + @FXML + public void handlePlayAction(ActionEvent event) { //Update labels, change button icons, etc. + Button clickedButton = (Button) event.getSource(); + Song songToPlay = null; + + if (clickedButton == song01) { + songToPlay = allSongs.get(0); + } else if (clickedButton == song02) { + songToPlay = allSongs.get(1); + } else if (clickedButton == song03) { + songToPlay = allSongs.get(2); + } + + if (songToPlay != null) { + + if (currentlyPlaying != songToPlay) { + playNewSong(songToPlay, clickedButton); + } else { + // toggle play/pause + togglePlayPause(clickedButton); + } + } + } //TODO: Logic to add a specific song to the user's playlist. - - public void addToPlaylist(String songName) { + @FXML + public void addToPlaylist() { //Add the song to a list or update a ListView. + song01P.setOnAction(event -> { + playList.add(allSongs.get(0)); + }); + + song02P.setOnAction(event -> { + playList.add(allSongs.get(1)); + }); + + song03P.setOnAction(event -> { + playList.add(allSongs.get(2)); + }); + } + private void playNewSong(Song song, Button playButton) { + if (mediaPlayer != null) { + mediaPlayer.stop(); + mediaPlayer.dispose(); + // Reset the previous play button text if it exists + if (currentPlayButton != null && currentPlayButton != playButton) { + currentPlayButton.setText("Play"); + } + } + + try { + File audioFile = new File(song.getFilePath()); + if (!audioFile.exists()) { + nowPlayingLabel.setText("File not found: " + song.getSongName()); + return; + } + + Media media = new Media(audioFile.toURI().toString()); + mediaPlayer = new MediaPlayer(media); + + mediaPlayer.setOnReady(() -> { + currentlyPlaying = song; + nowPlayingLabel.setText(song.getSongName() + " - " + song.getArtistName()); + isPlaying = true; + playButton.setText("Playing"); + currentPlayButton = playButton; + mediaPlayer.play(); + }); + + mediaPlayer.setOnEndOfMedia(() -> { + isPlaying = false; + if (currentPlayButton != null) { + currentPlayButton.setText("Play"); + } + nowPlayingLabel.setText("Finished: " + song.getSongName()); + }); + + mediaPlayer.setOnError(() -> { + System.err.println("Media error: " + mediaPlayer.getError()); + nowPlayingLabel.setText("Error playing: " + song.getSongName()); + playButton.setText("Play"); + isPlaying = false; + }); + + } catch (Exception e) { + e.printStackTrace(); + nowPlayingLabel.setText("Cannot play: " + song.getSongName()); + } + } + + private void togglePlayPause(Button playButton) { + if (mediaPlayer != null) { + if (isPlaying) { + mediaPlayer.pause(); + isPlaying = false; + playButton.setText("Play"); + } else { + mediaPlayer.play(); + isPlaying = true; + playButton.setText("Playing"); + } + } + } + + // TODO:This method should open a new window or change the current scene to display the "Playlist" page. - + @FXML public void openPlaylistWindow() { //Create a new stage and show the playlist UI. + + try { + Stage playlistStage = new Stage(); + playlistStage.setTitle("Playlist"); + + VBox playlistLayout = new VBox(10); + playlistLayout.setStyle("-fx-padding: 20; -fx-alignment: center; -fx-background-color: rgba(52, 152, 219, 0.68);"); + + Label titleLabel = new Label("Your Playlist"); + titleLabel.setStyle("-fx-font-size: 18px; -fx-font-weight: bold;"); + + ListView playlistListView = new ListView<>(); + + if (playList != null) { + for (Song song : playList) { + playlistListView.getItems().add(song.getSongName() + " - " + song.getArtistName() + " (" + song.getDuration() + ")"); + } + } + + Label emptyLabel = new Label("Your playlist is empty. Add any song you like!"); + emptyLabel.setStyle("-fx-text-fill: gray; -fx-font-weight: bold"); + + if (playList == null || playList.isEmpty()) { + playlistLayout.getChildren().addAll(titleLabel, emptyLabel); + } else { + playlistLayout.getChildren().addAll(titleLabel, playlistListView); + } + + // Set up the scene and show the stage + Scene playlistScene = new Scene(playlistLayout, 300, 200); + playlistStage.setScene(playlistScene); + playlistStage.setResizable(false); + playlistStage.getIcons().add(new Image(getClass().getResourceAsStream("MusicPlayerIcon.png"))); + playlistStage.show(); + + } catch (Exception e) { + e.printStackTrace(); + System.out.println("Error opening playlist window: " + e.getMessage()); + } + } } diff --git a/src/main/java/sbu/javafx/Song.java b/src/main/java/sbu/javafx/Song.java new file mode 100644 index 0000000..aedadb9 --- /dev/null +++ b/src/main/java/sbu/javafx/Song.java @@ -0,0 +1,34 @@ +package sbu.javafx; + +import java.sql.Time; + +public class Song { + private String songName; + private String artistName; + private String duration; + private String filePath; + + public Song(String songName, String artistName, String duration, String filePath) { + this.songName = songName; + this.artistName = artistName; + this.duration = duration; + this.filePath = filePath; + } + + //getters and setters + public String getSongName() { + return songName; + } + + public String getArtistName() { + return artistName; + } + + public String getDuration() { + return duration; + } + + public String getFilePath() { + return filePath; + } +} diff --git a/src/main/resources/sbu/songs/Married Life.mp3 b/src/main/resources/sbu/songs/Married Life.mp3 new file mode 100644 index 0000000..42adce2 Binary files /dev/null and b/src/main/resources/sbu/songs/Married Life.mp3 differ