Established a connection between the Interface and the browser.
All we're doing right now is pinging, but it should be fairly simple to get an API working now that the browser and interface can talk.
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2021 William Hubbard. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package edu.regis.universeplayer.browserCommands;
|
||||
|
||||
/**
|
||||
* Browser commands are used to send orders to the browser, requesting
|
||||
* confirmation as to whether those commands were completed or not.
|
||||
*/
|
||||
public interface BrowserCommand extends BrowserQuery<Void>
|
||||
{
|
||||
@Override
|
||||
default Class<Void> getReturnType()
|
||||
{
|
||||
return Void.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) 2021 William Hubbard. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package edu.regis.universeplayer.browserCommands;
|
||||
|
||||
public class BrowserConstants
|
||||
{
|
||||
/**
|
||||
* The IP that the connection will be hosted on.
|
||||
*/
|
||||
public static final String IP = "127.0.0.1";
|
||||
/**
|
||||
* The port both processes use for connection.
|
||||
*/
|
||||
public static final int PORT = 3000;
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (c) 2021 William Hubbard. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package edu.regis.universeplayer.browserCommands;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* A browser error is a special Throwable that contains information about an
|
||||
* error that occurred within the browser. This is so that we can properly log
|
||||
* browser errors under standard Java logging.
|
||||
*
|
||||
* @author William Hubbard
|
||||
* @version 0.1
|
||||
*/
|
||||
public class BrowserError extends Throwable
|
||||
{
|
||||
private final String name;
|
||||
private final String message;
|
||||
|
||||
/**
|
||||
* Creats a browser error.
|
||||
*
|
||||
* @param name - The type of error thrown.
|
||||
* @param message - The message as reported by the browser.
|
||||
* @param stackTrace - The stack trace string provided by the browser.
|
||||
*/
|
||||
public BrowserError(String name, String message, String stackTrace)
|
||||
{
|
||||
super(name + ": " + message, null, false, true);
|
||||
this.name = name;
|
||||
this.message = message;
|
||||
this.setStackTrace(this.parseFirefoxTrace(stackTrace));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of error returned by the browser.
|
||||
*
|
||||
* @return - The browser error type.
|
||||
*/
|
||||
public String getType()
|
||||
{
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the original message from the browser.
|
||||
*
|
||||
* @return - The browser error message.
|
||||
*/
|
||||
public String getBrowserMessage()
|
||||
{
|
||||
return this.message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a stack trace string as per the specifications of Mozilla Firefox
|
||||
* version 30+.
|
||||
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/Stack.
|
||||
*
|
||||
* @param stackTrace - The stack trace string provided by the browser.
|
||||
* @return A stack trace that Java can parse.
|
||||
*/
|
||||
private StackTraceElement[] parseFirefoxTrace(String stackTrace)
|
||||
{
|
||||
StackTraceElement trace;
|
||||
String methodName;
|
||||
String file;
|
||||
String fileLoc;
|
||||
int line;
|
||||
// int column;
|
||||
|
||||
/*
|
||||
* Parses the Firefox trace into
|
||||
*/
|
||||
String[] scriptTrace = stackTrace.split("\n");
|
||||
StackTraceElement[] javaTrace = new StackTraceElement[scriptTrace.length];
|
||||
for (int i = 0, l = scriptTrace.length; i < l; i++)
|
||||
{
|
||||
methodName = scriptTrace[i].substring(0, scriptTrace[i].indexOf('@'));
|
||||
file = scriptTrace[i].substring(methodName.length() + 1, scriptTrace[i].indexOf(':'));
|
||||
// column = Integer.parseInt(scriptTrace[i].substring(scriptTrace[i].lastIndexOf(':')));
|
||||
/*
|
||||
* Windows paths often have colons in their file name, so we can't use the first index of one.
|
||||
*/
|
||||
fileLoc = scriptTrace[i].substring(0, scriptTrace[i].lastIndexOf(':'));
|
||||
line = Integer.parseInt(fileLoc.substring(fileLoc.lastIndexOf(':')));
|
||||
|
||||
trace = new StackTraceElement(null, null, null, "", methodName, file, line);
|
||||
javaTrace[i] = trace;
|
||||
}
|
||||
|
||||
return javaTrace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a stack trace string as per the specifications of IE 10+ (and used
|
||||
* by modern Chromium browsers).
|
||||
* https://web.archive.org/web/20140210004225/https://msdn.microsoft.com/en-us/library/windows/apps/hh699850.aspx
|
||||
*
|
||||
* @param stackTrace - The stack trace string to parse.
|
||||
* @return A stack trace that Java can parse.
|
||||
*/
|
||||
private StackTraceElement[] parseChromeTrace(String stackTrace)
|
||||
{
|
||||
StackTraceElement trace;
|
||||
String methodName;
|
||||
String fileLoc;
|
||||
int line;
|
||||
// int column;
|
||||
|
||||
/*
|
||||
* Parses the Chromium trace.
|
||||
*/
|
||||
String[] scriptTrace = stackTrace.split("\n");
|
||||
/*
|
||||
* The first line of the trace contains the error message itself. We do
|
||||
* not want this in the stack trace.
|
||||
*/
|
||||
StackTraceElement[] javaTrace = new StackTraceElement[scriptTrace.length - 1];
|
||||
|
||||
for (int i = 1, l = scriptTrace.length; i < l; i++)
|
||||
{
|
||||
// column = Integer.parseInt(scriptTrace[i].substring(scriptTrace[i].lastIndexOf(':')));
|
||||
fileLoc = scriptTrace[i].substring(0, scriptTrace[i].lastIndexOf(':'));
|
||||
line = Integer.parseInt(fileLoc.substring(fileLoc.lastIndexOf(':')));
|
||||
methodName = fileLoc.substring(fileLoc.indexOf("at") + 3, fileLoc.lastIndexOf(':'));
|
||||
|
||||
trace = new StackTraceElement(null, null, null, "", methodName, null, line);
|
||||
javaTrace[i - 1] = trace;
|
||||
}
|
||||
|
||||
return javaTrace;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2021 William Hubbard. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package edu.regis.universeplayer.browserCommands;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Objects of this type are used by the interface to request information from
|
||||
* the browser.
|
||||
*
|
||||
* @author William Hubbard
|
||||
* @version 0.1
|
||||
*/
|
||||
public interface BrowserQuery<T> extends Serializable
|
||||
{
|
||||
/**
|
||||
* Obtains the name of the command.
|
||||
* @return The command name.
|
||||
*/
|
||||
String getCommandName();
|
||||
|
||||
/**
|
||||
* Obtains the type of value this command returns.
|
||||
* @return The return type.
|
||||
*/
|
||||
Class<T> getReturnType();
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2021 William Hubbard. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package edu.regis.universeplayer.browserCommands;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* This class contains information as to the success of a command.
|
||||
*
|
||||
* @author William Hubbard
|
||||
* @version 0.1
|
||||
*/
|
||||
public class CommandConfirmation implements Serializable
|
||||
{
|
||||
/**
|
||||
* The error returned by the browser, or null if execution was successful.
|
||||
*/
|
||||
private BrowserError errorCode;
|
||||
private String message;
|
||||
|
||||
/**
|
||||
* Confirms a successful command.
|
||||
*/
|
||||
public CommandConfirmation()
|
||||
{
|
||||
this("Command successful");
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirms a successful command.
|
||||
*
|
||||
* @param message - Details on the nature of the command execution.
|
||||
*/
|
||||
public CommandConfirmation(String message)
|
||||
{
|
||||
this((BrowserError) null);
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirms an unsuccessful command.
|
||||
*
|
||||
* @param error - The error thrown, or null if the command was successful.
|
||||
*/
|
||||
public CommandConfirmation(BrowserError error)
|
||||
{
|
||||
this.errorCode = error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the command executed properly.
|
||||
*
|
||||
* @return True if the command was successful, false otherwise.
|
||||
*/
|
||||
public boolean wasSuccessful()
|
||||
{
|
||||
return this.errorCode == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the error returned by the browser.
|
||||
*
|
||||
* @return The error, or null if the command was successful.
|
||||
*/
|
||||
public BrowserError getError()
|
||||
{
|
||||
return this.errorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains details as to the nature of the command execution.
|
||||
*
|
||||
* @return The detailed message on the command.
|
||||
*/
|
||||
public String getMessage()
|
||||
{
|
||||
return this.errorCode != null ? this.errorCode.getMessage() : this.message;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2021 William Hubbard. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package edu.regis.universeplayer.browserCommands;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* This command is used to tell the browser to load a song URL, such as a
|
||||
* YouTube video.
|
||||
*
|
||||
* @author William Hubbard
|
||||
* @version 0.1
|
||||
*/
|
||||
public class CommandLoadSong implements BrowserCommand
|
||||
{
|
||||
/**
|
||||
* The song to load.
|
||||
*/
|
||||
private URL song;
|
||||
|
||||
/**
|
||||
* Used for serialization only. Do not use.
|
||||
*/
|
||||
public CommandLoadSong()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells the browser to load a song.
|
||||
*
|
||||
* @param song - The song to load.
|
||||
*/
|
||||
public CommandLoadSong(URL song)
|
||||
{
|
||||
this.song = song;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells the browser to load a song.
|
||||
*
|
||||
* @param song - The song to load.
|
||||
*/
|
||||
public CommandLoadSong(String song) throws MalformedURLException
|
||||
{
|
||||
this.song = new URL(song);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName()
|
||||
{
|
||||
return "loadSong";
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the song that is to be loaded.
|
||||
*
|
||||
* @return - The loaded song.
|
||||
*/
|
||||
public URL getSong()
|
||||
{
|
||||
return this.song;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2021 William Hubbard. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package edu.regis.universeplayer.browserCommands;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* This wrapper class serves to return a browser return value over serialization protocols.
|
||||
*
|
||||
* @param <T> The type of return value.
|
||||
* @author William Hubbard
|
||||
* @version 0.1
|
||||
*/
|
||||
public class CommandReturn<T> implements Serializable
|
||||
{
|
||||
private T returnValue;
|
||||
|
||||
private CommandConfirmation confirmation;
|
||||
|
||||
/**
|
||||
* For serialization only. Do not use.
|
||||
*/
|
||||
public CommandReturn()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new return object.
|
||||
*
|
||||
* @param value - The value to return.
|
||||
* @param confirmation - Information on the execution of the command.
|
||||
*/
|
||||
public CommandReturn(T value, CommandConfirmation confirmation)
|
||||
{
|
||||
this.returnValue = value;
|
||||
this.confirmation = confirmation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the value returned.
|
||||
*
|
||||
* @return The returned value. May be null.
|
||||
*/
|
||||
public T getReturnValue()
|
||||
{
|
||||
return this.returnValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains information about the execution of this command.
|
||||
*
|
||||
* @return The execution status.
|
||||
*/
|
||||
public CommandConfirmation getConfirmation()
|
||||
{
|
||||
return this.confirmation;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2021 William Hubbard. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package edu.regis.universeplayer.browserCommands;
|
||||
|
||||
/**
|
||||
* The seek command tells the browser to move playback to a certain location.
|
||||
*
|
||||
* @author William Hubbard
|
||||
* @version 0.1
|
||||
*/
|
||||
public class CommandSeek implements BrowserCommand
|
||||
{
|
||||
/**
|
||||
* The time to seek to.
|
||||
*/
|
||||
private float time;
|
||||
/**
|
||||
* Whether the {@link #time} parameter should be interpreted as relative to
|
||||
* the current position or absolute.
|
||||
*/
|
||||
private boolean relative;
|
||||
|
||||
/**
|
||||
* For serialization only. Do not use.
|
||||
*/
|
||||
public CommandSeek()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells the browser to seek to a certain absolute time in the song.
|
||||
*
|
||||
* @param time - The time to seek to.
|
||||
*/
|
||||
public CommandSeek(float time)
|
||||
{
|
||||
this.time = time;
|
||||
this.relative = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells the browser to seek to a certain time in the song.
|
||||
*
|
||||
* @param time - The time to seek to.
|
||||
* @param relative - Whether or not the time should be treated as relative
|
||||
* to the current play time or not.
|
||||
*/
|
||||
public CommandSeek(float time, boolean relative)
|
||||
{
|
||||
this.time = time;
|
||||
this.relative = relative;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName()
|
||||
{
|
||||
return "seek";
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the time to seek to.
|
||||
*
|
||||
* @return The new playback time.
|
||||
*/
|
||||
public float getSeekTime()
|
||||
{
|
||||
return this.time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see whether the command should be interpreted as local to the
|
||||
* current play time.
|
||||
*
|
||||
* @return Whether the seek time is local or not.
|
||||
*/
|
||||
public boolean isRelative()
|
||||
{
|
||||
return this.relative;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) 2021 William Hubbard. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package edu.regis.universeplayer.browserCommands;
|
||||
|
||||
/**
|
||||
* This command sets the playback status of the browser.
|
||||
*
|
||||
* @author William Hubbard
|
||||
* @version 0.1
|
||||
*/
|
||||
public class CommandSetPlayback implements BrowserCommand
|
||||
{
|
||||
/**
|
||||
* An enum for playback status.
|
||||
*/
|
||||
public enum Playback
|
||||
{
|
||||
PLAY, PAUSE
|
||||
}
|
||||
|
||||
/**
|
||||
* The playback status communicated by the interface.
|
||||
*/
|
||||
private Playback status;
|
||||
|
||||
/**
|
||||
* Creates a play command.
|
||||
* @return A new play command.
|
||||
*/
|
||||
public static CommandSetPlayback playCommand()
|
||||
{
|
||||
return new CommandSetPlayback(Playback.PLAY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a pause command.
|
||||
* @return A new pause command.
|
||||
*/
|
||||
public static CommandSetPlayback pauseCommand()
|
||||
{
|
||||
return new CommandSetPlayback(Playback.PAUSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for serialization only. Do not use.
|
||||
*/
|
||||
public CommandSetPlayback()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells the browser to chang the playback.
|
||||
*
|
||||
* @param status - Whether the browser should be playing or pausing.
|
||||
*/
|
||||
public CommandSetPlayback(Playback status)
|
||||
{
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName()
|
||||
{
|
||||
return "playback";
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the playback command.
|
||||
*
|
||||
* @return Whether the browser should be playing or not.
|
||||
*/
|
||||
public Playback getPlayback()
|
||||
{
|
||||
return this.status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this command sets the browser playing.
|
||||
*
|
||||
* @return Whether the browser should be playing or not.
|
||||
*/
|
||||
public boolean shouldPlay()
|
||||
{
|
||||
return this.status == Playback.PLAY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this command pauses
|
||||
*
|
||||
* @return Whether the browser should be playing or not.
|
||||
*/
|
||||
public boolean shouldPause()
|
||||
{
|
||||
return this.status == Playback.PAUSE;
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
@@ -22,7 +23,9 @@ import java.util.concurrent.Future;
|
||||
*/
|
||||
public class MessageHandler implements Runnable, MessageSerializer
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(MessageHandler.class);
|
||||
private final Logger logger;
|
||||
|
||||
private final String name;
|
||||
|
||||
private final InputStream input;
|
||||
private final OutputStream output;
|
||||
@@ -34,16 +37,25 @@ public class MessageHandler implements Runnable, MessageSerializer
|
||||
/**
|
||||
* Creates a message handler.
|
||||
*
|
||||
* @param name - The name of the handler. This is used in logging.
|
||||
* @param input - The input from our external source.
|
||||
* @param output - The output to the external source.
|
||||
*/
|
||||
public MessageHandler(InputStream input, OutputStream output)
|
||||
public MessageHandler(String name, InputStream input, OutputStream output)
|
||||
{
|
||||
this.name = name;
|
||||
this.logger = LoggerFactory.getLogger(name);
|
||||
this.input = input;
|
||||
this.output = output;
|
||||
this.executor = Executors.newCachedThreadPool();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Logger getLogger()
|
||||
{
|
||||
return logger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
@@ -84,6 +96,7 @@ public class MessageHandler implements Runnable, MessageSerializer
|
||||
messageResponse = this.triggerListeners(messageOb);
|
||||
synchronized (this.messageResponses)
|
||||
{
|
||||
numBuffer.clear();
|
||||
this.messageResponses.put(numBuffer.getInt(), messageResponse);
|
||||
}
|
||||
}
|
||||
@@ -108,7 +121,7 @@ public class MessageHandler implements Runnable, MessageSerializer
|
||||
if (responses.getValue().isDone())
|
||||
{
|
||||
toRemove.add(responses.getKey());
|
||||
messageByte = serializeObject(responses.getValue());
|
||||
messageByte = serializeObject(responses.getValue().get());
|
||||
writeMessage(browserOut, responses.getKey(), messageByte);
|
||||
}
|
||||
}
|
||||
@@ -123,6 +136,10 @@ public class MessageHandler implements Runnable, MessageSerializer
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
logger.error(this.getClass().getName() + " Error", e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
/*
|
||||
@@ -255,6 +272,6 @@ public class MessageHandler implements Runnable, MessageSerializer
|
||||
* have generated return values.
|
||||
* @return The value to be returned to the remote.
|
||||
*/
|
||||
Object onMessage(Object providedValue, Object previousReturn);
|
||||
Object onMessage(Object providedValue, Object previousReturn) throws IOException, ExecutionException, InterruptedException;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,8 +22,9 @@ import java.util.concurrent.TimeoutException;
|
||||
*/
|
||||
public abstract class MessageRunner implements Runnable, MessageSerializer
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(MessageRunner.class);
|
||||
private final Logger logger;
|
||||
|
||||
private final String name;
|
||||
private final InputStream input;
|
||||
private final OutputStream output;
|
||||
private final Object readLock = new Object();
|
||||
@@ -41,15 +42,24 @@ public abstract class MessageRunner implements Runnable, MessageSerializer
|
||||
/**
|
||||
* Creates a message runner.
|
||||
*
|
||||
* @param name - The name of the runner. This is used in logging.
|
||||
* @param input - The input from our external source.
|
||||
* @param output - The output to the external source.
|
||||
*/
|
||||
public MessageRunner(InputStream input, OutputStream output)
|
||||
public MessageRunner(String name, InputStream input, OutputStream output)
|
||||
{
|
||||
this.name = name;
|
||||
this.logger = LoggerFactory.getLogger(name);
|
||||
this.input = input;
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Logger getLogger()
|
||||
{
|
||||
return logger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
@@ -91,7 +101,7 @@ public abstract class MessageRunner implements Runnable, MessageSerializer
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
logger.error("Could not send message " + new String(packet.message, StandardCharsets.UTF_8), e);
|
||||
logger.error("Could not send message " + this.messagesSent + " " + new String(packet.message, StandardCharsets.UTF_8), e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,6 +155,10 @@ public abstract class MessageRunner implements Runnable, MessageSerializer
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
logger.error(this.getClass().getName() + " Error", e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
/*
|
||||
|
||||
@@ -5,14 +5,13 @@
|
||||
package edu.regis.universeplayer.browserCommands;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public interface MessageSerializer
|
||||
{
|
||||
Logger logger = LoggerFactory.getLogger(MessageSerializer.class);
|
||||
Logger getLogger();
|
||||
|
||||
/**
|
||||
* Converts an object into a form that can be sent.
|
||||
@@ -63,7 +62,7 @@ public interface MessageSerializer
|
||||
default void writeMessage(OutputStream out, int messageNum, byte[] message) throws IOException
|
||||
{
|
||||
ByteBuffer lengthBuffer = ByteBuffer.allocate(4);
|
||||
logger.debug("Writing message {} {}", messageNum, message);
|
||||
getLogger().trace("Writing message {} {}", messageNum, message);
|
||||
/*
|
||||
* Writes the message number.
|
||||
*/
|
||||
@@ -110,7 +109,7 @@ public interface MessageSerializer
|
||||
readLength = in.read(messageNum);
|
||||
if (readLength == 0)
|
||||
{
|
||||
logger.debug("Input stream closed, no more messages.");
|
||||
getLogger().debug("Input stream closed, no more messages.");
|
||||
return null;
|
||||
}
|
||||
/*
|
||||
@@ -120,7 +119,7 @@ public interface MessageSerializer
|
||||
readLength = in.read(lengthBuffer.array());
|
||||
if (readLength == 0)
|
||||
{
|
||||
logger.error("Malformed message, could not get message length.");
|
||||
getLogger().error("Malformed message, could not get message length.");
|
||||
return null;
|
||||
}
|
||||
message = new byte[lengthBuffer.getInt()];
|
||||
@@ -130,9 +129,9 @@ public interface MessageSerializer
|
||||
readLength = in.read(message);
|
||||
if (readLength < message.length)
|
||||
{
|
||||
logger.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);
|
||||
}
|
||||
logger.debug("Reading message");
|
||||
getLogger().trace("Reading message");
|
||||
return new byte[][] {messageNum, message};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2021 William Hubbard. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package edu.regis.universeplayer.browserCommands;
|
||||
|
||||
import java.util.concurrent.*;
|
||||
|
||||
/**
|
||||
* This future contains extra information regarding the success of a browser
|
||||
* command on the browser side.
|
||||
*
|
||||
* @param <V> The return type.
|
||||
*/
|
||||
public interface QueryFuture<V> extends Future<V>
|
||||
{
|
||||
/**
|
||||
* Waits if necessary for the computation to complete, and then checks to see whether execution was successful.
|
||||
*
|
||||
* @return A status code on whether the command was successful or not.
|
||||
* @throws CancellationException – if the computation was cancelled
|
||||
* @throws ExecutionException – if the computation threw an exception
|
||||
* @throws InterruptedException – if the current thread was interrupted while waiting
|
||||
*/
|
||||
CommandConfirmation getConfirmation() throws CancellationException, ExecutionException, InterruptedException;
|
||||
|
||||
/**
|
||||
* Waits if necessary for the computation to complete, and then checks to see whether execution was successful.
|
||||
*
|
||||
* @param timeout - How long to hang the thread.
|
||||
* @param unit - What units was specified in the timeout parameter.
|
||||
* @return A status code on whether the command was successful or not.
|
||||
* @throws TimeoutException – if the computation timed out
|
||||
* @throws ExecutionException – if the computation threw an exception
|
||||
* @throws InterruptedException – if the current thread was interrupted while waiting
|
||||
*/
|
||||
CommandConfirmation getConfirmation(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2021 William Hubbard. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package edu.regis.universeplayer.browserCommands;
|
||||
|
||||
/**
|
||||
* This query asks for the total length of the song.
|
||||
*
|
||||
* @author William Hubbard
|
||||
* @version 0.1
|
||||
*/
|
||||
public class QueryLength implements BrowserQuery<Float>
|
||||
{
|
||||
@Override
|
||||
public String getCommandName()
|
||||
{
|
||||
return "length";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Float> getReturnType()
|
||||
{
|
||||
return Float.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2021 William Hubbard. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package edu.regis.universeplayer.browserCommands;
|
||||
|
||||
/**
|
||||
* This query asks for confirmation as to whether the browser playback is paused
|
||||
* or not.
|
||||
*
|
||||
* @author William Hubbard
|
||||
* @version 0.1
|
||||
*/
|
||||
public class QueryPaused implements BrowserQuery<Boolean>
|
||||
{
|
||||
@Override
|
||||
public String getCommandName()
|
||||
{
|
||||
return "isPaused";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Boolean> getReturnType()
|
||||
{
|
||||
return Boolean.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2021 William Hubbard. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package edu.regis.universeplayer.browserCommands;
|
||||
|
||||
/**
|
||||
* This query asks for whether a song is currently playing or not. Note that
|
||||
* this is not the same as whether it is paused or not, as a song could have
|
||||
* run into a playback error.
|
||||
*
|
||||
* @author William Hubbard
|
||||
* @version 0.1
|
||||
*/
|
||||
public class QueryPlaying implements BrowserQuery<Boolean>
|
||||
{
|
||||
@Override
|
||||
public String getCommandName()
|
||||
{
|
||||
return "isPlaying";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Boolean> getReturnType()
|
||||
{
|
||||
return Boolean.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2021 William Hubbard. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package edu.regis.universeplayer.browserCommands;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* This query asks for the currently loaded song.
|
||||
*
|
||||
* @author William Hubbard
|
||||
* @version 0.1
|
||||
*/
|
||||
public class QuerySong implements BrowserQuery<URL>
|
||||
{
|
||||
@Override
|
||||
public String getCommandName()
|
||||
{
|
||||
return "getSong";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<URL> getReturnType()
|
||||
{
|
||||
return URL.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2021 William Hubbard. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package edu.regis.universeplayer.browserCommands;
|
||||
|
||||
/**
|
||||
* This query asks for the current playback time.
|
||||
*
|
||||
* @author William Hubbard
|
||||
* @version 0.1
|
||||
*/
|
||||
public class QueryTime implements BrowserQuery<Float>
|
||||
{
|
||||
@Override
|
||||
public String getCommandName()
|
||||
{
|
||||
return "currentTime";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Float> getReturnType()
|
||||
{
|
||||
return Float.class;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user