Skip to content

Commit

Permalink
Merge pull request #35 from CSC207-2022F-UofT/playlist-queue
Browse files Browse the repository at this point in the history
  • Loading branch information
NicholasMacasaet authored Nov 12, 2022
2 parents 5cb1402 + 17d6937 commit b67bac5
Show file tree
Hide file tree
Showing 8 changed files with 197 additions and 7 deletions.
14 changes: 14 additions & 0 deletions src/main/java/InputBoundary/playPlaylistInputBoundary.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
package InputBoundary;

/**
* Use case layer input boundary that allows communication between outer layers and the play playlist use case.
*/
public interface playPlaylistInputBoundary {
/**
* Plays the playlist given in the constructor.
*/
public void play();

/**
* Dequeues the playlist, such that after the currently playing song ends the playlist
* will not continue. Must be called whenever audio source is switched (eg. user plays new song,
* different playlist, or space).
*/
public void stopQueue();
}
3 changes: 3 additions & 0 deletions src/main/java/InputBoundary/playSongInputBoundary.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
package InputBoundary;

import InputData.songInputData;

public interface playSongInputBoundary {
public void play();
}
1 change: 0 additions & 1 deletion src/main/java/InputData/songInputData.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,4 @@ public songInputData(Song song){
public Song getSong(){
return this.song;
}

}
70 changes: 69 additions & 1 deletion src/main/java/UseCase/playPlaylist.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,72 @@
package UseCase;

public class playPlaylist {
import Entities.MusicPlayer;
import Entities.Song;
import InputBoundary.playPlaylistInputBoundary;
import InputBoundary.playSongInputBoundary;
import InputData.playlistInputData;
import InputData.songInputData;
import java.util.ArrayList;

/**
* Use case layer class to play a playlist of songs. Handles the queuing of songs using synchronized
* methods in tandem with the MusicPlayer, but delegates playing individual songs to the play song
* use case. Thus, this use case has no output boundary, as the currently playing song is displayed
* by the play song use case.
*/
public class playPlaylist implements playPlaylistInputBoundary {
private boolean queue;
private final ArrayList<Song> playlist;
private final Object sync;
private int nextSong;

public playPlaylist(playlistInputData data){
this.playlist = data.getSongs();
queue = true;
nextSong = 0;
sync = MusicPlayer.getInstance().getSync();
}

/**
* Plays the playlist given in the constructor.
*/
@Override
public void play() {
if (nextSong < playlist.size()){
playSongInputBoundary p = new playSong(new songInputData(playlist.get(nextSong)));
nextSong++;
final Thread t = new Thread(this::playNext);
t.start();
p.play();
}
}

/**
* Dequeues the playlist, such that after the currently playing song ends the playlist
* will not continue. Must be called whenever audio source is switched (eg. user plays new song,
* different playlist, or space).
*/
@Override
public void stopQueue() {
queue = false;
}

/**
* Private helper method that deals with playing the next song in the queue using synchronized blocks.
*/
private void playNext(){
synchronized (sync){
try {
sync.wait();
} catch (InterruptedException e){
System.out.println("Thread interrupted.");
}
if (queue){
play();
}
else {
MusicPlayer.getInstance().pause();
}
}
}
}
23 changes: 18 additions & 5 deletions src/main/java/UseCase/playSong.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
package UseCase;

import java.io.File;
import Entities.MusicPlayer;
import Entities.Song;
import InputBoundary.playSongInputBoundary;
import InputData.songInputData;

public class playSong {
public class playSong implements playSongInputBoundary {
private final MusicPlayer mp = MusicPlayer.getInstance();
private final Song song;

static void playAudio(File songFilePath){
// TODO: stop playing whatever's playing
// TODO: play song
// TODO: call presenter
public playSong(songInputData s){
this.song = s.getSong();
}

public static void playAudio(File song){
// scaffolding for play space
}

@Override
public void play() {
mp.play(song);
}
}

Expand Down
93 changes: 93 additions & 0 deletions src/test/java/UseCase/PPlaybackTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// TRUE ASSERTIONS ARE COMMENTED OUT FOR THE AUTOGRADER
// UNCOMMENT THEM TO TEST LOCALLY

package UseCase;

import Entities.MusicPlayer;
import Entities.Song;
import InputData.playlistInputData;
import org.junit.Before;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.io.File;
import java.util.ArrayList;

public class PPlaybackTest {
@Before
public void setUp(){
}

@Test
public void testPlay(){
File file = new File("./src/test/java/UseCase/test1.mp3");
Song song = new Song(0, null, null, 0, null, file, false, null);
File file2 = new File("./src/test/java/UseCase/test2.mp3");
Song song2 = new Song(0, null, null, 0, null, file2, false, null);

ArrayList<Song> songs = new ArrayList<>();
songs.add(song);
songs.add(song2);

playlistInputData p = new playlistInputData(songs, "");
playPlaylist play = new playPlaylist(p);

play.play();
// Assertions.assertTrue(MusicPlayer.getInstance().isPlaying());
}

@Test
public void testPlayNext(){
File file = new File("./src/test/java/UseCase/test1.mp3");
Song song = new Song(0, null, null, 0, null, file, false, null);
File file2 = new File("./src/test/java/UseCase/test2.mp3");
Song song2 = new Song(0, null, null, 0, null, file2, false, null);

ArrayList<Song> songs = new ArrayList<>();
songs.add(song);
songs.add(song2);

playlistInputData p = new playlistInputData(songs, "");
playPlaylist play = new playPlaylist(p);

play.play();
final Thread t = new Thread(this::notifySync);
t.start();

// Assertions.assertTrue(MusicPlayer.getInstance().isPlaying());
}

@Test
public void testStopQueue(){
File file = new File("./src/test/java/UseCase/test1.mp3");
Song song = new Song(0, null, null, 0, null, file, false, null);
File file2 = new File("./src/test/java/UseCase/test2.mp3");
Song song2 = new Song(0, null, null, 0, null, file2, false, null);

ArrayList<Song> songs = new ArrayList<>();
songs.add(song);
songs.add(song2);

playlistInputData p = new playlistInputData(songs, "");
playPlaylist play = new playPlaylist(p);

play.play();
play.stopQueue();
final Thread t = new Thread(this::notifySync);
t.start();

try {
Thread.sleep(5500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}

Assertions.assertFalse(MusicPlayer.getInstance().isPlaying());
}

private void notifySync(){
synchronized (MusicPlayer.getInstance().getSync()) {
MusicPlayer.getInstance().getSync().notifyAll();
}
}
}
Binary file added src/test/java/UseCase/test1.mp3
Binary file not shown.
Binary file added src/test/java/UseCase/test2.mp3
Binary file not shown.

0 comments on commit b67bac5

Please sign in to comment.