Improves error handling (foreground still needs testing).
This commit is contained in:
@@ -125,6 +125,18 @@ var listeners = [function (message, returnValue) {
|
|||||||
case "CommandQuit":
|
case "CommandQuit":
|
||||||
returnValue = quit();
|
returnValue = quit();
|
||||||
break;
|
break;
|
||||||
|
case "CommandError":
|
||||||
|
console.error("Error message", message);
|
||||||
|
if (message.forward)
|
||||||
|
{
|
||||||
|
returnValue = queryTab(message);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new TypeError("This is a background test");
|
||||||
|
returnValue = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (message == "quit")
|
else if (message == "quit")
|
||||||
@@ -202,7 +214,19 @@ interfacePort.onMessage.addListener((message) => {
|
|||||||
console.log("Sending ", returnValue)
|
console.log("Sending ", returnValue)
|
||||||
interfacePort.postMessage(returnValue);
|
interfacePort.postMessage(returnValue);
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
console.error("Error in evaluating message: ", error)
|
// console.error("Error in evaluating message: ", error);
|
||||||
|
interfacePort.postMessage({
|
||||||
|
"messageNum": message.messageNum,
|
||||||
|
"message": {
|
||||||
|
"type": "edu.regis.universeplayer.browserCommands.CommandReturn",
|
||||||
|
"returnValue": null,
|
||||||
|
"confirmation": {
|
||||||
|
type: "edu.regis.universeplayer.browserCommands.CommandConfirmation",
|
||||||
|
message: "Error in executing request",
|
||||||
|
errorCode: JSON.parse(JSON.stringify(error, Object.getOwnPropertyNames(error)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ function handleMessage(message)
|
|||||||
return false;
|
return false;
|
||||||
case "CommandSeek":
|
case "CommandSeek":
|
||||||
return seek(message.time);
|
return seek(message.time);
|
||||||
|
case "CommandError":
|
||||||
|
throw new TypeError("This is a foreground test");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
package edu.regis.universeplayer.addon;
|
package edu.regis.universeplayer.addon;
|
||||||
|
|
||||||
import com.google.gson.*;
|
import com.google.gson.*;
|
||||||
|
|
||||||
|
import edu.regis.universeplayer.browserCommands.CommandConfirmation;
|
||||||
import edu.regis.universeplayer.browserCommands.MessageRunner;
|
import edu.regis.universeplayer.browserCommands.MessageRunner;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -266,4 +268,10 @@ public class BrowserLink extends MessageRunner
|
|||||||
}
|
}
|
||||||
return returnValue;
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getErrorObject(Throwable e)
|
||||||
|
{
|
||||||
|
return new CommandConfirmation(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public class ThrowableSerializer implements JsonSerializer<Throwable>, JsonDeser
|
|||||||
{
|
{
|
||||||
stack.add(context.serialize(trace));
|
stack.add(context.serialize(trace));
|
||||||
}
|
}
|
||||||
ob.add("trace", stack);
|
ob.add("stack", stack);
|
||||||
JsonArray suppressed = new JsonArray();
|
JsonArray suppressed = new JsonArray();
|
||||||
for (Throwable throwable: src.getSuppressed())
|
for (Throwable throwable: src.getSuppressed())
|
||||||
{
|
{
|
||||||
@@ -35,19 +35,37 @@ public class ThrowableSerializer implements JsonSerializer<Throwable>, JsonDeser
|
|||||||
public Throwable deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
|
public Throwable deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
|
||||||
{
|
{
|
||||||
JsonObject ob = json.getAsJsonObject();
|
JsonObject ob = json.getAsJsonObject();
|
||||||
Throwable throwable = new Throwable(ob.get("message").getAsString(), context.deserialize(ob.get("cause"), typeOfT));
|
Throwable cause = context.deserialize(ob.get("cause"), typeOfT);
|
||||||
|
Throwable throwable;
|
||||||
|
if (cause == null)
|
||||||
|
{
|
||||||
|
throwable = new Throwable(ob.get("message").getAsString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throwable = new Throwable(ob.get("message").getAsString(), context
|
||||||
|
.deserialize(ob.get("cause"), typeOfT));
|
||||||
throwable.initCause(context.deserialize(ob.get("cause"), Throwable.class));
|
throwable.initCause(context.deserialize(ob.get("cause"), Throwable.class));
|
||||||
JsonArray traceJson = ob.getAsJsonArray("trace");
|
}
|
||||||
|
JsonArray traceJson = ob.getAsJsonArray("stack");
|
||||||
|
if (traceJson != null)
|
||||||
|
{
|
||||||
StackTraceElement[] trace = new StackTraceElement[traceJson.size()];
|
StackTraceElement[] trace = new StackTraceElement[traceJson.size()];
|
||||||
for (int i = 0; i < trace.length; i++)
|
for (int i = 0; i < trace.length; i++)
|
||||||
{
|
{
|
||||||
trace[i] = context.deserialize(traceJson.get(i), StackTraceElement.class);
|
trace[i] = context
|
||||||
|
.deserialize(traceJson.get(i), StackTraceElement.class);
|
||||||
}
|
}
|
||||||
throwable.setStackTrace(trace);
|
throwable.setStackTrace(trace);
|
||||||
|
}
|
||||||
JsonArray suppressed = ob.getAsJsonArray("suppressed");
|
JsonArray suppressed = ob.getAsJsonArray("suppressed");
|
||||||
for (JsonElement el: suppressed)
|
if (suppressed != null)
|
||||||
{
|
{
|
||||||
throwable.addSuppressed(context.deserialize(el, Throwable.class));
|
for (JsonElement el : suppressed)
|
||||||
|
{
|
||||||
|
throwable.addSuppressed(context
|
||||||
|
.deserialize(el, Throwable.class));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return throwable;
|
return throwable;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package edu.regis.universeplayer.browserCommands;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A debugging command that instructs the browser to throw an error.
|
||||||
|
*/
|
||||||
|
public class CommandError implements BrowserCommand
|
||||||
|
{
|
||||||
|
private boolean forward;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an error command.
|
||||||
|
*
|
||||||
|
* @param forward - Determines where the error should be thrown. If true, it
|
||||||
|
* will be thrown from the website tab. If false, it will be
|
||||||
|
* thrown by the addon background script.
|
||||||
|
*/
|
||||||
|
public CommandError(boolean forward)
|
||||||
|
{
|
||||||
|
this.forward = forward;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the error will be thrown from the foreground or background
|
||||||
|
* script.
|
||||||
|
*
|
||||||
|
* @return True if the error will be thrown from the foreground script,
|
||||||
|
* false if it will be thrown from the background.
|
||||||
|
*/
|
||||||
|
public boolean isForeground()
|
||||||
|
{
|
||||||
|
return this.forward;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the name of the command.
|
||||||
|
*
|
||||||
|
* @return The command name.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getCommandName()
|
||||||
|
{
|
||||||
|
return "error";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -99,17 +99,27 @@ public class MessageHandler implements Runnable, MessageSerializer
|
|||||||
{
|
{
|
||||||
numBuffer.clear();
|
numBuffer.clear();
|
||||||
numBuffer.put(message[0]);
|
numBuffer.put(message[0]);
|
||||||
|
try
|
||||||
|
{
|
||||||
messageOb = this.deserializeObject(message[1]);
|
messageOb = this.deserializeObject(message[1]);
|
||||||
messageResponse = this.triggerListeners(messageOb);
|
}
|
||||||
|
catch (IOException | ClassNotFoundException e)
|
||||||
|
{
|
||||||
|
logger.error("Could not read message", e);
|
||||||
|
messageOb = this.getErrorObject(e);
|
||||||
|
}
|
||||||
|
messageResponse = this
|
||||||
|
.triggerListeners(messageOb);
|
||||||
synchronized (this.messageResponses)
|
synchronized (this.messageResponses)
|
||||||
{
|
{
|
||||||
numBuffer.clear();
|
numBuffer.clear();
|
||||||
this.messageResponses.put(numBuffer.getInt(), messageResponse);
|
this.messageResponses.put(numBuffer
|
||||||
|
.getInt(), messageResponse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (IOException | ClassNotFoundException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
logger.error("Could not retrieve message", e);
|
logger.error("Could not retrieve message", e);
|
||||||
running = false;
|
running = false;
|
||||||
|
|||||||
@@ -37,7 +37,8 @@ public interface MessageSerializer
|
|||||||
*
|
*
|
||||||
* @param message - The message received.
|
* @param message - The message received.
|
||||||
* @return An object.
|
* @return An object.
|
||||||
* @throws IOException If there is an error in parsing the message.
|
* @throws IOException If there is an error in parsing the
|
||||||
|
* message.
|
||||||
* @throws ClassNotFoundException If the object is not recognized
|
* @throws ClassNotFoundException If the object is not recognized
|
||||||
*/
|
*/
|
||||||
default Object deserializeObject(byte[] message) throws IOException, ClassNotFoundException
|
default Object deserializeObject(byte[] message) throws IOException, ClassNotFoundException
|
||||||
@@ -55,7 +56,8 @@ public interface MessageSerializer
|
|||||||
* Writes a message to the output stream.
|
* Writes a message to the output stream.
|
||||||
*
|
*
|
||||||
* @param out - The output stream to write to.
|
* @param out - The output stream to write to.
|
||||||
* @param messageNum - The ID of the message being sent. This will help keep track of responses.
|
* @param messageNum - The ID of the message being sent. This will help keep
|
||||||
|
* track of responses.
|
||||||
* @param message - The actual message contents to write.
|
* @param message - The actual message contents to write.
|
||||||
* @throws IOException Thrown when an exception occures
|
* @throws IOException Thrown when an exception occures
|
||||||
*/
|
*/
|
||||||
@@ -119,7 +121,8 @@ public interface MessageSerializer
|
|||||||
readLength = in.read(lengthBuffer.array());
|
readLength = in.read(lengthBuffer.array());
|
||||||
if (readLength == 0)
|
if (readLength == 0)
|
||||||
{
|
{
|
||||||
getLogger().error("Malformed message, could not get message length.");
|
getLogger()
|
||||||
|
.error("Malformed message, could not get message length.");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
message = new byte[lengthBuffer.getInt()];
|
message = new byte[lengthBuffer.getInt()];
|
||||||
@@ -129,9 +132,21 @@ public interface MessageSerializer
|
|||||||
readLength = in.read(message);
|
readLength = in.read(message);
|
||||||
if (readLength < message.length)
|
if (readLength < message.length)
|
||||||
{
|
{
|
||||||
getLogger().warn("Message shorter than reported (expected {} bytes, got {} bytes)", message.length, readLength);
|
getLogger()
|
||||||
|
.warn("Message shorter than reported (expected {} bytes, got {} bytes)", message.length, readLength);
|
||||||
}
|
}
|
||||||
getLogger().trace("Reading message");
|
getLogger().trace("Reading message");
|
||||||
return new byte[][] {messageNum, message};
|
return new byte[][]{messageNum, message};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called when an error in deserialization occurs.
|
||||||
|
*
|
||||||
|
* @param e - The error thrown.
|
||||||
|
* @return An object to return to listeners in the event of a read error.
|
||||||
|
*/
|
||||||
|
default Object getErrorObject(Throwable e)
|
||||||
|
{
|
||||||
|
return e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import edu.regis.universeplayer.browserCommands.*;
|
|||||||
import edu.regis.universeplayer.data.InternetSong;
|
import edu.regis.universeplayer.data.InternetSong;
|
||||||
import edu.regis.universeplayer.data.PlaybackEvent;
|
import edu.regis.universeplayer.data.PlaybackEvent;
|
||||||
import edu.regis.universeplayer.data.Song;
|
import edu.regis.universeplayer.data.Song;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@@ -28,7 +29,8 @@ import java.util.concurrent.*;
|
|||||||
*/
|
*/
|
||||||
public class BrowserPlayer implements Player<InternetSong>, UpdateListener
|
public class BrowserPlayer implements Player<InternetSong>, UpdateListener
|
||||||
{
|
{
|
||||||
private static final Logger logger = LoggerFactory.getLogger(BrowserPlayer.class);
|
private static final Logger logger = LoggerFactory
|
||||||
|
.getLogger(BrowserPlayer.class);
|
||||||
|
|
||||||
private final LinkedList<PlaybackListener> listeners = new LinkedList<>();
|
private final LinkedList<PlaybackListener> listeners = new LinkedList<>();
|
||||||
|
|
||||||
@@ -68,7 +70,8 @@ public class BrowserPlayer implements Player<InternetSong>, UpdateListener
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return new ForwardedFuture(getBrowser().sendObject(new CommandLoadSong(song.location)));
|
return new ForwardedFuture(getBrowser()
|
||||||
|
.sendObject(new CommandLoadSong(song.location)));
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
@@ -85,7 +88,8 @@ public class BrowserPlayer implements Player<InternetSong>, UpdateListener
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
QueryFuture<Void> future = new ForwardedFuture(getBrowser().sendObject(new CommandQuit()));
|
QueryFuture<Void> future = new ForwardedFuture(getBrowser()
|
||||||
|
.sendObject(new CommandQuit()));
|
||||||
return future;
|
return future;
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
@@ -134,7 +138,8 @@ public class BrowserPlayer implements Player<InternetSong>, UpdateListener
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return new ForwardedFuture(getBrowser().sendObject(new CommandSetPlayback(CommandSetPlayback.Playback.PLAY)));
|
return new ForwardedFuture(getBrowser()
|
||||||
|
.sendObject(new CommandSetPlayback(CommandSetPlayback.Playback.PLAY)));
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
@@ -148,7 +153,8 @@ public class BrowserPlayer implements Player<InternetSong>, UpdateListener
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return new ForwardedFuture(getBrowser().sendObject(new CommandSetPlayback(CommandSetPlayback.Playback.PAUSE)));
|
return new ForwardedFuture(getBrowser()
|
||||||
|
.sendObject(new CommandSetPlayback(CommandSetPlayback.Playback.PAUSE)));
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
@@ -162,7 +168,8 @@ public class BrowserPlayer implements Player<InternetSong>, UpdateListener
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return new ForwardedFuture(getBrowser().sendObject(new CommandSetPlayback(CommandSetPlayback.Playback.PAUSE)));
|
return new ForwardedFuture(getBrowser()
|
||||||
|
.sendObject(new CommandSetPlayback(CommandSetPlayback.Playback.PAUSE)));
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
@@ -179,7 +186,8 @@ public class BrowserPlayer implements Player<InternetSong>, UpdateListener
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return new ForwardedFuture(getBrowser().sendObject(new CommandLoadSong((URL) null)));
|
return new ForwardedFuture(getBrowser()
|
||||||
|
.sendObject(new CommandLoadSong((URL) null)));
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
@@ -193,7 +201,8 @@ public class BrowserPlayer implements Player<InternetSong>, UpdateListener
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return new ForwardedFuture(getBrowser().sendObject(new CommandSeek(time)));
|
return new ForwardedFuture(getBrowser()
|
||||||
|
.sendObject(new CommandSeek(time)));
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
@@ -290,6 +299,27 @@ public class BrowserPlayer implements Player<InternetSong>, UpdateListener
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Causes the browser to throw an error
|
||||||
|
*
|
||||||
|
* @param forward - Whether the error should be thrown from the foreground
|
||||||
|
* script or the background script.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public QueryFuture<Void> throwError(boolean forward)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return new ForwardedFuture(getBrowser()
|
||||||
|
.sendObject(new CommandError(forward)));
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
logger.error("Could not send message", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onUpdate(Object object, MessageRunner runner)
|
public void onUpdate(Object object, MessageRunner runner)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ package edu.regis.universeplayer.player;
|
|||||||
import edu.regis.universeplayer.Player;
|
import edu.regis.universeplayer.Player;
|
||||||
import edu.regis.universeplayer.browser.Browser;
|
import edu.regis.universeplayer.browser.Browser;
|
||||||
import edu.regis.universeplayer.browser.BrowserPlayer;
|
import edu.regis.universeplayer.browser.BrowserPlayer;
|
||||||
|
import edu.regis.universeplayer.browserCommands.CommandError;
|
||||||
|
import edu.regis.universeplayer.browserCommands.QueryFuture;
|
||||||
import edu.regis.universeplayer.data.InternetSong;
|
import edu.regis.universeplayer.data.InternetSong;
|
||||||
import edu.regis.universeplayer.data.Queue;
|
import edu.regis.universeplayer.data.Queue;
|
||||||
import edu.regis.universeplayer.data.*;
|
import edu.regis.universeplayer.data.*;
|
||||||
@@ -28,9 +30,11 @@ import java.util.Collection;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Interface class serves as the primary GUI that the player interacts with.
|
* The Interface class serves as the primary GUI that the player interacts
|
||||||
|
* with.
|
||||||
*
|
*
|
||||||
* @author William Hubbard
|
* @author William Hubbard
|
||||||
* @version 0.1
|
* @version 0.1
|
||||||
@@ -40,7 +44,8 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL
|
|||||||
// static {
|
// static {
|
||||||
// Locale.setDefault(new Locale("es", "ES"));
|
// Locale.setDefault(new Locale("es", "ES"));
|
||||||
// }
|
// }
|
||||||
private static final Logger logger = LoggerFactory.getLogger(Interface.class);
|
private static final Logger logger = LoggerFactory
|
||||||
|
.getLogger(Interface.class);
|
||||||
private static final ResourceBundle langs = ResourceBundle
|
private static final ResourceBundle langs = ResourceBundle
|
||||||
.getBundle("lang.interface", Locale.getDefault());
|
.getBundle("lang.interface", Locale.getDefault());
|
||||||
|
|
||||||
@@ -119,8 +124,10 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL
|
|||||||
inter.players.add(browserPlayer = new BrowserPlayer());
|
inter.players.add(browserPlayer = new BrowserPlayer());
|
||||||
logger.debug("Sending ping");
|
logger.debug("Sending ping");
|
||||||
browser.sendObject("ping");
|
browser.sendObject("ping");
|
||||||
Runtime.getRuntime().addShutdownHook(new Thread(browserPlayer::close));
|
Runtime.getRuntime()
|
||||||
Player.REGISTERED_PLAYERS.put(InternetSong.class, browserPlayer);
|
.addShutdownHook(new Thread(browserPlayer::close));
|
||||||
|
Player.REGISTERED_PLAYERS
|
||||||
|
.put(InternetSong.class, browserPlayer);
|
||||||
|
|
||||||
// LinkedList<Future<Object>> pingRequests = new LinkedList<>();
|
// LinkedList<Future<Object>> pingRequests = new LinkedList<>();
|
||||||
// for (int i = 0; i < 20; i++)
|
// for (int i = 0; i < 20; i++)
|
||||||
@@ -155,7 +162,8 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL
|
|||||||
{
|
{
|
||||||
logger.error("Could not open browser background", e);
|
logger.error("Could not open browser background", e);
|
||||||
JOptionPane
|
JOptionPane
|
||||||
.showMessageDialog(inter != null && inter.isVisible() ? inter : null, e, langs
|
.showMessageDialog(inter != null && inter
|
||||||
|
.isVisible() ? inter : null, e, langs
|
||||||
.getString("error.generic"), JOptionPane.ERROR_MESSAGE);
|
.getString("error.generic"), JOptionPane.ERROR_MESSAGE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -221,7 +229,8 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL
|
|||||||
{
|
{
|
||||||
if (!commDir.getParentFile().mkdir())
|
if (!commDir.getParentFile().mkdir())
|
||||||
{
|
{
|
||||||
logger.error("Could not create shared directory {}", commDir.getParent());
|
logger.error("Could not create shared directory {}", commDir
|
||||||
|
.getParent());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!commDir.exists())
|
if (!commDir.exists())
|
||||||
@@ -262,7 +271,8 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL
|
|||||||
{
|
{
|
||||||
AbstractAction action;
|
AbstractAction action;
|
||||||
|
|
||||||
this.actions.put("refresh", action = new AbstractAction(langs.getString("actions.refresh"))
|
this.actions.put("refresh", action = new AbstractAction(langs
|
||||||
|
.getString("actions.refresh"))
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e)
|
public void actionPerformed(ActionEvent e)
|
||||||
@@ -302,7 +312,8 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL
|
|||||||
});
|
});
|
||||||
action.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_E);
|
action.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_E);
|
||||||
|
|
||||||
this.actions.put("exit", action = new AbstractAction(langs.getString("actions.exit"))
|
this.actions.put("exit", action = new AbstractAction(langs
|
||||||
|
.getString("actions.exit"))
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e)
|
public void actionPerformed(ActionEvent e)
|
||||||
@@ -316,7 +327,8 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL
|
|||||||
});
|
});
|
||||||
action.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_X);
|
action.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_X);
|
||||||
|
|
||||||
this.actions.put("logs", action = new AbstractAction(langs.getString("actions.logs"))
|
this.actions.put("logs", action = new AbstractAction(langs
|
||||||
|
.getString("actions.logs"))
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e)
|
public void actionPerformed(ActionEvent e)
|
||||||
@@ -330,9 +342,114 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
action.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_F12, 0));
|
action.putValue(Action.ACCELERATOR_KEY, KeyStroke
|
||||||
|
.getKeyStroke(KeyEvent.VK_F12, 0));
|
||||||
|
|
||||||
this.actions.put("about", action = new AbstractAction(langs.getString("actions.about"))
|
this.actions.put("debug.error", action =
|
||||||
|
new AbstractAction(langs.getString("actions.debug.error"))
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e)
|
||||||
|
{
|
||||||
|
if (this.isEnabled())
|
||||||
|
{
|
||||||
|
new SwingWorker<Void, Void>()
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Computes
|
||||||
|
* a
|
||||||
|
* result,
|
||||||
|
* or
|
||||||
|
* throws
|
||||||
|
* an
|
||||||
|
* exception
|
||||||
|
* if
|
||||||
|
* unable
|
||||||
|
* to
|
||||||
|
* do
|
||||||
|
* so.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Note
|
||||||
|
* that
|
||||||
|
* this
|
||||||
|
* method
|
||||||
|
* is
|
||||||
|
* executed
|
||||||
|
* only
|
||||||
|
* once.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Note:
|
||||||
|
* this
|
||||||
|
* method
|
||||||
|
* is
|
||||||
|
* executed
|
||||||
|
* in
|
||||||
|
* a
|
||||||
|
* background
|
||||||
|
* thread.
|
||||||
|
*
|
||||||
|
* @return the computed result
|
||||||
|
* @throws Exception if unable to compute a result
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground() throws Exception
|
||||||
|
{
|
||||||
|
Interface.this.players.stream()
|
||||||
|
.filter(p -> p instanceof BrowserPlayer)
|
||||||
|
.map(p -> (BrowserPlayer) p)
|
||||||
|
.findFirst()
|
||||||
|
.ifPresentOrElse(p -> {
|
||||||
|
logger.debug("Throwing " +
|
||||||
|
"error");
|
||||||
|
QueryFuture<Void> command = p
|
||||||
|
.throwError((false));
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!command
|
||||||
|
.getConfirmation()
|
||||||
|
.wasSuccessful())
|
||||||
|
{
|
||||||
|
logger.error("Could not run command",
|
||||||
|
command.getConfirmation()
|
||||||
|
.getError());
|
||||||
|
JOptionPane
|
||||||
|
.showMessageDialog(Interface.this,
|
||||||
|
command.getConfirmation()
|
||||||
|
.getError(),
|
||||||
|
command.getConfirmation()
|
||||||
|
.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);
|
||||||
|
}
|
||||||
|
}, () -> JOptionPane
|
||||||
|
.showMessageDialog(Interface.this, langs
|
||||||
|
.getString("error.browser.null"), langs
|
||||||
|
.getString("error.debug.error"), JOptionPane.ERROR_MESSAGE));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}.execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
action.putValue(Action.ACCELERATOR_KEY, KeyStroke
|
||||||
|
.getKeyStroke(KeyEvent.VK_F12, 0));
|
||||||
|
|
||||||
|
this.actions.put("about", action = new AbstractAction(langs
|
||||||
|
.getString("actions.about"))
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e)
|
public void actionPerformed(ActionEvent e)
|
||||||
@@ -345,7 +462,8 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.actions
|
this.actions
|
||||||
.put("view.all", action = new AbstractAction(langs.getString("actions.view.all"))
|
.put("view.all", action = new AbstractAction(langs
|
||||||
|
.getString("actions.view.all"))
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e)
|
public void actionPerformed(ActionEvent e)
|
||||||
@@ -521,7 +639,8 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL
|
|||||||
protected void constructWindow()
|
protected void constructWindow()
|
||||||
{
|
{
|
||||||
JMenuBar toolbar;
|
JMenuBar toolbar;
|
||||||
JMenu fileMenu, viewMenu, collectionsMenu, playbackMenu, helpMenu;
|
JMenu fileMenu, viewMenu, collectionsMenu, playbackMenu, helpMenu,
|
||||||
|
debugMenu;
|
||||||
|
|
||||||
this.setTitle(langs.getString("title"));
|
this.setTitle(langs.getString("title"));
|
||||||
this.getContentPane().setLayout(new BorderLayout());
|
this.getContentPane().setLayout(new BorderLayout());
|
||||||
@@ -569,6 +688,10 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL
|
|||||||
helpMenu.setMnemonic(KeyEvent.VK_H);
|
helpMenu.setMnemonic(KeyEvent.VK_H);
|
||||||
toolbar.add(helpMenu);
|
toolbar.add(helpMenu);
|
||||||
|
|
||||||
|
debugMenu = new JMenu(langs.getString("menu.debug.title"));
|
||||||
|
debugMenu.setMnemonic(KeyEvent.VK_D);
|
||||||
|
helpMenu.add(debugMenu);
|
||||||
|
|
||||||
fileMenu.add(new JMenuItem(actions.get("refresh")));
|
fileMenu.add(new JMenuItem(actions.get("refresh")));
|
||||||
|
|
||||||
fileMenu.add(actions.get("addExternal"));
|
fileMenu.add(actions.get("addExternal"));
|
||||||
@@ -590,6 +713,9 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL
|
|||||||
|
|
||||||
helpMenu.add(new JMenuItem(actions.get("logs")));
|
helpMenu.add(new JMenuItem(actions.get("logs")));
|
||||||
|
|
||||||
|
helpMenu.add(debugMenu);
|
||||||
|
debugMenu.add(new JMenuItem(actions.get("debug.error")));
|
||||||
|
|
||||||
helpMenu.add(new JMenuItem(actions.get("about")));
|
helpMenu.add(new JMenuItem(actions.get("about")));
|
||||||
|
|
||||||
this.setJMenuBar(toolbar);
|
this.setJMenuBar(toolbar);
|
||||||
@@ -606,15 +732,18 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL
|
|||||||
((SortingFocusTraversalPolicy) this.getFocusTraversalPolicy())
|
((SortingFocusTraversalPolicy) this.getFocusTraversalPolicy())
|
||||||
.setImplicitDownCycleTraversal(true);
|
.setImplicitDownCycleTraversal(true);
|
||||||
this.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, Set
|
this.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, Set
|
||||||
.of(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_DOWN, 0), AWTKeyStroke
|
.of(AWTKeyStroke
|
||||||
|
.getAWTKeyStroke(KeyEvent.VK_DOWN, 0), AWTKeyStroke
|
||||||
.getAWTKeyStroke(KeyEvent.VK_RIGHT, 0)));
|
.getAWTKeyStroke(KeyEvent.VK_RIGHT, 0)));
|
||||||
this.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, Set
|
this.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, Set
|
||||||
.of(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_UP, 0), AWTKeyStroke
|
.of(AWTKeyStroke
|
||||||
|
.getAWTKeyStroke(KeyEvent.VK_UP, 0), AWTKeyStroke
|
||||||
.getAWTKeyStroke(KeyEvent.VK_LEFT, 0)));
|
.getAWTKeyStroke(KeyEvent.VK_LEFT, 0)));
|
||||||
this.setFocusTraversalKeys(KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, Set
|
this.setFocusTraversalKeys(KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, Set
|
||||||
.of(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, 0)));
|
.of(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, 0)));
|
||||||
this.setFocusTraversalKeys(KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS, Set
|
this.setFocusTraversalKeys(KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS, Set
|
||||||
.of(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, KeyEvent.SHIFT_DOWN_MASK)));
|
.of(AWTKeyStroke
|
||||||
|
.getAWTKeyStroke(KeyEvent.VK_TAB, KeyEvent.SHIFT_DOWN_MASK)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -752,7 +881,8 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
int index = -1;
|
int index = -1;
|
||||||
Component[] children = ((Container) e.getComponent()).getComponents();
|
Component[] children = ((Container) e.getComponent())
|
||||||
|
.getComponents();
|
||||||
for (int i = 0, l = children.length; index == -1 && i < l; i++)
|
for (int i = 0, l = children.length; index == -1 && i < l; i++)
|
||||||
{
|
{
|
||||||
if (children[i] == e.getOppositeComponent())
|
if (children[i] == e.getOppositeComponent())
|
||||||
|
|||||||
@@ -8,31 +8,42 @@ import edu.regis.universeplayer.PlaybackInfo;
|
|||||||
import edu.regis.universeplayer.PlaybackListener;
|
import edu.regis.universeplayer.PlaybackListener;
|
||||||
import edu.regis.universeplayer.PlaybackStatus;
|
import edu.regis.universeplayer.PlaybackStatus;
|
||||||
import edu.regis.universeplayer.Player;
|
import edu.regis.universeplayer.Player;
|
||||||
|
import edu.regis.universeplayer.browserCommands.CommandConfirmation;
|
||||||
|
import edu.regis.universeplayer.browserCommands.CommandReturn;
|
||||||
|
import edu.regis.universeplayer.browserCommands.QueryFuture;
|
||||||
import edu.regis.universeplayer.data.PlaybackEvent;
|
import edu.regis.universeplayer.data.PlaybackEvent;
|
||||||
import edu.regis.universeplayer.data.Queue;
|
import edu.regis.universeplayer.data.Queue;
|
||||||
import edu.regis.universeplayer.data.Song;
|
import edu.regis.universeplayer.data.Song;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.FocusAdapter;
|
import java.awt.event.FocusAdapter;
|
||||||
import java.awt.event.FocusEvent;
|
import java.awt.event.FocusEvent;
|
||||||
import java.awt.event.MouseAdapter;
|
import java.awt.event.MouseAdapter;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.ForkJoinPool;
|
import java.util.concurrent.ForkJoinPool;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This panel contains the buttons necessary for controlling the playback of audio.
|
* This panel contains the buttons necessary for controlling the playback of
|
||||||
|
* audio.
|
||||||
*
|
*
|
||||||
* @author William Hubbard
|
* @author William Hubbard
|
||||||
* @version 0.1
|
* @version 0.1
|
||||||
*/
|
*/
|
||||||
public class PlayerControls extends JPanel implements Queue.SongChangeListener, PlaybackListener
|
public class PlayerControls extends JPanel implements Queue.SongChangeListener, PlaybackListener
|
||||||
{
|
{
|
||||||
private static final Logger logger = LoggerFactory.getLogger(PlayerControls.class);
|
private static final Logger logger = LoggerFactory
|
||||||
|
.getLogger(PlayerControls.class);
|
||||||
|
private static final ResourceBundle langs = ResourceBundle
|
||||||
|
.getBundle("lang.interface", Locale.getDefault());
|
||||||
private final ImageIcon PLAY_ICON, PAUSE_ICON;
|
private final ImageIcon PLAY_ICON, PAUSE_ICON;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -72,29 +83,39 @@ public class PlayerControls extends JPanel implements Queue.SongChangeListener,
|
|||||||
buttonCont = new JPanel(buttonLayout);
|
buttonCont = new JPanel(buttonLayout);
|
||||||
this.add(buttonCont);
|
this.add(buttonCont);
|
||||||
|
|
||||||
this.prevButton = new JButton(Interface.getInstance().actions.get("playback.skipPrev"));
|
this.prevButton = new JButton(Interface.getInstance().actions
|
||||||
|
.get("playback.skipPrev"));
|
||||||
this.prevButton.setText("");
|
this.prevButton.setText("");
|
||||||
icon = new ImageIcon(this.getClass()
|
icon = new ImageIcon(this.getClass()
|
||||||
.getResource("/gui/icons/skipPrev.png"), "Previous Button");
|
.getResource("/gui/icons/skipPrev.png"), "Previous Button");
|
||||||
icon.setImage(icon.getImage().getScaledInstance(ICON_SIZE.width, ICON_SIZE.height, 0));
|
icon.setImage(icon.getImage()
|
||||||
|
.getScaledInstance(ICON_SIZE.width, ICON_SIZE.height, 0));
|
||||||
this.prevButton.setIcon(icon);
|
this.prevButton.setIcon(icon);
|
||||||
this.prevButton.setPreferredSize(BUTTON_SIZE);
|
this.prevButton.setPreferredSize(BUTTON_SIZE);
|
||||||
buttonCont.add(this.prevButton);
|
buttonCont.add(this.prevButton);
|
||||||
|
|
||||||
this.playButton = new JButton(Interface.getInstance().actions.get("playback.toggle"));
|
this.playButton = new JButton(Interface.getInstance().actions
|
||||||
|
.get("playback.toggle"));
|
||||||
this.playButton.setText("");
|
this.playButton.setText("");
|
||||||
PAUSE_ICON = icon = new ImageIcon(this.getClass().getResource("/gui/icons/pause.png"), "Pause Button");
|
PAUSE_ICON = icon = new ImageIcon(this.getClass()
|
||||||
icon.setImage(icon.getImage().getScaledInstance(ICON_SIZE.width, ICON_SIZE.height, 0));
|
.getResource("/gui/icons/pause.png"), "Pause Button");
|
||||||
PLAY_ICON = icon = new ImageIcon(this.getClass().getResource("/gui/icons/play.png"), "Play Button");
|
icon.setImage(icon.getImage()
|
||||||
icon.setImage(icon.getImage().getScaledInstance(ICON_SIZE.width, ICON_SIZE.height, 0));
|
.getScaledInstance(ICON_SIZE.width, ICON_SIZE.height, 0));
|
||||||
|
PLAY_ICON = icon = new ImageIcon(this.getClass()
|
||||||
|
.getResource("/gui/icons/play.png"), "Play Button");
|
||||||
|
icon.setImage(icon.getImage()
|
||||||
|
.getScaledInstance(ICON_SIZE.width, ICON_SIZE.height, 0));
|
||||||
this.playButton.setIcon(icon);
|
this.playButton.setIcon(icon);
|
||||||
this.playButton.setPreferredSize(BUTTON_SIZE);
|
this.playButton.setPreferredSize(BUTTON_SIZE);
|
||||||
buttonCont.add(this.playButton);
|
buttonCont.add(this.playButton);
|
||||||
|
|
||||||
this.nextButton = new JButton(Interface.getInstance().actions.get("playback.skipNext"));
|
this.nextButton = new JButton(Interface.getInstance().actions
|
||||||
|
.get("playback.skipNext"));
|
||||||
this.nextButton.setText("");
|
this.nextButton.setText("");
|
||||||
icon = new ImageIcon(this.getClass().getResource("/gui/icons/skipNext.png"), "Next Button");
|
icon = new ImageIcon(this.getClass()
|
||||||
icon.setImage(icon.getImage().getScaledInstance(ICON_SIZE.width, ICON_SIZE.height, 0));
|
.getResource("/gui/icons/skipNext.png"), "Next Button");
|
||||||
|
icon.setImage(icon.getImage()
|
||||||
|
.getScaledInstance(ICON_SIZE.width, ICON_SIZE.height, 0));
|
||||||
this.nextButton.setIcon(icon);
|
this.nextButton.setIcon(icon);
|
||||||
this.nextButton.setPreferredSize(BUTTON_SIZE);
|
this.nextButton.setPreferredSize(BUTTON_SIZE);
|
||||||
buttonCont.add(this.nextButton);
|
buttonCont.add(this.nextButton);
|
||||||
@@ -109,7 +130,9 @@ public class PlayerControls extends JPanel implements Queue.SongChangeListener,
|
|||||||
@Override
|
@Override
|
||||||
public void mouseClicked(MouseEvent e)
|
public void mouseClicked(MouseEvent e)
|
||||||
{
|
{
|
||||||
seek((float) e.getX() / (float) e.getComponent().getWidth() * ((JProgressBar) e.getComponent()).getMaximum());
|
seek((float) e.getX() / (float) e.getComponent()
|
||||||
|
.getWidth() * ((JProgressBar) e
|
||||||
|
.getComponent()).getMaximum());
|
||||||
logger.debug("Changing time");
|
logger.debug("Changing time");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -126,7 +149,8 @@ public class PlayerControls extends JPanel implements Queue.SongChangeListener,
|
|||||||
public void focusGained(FocusEvent e)
|
public void focusGained(FocusEvent e)
|
||||||
{
|
{
|
||||||
int index = -1;
|
int index = -1;
|
||||||
Component[] children = ((Container) e.getComponent()).getComponents();
|
Component[] children = ((Container) e.getComponent())
|
||||||
|
.getComponents();
|
||||||
for (int i = 0, l = children.length; index == -1 && i < l; i++)
|
for (int i = 0, l = children.length; index == -1 && i < l; i++)
|
||||||
{
|
{
|
||||||
if (children[i] == e.getOppositeComponent())
|
if (children[i] == e.getOppositeComponent())
|
||||||
@@ -166,7 +190,26 @@ public class PlayerControls extends JPanel implements Queue.SongChangeListener,
|
|||||||
this.service.execute(() -> {
|
this.service.execute(() -> {
|
||||||
if (this.currentPlayer != null)
|
if (this.currentPlayer != null)
|
||||||
{
|
{
|
||||||
this.currentPlayer.seek(value);
|
QueryFuture<Void> command = this.currentPlayer.seek(value);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!command.getConfirmation().wasSuccessful())
|
||||||
|
{
|
||||||
|
JOptionPane.showMessageDialog(this,
|
||||||
|
command.getConfirmation().getError(),
|
||||||
|
command.getConfirmation().getMessage(),
|
||||||
|
JOptionPane.ERROR_MESSAGE);
|
||||||
|
logger.error("Could not run command",
|
||||||
|
command.getConfirmation().getError());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ExecutionException | InterruptedException e)
|
||||||
|
{
|
||||||
|
logger.error("Could not run command", e);
|
||||||
|
JOptionPane.showMessageDialog(this, e.getMessage(), langs
|
||||||
|
.getString(
|
||||||
|
"error.command"), JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.triggerCommandListeners(PlaybackCommand.SEEK, value);
|
this.triggerCommandListeners(PlaybackCommand.SEEK, value);
|
||||||
@@ -179,28 +222,49 @@ public class PlayerControls extends JPanel implements Queue.SongChangeListener,
|
|||||||
{
|
{
|
||||||
if (this.currentPlayer != null)
|
if (this.currentPlayer != null)
|
||||||
{
|
{
|
||||||
switch ((PlaybackStatus) this.currentPlayer.getStatus().get())
|
QueryFuture<PlaybackStatus> status =
|
||||||
|
this.currentPlayer.getStatus();
|
||||||
|
CommandConfirmation confirmation = status.getConfirmation();
|
||||||
|
if (status.getConfirmation().wasSuccessful())
|
||||||
{
|
{
|
||||||
case PAUSED -> this.currentPlayer.play();
|
switch (status.get())
|
||||||
|
{
|
||||||
|
case PAUSED -> confirmation = this.currentPlayer.play()
|
||||||
|
.getConfirmation();
|
||||||
case STOPPED, EMPTY -> {
|
case STOPPED, EMPTY -> {
|
||||||
if (Queue.getInstance().size() > 0)
|
if (Queue.getInstance().size() > 0)
|
||||||
{
|
{
|
||||||
if (Queue.getInstance().getCurrentSong() == null)
|
if (Queue.getInstance()
|
||||||
|
.getCurrentSong() == null)
|
||||||
{
|
{
|
||||||
Queue.getInstance().skipToSong(0);
|
Queue.getInstance().skipToSong(0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this.currentPlayer.play();
|
confirmation = this.currentPlayer.play()
|
||||||
|
.getConfirmation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (confirmation != null && !confirmation.wasSuccessful())
|
||||||
|
{
|
||||||
|
JOptionPane.showMessageDialog(this,
|
||||||
|
confirmation.getError(),
|
||||||
|
confirmation.getMessage(),
|
||||||
|
JOptionPane.ERROR_MESSAGE);
|
||||||
|
logger.error("Could not run command",
|
||||||
|
confirmation.getError());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (ExecutionException | InterruptedException e)
|
catch (ExecutionException | InterruptedException e)
|
||||||
{
|
{
|
||||||
logger.error("Could not get current playback status", e);
|
logger.error("Could not get current playback status", e);
|
||||||
|
JOptionPane.showMessageDialog(this, e.getMessage(), langs
|
||||||
|
.getString(
|
||||||
|
"error.command"), JOptionPane.ERROR_MESSAGE);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.triggerCommandListeners(PlaybackCommand.PLAY, null);
|
this.triggerCommandListeners(PlaybackCommand.PLAY, null);
|
||||||
@@ -213,15 +277,34 @@ public class PlayerControls extends JPanel implements Queue.SongChangeListener,
|
|||||||
{
|
{
|
||||||
if (this.currentPlayer != null)
|
if (this.currentPlayer != null)
|
||||||
{
|
{
|
||||||
switch ((PlaybackStatus) this.currentPlayer.getStatus().get())
|
QueryFuture<PlaybackStatus> status =
|
||||||
|
this.currentPlayer.getStatus();
|
||||||
|
CommandConfirmation confirmation = status.getConfirmation();
|
||||||
|
if (status.getConfirmation().wasSuccessful())
|
||||||
{
|
{
|
||||||
case PLAYING -> this.currentPlayer.pause();
|
switch (status.get())
|
||||||
|
{
|
||||||
|
case PLAYING -> confirmation =
|
||||||
|
this.currentPlayer.pause().getConfirmation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (confirmation != null && !confirmation.wasSuccessful())
|
||||||
|
{
|
||||||
|
JOptionPane.showMessageDialog(this,
|
||||||
|
confirmation.getError(),
|
||||||
|
confirmation.getMessage(),
|
||||||
|
JOptionPane.ERROR_MESSAGE);
|
||||||
|
logger.error("Could not run command",
|
||||||
|
confirmation.getError());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (ExecutionException | InterruptedException e)
|
catch (ExecutionException | InterruptedException e)
|
||||||
{
|
{
|
||||||
logger.error("Could not get current playback status", e);
|
logger.error("Could not get current playback status", e);
|
||||||
|
JOptionPane.showMessageDialog(this, e.getMessage(), langs
|
||||||
|
.getString(
|
||||||
|
"error.command"), JOptionPane.ERROR_MESSAGE);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.triggerCommandListeners(PlaybackCommand.PAUSE, null);
|
this.triggerCommandListeners(PlaybackCommand.PAUSE, null);
|
||||||
@@ -237,29 +320,51 @@ public class PlayerControls extends JPanel implements Queue.SongChangeListener,
|
|||||||
{
|
{
|
||||||
if (this.currentPlayer != null)
|
if (this.currentPlayer != null)
|
||||||
{
|
{
|
||||||
switch ((PlaybackStatus) this.currentPlayer.getStatus().get())
|
QueryFuture<PlaybackStatus> status =
|
||||||
|
this.currentPlayer.getStatus();
|
||||||
|
CommandConfirmation confirmation = status.getConfirmation();
|
||||||
|
if (status.getConfirmation().wasSuccessful())
|
||||||
{
|
{
|
||||||
case PAUSED -> this.currentPlayer.play();
|
switch (status.get())
|
||||||
case PLAYING -> this.currentPlayer.pause();
|
{
|
||||||
|
case PAUSED -> confirmation = this.currentPlayer.play()
|
||||||
|
.getConfirmation();
|
||||||
|
case PLAYING -> confirmation = this.currentPlayer.pause()
|
||||||
|
.getConfirmation();
|
||||||
case STOPPED, EMPTY -> {
|
case STOPPED, EMPTY -> {
|
||||||
if (Queue.getInstance().size() > 0)
|
if (Queue.getInstance().size() > 0)
|
||||||
{
|
{
|
||||||
if (Queue.getInstance().getCurrentSong() == null)
|
if (Queue.getInstance()
|
||||||
|
.getCurrentSong() == null)
|
||||||
{
|
{
|
||||||
Queue.getInstance().skipToSong(0);
|
Queue.getInstance().skipToSong(0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this.currentPlayer.play();
|
confirmation = this.currentPlayer.play()
|
||||||
|
.getConfirmation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (confirmation != null && !confirmation.wasSuccessful())
|
||||||
|
{
|
||||||
|
JOptionPane.showMessageDialog(this,
|
||||||
|
confirmation.getError(),
|
||||||
|
confirmation.getMessage(),
|
||||||
|
JOptionPane.ERROR_MESSAGE);
|
||||||
|
logger.error("Could not run command",
|
||||||
|
confirmation.getError());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (ExecutionException | InterruptedException e)
|
catch (ExecutionException | InterruptedException e)
|
||||||
{
|
{
|
||||||
logger.error("Could not get current playback status", e);
|
logger.error("Could not get current playback status", e);
|
||||||
|
JOptionPane.showMessageDialog(this, e.getMessage(), langs
|
||||||
|
.getString(
|
||||||
|
"error.command"), JOptionPane.ERROR_MESSAGE);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.triggerCommandListeners(PlaybackCommand.PLAY, null);
|
this.triggerCommandListeners(PlaybackCommand.PLAY, null);
|
||||||
@@ -349,14 +454,37 @@ public class PlayerControls extends JPanel implements Queue.SongChangeListener,
|
|||||||
{
|
{
|
||||||
if (this.currentPlayer != null)
|
if (this.currentPlayer != null)
|
||||||
{
|
{
|
||||||
this.currentPlayer.stopSong();
|
this.service.execute(() -> {
|
||||||
|
QueryFuture<Void> command = this.currentPlayer.stopSong();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!command.getConfirmation().wasSuccessful())
|
||||||
|
{
|
||||||
|
JOptionPane.showMessageDialog(this,
|
||||||
|
command.getConfirmation().getError(),
|
||||||
|
command.getConfirmation().getMessage(),
|
||||||
|
JOptionPane.ERROR_MESSAGE);
|
||||||
|
logger.error("Could not run command",
|
||||||
|
command.getConfirmation().getError());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ExecutionException | InterruptedException e)
|
||||||
|
{
|
||||||
|
logger.error("Could not get current playback status", e);
|
||||||
|
JOptionPane
|
||||||
|
.showMessageDialog(this, e.getMessage(), langs
|
||||||
|
.getString(
|
||||||
|
"error.command"), JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.currentSong = queue.getCurrentSong();
|
this.currentSong = queue.getCurrentSong();
|
||||||
this.playButton.setIcon(PLAY_ICON);
|
this.playButton.setIcon(PLAY_ICON);
|
||||||
if (this.currentSong != null)
|
if (this.currentSong != null)
|
||||||
{
|
{
|
||||||
this.currentPlayer = Player.REGISTERED_PLAYERS.get(this.currentSong.getClass());
|
this.currentPlayer = Player.REGISTERED_PLAYERS
|
||||||
|
.get(this.currentSong.getClass());
|
||||||
this.progress.setMaximum((int) (this.currentSong.duration / 1000));
|
this.progress.setMaximum((int) (this.currentSong.duration / 1000));
|
||||||
if (this.currentPlayer != null)
|
if (this.currentPlayer != null)
|
||||||
{
|
{
|
||||||
@@ -364,12 +492,37 @@ public class PlayerControls extends JPanel implements Queue.SongChangeListener,
|
|||||||
{
|
{
|
||||||
this.currentPlayer.addPlaybackListener(this);
|
this.currentPlayer.addPlaybackListener(this);
|
||||||
}
|
}
|
||||||
|
this.service.execute(() -> {
|
||||||
|
QueryFuture<Void> command =
|
||||||
this.currentPlayer.loadSong(this.currentSong);
|
this.currentPlayer.loadSong(this.currentSong);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!command.getConfirmation().wasSuccessful())
|
||||||
|
{
|
||||||
|
JOptionPane.showMessageDialog(this,
|
||||||
|
command.getConfirmation().getError(),
|
||||||
|
command.getConfirmation().getMessage(),
|
||||||
|
JOptionPane.ERROR_MESSAGE);
|
||||||
|
logger.error("Could not run command",
|
||||||
|
command.getConfirmation().getError());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ExecutionException | InterruptedException e)
|
||||||
|
{
|
||||||
|
logger.error("Could not get current playback status", e);
|
||||||
|
JOptionPane
|
||||||
|
.showMessageDialog(this, e.getMessage(), langs
|
||||||
|
.getString(
|
||||||
|
"error.command"), JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// this.currentPlayer.play();
|
// this.currentPlayer.play();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
logger.error("No logger found for song {}", this.currentSong.getClass());
|
logger.error("No logger found for song {}", this.currentSong
|
||||||
|
.getClass());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -382,7 +535,8 @@ public class PlayerControls extends JPanel implements Queue.SongChangeListener,
|
|||||||
@Override
|
@Override
|
||||||
public void onPlaybackChanged(PlaybackEvent status)
|
public void onPlaybackChanged(PlaybackEvent status)
|
||||||
{
|
{
|
||||||
if (status.getSource() != null && status.getSource() == this.currentPlayer)
|
if (status.getSource() != null && status
|
||||||
|
.getSource() == this.currentPlayer)
|
||||||
{
|
{
|
||||||
switch (status.getInfo().getStatus())
|
switch (status.getInfo().getStatus())
|
||||||
{
|
{
|
||||||
@@ -391,7 +545,8 @@ public class PlayerControls extends JPanel implements Queue.SongChangeListener,
|
|||||||
case PAUSED, STOPPED, EMPTY -> this.playButton.setIcon(PLAY_ICON);
|
case PAUSED, STOPPED, EMPTY -> this.playButton.setIcon(PLAY_ICON);
|
||||||
}
|
}
|
||||||
this.progress.setValue((int) status.getInfo().getPlayTime());
|
this.progress.setValue((int) status.getInfo().getPlayTime());
|
||||||
this.progress.setMaximum((int) (status.getInfo().getSong().duration / 1000));
|
this.progress.setMaximum((int) (status.getInfo()
|
||||||
|
.getSong().duration / 1000));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ menu.view.title=View
|
|||||||
menu.view.collections=Collections
|
menu.view.collections=Collections
|
||||||
menu.playback.title=Playback
|
menu.playback.title=Playback
|
||||||
menu.help.title=Help
|
menu.help.title=Help
|
||||||
|
menu.debug.title=Debugging
|
||||||
|
|
||||||
albumInfo.album=Album
|
albumInfo.album=Album
|
||||||
albumInfo.artists=Artists
|
albumInfo.artists=Artists
|
||||||
@@ -42,6 +43,7 @@ actions.refresh=Refresh Song Cache
|
|||||||
actions.exit=Exit
|
actions.exit=Exit
|
||||||
|
|
||||||
actions.logs=Show Logs
|
actions.logs=Show Logs
|
||||||
|
actions.debug.error=Throw Error
|
||||||
|
|
||||||
actions.about=About
|
actions.about=About
|
||||||
|
|
||||||
@@ -61,4 +63,7 @@ actions.playback.skipPrev=Skip Previously
|
|||||||
actions.playback.skipNext=Skip Next
|
actions.playback.skipNext=Skip Next
|
||||||
|
|
||||||
error.generic=Error!
|
error.generic=Error!
|
||||||
|
error.command=Could not run command
|
||||||
|
error.debug.error=Could not create error
|
||||||
error.browser.launch=Could not open browser background
|
error.browser.launch=Could not open browser background
|
||||||
|
error.browser.null=Could not find browser background
|
||||||
Reference in New Issue
Block a user