Adds the ability to play youtube videos.

It still needs a bit of work, but playing and pausing are operational.
This commit is contained in:
Markil3
2021-08-16 22:42:44 -06:00
parent b546c81fa1
commit ede9132279
23 changed files with 799 additions and 140 deletions

View File

@@ -0,0 +1,32 @@
/*
* Copyright (c) 2021 William Hubbard. All Rights Reserved.
*/
package edu.regis.universeplayer;
/**
* This contains possible states that a player can be in.
*/
public enum PlaybackStatus
{
/**
* The player is currently playing a song.
*/
PLAYING,
/**
* The player has been paused.
*/
PAUSED,
/**
* The player has a song loaded, but is not playing it.
*/
STOPPED,
/**
* The player has is stopped, but just finished a song and may have more.
*/
FINISHED,
/**
* No song is loaded.
*/
EMPTY
}

View File

@@ -4,14 +4,51 @@
package edu.regis.universeplayer.browserCommands;
import net.harawata.appdirs.AppDirsFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
public class BrowserConstants
{
private static final Logger logger = LoggerFactory.getLogger(BrowserConstants.class);
/**
* The IP that the connection will be hosted on.
*/
public static final String IP = "127.0.0.1";
public static final String IP = "localhost";
/**
* The port both processes use for connection.
*/
public static final int PORT = 3000;
private static File commDir;
/**
* Obtains the directory for memory mapped files
*
* @return The communications storage directory.
*/
public static File getCommDir()
{
if (commDir == null)
{
commDir = new File(AppDirsFactory.getInstance().getSharedDir("universalmusic", null, null), "comm");
if (!commDir.getParentFile().exists())
{
if (!commDir.getParentFile().mkdir())
{
logger.error("Could not create shared directory {}", commDir.getParent());
}
}
if (!commDir.exists())
{
if (!commDir.mkdir())
{
logger.error("Could not create data directory {}", commDir);
}
}
}
return commDir;
}
}

View File

@@ -0,0 +1,25 @@
/*
* Copyright (c) 2021 William Hubbard. All Rights Reserved.
*/
package edu.regis.universeplayer.browserCommands;
/**
* The quit command tells the browser to shut down.
*
* @author William Hubbard
* @version 0.1
*/
public class CommandQuit implements BrowserCommand
{
public CommandQuit()
{
}
@Override
public String getCommandName()
{
return "quit";
}
}

View File

@@ -19,20 +19,20 @@ import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
*
* Dispatches messages sent from a corresponding {@link MessageRunner}.
*/
public class MessageHandler implements Runnable, MessageSerializer
{
private final Logger logger;
private final String name;
public final String name;
private final InputStream input;
private final OutputStream output;
private final ExecutorService executor;
private final LinkedList<MessageListener> listeners = new LinkedList<>();
private final HashMap<Integer, Future<Object>> messageResponses = new HashMap<>();
protected final HashMap<Integer, Future<Object>> messageResponses = new HashMap<>();
/**
* Creates a message handler.
@@ -56,14 +56,22 @@ public class MessageHandler implements Runnable, MessageSerializer
return logger;
}
/**
* Called at the beginning of every loop to do extra processing and check to see if we can still run.
*
* @return True if we should close the runner, false otherwise.
*/
protected boolean onRun()
{
return false;
}
@Override
public void run()
{
BufferedInputStream browserIn = null;
BufferedOutputStream browserOut = null;
boolean running = true;
byte[][] message;
byte[] messageByte;
Object messageOb;
@@ -76,7 +84,7 @@ public class MessageHandler implements Runnable, MessageSerializer
browserIn = new BufferedInputStream(this.input);
browserOut = new BufferedOutputStream(this.output);
while (running)
while (!this.onRun())
{
try
{
@@ -86,7 +94,7 @@ public class MessageHandler implements Runnable, MessageSerializer
if (message == null)
{
logger.info("Connection closed.");
running = false;
break;
}
else
{

View File

@@ -24,25 +24,25 @@ public abstract class MessageRunner implements Runnable, MessageSerializer
{
private final Logger logger;
private final String name;
public final String name;
private final InputStream input;
private final OutputStream output;
private final Object readLock = new Object();
protected final Object readLock = new Object();
/**
* This queue serves as a cache for objects we need to send.
*/
private final LinkedList<MessagePacket> sendQueue = new LinkedList<>();
protected final LinkedList<MessagePacket> sendQueue = new LinkedList<>();
/**
* This queue serves as a cache for objects that are waiting for a response.
*/
private final HashMap<Integer, MessagePacket> sentQueue = new HashMap<>();
private int messagesSent = 0;
protected final HashMap<Integer, MessagePacket> sentQueue = new HashMap<>();
protected int messagesSent = 0;
/**
* Creates a message runner.
*
* @param name - The name of the runner. This is used in logging.
* @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.
*/
@@ -60,14 +60,22 @@ public abstract class MessageRunner implements Runnable, MessageSerializer
return logger;
}
/**
* Called at the beginning of every loop to do extra processing and check to see if we can still run.
*
* @return True if we should close the runner, false otherwise.
*/
protected boolean onRun()
{
return false;
}
@Override
public void run()
{
BufferedInputStream browserIn = null;
BufferedOutputStream browserOut = null;
MessagePacket packet;
boolean running = true;
byte[][] returnMessage;
ByteBuffer numBuffer = ByteBuffer.allocate(4);
@@ -77,7 +85,7 @@ public abstract class MessageRunner implements Runnable, MessageSerializer
browserIn = new BufferedInputStream(this.input);
browserOut = new BufferedOutputStream(this.output);
while (running)
while (!this.onRun())
{
/*
* Sends a messages
@@ -121,7 +129,7 @@ public abstract class MessageRunner implements Runnable, MessageSerializer
if (returnMessage == null)
{
logger.info("Connection closed.");
running = false;
break;
}
else
{
@@ -138,7 +146,7 @@ public abstract class MessageRunner implements Runnable, MessageSerializer
{
packet.returnMessage = returnMessage[1];
numBuffer.clear();
logger.debug("Reading message {} {}", numBuffer.getInt(), packet.returnMessage);
logger.debug("Reading message {} {}", numBuffer.getInt(), new String(packet.returnMessage, StandardCharsets.UTF_8));
synchronized (this.readLock)
{
logger.trace("Received message {}, notifying futures.", packet.returnValue.index);
@@ -254,9 +262,9 @@ public abstract class MessageRunner implements Runnable, MessageSerializer
*/
public class MessageFuture implements Future<Object>
{
private final MessagePacket packetEntry;
private int index;
private boolean canceled = false;
protected final MessagePacket packetEntry;
public int index;
protected boolean canceled = false;
private MessageFuture(MessagePacket packet)
{

View File

@@ -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 QueryStatus implements BrowserQuery<Integer>
{
@Override
public String getCommandName()
{
return "getStatus";
}
@Override
public Class<Integer> getReturnType()
{
return Integer.class;
}
}