diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5ad66ef
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,91 @@
+##############################
+## Java
+##############################
+.mtj.tmp/
+*.class
+*.jar
+*.war
+*.ear
+*.nar
+hs_err_pid*
+replay_pid*
+
+##############################
+## Maven
+##############################
+target/
+pom.xml.tag
+pom.xml.releaseBackup
+pom.xml.versionsBackup
+pom.xml.next
+pom.xml.bak
+release.properties
+dependency-reduced-pom.xml
+buildNumber.properties
+.mvn/timing.properties
+.mvn/wrapper/maven-wrapper.jar
+
+##############################
+## Gradle
+##############################
+bin/
+build/
+.gradle
+.gradletasknamecache
+gradle-app.setting
+!gradle-wrapper.jar
+
+##############################
+## IntelliJ
+##############################
+out/
+.idea/
+.idea_modules/
+*.iml
+*.ipr
+*.iws
+
+##############################
+## Eclipse
+##############################
+.settings/
+bin/
+tmp/
+.metadata
+.classpath
+.project
+*.tmp
+*.bak
+*.swp
+*~.nib
+local.properties
+.loadpath
+.factorypath
+
+##############################
+## NetBeans
+##############################
+nbproject/
+nbproject/private/
+build/
+nbbuild/
+dist/
+nbdist/
+nbactions.xml
+nb-configuration.xml
+build.xml
+manifest.mf
+##############################
+## Visual Studio Code
+##############################
+.vscode/
+.code-workspace
+
+##############################
+## OS X
+##############################
+.DS_Store
+
+src/main/ts/.env
+
+.env
\ No newline at end of file
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..463e948
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..aa00ffa
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
new file mode 100644
index 0000000..712ab9d
--- /dev/null
+++ b/.idea/jarRepositories.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..ea0b3a9
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
\ 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/README.md b/README.md
index 6e523cc..86c6c34 100644
--- a/README.md
+++ b/README.md
@@ -38,3 +38,6 @@
+
+
Build
+Build to jar file: mvn package
\ No newline at end of file
diff --git a/dependency-reduced-pom.xml b/dependency-reduced-pom.xml
new file mode 100644
index 0000000..bd82758
--- /dev/null
+++ b/dependency-reduced-pom.xml
@@ -0,0 +1,52 @@
+
+
+ 4.0.0
+ com.music
+ Java-Swing-MusicPlayer
+ 1.0-SNAPSHOT
+
+
+
+ src/main/resources
+
+ **/*.*
+
+
+
+ Music Player Swing
+
+
+ maven-shade-plugin
+ 3.2.4
+
+
+ package
+
+ shade
+
+
+
+
+ App
+
+
+
+
+
+
+
+
+
+
+ org.projectlombok
+ lombok
+ 1.18.30
+ provided
+
+
+
+ 18
+ 18
+ UTF-8
+
+
diff --git a/lib/jaudiotagger-3.0.1.jar b/lib/jaudiotagger-3.0.1.jar
deleted file mode 100644
index b1b4045..0000000
Binary files a/lib/jaudiotagger-3.0.1.jar and /dev/null differ
diff --git a/lib/jlayer-1.0.1.jar b/lib/jlayer-1.0.1.jar
deleted file mode 100644
index b4870bc..0000000
Binary files a/lib/jlayer-1.0.1.jar and /dev/null differ
diff --git a/lib/mp3agic-0.9.0.jar b/lib/mp3agic-0.9.0.jar
deleted file mode 100644
index 632ae3f..0000000
Binary files a/lib/mp3agic-0.9.0.jar and /dev/null differ
diff --git a/out/production/MP3MusicPlayer/App$1.class b/out/production/MP3MusicPlayer/App$1.class
deleted file mode 100644
index 59f2730..0000000
Binary files a/out/production/MP3MusicPlayer/App$1.class and /dev/null differ
diff --git a/out/production/MP3MusicPlayer/App.class b/out/production/MP3MusicPlayer/App.class
deleted file mode 100644
index 95a00a7..0000000
Binary files a/out/production/MP3MusicPlayer/App.class and /dev/null differ
diff --git a/out/production/MP3MusicPlayer/MusicPlayer$1.class b/out/production/MP3MusicPlayer/MusicPlayer$1.class
deleted file mode 100644
index b53d27c..0000000
Binary files a/out/production/MP3MusicPlayer/MusicPlayer$1.class and /dev/null differ
diff --git a/out/production/MP3MusicPlayer/MusicPlayer$2.class b/out/production/MP3MusicPlayer/MusicPlayer$2.class
deleted file mode 100644
index 3068b92..0000000
Binary files a/out/production/MP3MusicPlayer/MusicPlayer$2.class and /dev/null differ
diff --git a/out/production/MP3MusicPlayer/MusicPlayer.class b/out/production/MP3MusicPlayer/MusicPlayer.class
deleted file mode 100644
index d6be323..0000000
Binary files a/out/production/MP3MusicPlayer/MusicPlayer.class and /dev/null differ
diff --git a/out/production/MP3MusicPlayer/MusicPlayerGUI$1.class b/out/production/MP3MusicPlayer/MusicPlayerGUI$1.class
deleted file mode 100644
index fb75d8c..0000000
Binary files a/out/production/MP3MusicPlayer/MusicPlayerGUI$1.class and /dev/null differ
diff --git a/out/production/MP3MusicPlayer/MusicPlayerGUI$2.class b/out/production/MP3MusicPlayer/MusicPlayerGUI$2.class
deleted file mode 100644
index 5e738c3..0000000
Binary files a/out/production/MP3MusicPlayer/MusicPlayerGUI$2.class and /dev/null differ
diff --git a/out/production/MP3MusicPlayer/MusicPlayerGUI$3.class b/out/production/MP3MusicPlayer/MusicPlayerGUI$3.class
deleted file mode 100644
index 00e1a6c..0000000
Binary files a/out/production/MP3MusicPlayer/MusicPlayerGUI$3.class and /dev/null differ
diff --git a/out/production/MP3MusicPlayer/MusicPlayerGUI$4.class b/out/production/MP3MusicPlayer/MusicPlayerGUI$4.class
deleted file mode 100644
index 3a8f73c..0000000
Binary files a/out/production/MP3MusicPlayer/MusicPlayerGUI$4.class and /dev/null differ
diff --git a/out/production/MP3MusicPlayer/MusicPlayerGUI$5.class b/out/production/MP3MusicPlayer/MusicPlayerGUI$5.class
deleted file mode 100644
index 0788c55..0000000
Binary files a/out/production/MP3MusicPlayer/MusicPlayerGUI$5.class and /dev/null differ
diff --git a/out/production/MP3MusicPlayer/MusicPlayerGUI$6.class b/out/production/MP3MusicPlayer/MusicPlayerGUI$6.class
deleted file mode 100644
index 9b87dec..0000000
Binary files a/out/production/MP3MusicPlayer/MusicPlayerGUI$6.class and /dev/null differ
diff --git a/out/production/MP3MusicPlayer/MusicPlayerGUI$7.class b/out/production/MP3MusicPlayer/MusicPlayerGUI$7.class
deleted file mode 100644
index a8d0f01..0000000
Binary files a/out/production/MP3MusicPlayer/MusicPlayerGUI$7.class and /dev/null differ
diff --git a/out/production/MP3MusicPlayer/MusicPlayerGUI$8.class b/out/production/MP3MusicPlayer/MusicPlayerGUI$8.class
deleted file mode 100644
index 58efb91..0000000
Binary files a/out/production/MP3MusicPlayer/MusicPlayerGUI$8.class and /dev/null differ
diff --git a/out/production/MP3MusicPlayer/MusicPlayerGUI.class b/out/production/MP3MusicPlayer/MusicPlayerGUI.class
deleted file mode 100644
index 96896ea..0000000
Binary files a/out/production/MP3MusicPlayer/MusicPlayerGUI.class and /dev/null differ
diff --git a/out/production/MP3MusicPlayer/MusicPlaylistDialog$1.class b/out/production/MP3MusicPlayer/MusicPlaylistDialog$1.class
deleted file mode 100644
index b2e28f9..0000000
Binary files a/out/production/MP3MusicPlayer/MusicPlaylistDialog$1.class and /dev/null differ
diff --git a/out/production/MP3MusicPlayer/MusicPlaylistDialog$2.class b/out/production/MP3MusicPlayer/MusicPlaylistDialog$2.class
deleted file mode 100644
index 5d6052e..0000000
Binary files a/out/production/MP3MusicPlayer/MusicPlaylistDialog$2.class and /dev/null differ
diff --git a/out/production/MP3MusicPlayer/MusicPlaylistDialog.class b/out/production/MP3MusicPlayer/MusicPlaylistDialog.class
deleted file mode 100644
index c3539b1..0000000
Binary files a/out/production/MP3MusicPlayer/MusicPlaylistDialog.class and /dev/null differ
diff --git a/out/production/MP3MusicPlayer/Song.class b/out/production/MP3MusicPlayer/Song.class
deleted file mode 100644
index adeb51e..0000000
Binary files a/out/production/MP3MusicPlayer/Song.class and /dev/null differ
diff --git a/out/production/MP3MusicPlayer/assets/playlist.txt b/out/production/MP3MusicPlayer/assets/playlist.txt
deleted file mode 100644
index 122aeab..0000000
--- a/out/production/MP3MusicPlayer/assets/playlist.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-D:\Programming\Youtube Videos\Java\MP3MusicPlayer\src\assets\Auld Lang Syne (Instrumental) - Jingle Punks.mp3
-D:\Programming\Youtube Videos\Java\MP3MusicPlayer\src\assets\Tropic Fuse - French Fuse.mp3
-D:\Programming\Youtube Videos\Java\MP3MusicPlayer\src\assets\Wind Riders - Asher Fulero.mp3
diff --git a/out/production/MP3MusicPlayer/assets/playlist2.txt b/out/production/MP3MusicPlayer/assets/playlist2.txt
deleted file mode 100644
index 122aeab..0000000
--- a/out/production/MP3MusicPlayer/assets/playlist2.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-D:\Programming\Youtube Videos\Java\MP3MusicPlayer\src\assets\Auld Lang Syne (Instrumental) - Jingle Punks.mp3
-D:\Programming\Youtube Videos\Java\MP3MusicPlayer\src\assets\Tropic Fuse - French Fuse.mp3
-D:\Programming\Youtube Videos\Java\MP3MusicPlayer\src\assets\Wind Riders - Asher Fulero.mp3
diff --git a/out/production/MP3MusicPlayer/assets/playlist3.txt b/out/production/MP3MusicPlayer/assets/playlist3.txt
deleted file mode 100644
index 122aeab..0000000
--- a/out/production/MP3MusicPlayer/assets/playlist3.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-D:\Programming\Youtube Videos\Java\MP3MusicPlayer\src\assets\Auld Lang Syne (Instrumental) - Jingle Punks.mp3
-D:\Programming\Youtube Videos\Java\MP3MusicPlayer\src\assets\Tropic Fuse - French Fuse.mp3
-D:\Programming\Youtube Videos\Java\MP3MusicPlayer\src\assets\Wind Riders - Asher Fulero.mp3
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..6890778
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,82 @@
+
+
+ 4.0.0
+
+ com.music
+ Java-Swing-MusicPlayer
+ 1.0-SNAPSHOT
+
+
+ 18
+ 18
+ UTF-8
+
+
+
+
+
+ net.jthink
+ jaudiotagger
+ 3.0.1
+
+
+
+ javazoom
+ jlayer
+ 1.0.1
+
+
+
+ com.mpatric
+ mp3agic
+ 0.9.0
+
+
+
+ org.projectlombok
+ lombok
+ 1.18.30
+ provided
+
+
+
+
+ Music Player Swing
+
+
+ src/main/resources
+ false
+
+ **/*.*
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.2.4
+
+
+ package
+
+ shade
+
+
+
+
+ App
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/MusicPlayer.java b/src/MusicPlayer.java
deleted file mode 100644
index a3e38d8..0000000
--- a/src/MusicPlayer.java
+++ /dev/null
@@ -1,351 +0,0 @@
-import javazoom.jl.player.advanced.AdvancedPlayer;
-import javazoom.jl.player.advanced.PlaybackEvent;
-import javazoom.jl.player.advanced.PlaybackListener;
-
-import java.io.*;
-import java.util.ArrayList;
-
-public class MusicPlayer extends PlaybackListener {
- // this will be used to update isPaused more synchronously
- private static final Object playSignal = new Object();
-
- // need reference so that we can update the gui in this class
- private MusicPlayerGUI musicPlayerGUI;
-
- // we will need a way to store our song's details, so we will be creating a song class
- private Song currentSong;
- public Song getCurrentSong(){
- return currentSong;
- }
-
- private ArrayList playlist;
-
- // we will need to keep track the index we are in the playlist
- private int currentPlaylistIndex;
-
- // use JLayer library to create an AdvancedPlayer obj which will handle playing the music
- private AdvancedPlayer advancedPlayer;
-
- // pause boolean flag used to indicate whether the player has been paused
- private boolean isPaused;
-
- // boolean flag used to tell when the song has finished
- private boolean songFinished;
-
- private boolean pressedNext, pressedPrev;
-
- // stores in teh last frame when the playback is finished (used for pausing and resuming)
- private int currentFrame;
- public void setCurrentFrame(int frame){
- currentFrame = frame;
- }
-
- // track how many milliseconds has passed since playing the song (used for updating the slider)
- private int currentTimeInMilli;
- public void setCurrentTimeInMilli(int timeInMilli){
- currentTimeInMilli = timeInMilli;
- }
-
- // constructor
- public MusicPlayer(MusicPlayerGUI musicPlayerGUI){
- this.musicPlayerGUI = musicPlayerGUI;
- }
-
- public void loadSong(Song song){
- currentSong = song;
- playlist = null;
-
- // stop the song if possible
- if(!songFinished)
- stopSong();
-
- // play the current song if not null
- if(currentSong != null){
- // reset frame
- currentFrame = 0;
-
- // reset current time in milli
- currentTimeInMilli = 0;
-
- // update gui
- musicPlayerGUI.setPlaybackSliderValue(0);
-
- playCurrentSong();
- }
- }
-
- public void loadPlaylist(File playlistFile){
- playlist = new ArrayList<>();
-
- // store the paths from the text file into the playlist array list
- try{
- FileReader fileReader = new FileReader(playlistFile);
- BufferedReader bufferedReader = new BufferedReader(fileReader);
-
- // reach each line from the text file and store the text into the songPath variable
- String songPath;
- while((songPath = bufferedReader.readLine()) != null){
- // create song object based on song path
- Song song = new Song(songPath);
-
- // add to playlist array list
- playlist.add(song);
- }
- }catch(Exception e){
- e.printStackTrace();
- }
-
- if(playlist.size() > 0){
- // reset playback slider
- musicPlayerGUI.setPlaybackSliderValue(0);
- currentTimeInMilli = 0;
-
- // update current song to the first song in the playlist
- currentSong = playlist.get(0);
-
- // start from the beginning frame
- currentFrame = 0;
-
- // update gui
- musicPlayerGUI.enablePauseButtonDisablePlayButton();
- musicPlayerGUI.updateSongTitleAndArtist(currentSong);
- musicPlayerGUI.updatePlaybackSlider(currentSong);
-
- // start song
- playCurrentSong();
- }
- }
-
- public void pauseSong(){
- if(advancedPlayer != null){
- // update isPaused flag
- isPaused = true;
-
- // then we want to stop the player
- stopSong();
- }
- }
-
- public void stopSong(){
- if(advancedPlayer != null){
- advancedPlayer.stop();
- advancedPlayer.close();
- advancedPlayer = null;
- }
- }
-
- public void nextSong(){
- // no need to go to the next song if there is no playlist
- if(playlist == null) return;
-
- // check to see if we have reached the end of the playlist, if so then don't do anything
- if(currentPlaylistIndex + 1 > playlist.size() - 1) return;
-
- pressedNext = true;
-
- // stop the song if possible
- if(!songFinished)
- stopSong();
-
- // increase current playlist index
- currentPlaylistIndex++;
-
- // update current song
- currentSong = playlist.get(currentPlaylistIndex);
-
- // reset frame
- currentFrame = 0;
-
- // reset current time in milli
- currentTimeInMilli = 0;
-
- // update gui
- musicPlayerGUI.enablePauseButtonDisablePlayButton();
- musicPlayerGUI.updateSongTitleAndArtist(currentSong);
- musicPlayerGUI.updatePlaybackSlider(currentSong);
-
- // play the song
- playCurrentSong();
- }
-
- public void prevSong(){
- // no need to go to the next song if there is no playlist
- if(playlist == null) return;
-
- // check to see if we can go to the previous song
- if(currentPlaylistIndex - 1 < 0) return;
-
- pressedPrev = true;
-
- // stop the song if possible
- if(!songFinished)
- stopSong();
-
- // decrease current playlist index
- currentPlaylistIndex--;
-
- // update current song
- currentSong = playlist.get(currentPlaylistIndex);
-
- // reset frame
- currentFrame = 0;
-
- // reset current time in milli
- currentTimeInMilli = 0;
-
- // update gui
- musicPlayerGUI.enablePauseButtonDisablePlayButton();
- musicPlayerGUI.updateSongTitleAndArtist(currentSong);
- musicPlayerGUI.updatePlaybackSlider(currentSong);
-
- // play the song
- playCurrentSong();
- }
-
- public void playCurrentSong(){
- if(currentSong == null) return;
-
- try{
- // read mp3 audio data
- FileInputStream fileInputStream = new FileInputStream(currentSong.getFilePath());
- BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
-
- // create a new advanced player
- advancedPlayer = new AdvancedPlayer(bufferedInputStream);
- advancedPlayer.setPlayBackListener(this);
-
- // start music
- startMusicThread();
-
- // start playback slider thread
- startPlaybackSliderThread();
-
- }catch(Exception e){
- e.printStackTrace();
- }
- }
-
- // create a thread that will handle playing the music
- private void startMusicThread(){
- new Thread(new Runnable() {
- @Override
- public void run() {
- try{
- if(isPaused){
- synchronized(playSignal){
- // update flag
- isPaused = false;
-
- // notify the other thread to continue (makes sure that isPaused is updated to false properly)
- playSignal.notify();
- }
-
- // resume music from last frame
- advancedPlayer.play(currentFrame, Integer.MAX_VALUE);
- }else{
- // play music from the beginning
- advancedPlayer.play();
- }
- }catch(Exception e){
- e.printStackTrace();
- }
- }
- }).start();
- }
-
- // create a thread that will handle updating the slider
- private void startPlaybackSliderThread(){
- new Thread(new Runnable() {
- @Override
- public void run() {
- if(isPaused){
- try{
- // wait till it gets notified by other thread to continue
- // makes sure that isPaused boolean flag updates to false before continuing
- synchronized(playSignal){
- playSignal.wait();
- }
- }catch(Exception e){
- e.printStackTrace();
- }
- }
-
- while(!isPaused && !songFinished && !pressedNext && !pressedPrev){
- try{
- // increment current time milli
- currentTimeInMilli++;
-
- // calculate into frame value
- int calculatedFrame = (int) ((double) currentTimeInMilli * 2.08 * currentSong.getFrameRatePerMilliseconds());
-
- // update gui
- musicPlayerGUI.setPlaybackSliderValue(calculatedFrame);
-
- // mimic 1 millisecond using thread.sleep
- Thread.sleep(1);
- }catch(Exception e){
- e.printStackTrace();
- }
- }
- }
- }).start();
- }
-
- @Override
- public void playbackStarted(PlaybackEvent evt) {
- // this method gets called in the beginning of the song
- System.out.println("Playback Started");
- songFinished = false;
- pressedNext = false;
- pressedPrev = false;
- }
-
- @Override
- public void playbackFinished(PlaybackEvent evt) {
- // this method gets called when the song finishes or if the player gets closed
- System.out.println("Playback Finished");
- if(isPaused){
- currentFrame += (int) ((double) evt.getFrame() * currentSong.getFrameRatePerMilliseconds());
- }else{
- // if the user pressed next or prev we don't need to execute the rest of the code
- if(pressedNext || pressedPrev) return;
-
- // when the song ends
- songFinished = true;
-
- if(playlist == null){
- // update gui
- musicPlayerGUI.enablePlayButtonDisablePauseButton();
- }else{
- // last song in the playlist
- if(currentPlaylistIndex == playlist.size() - 1){
- // update gui
- musicPlayerGUI.enablePlayButtonDisablePauseButton();
- }else{
- // go to the next song in the playlist
- nextSong();
- }
- }
- }
- }
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/MusicPlaylistDialog.java b/src/MusicPlaylistDialog.java
deleted file mode 100644
index 1b23408..0000000
--- a/src/MusicPlaylistDialog.java
+++ /dev/null
@@ -1,130 +0,0 @@
-import javax.swing.*;
-import javax.swing.filechooser.FileNameExtensionFilter;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileWriter;
-import java.util.ArrayList;
-
-public class MusicPlaylistDialog extends JDialog {
- private MusicPlayerGUI musicPlayerGUI;
-
- // store all of the paths to be written to a txt file (when we load a playlist)
- private ArrayList songPaths;
-
- public MusicPlaylistDialog(MusicPlayerGUI musicPlayerGUI){
- this.musicPlayerGUI = musicPlayerGUI;
- songPaths = new ArrayList<>();
-
- // configure dialog
- setTitle("Create Playlist");
- setSize(400, 400);
- setResizable(false);
- getContentPane().setBackground(MusicPlayerGUI.FRAME_COLOR);
- setLayout(null);
- setModal(true); // this property makes it so that the dialog has to be closed to give focus
- setLocationRelativeTo(musicPlayerGUI);
-
- addDialogComponents();
- }
-
- private void addDialogComponents(){
- // container to hold each song path
- JPanel songContainer = new JPanel();
- songContainer.setLayout(new BoxLayout(songContainer, BoxLayout.Y_AXIS));
- songContainer.setBounds((int)(getWidth() * 0.025), 10, (int)(getWidth() * 0.90), (int) (getHeight() * 0.75));
- add(songContainer);
-
- // add song button
- JButton addSongButton = new JButton("Add");
- addSongButton.setBounds(60, (int) (getHeight() * 0.80), 100, 25);
- addSongButton.setFont(new Font("Dialog", Font.BOLD, 14));
- addSongButton.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- // open file explorer
- JFileChooser jFileChooser = new JFileChooser();
- jFileChooser.setFileFilter(new FileNameExtensionFilter("MP3", "mp3"));
- jFileChooser.setCurrentDirectory(new File("src/assets"));
- int result = jFileChooser.showOpenDialog(MusicPlaylistDialog.this);
-
- File selectedFile = jFileChooser.getSelectedFile();
- if(result == JFileChooser.APPROVE_OPTION && selectedFile != null){
- JLabel filePathLabel = new JLabel(selectedFile.getPath());
- filePathLabel.setFont(new Font("Dialog", Font.BOLD, 12));
- filePathLabel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
-
- // add to the list
- songPaths.add(filePathLabel.getText());
-
- // add to container
- songContainer.add(filePathLabel);
-
- // refreshes dialog to show newly added JLabel
- songContainer.revalidate();
- }
- }
- });
- add(addSongButton);
-
- // save playlist button
- JButton savePlaylistButton = new JButton("Save");
- savePlaylistButton.setBounds(215, (int) (getHeight() * 0.80), 100, 25);
- savePlaylistButton.setFont(new Font("Dialog", Font.BOLD, 14));
- savePlaylistButton.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- try{
- JFileChooser jFileChooser = new JFileChooser();
- jFileChooser.setCurrentDirectory(new File("src/assets"));
- int result = jFileChooser.showSaveDialog(MusicPlaylistDialog.this);
-
- if(result == JFileChooser.APPROVE_OPTION){
- // we use getSelectedFile() to get reference to the file that we are about to save
- File selectedFile = jFileChooser.getSelectedFile();
-
- // convert to .txt file if not done so already
- // this will check to see if the file does not have the ".txt" file extension
- if(!selectedFile.getName().substring(selectedFile.getName().length() - 4).equalsIgnoreCase(".txt")){
- selectedFile = new File(selectedFile.getAbsoluteFile() + ".txt");
- }
-
- // create the new file at the destinated directory
- selectedFile.createNewFile();
-
- // now we will write all of the song paths into this file
- FileWriter fileWriter = new FileWriter(selectedFile);
- BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
-
- // iterate through our song paths list and write each string into the file
- // each song will be written in their own row
- for(String songPath : songPaths){
- bufferedWriter.write(songPath + "\n");
- }
- bufferedWriter.close();
-
- // display success dialog
- JOptionPane.showMessageDialog(MusicPlaylistDialog.this, "Successfully Created Playlist!");
-
- // close this dialog
- MusicPlaylistDialog.this.dispose();
- }
- }catch(Exception exception){
- exception.printStackTrace();
- }
- }
- });
- add(savePlaylistButton);
- }
-}
-
-
-
-
-
-
-
-
-
diff --git a/src/assets/Auld Lang Syne (Instrumental) - Jingle Punks.mp3 b/src/assets/Auld Lang Syne (Instrumental) - Jingle Punks.mp3
deleted file mode 100644
index 29f2835..0000000
Binary files a/src/assets/Auld Lang Syne (Instrumental) - Jingle Punks.mp3 and /dev/null differ
diff --git a/src/assets/Tropic Fuse - French Fuse.mp3 b/src/assets/Tropic Fuse - French Fuse.mp3
deleted file mode 100644
index 52851b9..0000000
Binary files a/src/assets/Tropic Fuse - French Fuse.mp3 and /dev/null differ
diff --git a/src/assets/Wind Riders - Asher Fulero.mp3 b/src/assets/Wind Riders - Asher Fulero.mp3
deleted file mode 100644
index 6d802f2..0000000
Binary files a/src/assets/Wind Riders - Asher Fulero.mp3 and /dev/null differ
diff --git a/src/assets/next.png b/src/assets/next.png
deleted file mode 100644
index 85242a1..0000000
Binary files a/src/assets/next.png and /dev/null differ
diff --git a/src/assets/pause.png b/src/assets/pause.png
deleted file mode 100644
index 555abe7..0000000
Binary files a/src/assets/pause.png and /dev/null differ
diff --git a/src/assets/play.png b/src/assets/play.png
deleted file mode 100644
index 83bb1ce..0000000
Binary files a/src/assets/play.png and /dev/null differ
diff --git a/src/assets/playlist.txt b/src/assets/playlist.txt
deleted file mode 100644
index 122aeab..0000000
--- a/src/assets/playlist.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-D:\Programming\Youtube Videos\Java\MP3MusicPlayer\src\assets\Auld Lang Syne (Instrumental) - Jingle Punks.mp3
-D:\Programming\Youtube Videos\Java\MP3MusicPlayer\src\assets\Tropic Fuse - French Fuse.mp3
-D:\Programming\Youtube Videos\Java\MP3MusicPlayer\src\assets\Wind Riders - Asher Fulero.mp3
diff --git a/src/assets/playlist2.txt b/src/assets/playlist2.txt
deleted file mode 100644
index 122aeab..0000000
--- a/src/assets/playlist2.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-D:\Programming\Youtube Videos\Java\MP3MusicPlayer\src\assets\Auld Lang Syne (Instrumental) - Jingle Punks.mp3
-D:\Programming\Youtube Videos\Java\MP3MusicPlayer\src\assets\Tropic Fuse - French Fuse.mp3
-D:\Programming\Youtube Videos\Java\MP3MusicPlayer\src\assets\Wind Riders - Asher Fulero.mp3
diff --git a/src/assets/playlist3.txt b/src/assets/playlist3.txt
deleted file mode 100644
index 122aeab..0000000
--- a/src/assets/playlist3.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-D:\Programming\Youtube Videos\Java\MP3MusicPlayer\src\assets\Auld Lang Syne (Instrumental) - Jingle Punks.mp3
-D:\Programming\Youtube Videos\Java\MP3MusicPlayer\src\assets\Tropic Fuse - French Fuse.mp3
-D:\Programming\Youtube Videos\Java\MP3MusicPlayer\src\assets\Wind Riders - Asher Fulero.mp3
diff --git a/src/assets/previous.png b/src/assets/previous.png
deleted file mode 100644
index 4c815ec..0000000
Binary files a/src/assets/previous.png and /dev/null differ
diff --git a/src/assets/record.png b/src/assets/record.png
deleted file mode 100644
index ebfc74a..0000000
Binary files a/src/assets/record.png and /dev/null differ
diff --git a/src/App.java b/src/main/java/App.java
similarity index 65%
rename from src/App.java
rename to src/main/java/App.java
index a4a805b..141056e 100644
--- a/src/App.java
+++ b/src/main/java/App.java
@@ -1,16 +1,17 @@
-import javax.swing.*;
-
-public class App {
- public static void main(String[] args) {
- SwingUtilities.invokeLater(new Runnable(){
- @Override
- public void run(){
- new MusicPlayerGUI().setVisible(true);
-
-// Song song = new Song("src/assets/Wind Riders - Asher Fulero.mp3");
-// System.out.println(song.getSongTitle());
-// System.out.println(song.getSongArtist());
- }
- });
- }
-}
+import javax.swing.*;
+import views.MusicPlayerView;
+
+public class App {
+ public static void main(String[] args) {
+ SwingUtilities.invokeLater(new Runnable(){
+ @Override
+ public void run(){
+ new MusicPlayerView().setVisible(true);
+
+// models.Song song = new models.Song("src/assets/Wind Riders - Asher Fulero.mp3");
+// System.out.println(song.getSongTitle());
+// System.out.println(song.getSongArtist());
+ }
+ });
+ }
+}
diff --git a/src/main/java/constants/ResourcesPath.java b/src/main/java/constants/ResourcesPath.java
new file mode 100644
index 0000000..6a7ee49
--- /dev/null
+++ b/src/main/java/constants/ResourcesPath.java
@@ -0,0 +1,11 @@
+package constants;
+
+public class ResourcesPath {
+ public static final String CURRENT_DIRECTORY = "src/main/resources";
+ public static final String SONG_IMAGE = "/record.png";
+ public static final String PREVIOUS_BUTTON = "/previous.png";
+ public static final String PLAY_BUTTON = "/play.png";
+ public static final String PAUSE_BUTTON = "/pause.png";
+ public static final String NEXT_BUTTON = "/next.png";
+
+}
diff --git a/src/main/java/controllers/MusicPlayerController.java b/src/main/java/controllers/MusicPlayerController.java
new file mode 100644
index 0000000..15c175a
--- /dev/null
+++ b/src/main/java/controllers/MusicPlayerController.java
@@ -0,0 +1,459 @@
+package controllers;
+
+import constants.ResourcesPath;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import javax.swing.JButton;
+import javax.swing.JFileChooser;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import javazoom.jl.player.advanced.AdvancedPlayer;
+import javazoom.jl.player.advanced.PlaybackEvent;
+import javazoom.jl.player.advanced.PlaybackListener;
+
+import java.io.*;
+import java.util.ArrayList;
+import models.Song;
+import views.MusicPlayerView;
+import views.MusicPlaylistDialog;
+
+public class MusicPlayerController extends PlaybackListener implements ActionListener {
+
+ // this will be used to update isPaused more synchronously
+ private static final Object playSignal = new Object();
+
+ // need reference so that we can update the gui in this class
+ private MusicPlayerView musicPlayerView;
+
+ // we will need a way to store our song's details, so we will be creating a song class
+ private Song currentSong;
+ boolean isPlaying = false;
+
+ public Song getCurrentSong() {
+ return currentSong;
+ }
+
+ private ArrayList playlist;
+
+ // we will need to keep track the index we are in the playlist
+ private int currentPlaylistIndex;
+
+ // use JLayer library to create an AdvancedPlayer obj which will handle playing the music
+ private AdvancedPlayer advancedPlayer;
+
+ // pause boolean flag used to indicate whether the player has been paused
+ private boolean isPaused;
+
+ // boolean flag used to tell when the song has finished
+ private boolean songFinished;
+
+ private boolean pressedNext, pressedPrev;
+
+ // stores in teh last frame when the playback is finished (used for pausing and resuming)
+ private int currentFrame;
+
+ public void setCurrentFrame(int frame) {
+ currentFrame = frame;
+ }
+
+ // track how many milliseconds has passed since playing the song (used for updating the slider)
+ private int currentTimeInMilli;
+
+ public void setCurrentTimeInMilli(int timeInMilli) {
+ currentTimeInMilli = timeInMilli;
+ }
+
+ // constructor
+ public MusicPlayerController(MusicPlayerView musicPlayerView) {
+ this.musicPlayerView = musicPlayerView;
+ }
+
+ public void loadSong(Song song) {
+ currentSong = song;
+ playlist = null;
+
+ // stop the song if possible
+ if (!songFinished) {
+ stopSong();
+ }
+
+ // play the current song if not null
+ if (currentSong != null) {
+ // reset frame
+ currentFrame = 0;
+
+ // reset current time in milli
+ currentTimeInMilli = 0;
+
+ // update gui
+ musicPlayerView.setPlaybackSliderValue(0);
+
+ playCurrentSong();
+ }
+ }
+
+ public void loadPlaylist(File playlistFile) {
+ playlist = new ArrayList<>();
+
+ // store the paths from the text file into the playlist array list
+ try {
+ FileReader fileReader = new FileReader(playlistFile);
+ BufferedReader bufferedReader = new BufferedReader(fileReader);
+
+ // reach each line from the text file and store the text into the songPath variable
+ String songPath;
+ while ((songPath = bufferedReader.readLine()) != null) {
+ // create song object based on song path
+ Song song = new Song(songPath);
+
+ // add to playlist array list
+ playlist.add(song);
+ }
+ } catch (Exception e) {
+ System.out.println(e.getMessage());
+ }
+
+ if (playlist.size() > 0) {
+ // reset playback slider
+ musicPlayerView.setPlaybackSliderValue(0);
+ currentTimeInMilli = 0;
+
+ // update current song to the first song in the playlist
+ currentSong = playlist.get(0);
+
+ // start from the beginning frame
+ currentFrame = 0;
+
+ // update gui
+ musicPlayerView.enablePauseButtonDisablePlayButton();
+ musicPlayerView.updateSongTitleAndArtist(currentSong);
+ musicPlayerView.updatePlaybackSlider(currentSong);
+
+ // start song
+ playCurrentSong();
+ }
+ }
+
+ public void pauseSong() {
+ if (advancedPlayer != null) {
+ // update isPaused flag
+ isPaused = true;
+
+ // then we want to stop the player
+ stopSong();
+ }
+ }
+
+ public void stopSong() {
+ if (advancedPlayer != null) {
+ advancedPlayer.stop();
+ advancedPlayer.close();
+ advancedPlayer = null;
+ }
+ }
+
+ public void nextSong() {
+ // no need to go to the next song if there is no playlist
+ if (playlist == null) {
+ return;
+ }
+
+ // check to see if we have reached the end of the playlist, if so then don't do anything
+ if (currentPlaylistIndex + 1 > playlist.size() - 1) {
+ return;
+ }
+
+ pressedNext = true;
+
+ // stop the song if possible
+ if (!songFinished) {
+ stopSong();
+ }
+
+ // increase current playlist index
+ currentPlaylistIndex++;
+
+ // update current song
+ currentSong = playlist.get(currentPlaylistIndex);
+
+ // reset frame
+ currentFrame = 0;
+
+ // reset current time in milli
+ currentTimeInMilli = 0;
+
+ // update gui
+ musicPlayerView.enablePauseButtonDisablePlayButton();
+ musicPlayerView.updateSongTitleAndArtist(currentSong);
+ musicPlayerView.updatePlaybackSlider(currentSong);
+
+ // play the song
+ playCurrentSong();
+ }
+
+ public void prevSong() {
+ // no need to go to the next song if there is no playlist
+ if (playlist == null) {
+ return;
+ }
+
+ // check to see if we can go to the previous song
+ if (currentPlaylistIndex - 1 < 0) {
+ return;
+ }
+
+ pressedPrev = true;
+
+ // stop the song if possible
+ if (!songFinished) {
+ stopSong();
+ }
+
+ // decrease current playlist index
+ currentPlaylistIndex--;
+
+ // update current song
+ currentSong = playlist.get(currentPlaylistIndex);
+
+ // reset frame
+ currentFrame = 0;
+
+ // reset current time in milli
+ currentTimeInMilli = 0;
+
+ // update gui
+ musicPlayerView.enablePauseButtonDisablePlayButton();
+ musicPlayerView.updateSongTitleAndArtist(currentSong);
+ musicPlayerView.updatePlaybackSlider(currentSong);
+
+ // play the song
+ playCurrentSong();
+ }
+
+ public void playCurrentSong() {
+ if (currentSong == null) {
+ return;
+ }
+
+ try {
+ // read mp3 audio data
+ FileInputStream fileInputStream = new FileInputStream(currentSong.getFilePath());
+ BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
+
+ // create a new advanced player
+ advancedPlayer = new AdvancedPlayer(bufferedInputStream);
+ advancedPlayer.setPlayBackListener(this);
+
+ // start music
+ startMusicThread();
+
+ // start playback slider thread
+ startPlaybackSliderThread();
+
+ } catch (Exception e) {
+ System.out.println(e.getMessage());
+ }
+ }
+
+ // create a thread that will handle playing the music
+ private void startMusicThread() {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ if (isPaused) {
+ synchronized (playSignal) {
+ // update flag
+ isPaused = false;
+
+ // notify the other thread to continue (makes sure that isPaused is updated to false properly)
+ playSignal.notify();
+ }
+
+ // resume music from last frame
+ advancedPlayer.play(currentFrame, Integer.MAX_VALUE);
+ } else {
+ // play music from the beginning
+ advancedPlayer.play();
+ }
+ } catch (Exception e) {
+ System.out.println(e.getMessage());
+ }
+ }
+ }).start();
+ }
+
+ // create a thread that will handle updating the slider
+ private void startPlaybackSliderThread() {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ if (isPaused) {
+ try {
+ // wait till it gets notified by other thread to continue
+ // makes sure that isPaused boolean flag updates to false before continuing
+ synchronized (playSignal) {
+ playSignal.wait();
+ }
+ } catch (Exception e) {
+ System.out.println(e.getMessage());
+ }
+ }
+
+ while (!isPaused && !songFinished && !pressedNext && !pressedPrev) {
+ try {
+ // increment current time milli
+ currentTimeInMilli++;
+
+ // calculate into frame value
+ int calculatedFrame = (int) ((double) currentTimeInMilli * 2.08
+ * currentSong.getFrameRatePerMilliseconds());
+
+ // update gui
+ musicPlayerView.setPlaybackSliderValue(calculatedFrame);
+
+ // mimic 1 millisecond using thread.sleep
+ Thread.sleep(1);
+ } catch (Exception e) {
+ System.out.println(e.getMessage());
+ }
+ }
+ }
+ }).start();
+ }
+
+ @Override
+ public void playbackStarted(PlaybackEvent evt) {
+ // this method gets called in the beginning of the song
+ System.out.println("Playback Started");
+ songFinished = false;
+ pressedNext = false;
+ pressedPrev = false;
+ }
+
+ @Override
+ public void playbackFinished(PlaybackEvent evt) {
+ // this method gets called when the song finishes or if the player gets closed
+ System.out.println("Playback Finished");
+ if (isPaused) {
+ currentFrame += (int) ((double) evt.getFrame()
+ * currentSong.getFrameRatePerMilliseconds());
+ } else {
+ // if the user pressed next or prev we don't need to execute the rest of the code
+ if (pressedNext || pressedPrev) {
+ return;
+ }
+
+ // when the song ends
+ songFinished = true;
+
+ if (playlist == null) {
+ // update gui
+ musicPlayerView.enablePlayButtonDisablePauseButton();
+ } else {
+ // last song in the playlist
+ if (currentPlaylistIndex == playlist.size() - 1) {
+ // update gui
+ musicPlayerView.enablePlayButtonDisablePauseButton();
+ } else {
+ // go to the next song in the playlist
+ nextSong();
+ }
+ }
+ }
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (e.getActionCommand().equals("Load Song")) {
+ // an integer is returned to us to let us know what the user did
+ int result = musicPlayerView.getjFileChooser().showOpenDialog(null);
+ musicPlayerView.setSelectedFile(musicPlayerView.getjFileChooser().getSelectedFile());
+
+ // this means that we are also checking to see if the user pressed the "open" button
+ if (result == JFileChooser.APPROVE_OPTION
+ && musicPlayerView.getjFileChooser().getSelectedFile() != null) {
+ // create a song obj based on selected file
+ Song song = new Song(musicPlayerView.getjFileChooser().getSelectedFile().getPath());
+
+ // load song in music player
+ this.loadSong(song);
+
+ // update song title and artist
+ musicPlayerView.updateSongTitleAndArtist(song);
+
+ // update playback slider
+ musicPlayerView.updatePlaybackSlider(song);
+
+ // toggle on pause button and toggle off play button
+ musicPlayerView.enablePauseButtonDisablePlayButton();
+ }
+ } else if (e.getActionCommand().equals("Load Playlist")) {
+ JFileChooser jFileChooser = new JFileChooser();
+ jFileChooser.setFileFilter(new FileNameExtensionFilter("Playlist", "txt"));
+ jFileChooser.setCurrentDirectory(new File(ResourcesPath.CURRENT_DIRECTORY));
+
+ int result = jFileChooser.showOpenDialog(null);
+ File selectedFile = jFileChooser.getSelectedFile();
+
+ if (result == JFileChooser.APPROVE_OPTION && selectedFile != null) {
+ // stop the music
+ this.stopSong();
+
+ // load playlist
+ this.loadPlaylist(selectedFile);
+ }
+ } else if (e.getActionCommand().equals("Create Playlist")) {
+ // load music playlist dialog
+ new MusicPlaylistDialog(musicPlayerView).setVisible(true);
+ } else if (e.getSource() instanceof JButton sourceButton) {
+ // 80 x of prev
+ // 233 x of next
+ // 159 x of play/pause
+ if (musicPlayerView.getButtonLocation(sourceButton).x == 80) {
+ System.out.println("Hello from Prev");
+ this.prevSong();
+ } else if (musicPlayerView.getButtonLocation(sourceButton).x == 233) {
+ System.out.println("Hello from Next");
+ this.nextSong();
+ } else if (musicPlayerView.getButtonLocation(sourceButton).x == 159) {
+ musicPlayerView.getPlayButton().addActionListener(play -> {
+ System.out.println("Hello from Play");
+ // toggle off play button and toggle on pause button
+ musicPlayerView.enablePauseButtonDisablePlayButton();
+
+ // play or resume song
+ playCurrentSong();
+ });
+
+ musicPlayerView.getPauseButton().addActionListener(pause -> {
+ System.out.println("Hello from Pause");
+ // toggle on play button and toggle off pause button
+ musicPlayerView.enablePlayButtonDisablePauseButton();
+
+ // pause song
+ pauseSong();
+ });
+ }
+ }
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Song.java b/src/main/java/models/Song.java
similarity index 75%
rename from src/Song.java
rename to src/main/java/models/Song.java
index aa5b332..292be0f 100644
--- a/src/Song.java
+++ b/src/main/java/models/Song.java
@@ -1,86 +1,71 @@
-import com.mpatric.mp3agic.Mp3File;
-import org.jaudiotagger.audio.AudioFile;
-import org.jaudiotagger.audio.AudioFileIO;
-import org.jaudiotagger.tag.FieldKey;
-import org.jaudiotagger.tag.Tag;
-
-import java.io.File;
-
-// class used to describe a song
-public class Song {
- private String songTitle;
- private String songArtist;
- private String songLength;
- private String filePath;
- private Mp3File mp3File;
- private double frameRatePerMilliseconds;
-
- public Song(String filePath){
- this.filePath = filePath;
- try{
- mp3File = new Mp3File(filePath);
- frameRatePerMilliseconds = (double) mp3File.getFrameCount() / mp3File.getLengthInMilliseconds();
- songLength = convertToSongLengthFormat();
-
- // use the jaudiotagger library to create an audiofile obj to read mp3 file's information
- AudioFile audioFile = AudioFileIO.read(new File(filePath));
-
- // read through the meta data of the audio file
- Tag tag = audioFile.getTag();
- if(tag != null){
- songTitle = tag.getFirst(FieldKey.TITLE);
- songArtist = tag.getFirst(FieldKey.ARTIST);
- }else{
- // could not read through mp3 file's meta data
- songTitle = "N/A";
- songArtist = "N/A";
- }
- }catch(Exception e){
- e.printStackTrace();
- }
- }
-
- private String convertToSongLengthFormat(){
- long minutes = mp3File.getLengthInSeconds() / 60;
- long seconds = mp3File.getLengthInSeconds() % 60;
- String formattedTime = String.format("%02d:%02d", minutes, seconds);
-
- return formattedTime;
- }
-
- // getters
- public String getSongTitle() {
- return songTitle;
- }
-
- public String getSongArtist() {
- return songArtist;
- }
-
- public String getSongLength() {
- return songLength;
- }
-
- public String getFilePath() {
- return filePath;
- }
-
- public Mp3File getMp3File(){return mp3File;}
- public double getFrameRatePerMilliseconds(){return frameRatePerMilliseconds;}
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+package models;
+
+import com.mpatric.mp3agic.Mp3File;
+import lombok.Data;
+import org.jaudiotagger.audio.AudioFile;
+import org.jaudiotagger.audio.AudioFileIO;
+import org.jaudiotagger.tag.FieldKey;
+import org.jaudiotagger.tag.Tag;
+
+import java.io.File;
+
+// class used to describe a song
+@Data
+public class Song {
+ private String songTitle;
+ private String songArtist;
+ private String songLength;
+ private String filePath;
+ private Mp3File mp3File;
+ private double frameRatePerMilliseconds;
+
+ public Song(String filePath){
+ this.filePath = filePath;
+ try{
+ mp3File = new Mp3File(filePath);
+ frameRatePerMilliseconds = (double) mp3File.getFrameCount() / mp3File.getLengthInMilliseconds();
+ songLength = convertToSongLengthFormat();
+
+ // use the jaudiotagger library to create an audiofile obj to read mp3 file's information
+ AudioFile audioFile = AudioFileIO.read(new File(filePath));
+
+ // read through the meta data of the audio file
+ Tag tag = audioFile.getTag();
+ if(tag != null){
+ songTitle = tag.getFirst(FieldKey.TITLE);
+ songArtist = tag.getFirst(FieldKey.ARTIST);
+ }else{
+ // could not read through mp3 file's meta data
+ songTitle = "N/A";
+ songArtist = "N/A";
+ }
+ }catch(Exception e){
+ System.out.println(e.getMessage());
+ }
+ }
+
+ private String convertToSongLengthFormat(){
+ long minutes = mp3File.getLengthInSeconds() / 60;
+ long seconds = mp3File.getLengthInSeconds() % 60;
+ String formattedTime = String.format("%02d:%02d", minutes, seconds);
+
+ return formattedTime;
+ }
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/java/styles/UIColor.java b/src/main/java/styles/UIColor.java
new file mode 100644
index 0000000..78a9dec
--- /dev/null
+++ b/src/main/java/styles/UIColor.java
@@ -0,0 +1,8 @@
+package styles;
+
+import java.awt.Color;
+
+public class UIColor {
+ public static final Color FRAME_COLOR = Color.BLACK;
+ public static final Color TEXT_COLOR = Color.WHITE;
+}
diff --git a/src/main/java/styles/UISize.java b/src/main/java/styles/UISize.java
new file mode 100644
index 0000000..a023bae
--- /dev/null
+++ b/src/main/java/styles/UISize.java
@@ -0,0 +1,8 @@
+package styles;
+
+public class UISize {
+ public static final int MUSIC_PLAYER_WIDTH = 400;
+ public static final int MUSIC_PLAYER_HEIGHT = 600;
+ public static final int PLAYLIST_DIALOG_WIDTH = 400;
+ public static final int PLAYLIST_DIALOG_HEIGHT = 400;
+}
diff --git a/src/MusicPlayerGUI.java b/src/main/java/views/MusicPlayerView.java
similarity index 56%
rename from src/MusicPlayerGUI.java
rename to src/main/java/views/MusicPlayerView.java
index a681d45..f0b311c 100644
--- a/src/MusicPlayerGUI.java
+++ b/src/main/java/views/MusicPlayerView.java
@@ -1,362 +1,346 @@
-import javax.imageio.ImageIO;
-import javax.swing.*;
-import javax.swing.filechooser.FileNameExtensionFilter;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.awt.image.BufferedImage;
-import java.io.File;
-import java.util.Hashtable;
-
-public class MusicPlayerGUI extends JFrame {
- // color configurations
- public static final Color FRAME_COLOR = Color.BLACK;
- public static final Color TEXT_COLOR = Color.WHITE;
-
- private MusicPlayer musicPlayer;
-
- // allow us to use file explorer in our app
- private JFileChooser jFileChooser;
-
- private JLabel songTitle, songArtist;
- private JPanel playbackBtns;
- private JSlider playbackSlider;
-
- public MusicPlayerGUI(){
- // calls JFrame constructor to configure out gui and set the title heaader to "Music Player"
- super("Music Player");
-
- // set the width and height
- setSize(400, 600);
-
- // end process when app is closed
- setDefaultCloseOperation(EXIT_ON_CLOSE);
-
- // launch the app at the center of the screen
- setLocationRelativeTo(null);
-
- // prevent the app from being resized
- setResizable(false);
-
- // set layout to null which allows us to control the (x, y) coordinates of our components
- // and also set the height and width
- setLayout(null);
-
- // change the frame color
- getContentPane().setBackground(FRAME_COLOR);
-
- musicPlayer = new MusicPlayer(this);
- jFileChooser = new JFileChooser();
-
- // set a default path for file explorer
- jFileChooser.setCurrentDirectory(new File("src/assets"));
-
- // filter file chooser to only see .mp3 files
- jFileChooser.setFileFilter(new FileNameExtensionFilter("MP3", "mp3"));
-
- addGuiComponents();
- }
-
- private void addGuiComponents(){
- // add toolbar
- addToolbar();
-
- // load record image
- JLabel songImage = new JLabel(loadImage("src/assets/record.png"));
- songImage.setBounds(0, 50, getWidth() - 20, 225);
- add(songImage);
-
- // song title
- songTitle = new JLabel("Song Title");
- songTitle.setBounds(0, 285, getWidth() - 10, 30);
- songTitle.setFont(new Font("Dialog", Font.BOLD, 24));
- songTitle.setForeground(TEXT_COLOR);
- songTitle.setHorizontalAlignment(SwingConstants.CENTER);
- add(songTitle);
-
- // song artist
- songArtist = new JLabel("Artist");
- songArtist.setBounds(0, 315, getWidth() - 10, 30);
- songArtist.setFont(new Font("Dialog", Font.PLAIN, 24));
- songArtist.setForeground(TEXT_COLOR);
- songArtist.setHorizontalAlignment(SwingConstants.CENTER);
- add(songArtist);
-
- // playback slider
- playbackSlider = new JSlider(JSlider.HORIZONTAL, 0, 100, 0);
- playbackSlider.setBounds(getWidth()/2 - 300/2, 365, 300, 40);
- playbackSlider.setBackground(null);
- playbackSlider.addMouseListener(new MouseAdapter() {
- @Override
- public void mousePressed(MouseEvent e) {
- // when the user is holding the tick we want to the pause the song
- musicPlayer.pauseSong();
- }
-
- @Override
- public void mouseReleased(MouseEvent e) {
- // when the user drops the tick
- JSlider source = (JSlider) e.getSource();
-
- // get the frame value from where the user wants to playback to
- int frame = source.getValue();
-
- // update the current frame in the music player to this frame
- musicPlayer.setCurrentFrame(frame);
-
- // update current time in milli as well
- musicPlayer.setCurrentTimeInMilli((int) (frame / (2.08 * musicPlayer.getCurrentSong().getFrameRatePerMilliseconds())));
-
- // resume the song
- musicPlayer.playCurrentSong();
-
- // toggle on pause button and toggle off play button
- enablePauseButtonDisablePlayButton();
- }
- });
- add(playbackSlider);
-
- // playback buttons (i.e. previous, play, next)
- addPlaybackBtns();
- }
-
- private void addToolbar(){
- JToolBar toolBar = new JToolBar();
- toolBar.setBounds(0, 0, getWidth(), 20);
-
- // prevent toolbar from being moved
- toolBar.setFloatable(false);
-
- // add drop down menu
- JMenuBar menuBar = new JMenuBar();
- toolBar.add(menuBar);
-
- // now we will add a song menu where we will place the loading song option
- JMenu songMenu = new JMenu("Song");
- menuBar.add(songMenu);
-
- // add the "load song" item in the songMenu
- JMenuItem loadSong = new JMenuItem("Load Song");
- loadSong.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- // an integer is returned to us to let us know what the user did
- int result = jFileChooser.showOpenDialog(MusicPlayerGUI.this);
- File selectedFile = jFileChooser.getSelectedFile();
-
- // this means that we are also checking to see if the user pressed the "open" button
- if(result == JFileChooser.APPROVE_OPTION && selectedFile != null){
- // create a song obj based on selected file
- Song song = new Song(selectedFile.getPath());
-
- // load song in music player
- musicPlayer.loadSong(song);
-
- // update song title and artist
- updateSongTitleAndArtist(song);
-
- // update playback slider
- updatePlaybackSlider(song);
-
- // toggle on pause button and toggle off play button
- enablePauseButtonDisablePlayButton();
- }
- }
- });
- songMenu.add(loadSong);
-
- // now we will add the playlist menu
- JMenu playlistMenu = new JMenu("Playlist");
- menuBar.add(playlistMenu);
-
- // then add the items to the playlist menu
- JMenuItem createPlaylist = new JMenuItem("Create Playlist");
- createPlaylist.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- // load music playlist dialog
- new MusicPlaylistDialog(MusicPlayerGUI.this).setVisible(true);
- }
- });
- playlistMenu.add(createPlaylist);
-
- JMenuItem loadPlaylist = new JMenuItem("Load Playlist");
- loadPlaylist.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- JFileChooser jFileChooser = new JFileChooser();
- jFileChooser.setFileFilter(new FileNameExtensionFilter("Playlist", "txt"));
- jFileChooser.setCurrentDirectory(new File("src/assets"));
-
- int result = jFileChooser.showOpenDialog(MusicPlayerGUI.this);
- File selectedFile = jFileChooser.getSelectedFile();
-
- if(result == JFileChooser.APPROVE_OPTION && selectedFile != null){
- // stop the music
- musicPlayer.stopSong();
-
- // load playlist
- musicPlayer.loadPlaylist(selectedFile);
- }
- }
- });
- playlistMenu.add(loadPlaylist);
-
- add(toolBar);
- }
-
- private void addPlaybackBtns(){
- playbackBtns = new JPanel();
- playbackBtns.setBounds(0, 435, getWidth() - 10, 80);
- playbackBtns.setBackground(null);
-
- // previous button
- JButton prevButton = new JButton(loadImage("src/assets/previous.png"));
- prevButton.setBorderPainted(false);
- prevButton.setBackground(null);
- prevButton.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- // go to the previous song
- musicPlayer.prevSong();
- }
- });
- playbackBtns.add(prevButton);
-
- // play button
- JButton playButton = new JButton(loadImage("src/assets/play.png"));
- playButton.setBorderPainted(false);
- playButton.setBackground(null);
- playButton.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- // toggle off play button and toggle on pause button
- enablePauseButtonDisablePlayButton();
-
- // play or resume song
- musicPlayer.playCurrentSong();
- }
- });
- playbackBtns.add(playButton);
-
- // pause button
- JButton pauseButton = new JButton(loadImage("src/assets/pause.png"));
- pauseButton.setBorderPainted(false);
- pauseButton.setBackground(null);
- pauseButton.setVisible(false);
- pauseButton.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- // toggle off pause button and toggle on play button
- enablePlayButtonDisablePauseButton();
-
- // pause the song
- musicPlayer.pauseSong();
- }
- });
- playbackBtns.add(pauseButton);
-
- // next button
- JButton nextButton = new JButton(loadImage("src/assets/next.png"));
- nextButton.setBorderPainted(false);
- nextButton.setBackground(null);
- nextButton.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- // go to the next song
- musicPlayer.nextSong();
- }
- });
- playbackBtns.add(nextButton);
-
- add(playbackBtns);
- }
-
- // this will be used to update our slider from the music player class
- public void setPlaybackSliderValue(int frame){
- playbackSlider.setValue(frame);
- }
-
- public void updateSongTitleAndArtist(Song song){
- songTitle.setText(song.getSongTitle());
- songArtist.setText(song.getSongArtist());
- }
-
- public void updatePlaybackSlider(Song song){
- // update max count for slider
- playbackSlider.setMaximum(song.getMp3File().getFrameCount());
-
- // create the song length label
- Hashtable labelTable = new Hashtable<>();
-
- // beginning will be 00:00
- JLabel labelBeginning = new JLabel("00:00");
- labelBeginning.setFont(new Font("Dialog", Font.BOLD, 18));
- labelBeginning.setForeground(TEXT_COLOR);
-
- // end will vary depending on the song
- JLabel labelEnd = new JLabel(song.getSongLength());
- labelEnd.setFont(new Font("Dialog", Font.BOLD, 18));
- labelEnd.setForeground(TEXT_COLOR);
-
- labelTable.put(0, labelBeginning);
- labelTable.put(song.getMp3File().getFrameCount(), labelEnd);
-
- playbackSlider.setLabelTable(labelTable);
- playbackSlider.setPaintLabels(true);
- }
-
- public void enablePauseButtonDisablePlayButton(){
- // retrieve reference to play button from playbackBtns panel
- JButton playButton = (JButton) playbackBtns.getComponent(1);
- JButton pauseButton = (JButton) playbackBtns.getComponent(2);
-
- // turn off play button
- playButton.setVisible(false);
- playButton.setEnabled(false);
-
- // turn on pause button
- pauseButton.setVisible(true);
- pauseButton.setEnabled(true);
- }
-
- public void enablePlayButtonDisablePauseButton(){
- // retrieve reference to play button from playbackBtns panel
- JButton playButton = (JButton) playbackBtns.getComponent(1);
- JButton pauseButton = (JButton) playbackBtns.getComponent(2);
-
- // turn on play button
- playButton.setVisible(true);
- playButton.setEnabled(true);
-
- // turn off pause button
- pauseButton.setVisible(false);
- pauseButton.setEnabled(false);
- }
-
- private ImageIcon loadImage(String imagePath){
- try{
- // read the image file from the given path
- BufferedImage image = ImageIO.read(new File(imagePath));
-
- // returns an image icon so that our component can render the image
- return new ImageIcon(image);
- }catch(Exception e){
- e.printStackTrace();
- }
-
- // could not find resource
- return null;
- }
-}
-
-
-
-
-
-
-
-
-
+package views;
+
+import constants.ResourcesPath;
+import controllers.MusicPlayerController;
+import java.awt.event.ActionListener;
+import javax.imageio.ImageIO;
+import javax.swing.*;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import java.awt.*;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.util.Hashtable;
+import models.Song;
+import styles.UIColor;
+import styles.UISize;
+
+public class MusicPlayerView extends JFrame {
+
+ private MusicPlayerController musicPlayerController;
+
+ // allow us to use file explorer in our app
+ private JFileChooser jFileChooser;
+
+ private JLabel songTitle, songArtist;
+ private JPanel playbackBtns;
+ private JSlider playbackSlider;
+ private JLabel songImage;
+ private JToolBar toolBar;
+ private JMenuBar menuBar;
+ private JMenu songMenu;
+ private JMenuItem createPlaylist;
+ private JMenuItem loadPlaylist;
+ private JMenuItem loadSong;
+ private JMenu playlistMenu;
+ private File selectedFile;
+ // 5 icon
+ private ImageIcon prevButtonIcon, playButtonIcon, pauseButtonIcon, nextButtonIcon;
+ private JButton prevButton, playButton, pauseButton, nextButton;
+
+ public MusicPlayerView(){
+ // calls JFrame constructor to configure out gui and set the title heaader to "Music Player"
+ super("Music Player");
+
+ // set the width and height
+ setSize(UISize.MUSIC_PLAYER_WIDTH, UISize.MUSIC_PLAYER_HEIGHT);
+
+ // end process when app is closed
+ setDefaultCloseOperation(EXIT_ON_CLOSE);
+
+ // launch the app at the center of the screen
+ setLocationRelativeTo(null);
+
+ // prevent the app from being resized
+ setResizable(false);
+
+ // set layout to null which allows us to control the (x, y) coordinates of our components
+ // and also set the height and width
+ setLayout(null);
+
+ // change the frame color
+ getContentPane().setBackground(UIColor.FRAME_COLOR);
+
+ musicPlayerController = new MusicPlayerController(this);
+ jFileChooser = new JFileChooser();
+
+ // set a default path for file explorer
+ jFileChooser.setCurrentDirectory(new File(ResourcesPath.CURRENT_DIRECTORY));
+
+ // filter file chooser to only see .mp3 files
+ jFileChooser.setFileFilter(new FileNameExtensionFilter("MP3", "mp3"));
+
+ initIcon();
+ addGuiComponents();
+ }
+
+ private void initIcon(){
+ prevButtonIcon = loadImage(ResourcesPath.PREVIOUS_BUTTON);
+ playButtonIcon = loadImage(ResourcesPath.PLAY_BUTTON);
+ pauseButtonIcon = loadImage(ResourcesPath.PAUSE_BUTTON);
+ nextButtonIcon = loadImage(ResourcesPath.NEXT_BUTTON);
+ }
+
+ private void addGuiComponents(){
+ // add toolbar
+ addToolbar();
+
+ // load record image
+ addRecordImage();
+
+ // song title
+ addSongTitle();
+
+ // song artist
+ addSongArtist();
+
+ // playback slider
+ addPlaybackSlider();
+
+ // playback buttons (i.e. previous, play, next)
+ addPlaybackBtns();
+ }
+
+ private void addToolbar(){
+ toolBar = new JToolBar();
+ toolBar.setBounds(0, 0, getWidth(), 20);
+
+ // prevent toolbar from being moved
+ toolBar.setFloatable(false);
+
+ // add drop down menu
+ menuBar = new JMenuBar();
+ toolBar.add(menuBar);
+
+ // now we will add a song menu where we will place the loading song option
+ songMenu = new JMenu("Song");
+ menuBar.add(songMenu);
+
+ // add the "load song" item in the songMenu
+ loadSong = new JMenuItem("Load Song");
+ loadSong.addActionListener(musicPlayerController);
+ songMenu.add(loadSong);
+
+ // now we will add the playlist menu
+ playlistMenu = new JMenu("Playlist");
+ menuBar.add(playlistMenu);
+
+ // then add the items to the playlist menu
+ createPlaylist = new JMenuItem("Create Playlist");
+ createPlaylist.addActionListener(musicPlayerController);
+ playlistMenu.add(createPlaylist);
+
+ loadPlaylist = new JMenuItem("Load Playlist");
+ loadPlaylist.addActionListener(musicPlayerController);
+ playlistMenu.add(loadPlaylist);
+
+ add(toolBar);
+ }
+
+ private void addRecordImage(){
+ songImage = new JLabel(loadImage(ResourcesPath.SONG_IMAGE));
+ songImage.setBounds(0, 50, getWidth() - 20, 225);
+ add(songImage);
+ }
+
+ private void addSongTitle(){
+ songTitle = new JLabel("Song Title");
+ songTitle.setBounds(0, 285, getWidth() - 10, 30);
+ songTitle.setFont(new Font("Dialog", Font.BOLD, 24));
+ songTitle.setForeground(UIColor.TEXT_COLOR);
+ songTitle.setHorizontalAlignment(SwingConstants.CENTER);
+ add(songTitle);
+ }
+
+ private void addSongArtist(){
+ songArtist = new JLabel("Artist");
+ songArtist.setBounds(0, 315, getWidth() - 10, 30);
+ songArtist.setFont(new Font("Dialog", Font.PLAIN, 24));
+ songArtist.setForeground(UIColor.TEXT_COLOR);
+ songArtist.setHorizontalAlignment(SwingConstants.CENTER);
+ add(songArtist);
+ }
+
+ private void addPlaybackSlider(){
+ playbackSlider = new JSlider(JSlider.HORIZONTAL, 0, 100, 0);
+ playbackSlider.setBounds(getWidth()/2 - 300/2, 365, 300, 40);
+ playbackSlider.setBackground(null);
+ playbackSlider.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mousePressed(MouseEvent e) {
+ // when the user is holding the tick we want to the pause the song
+ musicPlayerController.pauseSong();
+ }
+
+ @Override
+ public void mouseReleased(MouseEvent e) {
+ // when the user drops the tick
+ JSlider source = (JSlider) e.getSource();
+
+ // get the frame value from where the user wants to playback to
+ int frame = source.getValue();
+
+ // update the current frame in the music player to this frame
+ musicPlayerController.setCurrentFrame(frame);
+
+ // update current time in milli as well
+ musicPlayerController.setCurrentTimeInMilli((int) (frame / (2.08 * musicPlayerController.getCurrentSong().getFrameRatePerMilliseconds())));
+
+ // resume the song
+ musicPlayerController.playCurrentSong();
+
+ // toggle on pause button and toggle off play button
+ enablePauseButtonDisablePlayButton();
+ }
+ });
+ add(playbackSlider);
+ }
+
+ private void addPlaybackBtns(){
+ playbackBtns = new JPanel();
+ playbackBtns.setBounds(0, 435, getWidth() - 10, 80);
+ playbackBtns.setBackground(null);
+
+ // previous button
+ prevButton = new JButton(prevButtonIcon);
+ prevButton.setBorderPainted(false);
+ prevButton.setBackground(null);
+ prevButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
+ prevButton.addActionListener(musicPlayerController);
+ playbackBtns.add(prevButton);
+
+ // play button
+ playButton = new JButton(playButtonIcon);
+ playButton.setBorderPainted(false);
+ playButton.setBackground(null);
+ playButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
+ playButton.addActionListener(musicPlayerController);
+ playbackBtns.add(playButton);
+
+ // pause button
+ pauseButton = new JButton(pauseButtonIcon);
+ pauseButton.setBorderPainted(false);
+ pauseButton.setBackground(null);
+ pauseButton.setVisible(false);
+ pauseButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
+ pauseButton.addActionListener(musicPlayerController);
+ playbackBtns.add(pauseButton);
+
+ // next button
+ nextButton = new JButton(nextButtonIcon);
+ nextButton.setBorderPainted(false);
+ nextButton.setBackground(null);
+ nextButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
+ nextButton.addActionListener(musicPlayerController);
+ playbackBtns.add(nextButton);
+
+ add(playbackBtns);
+ }
+
+ // Utility methods
+ public JFileChooser getjFileChooser() {
+ return jFileChooser;
+ }
+ public JButton getPlayButton() {
+ return playButton;
+ }
+
+ public JButton getPauseButton() {
+ return pauseButton;
+ }
+
+ public void setSelectedFile(File selectedFile) {
+ this.selectedFile = selectedFile;
+ }
+
+ public Point getButtonLocation(JButton button){
+ return button.getLocation();
+ }
+
+ // this will be used to update our slider from the music player class
+ public void setPlaybackSliderValue(int frame){
+ playbackSlider.setValue(frame);
+ }
+
+ public void updateSongTitleAndArtist(Song song){
+ songTitle.setText(song.getSongTitle());
+ songArtist.setText(song.getSongArtist());
+ }
+
+ public void updatePlaybackSlider(Song song){
+ // update max count for slider
+ playbackSlider.setMaximum(song.getMp3File().getFrameCount());
+
+ // create the song length label
+ Hashtable labelTable = new Hashtable<>();
+
+ // beginning will be 00:00
+ JLabel labelBeginning = new JLabel("00:00");
+ labelBeginning.setFont(new Font("Dialog", Font.BOLD, 18));
+ labelBeginning.setForeground(UIColor.TEXT_COLOR);
+
+ // end will vary depending on the song
+ JLabel labelEnd = new JLabel(song.getSongLength());
+ labelEnd.setFont(new Font("Dialog", Font.BOLD, 18));
+ labelEnd.setForeground(UIColor.TEXT_COLOR);
+
+ labelTable.put(0, labelBeginning);
+ labelTable.put(song.getMp3File().getFrameCount(), labelEnd);
+
+ playbackSlider.setLabelTable(labelTable);
+ playbackSlider.setPaintLabels(true);
+ }
+
+ public void enablePauseButtonDisablePlayButton(){
+ // retrieve reference to play button from playbackBtns panel
+ JButton playButton = (JButton) playbackBtns.getComponent(1);
+ JButton pauseButton = (JButton) playbackBtns.getComponent(2);
+
+ // turn off play button
+ playButton.setVisible(false);
+ playButton.setEnabled(false);
+
+ // turn on pause button
+ pauseButton.setVisible(true);
+ pauseButton.setEnabled(true);
+ }
+
+ public void enablePlayButtonDisablePauseButton(){
+ // retrieve reference to play button from playbackBtns panel
+ JButton playButton = (JButton) playbackBtns.getComponent(1);
+ JButton pauseButton = (JButton) playbackBtns.getComponent(2);
+
+ // turn on play button
+ playButton.setVisible(true);
+ playButton.setEnabled(true);
+
+ // turn off pause button
+ pauseButton.setVisible(false);
+ pauseButton.setEnabled(false);
+ }
+
+ public ImageIcon loadImage(String imagePath){
+ try{
+ // read the image file from the given path
+ BufferedImage image = ImageIO.read(getClass().getResource(imagePath));
+
+ // returns an image icon so that our component can render the image
+ return new ImageIcon(image);
+ }catch(Exception e){
+ System.out.println(e.getMessage() + " " + imagePath);
+ }
+
+ // could not find resource
+ return null;
+ }
+}
+
+
+
+
+
+
+
+
+
diff --git a/src/main/java/views/MusicPlaylistDialog.java b/src/main/java/views/MusicPlaylistDialog.java
new file mode 100644
index 0000000..e6a457e
--- /dev/null
+++ b/src/main/java/views/MusicPlaylistDialog.java
@@ -0,0 +1,127 @@
+package views;
+
+import constants.ResourcesPath;
+import javax.swing.*;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import java.awt.*;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.util.ArrayList;
+import styles.UIColor;
+import styles.UISize;
+
+public class MusicPlaylistDialog extends JDialog {
+ private MusicPlayerView musicPlayerView;
+
+ // store all of the paths to be written to a txt file (when we load a playlist)
+ private ArrayList songPaths;
+
+ public MusicPlaylistDialog(MusicPlayerView musicPlayerView){
+ this.musicPlayerView = musicPlayerView;
+ songPaths = new ArrayList<>();
+
+ // configure dialog
+ setTitle("Create Playlist");
+ setSize(UISize.PLAYLIST_DIALOG_WIDTH, UISize.PLAYLIST_DIALOG_HEIGHT);
+ setResizable(false);
+ getContentPane().setBackground(UIColor.FRAME_COLOR);
+ setLayout(null);
+ setModal(true); // this property makes it so that the dialog has to be closed to give focus
+ setLocationRelativeTo(musicPlayerView);
+
+ addDialogComponents();
+ }
+
+ private void addDialogComponents(){
+ // container to hold each song path
+ JPanel songContainer = new JPanel();
+ songContainer.setLayout(new BoxLayout(songContainer, BoxLayout.Y_AXIS));
+ songContainer.setBounds((int)(getWidth() * 0.025), 10, (int)(getWidth() * 0.90), (int) (getHeight() * 0.75));
+ add(songContainer);
+
+ // add song button
+ JButton addSongButton = new JButton("Add");
+ addSongButton.setBounds(60, (int) (getHeight() * 0.80), 100, 25);
+ addSongButton.setFont(new Font("Dialog", Font.BOLD, 14));
+ addSongButton.addActionListener(e -> {
+ // open file explorer
+ JFileChooser jFileChooser = new JFileChooser();
+ jFileChooser.setFileFilter(new FileNameExtensionFilter("MP3", "mp3"));
+ jFileChooser.setCurrentDirectory(new File(ResourcesPath.CURRENT_DIRECTORY));
+ int result = jFileChooser.showOpenDialog(MusicPlaylistDialog.this);
+
+ File selectedFile = jFileChooser.getSelectedFile();
+ if(result == JFileChooser.APPROVE_OPTION && selectedFile != null){
+ JLabel filePathLabel = new JLabel(selectedFile.getPath());
+ filePathLabel.setFont(new Font("Dialog", Font.BOLD, 12));
+ filePathLabel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
+
+ // add to the list
+ songPaths.add(filePathLabel.getText());
+
+ // add to container
+ songContainer.add(filePathLabel);
+
+ // refreshes dialog to show newly added JLabel
+ songContainer.revalidate();
+ }
+ });
+ add(addSongButton);
+
+ // save playlist button
+ JButton savePlaylistButton = new JButton("Save");
+ savePlaylistButton.setBounds(215, (int) (getHeight() * 0.80), 100, 25);
+ savePlaylistButton.setFont(new Font("Dialog", Font.BOLD, 14));
+ savePlaylistButton.addActionListener(e -> {
+ try{
+ JFileChooser jFileChooser = new JFileChooser();
+ jFileChooser.setCurrentDirectory(new File(ResourcesPath.CURRENT_DIRECTORY));
+ int result = jFileChooser.showSaveDialog(MusicPlaylistDialog.this);
+
+ if(result == JFileChooser.APPROVE_OPTION){
+ // we use getSelectedFile() to get reference to the file that we are about to save
+ File selectedFile = jFileChooser.getSelectedFile();
+
+ // convert to .txt file if not done so already
+ // this will check to see if the file does not have the ".txt" file extension
+ if(!selectedFile.getName().substring(selectedFile.getName().length() - 4).equalsIgnoreCase(".txt")){
+ selectedFile = new File(selectedFile.getAbsoluteFile() + ".txt");
+ }
+
+ // create the new file at the destinated directory
+ selectedFile.createNewFile();
+
+ // now we will write all of the song paths into this file
+ FileWriter fileWriter = new FileWriter(selectedFile);
+ BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
+
+ // iterate through our song paths list and write each string into the file
+ // each song will be written in their own row
+ for(String songPath : songPaths){
+ bufferedWriter.write(songPath + "\n");
+ }
+ bufferedWriter.close();
+
+ // display success dialog
+ JOptionPane.showMessageDialog(MusicPlaylistDialog.this, "Successfully Created Playlist!");
+
+ // close this dialog
+ MusicPlaylistDialog.this.dispose();
+ }
+ }catch(Exception exception){
+ exception.printStackTrace();
+ }
+ });
+ add(savePlaylistButton);
+ }
+}
+
+
+
+
+
+
+
+
+
diff --git a/out/production/MP3MusicPlayer/assets/Auld Lang Syne (Instrumental) - Jingle Punks.mp3 b/src/main/resources/Auld Lang Syne (Instrumental) - Jingle Punks.mp3
similarity index 100%
rename from out/production/MP3MusicPlayer/assets/Auld Lang Syne (Instrumental) - Jingle Punks.mp3
rename to src/main/resources/Auld Lang Syne (Instrumental) - Jingle Punks.mp3
diff --git a/out/production/MP3MusicPlayer/assets/Tropic Fuse - French Fuse.mp3 b/src/main/resources/Tropic Fuse - French Fuse.mp3
similarity index 100%
rename from out/production/MP3MusicPlayer/assets/Tropic Fuse - French Fuse.mp3
rename to src/main/resources/Tropic Fuse - French Fuse.mp3
diff --git a/out/production/MP3MusicPlayer/assets/Wind Riders - Asher Fulero.mp3 b/src/main/resources/Wind Riders - Asher Fulero.mp3
similarity index 100%
rename from out/production/MP3MusicPlayer/assets/Wind Riders - Asher Fulero.mp3
rename to src/main/resources/Wind Riders - Asher Fulero.mp3
diff --git a/out/production/MP3MusicPlayer/assets/next.png b/src/main/resources/next.png
similarity index 100%
rename from out/production/MP3MusicPlayer/assets/next.png
rename to src/main/resources/next.png
diff --git a/out/production/MP3MusicPlayer/assets/pause.png b/src/main/resources/pause.png
similarity index 100%
rename from out/production/MP3MusicPlayer/assets/pause.png
rename to src/main/resources/pause.png
diff --git a/src/main/resources/pedro.mp3 b/src/main/resources/pedro.mp3
new file mode 100644
index 0000000..5ea4c36
Binary files /dev/null and b/src/main/resources/pedro.mp3 differ
diff --git a/out/production/MP3MusicPlayer/assets/play.png b/src/main/resources/play.png
similarity index 100%
rename from out/production/MP3MusicPlayer/assets/play.png
rename to src/main/resources/play.png
diff --git a/src/main/resources/playlist.txt b/src/main/resources/playlist.txt
new file mode 100644
index 0000000..a3d38df
--- /dev/null
+++ b/src/main/resources/playlist.txt
@@ -0,0 +1,3 @@
+D:\PERSONAL\Java\Java-Issues\Others\Useful-Project\Java-Swing-MusicPlayer\Java-Swing-MusicPlayer\src\main\resources\Auld Lang Syne (Instrumental) - Jingle Punks.mp3
+D:\PERSONAL\Java\Java-Issues\Others\Useful-Project\Java-Swing-MusicPlayer\Java-Swing-MusicPlayer\src\main\resources\Tropic Fuse - French Fuse.mp3
+D:\PERSONAL\Java\Java-Issues\Others\Useful-Project\Java-Swing-MusicPlayer\Java-Swing-MusicPlayer\src\main\resources\Wind Riders - Asher Fulero.mp3
\ No newline at end of file
diff --git a/src/main/resources/playlist2.txt b/src/main/resources/playlist2.txt
new file mode 100644
index 0000000..a3d38df
--- /dev/null
+++ b/src/main/resources/playlist2.txt
@@ -0,0 +1,3 @@
+D:\PERSONAL\Java\Java-Issues\Others\Useful-Project\Java-Swing-MusicPlayer\Java-Swing-MusicPlayer\src\main\resources\Auld Lang Syne (Instrumental) - Jingle Punks.mp3
+D:\PERSONAL\Java\Java-Issues\Others\Useful-Project\Java-Swing-MusicPlayer\Java-Swing-MusicPlayer\src\main\resources\Tropic Fuse - French Fuse.mp3
+D:\PERSONAL\Java\Java-Issues\Others\Useful-Project\Java-Swing-MusicPlayer\Java-Swing-MusicPlayer\src\main\resources\Wind Riders - Asher Fulero.mp3
\ No newline at end of file
diff --git a/src/main/resources/playlist3.txt b/src/main/resources/playlist3.txt
new file mode 100644
index 0000000..a3d38df
--- /dev/null
+++ b/src/main/resources/playlist3.txt
@@ -0,0 +1,3 @@
+D:\PERSONAL\Java\Java-Issues\Others\Useful-Project\Java-Swing-MusicPlayer\Java-Swing-MusicPlayer\src\main\resources\Auld Lang Syne (Instrumental) - Jingle Punks.mp3
+D:\PERSONAL\Java\Java-Issues\Others\Useful-Project\Java-Swing-MusicPlayer\Java-Swing-MusicPlayer\src\main\resources\Tropic Fuse - French Fuse.mp3
+D:\PERSONAL\Java\Java-Issues\Others\Useful-Project\Java-Swing-MusicPlayer\Java-Swing-MusicPlayer\src\main\resources\Wind Riders - Asher Fulero.mp3
\ No newline at end of file
diff --git a/out/production/MP3MusicPlayer/assets/previous.png b/src/main/resources/previous.png
similarity index 100%
rename from out/production/MP3MusicPlayer/assets/previous.png
rename to src/main/resources/previous.png
diff --git a/out/production/MP3MusicPlayer/assets/record.png b/src/main/resources/record.png
similarity index 100%
rename from out/production/MP3MusicPlayer/assets/record.png
rename to src/main/resources/record.png