Moved most player tasks to ForkJoin.
This system works a bit better.
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
package edu.regis.universeplayer;
|
||||
|
||||
import java.util.concurrent.ForkJoinTask;
|
||||
|
||||
/**
|
||||
* An abstract {@link ForkJoinTask} that has getters and setters automatically
|
||||
* set up.
|
||||
*
|
||||
* @param <T>
|
||||
*/
|
||||
public abstract class AbstractTask<T> extends ForkJoinTask<T>
|
||||
{
|
||||
private T value;
|
||||
|
||||
/**
|
||||
* Returns the result that would be returned by {@link #join}, even if this
|
||||
* task completed abnormally, or {@code null} if this task is not known to
|
||||
* have been completed. This method is designed to aid debugging, as well
|
||||
* as to support extensions. Its use in any other context is discouraged.
|
||||
*
|
||||
* @return the result, or {@code null} if not completed
|
||||
*/
|
||||
@Override
|
||||
public T getRawResult()
|
||||
{
|
||||
return this.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces the given value to be returned as a result. This method is
|
||||
* designed to support extensions, and should not in general be called
|
||||
* otherwise.
|
||||
*
|
||||
* @param value the value
|
||||
*/
|
||||
@Override
|
||||
protected void setRawResult(T value)
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,8 @@ import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Scanner;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.ForkJoinTask;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -149,66 +151,47 @@ public class PlayerEnvironment
|
||||
|
||||
Queue queue = Queue.getInstance();
|
||||
PlayerManager playback = PlayerManager.getPlayers();
|
||||
queue.addSongChangeListener(queue1 -> {
|
||||
QueryFuture<Void> command = PlayerManager.getPlayers()
|
||||
queue.addSongChangeListener(queue1 -> ForkJoinPool.commonPool().submit(() -> {
|
||||
ForkJoinTask<Void> command = PlayerManager.getPlayers()
|
||||
.stopSong();
|
||||
try
|
||||
{
|
||||
if (command != null && !command.getConfirmation()
|
||||
.wasSuccessful())
|
||||
command.join();
|
||||
if (command.isCompletedAbnormally())
|
||||
{
|
||||
logger.error("Could not run command",
|
||||
command.getException());
|
||||
if (Interface.getInstance() != null)
|
||||
{
|
||||
JOptionPane
|
||||
.showMessageDialog(Interface.getInstance(),
|
||||
command.getConfirmation()
|
||||
.getError(),
|
||||
command.getConfirmation()
|
||||
.getMessage(),
|
||||
command.getException(),
|
||||
command.getException().getMessage(),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
logger.error("Could not run command",
|
||||
command.getConfirmation().getError());
|
||||
}
|
||||
else if (queue1.getCurrentSong() != null)
|
||||
{
|
||||
command =
|
||||
PlayerManager.getPlayers()
|
||||
.playSong(queue1.getCurrentSong());
|
||||
if (!command.getConfirmation().wasSuccessful())
|
||||
command.join();
|
||||
if (command.isCompletedAbnormally())
|
||||
{
|
||||
if (Interface.getInstance() != null)
|
||||
{
|
||||
JOptionPane.showMessageDialog(Interface
|
||||
.getInstance(),
|
||||
command.getConfirmation().getError(),
|
||||
command.getConfirmation().getMessage(),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
logger.error("Could not run command",
|
||||
command.getConfirmation().getError());
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ExecutionException | InterruptedException e)
|
||||
{
|
||||
logger.error("Could not get current playback status", e);
|
||||
command.getException());
|
||||
if (Interface.getInstance() != null)
|
||||
{
|
||||
JOptionPane
|
||||
.showMessageDialog(Interface.getInstance(), e
|
||||
.getMessage()
|
||||
, langs
|
||||
.getString(
|
||||
"error.command"), JOptionPane.ERROR_MESSAGE);
|
||||
.showMessageDialog(Interface.getInstance(),
|
||||
command.getException(),
|
||||
command.getException().getMessage(),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}));
|
||||
playback.addPlaybackListener(status -> {
|
||||
logger.info("Receiving {} from {}", status.getInfo(), status.getSource());
|
||||
logger.info("Receiving {} from {}", status.getInfo(), status
|
||||
.getSource());
|
||||
if (status.getInfo().getStatus() == PlaybackStatus.FINISHED)
|
||||
{
|
||||
Queue.getInstance().skipNext();
|
||||
@@ -411,16 +394,9 @@ public class PlayerEnvironment
|
||||
out.println("Clearing");
|
||||
}
|
||||
case "status" -> {
|
||||
QueryFuture<PlaybackStatus> status =
|
||||
ForkJoinTask<PlaybackStatus> status =
|
||||
PlayerManager.getPlayers().getStatus();
|
||||
try
|
||||
{
|
||||
out.println(status.get());
|
||||
}
|
||||
catch (InterruptedException | ExecutionException e)
|
||||
{
|
||||
e.printStackTrace(out);
|
||||
}
|
||||
out.println(status.join());
|
||||
}
|
||||
case "song" -> {
|
||||
Song song = PlayerManager.getPlayers().getCurrentSong();
|
||||
|
||||
@@ -29,6 +29,7 @@ import java.util.Locale;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ForkJoinTask;
|
||||
|
||||
/**
|
||||
* The Interface class serves as the primary GUI that the player interacts
|
||||
@@ -76,8 +77,6 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL
|
||||
*/
|
||||
private final PlayerControls controls;
|
||||
|
||||
private int currentPlayer = -1;
|
||||
|
||||
public static Interface getInstance()
|
||||
{
|
||||
return INSTANCE;
|
||||
@@ -230,42 +229,24 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL
|
||||
* thread.
|
||||
*
|
||||
* @return the computed result
|
||||
* @throws Exception if unable to compute a result
|
||||
*/
|
||||
@Override
|
||||
protected Void doInBackground() throws Exception
|
||||
protected Void doInBackground()
|
||||
{
|
||||
QueryFuture<Void> command = PlayerManager
|
||||
ForkJoinTask<Void> command = PlayerManager
|
||||
.getPlayers().throwError(false);
|
||||
try
|
||||
{
|
||||
if (!command.getConfirmation()
|
||||
.wasSuccessful())
|
||||
command.join();
|
||||
if (command.isCompletedAbnormally())
|
||||
{
|
||||
logger.error("Could not run command",
|
||||
command.getConfirmation()
|
||||
.getError());
|
||||
command.getException());
|
||||
JOptionPane
|
||||
.showMessageDialog(Interface.this,
|
||||
command.getConfirmation()
|
||||
.getError(),
|
||||
command.getConfirmation()
|
||||
command.getException(),
|
||||
command.getException()
|
||||
.getMessage(),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
catch (ExecutionException | InterruptedException executionException)
|
||||
{
|
||||
logger.error("Error" +
|
||||
" creating " +
|
||||
"debug " +
|
||||
"message", executionException);
|
||||
JOptionPane
|
||||
.showMessageDialog(Interface.this, executionException
|
||||
.getMessage(), langs
|
||||
.getString(
|
||||
"error.command"), JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}.execute();
|
||||
@@ -298,7 +279,8 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL
|
||||
if (this.isEnabled())
|
||||
{
|
||||
collectionTypes
|
||||
.triggerSongDisplayListeners(new ArrayList<>(PlayerEnvironment.getSongs()
|
||||
.triggerSongDisplayListeners(new ArrayList<>(PlayerEnvironment
|
||||
.getSongs()
|
||||
.getSongs()));
|
||||
}
|
||||
}
|
||||
@@ -314,7 +296,8 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL
|
||||
if (this.isEnabled())
|
||||
{
|
||||
collectionTypes
|
||||
.triggerCollectionDisplayListeners(CollectionType.albumArtist, PlayerEnvironment.getAlbums()
|
||||
.triggerCollectionDisplayListeners(CollectionType.albumArtist, PlayerEnvironment
|
||||
.getAlbums()
|
||||
.getAlbumArtists());
|
||||
}
|
||||
}
|
||||
@@ -330,7 +313,8 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL
|
||||
if (this.isEnabled())
|
||||
{
|
||||
collectionTypes
|
||||
.triggerCollectionDisplayListeners(CollectionType.album, PlayerEnvironment.getSongs()
|
||||
.triggerCollectionDisplayListeners(CollectionType.album, PlayerEnvironment
|
||||
.getSongs()
|
||||
.getAlbums());
|
||||
}
|
||||
}
|
||||
@@ -346,7 +330,8 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL
|
||||
if (this.isEnabled())
|
||||
{
|
||||
collectionTypes
|
||||
.triggerCollectionDisplayListeners(CollectionType.genre, PlayerEnvironment.getAlbums()
|
||||
.triggerCollectionDisplayListeners(CollectionType.genre, PlayerEnvironment
|
||||
.getAlbums()
|
||||
.getGenres());
|
||||
}
|
||||
}
|
||||
@@ -362,7 +347,8 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL
|
||||
if (this.isEnabled())
|
||||
{
|
||||
collectionTypes
|
||||
.triggerCollectionDisplayListeners(CollectionType.year, PlayerEnvironment.getAlbums()
|
||||
.triggerCollectionDisplayListeners(CollectionType.year, PlayerEnvironment
|
||||
.getAlbums()
|
||||
.getYears());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import java.util.Locale;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.ForkJoinTask;
|
||||
|
||||
/**
|
||||
* This panel contains the buttons necessary for controlling the playback of
|
||||
@@ -181,27 +182,15 @@ public class PlayerControls extends JPanel implements PlaybackListener
|
||||
private void seek(float value)
|
||||
{
|
||||
this.service.execute(() -> {
|
||||
QueryFuture<Void> command = PlayerManager.getPlayers().seek(value);
|
||||
try
|
||||
{
|
||||
if (command != null && !command.getConfirmation()
|
||||
.wasSuccessful())
|
||||
ForkJoinTask<Void> status = PlayerManager.getPlayers().seek(value);
|
||||
status.join();
|
||||
if (status.isCompletedAbnormally())
|
||||
{
|
||||
logger.error("Could not run command",
|
||||
command.getConfirmation().getError());
|
||||
status.getException());
|
||||
JOptionPane.showMessageDialog(this,
|
||||
command.getConfirmation().getError(),
|
||||
command.getConfirmation().getMessage(),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
catch (ExecutionException | InterruptedException e)
|
||||
{
|
||||
logger.error("Could not run command",
|
||||
e);
|
||||
JOptionPane.showMessageDialog(this,
|
||||
e,
|
||||
e.getMessage(),
|
||||
status.getException(),
|
||||
status.getException().getMessage(),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
});
|
||||
@@ -213,16 +202,15 @@ public class PlayerControls extends JPanel implements PlaybackListener
|
||||
this.service.execute(() -> {
|
||||
try
|
||||
{
|
||||
QueryFuture<PlaybackStatus> status =
|
||||
ForkJoinTask status =
|
||||
PlayerManager.getPlayers().getStatus();
|
||||
CommandConfirmation confirmation = status.getConfirmation();
|
||||
if (status.getConfirmation().wasSuccessful())
|
||||
status.join();
|
||||
if (status.isCompletedNormally())
|
||||
{
|
||||
switch (status.get())
|
||||
switch ((PlaybackStatus) status.get())
|
||||
{
|
||||
case PAUSED -> confirmation = PlayerManager.getPlayers()
|
||||
.play()
|
||||
.getConfirmation();
|
||||
case PAUSED -> status = PlayerManager.getPlayers()
|
||||
.play();
|
||||
case STOPPED, EMPTY -> {
|
||||
if (Queue.getInstance().size() > 0)
|
||||
{
|
||||
@@ -230,23 +218,30 @@ public class PlayerControls extends JPanel implements PlaybackListener
|
||||
.getCurrentSong() == null)
|
||||
{
|
||||
Queue.getInstance().skipToSong(0);
|
||||
status = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
confirmation = PlayerManager.getPlayers().play()
|
||||
.getConfirmation();
|
||||
status = PlayerManager.getPlayers().play();
|
||||
}
|
||||
}
|
||||
}
|
||||
default -> {
|
||||
status = null;
|
||||
}
|
||||
}
|
||||
if (confirmation != null && !confirmation.wasSuccessful())
|
||||
if (status != null)
|
||||
{
|
||||
status.join();
|
||||
}
|
||||
}
|
||||
if (status != null && status.isCompletedAbnormally())
|
||||
{
|
||||
logger.error("Could not run command",
|
||||
confirmation.getError());
|
||||
status.getException());
|
||||
JOptionPane.showMessageDialog(this,
|
||||
confirmation.getError(),
|
||||
confirmation.getMessage(),
|
||||
status.getException(),
|
||||
status.getException().getMessage(),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
@@ -266,25 +261,25 @@ public class PlayerControls extends JPanel implements PlaybackListener
|
||||
this.service.execute(() -> {
|
||||
try
|
||||
{
|
||||
QueryFuture<PlaybackStatus> status =
|
||||
ForkJoinTask status =
|
||||
PlayerManager.getPlayers().getStatus();
|
||||
CommandConfirmation confirmation = status.getConfirmation();
|
||||
if (status.getConfirmation().wasSuccessful())
|
||||
status.join();
|
||||
if (status.isCompletedNormally())
|
||||
{
|
||||
if (status.get() == PlaybackStatus.PLAYING)
|
||||
{
|
||||
confirmation =
|
||||
PlayerManager.getPlayers().pause()
|
||||
.getConfirmation();
|
||||
status =
|
||||
PlayerManager.getPlayers().pause();
|
||||
status.join();
|
||||
}
|
||||
}
|
||||
if (confirmation != null && !confirmation.wasSuccessful())
|
||||
if (status.isCompletedAbnormally())
|
||||
{
|
||||
logger.error("Could not run command",
|
||||
confirmation.getError());
|
||||
status.getException());
|
||||
JOptionPane.showMessageDialog(this,
|
||||
confirmation.getError(),
|
||||
confirmation.getMessage(),
|
||||
status.getException(),
|
||||
status.getException().getMessage(),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
@@ -307,19 +302,17 @@ public class PlayerControls extends JPanel implements PlaybackListener
|
||||
this.service.execute(() -> {
|
||||
try
|
||||
{
|
||||
QueryFuture<PlaybackStatus> status =
|
||||
ForkJoinTask status =
|
||||
PlayerManager.getPlayers().getStatus();
|
||||
CommandConfirmation confirmation = status.getConfirmation();
|
||||
if (status.getConfirmation().wasSuccessful())
|
||||
status.join();
|
||||
if (status.isCompletedNormally())
|
||||
{
|
||||
switch (status.get())
|
||||
switch ((PlaybackStatus) status.get())
|
||||
{
|
||||
case PAUSED -> confirmation = PlayerManager.getPlayers()
|
||||
.play()
|
||||
.getConfirmation();
|
||||
case PLAYING -> confirmation = PlayerManager.getPlayers()
|
||||
.pause()
|
||||
.getConfirmation();
|
||||
case PAUSED -> status = PlayerManager.getPlayers()
|
||||
.play();
|
||||
case PLAYING -> status = PlayerManager.getPlayers()
|
||||
.pause();
|
||||
case STOPPED, EMPTY -> {
|
||||
if (Queue.getInstance().size() > 0)
|
||||
{
|
||||
@@ -327,24 +320,29 @@ public class PlayerControls extends JPanel implements PlaybackListener
|
||||
.getCurrentSong() == null)
|
||||
{
|
||||
Queue.getInstance().skipToSong(0);
|
||||
status = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
confirmation = PlayerManager.getPlayers().play()
|
||||
.getConfirmation();
|
||||
status = PlayerManager.getPlayers().play();
|
||||
}
|
||||
}
|
||||
}
|
||||
default -> status = null;
|
||||
}
|
||||
}
|
||||
if (confirmation != null && !confirmation.wasSuccessful())
|
||||
if (status != null)
|
||||
{
|
||||
status.join();
|
||||
}
|
||||
}
|
||||
if (status != null && status.isCompletedAbnormally())
|
||||
{
|
||||
JOptionPane.showMessageDialog(this,
|
||||
confirmation.getError(),
|
||||
confirmation.getMessage(),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
logger.error("Could not run command",
|
||||
confirmation.getError());
|
||||
status.getException());
|
||||
JOptionPane.showMessageDialog(this,
|
||||
status.getException(),
|
||||
status.getException().getMessage(),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
catch (ExecutionException | InterruptedException e)
|
||||
|
||||
@@ -5,6 +5,7 @@ package edu.regis.universeplayer.player;
|
||||
|
||||
import com.intervigil.wave.WaveReader;
|
||||
|
||||
import edu.regis.universeplayer.AbstractTask;
|
||||
import edu.regis.universeplayer.PlaybackInfo;
|
||||
import edu.regis.universeplayer.PlaybackListener;
|
||||
import edu.regis.universeplayer.PlaybackStatus;
|
||||
@@ -48,6 +49,7 @@ public class LocalPlayer implements Player<LocalSong>, MediaPlayerEventListener
|
||||
private final MediaPlayerFactory playerFactory;
|
||||
private final AudioPlayerComponent player;
|
||||
|
||||
private final ForkJoinPool service = new ForkJoinPool();
|
||||
private final LinkedList<PlaybackListener> listeners = new LinkedList<>();
|
||||
|
||||
private int currentId;
|
||||
@@ -55,8 +57,6 @@ public class LocalPlayer implements Player<LocalSong>, MediaPlayerEventListener
|
||||
private LocalSong currentSong;
|
||||
private AudioFile currentFile;
|
||||
|
||||
private final ExecutorService service = Executors.newSingleThreadExecutor();
|
||||
|
||||
public LocalPlayer()
|
||||
{
|
||||
this.playerFactory = new MediaPlayerFactory();
|
||||
@@ -118,83 +118,141 @@ public class LocalPlayer implements Player<LocalSong>, MediaPlayerEventListener
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryFuture<Void> loadSong(LocalSong song)
|
||||
public ForkJoinTask<Void> loadSong(LocalSong song)
|
||||
{
|
||||
if (this.currentSong != null)
|
||||
return this.service.submit(new AbstractTask<>()
|
||||
{
|
||||
this.stopSong();
|
||||
@Override
|
||||
protected boolean exec()
|
||||
{
|
||||
if (currentSong != null)
|
||||
{
|
||||
stopSong();
|
||||
}
|
||||
this.currentSong = song;
|
||||
if (!this.player.mediaPlayer().media()
|
||||
currentSong = song;
|
||||
if (!player.mediaPlayer().media()
|
||||
.play(song.file.getAbsolutePath()))
|
||||
{
|
||||
return new NullFuture<>(new RuntimeException("Could not play " +
|
||||
this.completeExceptionally(new RuntimeException("Could not play " +
|
||||
"song " + song));
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new NullFuture<>();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryFuture<Void> play()
|
||||
public ForkJoinTask<Void> play()
|
||||
{
|
||||
this.player.mediaPlayer()
|
||||
.submit((WrappedRunnable) () -> this.player.mediaPlayer()
|
||||
this.player.mediaPlayer().submit(() -> this.player.mediaPlayer()
|
||||
.controls()
|
||||
.play());
|
||||
return new NullFuture<>();
|
||||
return new AbstractTask<>()
|
||||
{
|
||||
@Override
|
||||
protected boolean exec()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryFuture<Void> pause()
|
||||
public ForkJoinTask<Void> pause()
|
||||
{
|
||||
this.player.mediaPlayer()
|
||||
.submit((WrappedRunnable) () -> this.player.mediaPlayer()
|
||||
.submit(() -> this.player.mediaPlayer()
|
||||
.controls()
|
||||
.pause());
|
||||
return new NullFuture<>();
|
||||
return new AbstractTask<>()
|
||||
{
|
||||
@Override
|
||||
protected boolean exec()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryFuture<Void> togglePlayback()
|
||||
public ForkJoinTask<Void> togglePlayback()
|
||||
{
|
||||
if (this.player.mediaPlayer().status().isPlaying())
|
||||
return this.service.submit(new AbstractTask<>()
|
||||
{
|
||||
return this.pause();
|
||||
@Override
|
||||
protected boolean exec()
|
||||
{
|
||||
ForkJoinTask<Void> command;
|
||||
if (player.mediaPlayer().status().isPlaying())
|
||||
{
|
||||
command = pause();
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.play();
|
||||
command = play();
|
||||
}
|
||||
command.join();
|
||||
if (command.isCompletedAbnormally())
|
||||
{
|
||||
this.completeExceptionally(command.getException());
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryFuture<Void> stopSong()
|
||||
public ForkJoinTask<Void> stopSong()
|
||||
{
|
||||
this.player.mediaPlayer()
|
||||
.submit((WrappedRunnable) () -> this.player.mediaPlayer()
|
||||
.submit(() -> this.player.mediaPlayer()
|
||||
.controls()
|
||||
.stop());
|
||||
return new NullFuture<>();
|
||||
return new AbstractTask<>()
|
||||
{
|
||||
@Override
|
||||
protected boolean exec()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryFuture<Void> seek(float time)
|
||||
public ForkJoinTask<Void> seek(float time)
|
||||
{
|
||||
this.player.mediaPlayer()
|
||||
.submit((WrappedRunnable) () -> this.player.mediaPlayer()
|
||||
.submit(() -> this.player.mediaPlayer()
|
||||
.controls()
|
||||
.setTime((long) (time * 1000)));
|
||||
return new NullFuture<>();
|
||||
return new AbstractTask<>()
|
||||
{
|
||||
@Override
|
||||
protected boolean exec()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryFuture<PlaybackStatus> getStatus()
|
||||
public ForkJoinTask<PlaybackStatus> getStatus()
|
||||
{
|
||||
return this.service.submit(new AbstractTask<>()
|
||||
{
|
||||
@Override
|
||||
protected boolean exec()
|
||||
{
|
||||
PlaybackStatus returnStatus;
|
||||
StatusApi status = this.player.mediaPlayer().status();
|
||||
StatusApi status = player.mediaPlayer().status();
|
||||
switch (status.state())
|
||||
{
|
||||
case NOTHING_SPECIAL -> returnStatus = PlaybackStatus.EMPTY;
|
||||
@@ -202,28 +260,54 @@ public class LocalPlayer implements Player<LocalSong>, MediaPlayerEventListener
|
||||
case PAUSED -> returnStatus = PlaybackStatus.PAUSED;
|
||||
default -> returnStatus = PlaybackStatus.STOPPED;
|
||||
}
|
||||
return new NullFuture<>(returnStatus);
|
||||
this.complete(returnStatus);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryFuture<Float> getCurrentTime()
|
||||
public ForkJoinTask<Float> getCurrentTime()
|
||||
{
|
||||
return new NullFuture<>(this.player.mediaPlayer().status()
|
||||
return this.service.submit(new AbstractTask<>()
|
||||
{
|
||||
@Override
|
||||
protected boolean exec()
|
||||
{
|
||||
complete(player.mediaPlayer().status()
|
||||
.time() / 1000F);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryFuture<Float> getLength()
|
||||
public ForkJoinTask<Float> getLength()
|
||||
{
|
||||
return new NullFuture<>(this.player.mediaPlayer().status()
|
||||
return this.service.submit(new AbstractTask<>()
|
||||
{
|
||||
@Override
|
||||
protected boolean exec()
|
||||
{
|
||||
complete(player.mediaPlayer().status()
|
||||
.length() / 1000F);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryFuture<Void> close()
|
||||
public ForkJoinTask<Void> close()
|
||||
{
|
||||
this.player.release();
|
||||
return new NullFuture<>();
|
||||
return this.service.submit(new AbstractTask<>()
|
||||
{
|
||||
@Override
|
||||
protected boolean exec()
|
||||
{
|
||||
player.release();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -10,6 +10,7 @@ import edu.regis.universeplayer.browserCommands.QueryFuture;
|
||||
import edu.regis.universeplayer.data.Song;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.ForkJoinTask;
|
||||
|
||||
/**
|
||||
* This interface serves as the connection to a music player of some sort, whether it be
|
||||
@@ -34,33 +35,33 @@ public interface Player<T extends Song>
|
||||
* @param song - The song to load.
|
||||
* @return A confirmation of whether the command was successful or not.
|
||||
*/
|
||||
QueryFuture<Void> loadSong(T song);
|
||||
ForkJoinTask<Void> loadSong(T song);
|
||||
|
||||
/**
|
||||
* Enables playback of the current song, if one is active.
|
||||
*
|
||||
* @return A confirmation of whether the command was successful or not.
|
||||
*/
|
||||
QueryFuture<Void> play();
|
||||
ForkJoinTask<Void> play();
|
||||
|
||||
/**
|
||||
* Pauses playback of the current song.
|
||||
*
|
||||
* @return A confirmation of whether the command was successful or not.
|
||||
*/
|
||||
QueryFuture<Void> pause();
|
||||
ForkJoinTask<Void> pause();
|
||||
|
||||
/**
|
||||
* Toggles between playing and pausing the current song.
|
||||
*
|
||||
* @return A confirmation of whether the command was successful or not.
|
||||
*/
|
||||
QueryFuture<Void> togglePlayback();
|
||||
ForkJoinTask<Void> togglePlayback();
|
||||
|
||||
/**
|
||||
* Stops playback of the current song.
|
||||
*/
|
||||
QueryFuture<Void> stopSong();
|
||||
ForkJoinTask<Void> stopSong();
|
||||
|
||||
/**
|
||||
* Sets the current song time to the specified position.
|
||||
@@ -68,34 +69,34 @@ public interface Player<T extends Song>
|
||||
* @param time - The specified time in the song, in seconds.
|
||||
* @return A confirmation of whether the command was successful or not.
|
||||
*/
|
||||
QueryFuture<Void> seek(float time);
|
||||
ForkJoinTask<Void> seek(float time);
|
||||
|
||||
/**
|
||||
* Obtains the player's current playback status.
|
||||
* @return A future for the request.
|
||||
*/
|
||||
QueryFuture<PlaybackStatus> getStatus();
|
||||
ForkJoinTask<PlaybackStatus> getStatus();
|
||||
|
||||
/**
|
||||
* Obtains the time we are currently at in the current song.
|
||||
*
|
||||
* @return - The current song position in seconds, or -1 if no song is playing.
|
||||
*/
|
||||
QueryFuture<Float> getCurrentTime();
|
||||
ForkJoinTask<Float> getCurrentTime();
|
||||
|
||||
/**
|
||||
* Gets the length of the current song.
|
||||
*
|
||||
* @return The song length, in seconds.
|
||||
*/
|
||||
QueryFuture<Float> getLength();
|
||||
ForkJoinTask<Float> getLength();
|
||||
|
||||
/**
|
||||
* Closes the player.
|
||||
*
|
||||
* @return A confirmation of whether the player was successfully closed.
|
||||
*/
|
||||
QueryFuture<Void> close();
|
||||
ForkJoinTask<Void> close();
|
||||
|
||||
/**
|
||||
* Adds a listener for playback status updates.
|
||||
|
||||
@@ -7,11 +7,13 @@ import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ForkJoinTask;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
import edu.regis.universeplayer.AbstractTask;
|
||||
import edu.regis.universeplayer.PlaybackListener;
|
||||
import edu.regis.universeplayer.PlaybackStatus;
|
||||
import edu.regis.universeplayer.browserCommands.CommandConfirmation;
|
||||
@@ -150,10 +152,10 @@ public class PlayerManager implements PlaybackListener
|
||||
*/
|
||||
private <T> QueryFuture<T> getNullPlayer(String message, T returnValue)
|
||||
{
|
||||
return new QueryFuture<T>()
|
||||
return new QueryFuture<>()
|
||||
{
|
||||
@Override
|
||||
public CommandConfirmation getConfirmation() throws CancellationException, ExecutionException, InterruptedException
|
||||
public CommandConfirmation getConfirmation() throws CancellationException
|
||||
{
|
||||
if (returnValue instanceof Throwable)
|
||||
{
|
||||
@@ -166,7 +168,7 @@ public class PlayerManager implements PlaybackListener
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfirmation getConfirmation(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
|
||||
public CommandConfirmation getConfirmation(long timeout, TimeUnit unit)
|
||||
{
|
||||
return this.getConfirmation();
|
||||
}
|
||||
@@ -190,13 +192,13 @@ public class PlayerManager implements PlaybackListener
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get() throws InterruptedException, ExecutionException
|
||||
public T get()
|
||||
{
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
|
||||
public T get(long timeout, TimeUnit unit)
|
||||
{
|
||||
return this.get();
|
||||
}
|
||||
@@ -211,16 +213,16 @@ public class PlayerManager implements PlaybackListener
|
||||
*/
|
||||
private <T> QueryFuture<T> getNullPlayer(Throwable message, T returnValue)
|
||||
{
|
||||
return new QueryFuture<T>()
|
||||
return new QueryFuture<>()
|
||||
{
|
||||
@Override
|
||||
public CommandConfirmation getConfirmation() throws CancellationException, ExecutionException, InterruptedException
|
||||
public CommandConfirmation getConfirmation() throws CancellationException
|
||||
{
|
||||
return new CommandConfirmation(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfirmation getConfirmation(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
|
||||
public CommandConfirmation getConfirmation(long timeout, TimeUnit unit)
|
||||
{
|
||||
return this.getConfirmation();
|
||||
}
|
||||
@@ -244,20 +246,20 @@ public class PlayerManager implements PlaybackListener
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get() throws InterruptedException, ExecutionException
|
||||
public T get()
|
||||
{
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
|
||||
public T get(long timeout, TimeUnit unit)
|
||||
{
|
||||
return this.get();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public QueryFuture<Void> playSong(Song song)
|
||||
public ForkJoinTask<Void> playSong(Song song)
|
||||
{
|
||||
if (this.currentSong != null)
|
||||
{
|
||||
@@ -274,16 +276,24 @@ public class PlayerManager implements PlaybackListener
|
||||
return this.currentPlayer.loadSong(song);
|
||||
}
|
||||
|
||||
public QueryFuture<PlaybackStatus> getStatus()
|
||||
public ForkJoinTask<PlaybackStatus> getStatus()
|
||||
{
|
||||
if (this.currentPlayer != null)
|
||||
{
|
||||
return this.currentPlayer.getStatus();
|
||||
}
|
||||
return this.getNullPlayer("Command successful", PlaybackStatus.EMPTY);
|
||||
return new AbstractTask<>()
|
||||
{
|
||||
@Override
|
||||
protected boolean exec()
|
||||
{
|
||||
complete(PlaybackStatus.EMPTY);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public QueryFuture<Void> seek(float time)
|
||||
public ForkJoinTask<Void> seek(float time)
|
||||
{
|
||||
if (this.currentPlayer != null)
|
||||
{
|
||||
@@ -292,7 +302,7 @@ public class PlayerManager implements PlaybackListener
|
||||
return null;
|
||||
}
|
||||
|
||||
public QueryFuture<Void> play()
|
||||
public ForkJoinTask<Void> play()
|
||||
{
|
||||
if (this.currentPlayer != null && this.currentSong != null)
|
||||
{
|
||||
@@ -301,7 +311,7 @@ public class PlayerManager implements PlaybackListener
|
||||
return null;
|
||||
}
|
||||
|
||||
public QueryFuture<Void> pause()
|
||||
public ForkJoinTask<Void> pause()
|
||||
{
|
||||
if (this.currentPlayer != null && this.currentSong != null)
|
||||
{
|
||||
@@ -310,7 +320,7 @@ public class PlayerManager implements PlaybackListener
|
||||
return null;
|
||||
}
|
||||
|
||||
public QueryFuture<Void> toggle()
|
||||
public ForkJoinTask<Void> toggle()
|
||||
{
|
||||
if (this.currentPlayer != null && this.currentSong != null)
|
||||
{
|
||||
@@ -319,7 +329,7 @@ public class PlayerManager implements PlaybackListener
|
||||
return null;
|
||||
}
|
||||
|
||||
public QueryFuture<Void> stopSong()
|
||||
public ForkJoinTask<Void> stopSong()
|
||||
{
|
||||
if (this.currentPlayer != null && this.currentSong != null)
|
||||
{
|
||||
@@ -370,14 +380,22 @@ public class PlayerManager implements PlaybackListener
|
||||
* script or a background script.
|
||||
* @return The command future.
|
||||
*/
|
||||
public QueryFuture<Void> throwError(boolean forward)
|
||||
public ForkJoinTask<Void> throwError(boolean forward)
|
||||
{
|
||||
BrowserPlayer player =
|
||||
(BrowserPlayer) this.players.get(InternetSong.class);
|
||||
if (player == null)
|
||||
{
|
||||
return this.getNullPlayer(new NullPointerException(
|
||||
"No browser found"), null);
|
||||
return new AbstractTask<>()
|
||||
{
|
||||
@Override
|
||||
protected boolean exec()
|
||||
{
|
||||
completeExceptionally(new NullPointerException("Couldn't " +
|
||||
"find internet player"));
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
return player.throwError(forward);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user