diff --git a/src/main/java/sbu/javafx/MusicController.java b/src/main/java/sbu/javafx/MusicController.java index b19baeb..9dac1a9 100644 --- a/src/main/java/sbu/javafx/MusicController.java +++ b/src/main/java/sbu/javafx/MusicController.java @@ -5,6 +5,8 @@ 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.image.ImageView; import javafx.scene.layout.VBox; import javafx.scene.media.Media; import javafx.scene.media.MediaPlayer; @@ -24,10 +26,31 @@ public class MusicController @FXML private Button playBtn2; @FXML private Button playBtn3; + @FXML private ImageView playIcon1; + @FXML private ImageView playIcon2; + @FXML private ImageView playIcon3; + + @FXML private Button stopBtn1; + @FXML private Button stopBtn2; + @FXML private Button stopBtn3; + private final List playlist = new ArrayList<>(); private MediaPlayer mediaPlayer; + private boolean darkTheme = false; + private String currentPlayingSongFile = null; + private boolean isPlaying = false; + + private boolean isSong1Playing = false; + private boolean isSong2Playing = false; + private boolean isSong3Playing = false; + + + private Image playImage; + private Image pauseImage; + private Image stopImage; + private final String song1 = "Careless Whisper"; private final String song2 = "Adore You"; private final String song3 = "Wildflower"; @@ -37,42 +60,40 @@ public class MusicController private final String song3File = "/sbu/javafx/audio/wildflower.mp3"; @FXML - private void initialize() {updateNowPlaying("None");applyLightTheme();} + private void initialize() + { + playImage = loadImage("/sbu/javafx/images/play.png"); + pauseImage = loadImage("/sbu/javafx/images/pause.png"); + stopImage = loadImage("/sbu/javafx/images/stop.png"); - @FXML - public void handlePlay1() {playSong(song1, song1File, playBtn1);} + updateAllButtonIcons(); + updateNowPlaying("None"); + applyLightTheme(); + } - @FXML - public void handlePlay2() {playSong(song2, song2File, playBtn2);} + @FXML public void handlePlay1() { togglePlay(song1, song1File, playIcon1, 1); } + @FXML public void handlePlay2() { togglePlay(song2, song2File, playIcon2, 2); } + @FXML public void handlePlay3() { togglePlay(song3, song3File, playIcon3, 3); } - @FXML - public void handlePlay3() {playSong(song3, song3File, playBtn3);} + @FXML public void handleStop1() { stopSong(1); } + @FXML public void handleStop2() { stopSong(2); } + @FXML public void handleStop3() { stopSong(3); } - @FXML - public void handleAdd1() {addToPlaylist(song1);} - - @FXML - public void handleAdd2() {addToPlaylist(song2);} - - @FXML - public void handleAdd3() {addToPlaylist(song3);} + @FXML public void handleAdd1() { addToPlaylist(song1); } + @FXML public void handleAdd2() { addToPlaylist(song2); } + @FXML public void handleAdd3() { addToPlaylist(song3); } @FXML public void handleViewPlaylist() { Stage stage = new Stage(); - VBox root = new VBox(10); root.setStyle("-fx-padding: 16; -fx-background-color: white;"); - Label title = new Label("My Playlist"); title.setStyle("-fx-font-size: 18px; -fx-font-weight: bold;"); - ListView listView = new ListView<>(); listView.getItems().addAll(playlist); - root.getChildren().addAll(title, listView); - Scene scene = new Scene(root, 300, 400); stage.setScene(scene); stage.setTitle("Playlist"); @@ -83,12 +104,161 @@ public class MusicController public void handleToggleTheme() { darkTheme = !darkTheme; - - if (darkTheme) {applyDarkTheme();} - else {applyLightTheme();} + if (darkTheme) applyDarkTheme(); else applyLightTheme(); } - private void playSong(String songName, String resourcePath, Button playButton) + private void togglePlay(String songName, String resourcePath, ImageView icon, int songIndex) + { + boolean shouldPlay = false; + + switch(songIndex) + { + case 1: shouldPlay = !isSong1Playing; break; + case 2: shouldPlay = !isSong2Playing; break; + case 3: shouldPlay = !isSong3Playing; break; + } + + if (shouldPlay) + { + playOrResumeSong(songName, resourcePath, icon, songIndex); + } + else + { + pauseSong(songIndex); + } + updateAllButtonIcons(); + } + + private void playOrResumeSong(String songName, String resourcePath, ImageView icon, int songIndex) + { + try + { + if (mediaPlayer != null && isPlaying && !resourcePath.equals(currentPlayingSongFile)) + { + stopPlayback(); + updateAllButtonIcons(); + } + + if (mediaPlayer != null && !isPlaying && resourcePath.equals(currentPlayingSongFile)) + { + mediaPlayer.play(); + isPlaying = true; + } + else + { + if (mediaPlayer != null) + { + mediaPlayer.stop(); + mediaPlayer.dispose(); + } + + URL url = getClass().getResource(resourcePath); + if (url == null) + { + updateNowPlaying(songName + " (file not found)"); + setSongStatus(songIndex, false); + return; + } + + Media media = new Media(url.toExternalForm()); + mediaPlayer = new MediaPlayer(media); + + currentPlayingSongFile = resourcePath; + isPlaying = true; + + mediaPlayer.setOnEndOfMedia(() -> + { + stopPlayback(); + updateNowPlaying("None"); + setSongStatus(songIndex, false); + updateAllButtonIcons(); + }); + + mediaPlayer.setOnError(() -> + { + stopPlayback(); + updateNowPlaying(songName + " (error)"); + setSongStatus(songIndex, false); + updateAllButtonIcons(); + }); + + mediaPlayer.play(); + } + + setSongStatus(songIndex, true); + updateNowPlaying(songName); + + } + catch (Exception e) + { + stopPlayback(); + updateNowPlaying(songName + " (error)"); + setSongStatus(songIndex, false); + e.printStackTrace(); + } + } + + private void pauseSong(int songIndex) + { + if (mediaPlayer != null && isPlaying && currentPlayingSongFile != null) + { + String targetFile = ""; + switch(songIndex) + { + case 1: targetFile = song1File; break; + case 2: targetFile = song2File; break; + case 3: targetFile = song3File; break; + } + + if (currentPlayingSongFile.equals(targetFile)) + { + mediaPlayer.pause(); + isPlaying = false; + setSongStatus(songIndex, false); + updateNowPlaying("Paused: " + getSongNameByIndex(songIndex)); + updateAllButtonIcons(); + } + } + } + + private void stopSong(int songIndex) + { + if (mediaPlayer != null && isPlaying) + { + String targetFile = ""; + switch(songIndex) + { + case 1: targetFile = song1File; break; + case 2: targetFile = song2File; break; + case 3: targetFile = song3File; break; + } + + if (currentPlayingSongFile != null && currentPlayingSongFile.equals(targetFile)) + { + mediaPlayer.stop(); + mediaPlayer.dispose(); + mediaPlayer = null; + isPlaying = false; + currentPlayingSongFile = null; + setSongStatus(songIndex, false); + updateNowPlaying("None"); + updateAllButtonIcons(); + } + else + { + setSongStatus(songIndex, false); + updateAllButtonIcons(); + } + } + else + { + setSongStatus(songIndex, false); + updateAllButtonIcons(); + } + } + + + private void stopPlayback() { try { @@ -96,81 +266,119 @@ public class MusicController { mediaPlayer.stop(); mediaPlayer.dispose(); + mediaPlayer = null; } - - URL url = getClass().getResource(resourcePath); - if (url == null) - { - updateNowPlaying(songName + " (file not found)"); - return; - } - - Media media = new Media(url.toExternalForm()); - mediaPlayer = new MediaPlayer(media); - mediaPlayer.play(); - - updateNowPlaying(songName); - - if (playBtn1 != null) playBtn1.setText("Play"); - if (playBtn2 != null) playBtn2.setText("Play"); - if (playBtn3 != null) playBtn3.setText("Play"); - - if (playButton != null) {playButton.setText("Playing");} - } - catch (Exception e) + catch (Exception ignored) { } + + isPlaying = false; + currentPlayingSongFile = null; + isSong1Playing = false; + isSong2Playing = false; + isSong3Playing = false; + } + + private void setSongStatus(int songIndex, boolean status) + { + switch(songIndex) { - updateNowPlaying(songName + " (error)"); - e.printStackTrace(); + case 1: isSong1Playing = status; break; + case 2: isSong2Playing = status; break; + case 3: isSong3Playing = status; break; } } - private void addToPlaylist(String songName) + private boolean getSongStatus(int songIndex) { - if (!playlist.contains(songName)) {playlist.add(songName);} + switch(songIndex) + { + case 1: return isSong1Playing; + case 2: return isSong2Playing; + case 3: return isSong3Playing; + default: return false; + } + } + + private String getSongNameByIndex(int songIndex) + { + switch(songIndex) + { + case 1: return song1; + case 2: return song2; + case 3: return song3; + default: return "Unknown"; + } + } + + public void addToPlaylist(String songName) + { + if (!playlist.contains(songName)) + { + playlist.add(songName); + System.out.println(songName + " added to playlist."); + } + else + { + System.out.println(songName + " is already in the playlist."); + } } private void updateNowPlaying(String text) { - if (nowPlayingLabel != null) + if (nowPlayingLabel != null) {nowPlayingLabel.setText("Now Playing: " + text);} + } + + private void updateAllButtonIcons() + { + updateIconButton(playIcon1, isSong1Playing, song1File); + updateIconButton(playIcon2, isSong2Playing, song2File); + updateIconButton(playIcon3, isSong3Playing, song3File); + } + + private void updateIconButton(ImageView icon, boolean isPlayingCurrent, String currentSongFile) + { + if (icon == null) return; + + if (isPlaying && currentPlayingSongFile != null && currentPlayingSongFile.equals(currentSongFile)) { - nowPlayingLabel.setText("Now Playing: " + text); + if (icon.getImage() != pauseImage) {icon.setImage(pauseImage);} + } + else + { + if (icon.getImage() != playImage) {icon.setImage(playImage);} + } + } + + private Image loadImage(String resourcePath) + { + try + { + URL url = getClass().getResource(resourcePath); + if (url == null) + { + System.err.println("Image not found: " + resourcePath); + return null; + } + return new Image(url.toExternalForm()); + } + catch (Exception e) + { + System.err.println("Error loading image: " + resourcePath + " - " + e.getMessage()); + return null; } } private void applyDarkTheme() { - if (rootPane != null) - { - rootPane.setStyle("-fx-padding: 24;" + "-fx-background-color: #121212;"); - } - - if (titleLabel != null) - { - titleLabel.setStyle("-fx-font-size: 26px;" + "-fx-font-weight: bold;" + "-fx-text-fill: white;"); - } - - if (nowPlayingLabel != null) - { - nowPlayingLabel.setStyle("-fx-padding: 12;" + "-fx-background-color: #1E1E1E;" + "-fx-background-radius: 10;" + "-fx-border-color: #444444;" + "-fx-border-radius: 10;" + "-fx-text-fill: white;"); - } + if (rootPane != null) rootPane.setStyle("-fx-padding: 24; -fx-background-color: #121212;"); + if (titleLabel != null) titleLabel.setStyle("-fx-font-size: 26px; -fx-font-weight: bold; -fx-text-fill: white;"); + if (nowPlayingLabel != null) nowPlayingLabel.setStyle("-fx-padding: 12;" + "-fx-background-color: #1E1E1E;" + "-fx-background-radius: 10;" + "-fx-border-color: #444444;" + "-fx-border-radius: 10;" + "-fx-text-fill: white;"); } private void applyLightTheme() { - if (rootPane != null) - { - rootPane.setStyle("-fx-padding: 24;" + "-fx-background-color: #F8F8F8;"); - } - - if (titleLabel != null) - { - titleLabel.setStyle("-fx-font-size: 26px;" + "-fx-font-weight: bold;" + "-fx-text-fill: #222222;"); - } - - if (nowPlayingLabel != null) - { - nowPlayingLabel.setStyle("-fx-padding: 12;" + "-fx-background-color: white;" + "-fx-background-radius: 10;" + "-fx-border-color: rgba(0,0,0,0.15);" + "-fx-border-radius: 10;" + "-fx-text-fill: black;"); - } + if (rootPane != null) rootPane.setStyle("-fx-padding: 24; -fx-background-color: #F8F8F8;"); + if (titleLabel != null) titleLabel.setStyle("-fx-font-size: 26px; -fx-font-weight: bold; -fx-text-fill: #222222;"); + if (nowPlayingLabel != null) nowPlayingLabel.setStyle("-fx-padding: 12;" + "-fx-background-color: white;" + "-fx-background-radius: 10;" + "-fx-border-color: rgba(0,0,0,0.15);" + "-fx-border-radius: 10;" + "-fx-text-fill: black;"); } } \ No newline at end of file diff --git a/src/main/resources/sbu/javafx/App-view.fxml b/src/main/resources/sbu/javafx/App-view.fxml index c1a5184..a57e3f4 100644 --- a/src/main/resources/sbu/javafx/App-view.fxml +++ b/src/main/resources/sbu/javafx/App-view.fxml @@ -1,36 +1,46 @@ + + - + spacing="18" + prefWidth="520" + prefHeight="720" + style="-fx-padding: 24; -fx-background-color: #F8F8F8;"> -