You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
626 lines
20 KiB
626 lines
20 KiB
package com.jotuntech.sketcher.client;
|
|
|
|
import java.io.File;
|
|
import java.io.FileInputStream;
|
|
import java.io.FileOutputStream;
|
|
import java.io.IOException;
|
|
import java.net.InetSocketAddress;
|
|
import java.nio.ByteBuffer;
|
|
import java.nio.channels.SocketChannel;
|
|
import java.util.Properties;
|
|
import java.util.Timer;
|
|
import java.util.TimerTask;
|
|
import java.util.concurrent.ArrayBlockingQueue;
|
|
import java.util.concurrent.BlockingQueue;
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
import javax.swing.event.ChangeEvent;
|
|
import javax.swing.event.ChangeListener;
|
|
|
|
import com.jotuntech.sketcher.client.command.PingCommand;
|
|
import com.jotuntech.sketcher.client.command.SignInCommand;
|
|
import com.jotuntech.sketcher.client.command.SignOutCommand;
|
|
import com.jotuntech.sketcher.client.voice.VoiceClient;
|
|
import com.jotuntech.sketcher.client.voice.VoiceEvent;
|
|
import com.jotuntech.sketcher.client.voice.VoiceListener;
|
|
import com.jotuntech.sketcher.common.Brush;
|
|
import com.jotuntech.sketcher.common.Canvas;
|
|
import com.jotuntech.sketcher.common.Layer;
|
|
import com.jotuntech.sketcher.common.Log;
|
|
import com.jotuntech.sketcher.common.StreamableUtils;
|
|
import com.jotuntech.sketcher.common.TwoWayHashMap;
|
|
import com.jotuntech.sketcher.common.User;
|
|
|
|
/**
|
|
* @author Thor Harald Johansen
|
|
*
|
|
*/
|
|
|
|
public class Client extends Thread {
|
|
private UserInterface userInterface;
|
|
private TwoWayHashMap<Integer, User> userMap;
|
|
private User[] userArray;
|
|
private Canvas canvas;
|
|
private long lastLayerClean;
|
|
private Connection connection;
|
|
private BlockingQueue<CommandEntry> commandQueue;
|
|
private ByteBuffer commandBuffer;
|
|
private String login;
|
|
private String password;
|
|
private String hostname;
|
|
private int port;
|
|
private VoiceClient voiceClient;
|
|
private boolean soundEnabled;
|
|
private boolean ads;
|
|
|
|
//private Random sendRandom = new Random(0x707733360A596E0AL);
|
|
//private Random recvRandom = new Random(0x59A70A401C8CD1EAL);
|
|
|
|
private Properties props;
|
|
private File propsFile;
|
|
Timer propsTimer = new Timer("PropsTimer", true);
|
|
|
|
private Brush defaultBrushes[] = new Brush[] {
|
|
new Brush("Pen", 255, 255, 3.375f, 1, 0.27f, true, false, true, 0, 0, 0, false, 0.5f),
|
|
new Brush("Pencil", 255, 255, 2f, 2, 0.45f, true, false, true, 1.5f, 0, 0, false, 0.5f),
|
|
new Brush("Water", 255, 255, 16f, 4, 0.22f, true, false, true, 0, 0, 128, false, 0.5f),
|
|
new Brush("Eraser", -255, 192, 16f, 4, 0.2f, false, true, false, 0, 0, 0, false, 0.5f),
|
|
new Brush("Ink", 255, 255, 4f, 1, 0.04f, false, false, true, 0, 0, 0, false, 0.5f),
|
|
new Brush("Wipe", -255, 255, 64f, 7, 0.2f, false, false, false, 0, 0, 0, false, 0.5f)
|
|
};
|
|
|
|
protected Brush[] brushes = new Brush[defaultBrushes.length];
|
|
|
|
public Client(String hostname, int port, String login, String password, boolean ads) {
|
|
super("ClientThread");
|
|
|
|
/** Save hostname and port */
|
|
this.hostname = hostname;
|
|
this.port = port;
|
|
|
|
/** Save login and password */
|
|
this.login = login;
|
|
this.password = password;
|
|
|
|
/** Save ad setting */
|
|
this.ads = ads;
|
|
|
|
/** Create user map & array */
|
|
userMap = new TwoWayHashMap<Integer, User>();
|
|
userMap.addChangeListener(new ChangeListener() {
|
|
public void stateChanged(ChangeEvent arg0) {
|
|
/** Populate user array in a thread-safe way */
|
|
User[] newUserArray = new User[0];
|
|
newUserArray = userMap.values().toArray(newUserArray);
|
|
userArray = newUserArray;
|
|
}
|
|
});
|
|
|
|
/** Create user array */
|
|
userArray = new User[0];
|
|
|
|
/** Create command queue */
|
|
commandQueue = new ArrayBlockingQueue<CommandEntry>(65536, true);
|
|
|
|
for(int i = 0; i < brushes.length; i++) {
|
|
brushes[i] = defaultBrushes[i].copy();
|
|
}
|
|
|
|
/** Create user interface */
|
|
userInterface = new UserInterface(this);
|
|
|
|
/** Load properties file */
|
|
try {
|
|
propsFile = new File(System.getProperty("user.home"), "sketcher.properties");
|
|
} catch(SecurityException e) {
|
|
propsFile = null;
|
|
}
|
|
|
|
loadProps();
|
|
|
|
/** Set last layer cleanup time */
|
|
lastLayerClean = System.currentTimeMillis();
|
|
|
|
propsTimer.schedule(new TimerTask() {
|
|
public void run() {
|
|
saveProps();
|
|
}
|
|
}, 60000, 60000);
|
|
}
|
|
|
|
synchronized public void resetProps() {
|
|
if(propsFile != null) {
|
|
propsFile.delete();
|
|
}
|
|
loadProps();
|
|
}
|
|
|
|
synchronized private void loadProps() {
|
|
props = new Properties();
|
|
|
|
if(propsFile != null) {
|
|
try {
|
|
if(propsFile.exists()) {
|
|
FileInputStream is = new FileInputStream(propsFile);
|
|
props.load(is);
|
|
is.close();
|
|
}
|
|
} catch(IOException e) {
|
|
|
|
} catch(SecurityException e) {
|
|
|
|
}
|
|
}
|
|
|
|
int propsVersion = Integer.valueOf(props.getProperty("file.version", "0"));
|
|
|
|
soundEnabled = "true".equals(props.getProperty("sound.enabled", "true"));
|
|
userInterface.getSoundItem().setSelected(soundEnabled);
|
|
|
|
userInterface.setSmoothZoom("true".equals(props.getProperty("zoom.smooth", "true")));
|
|
|
|
userInterface.getEditor().setTagsEnabled("true".equals(props.getProperty("tags.enabled", "true")));
|
|
userInterface.getEditor().setSoftwareCursorEnabled("true".equals(props.getProperty("cursor.software", "false")));
|
|
|
|
userInterface.getTagsItem().setSelected(userInterface.getEditor().isTagsEnabled());
|
|
|
|
for(JCollapsiblePanel panel : userInterface.getToolPanels()) {
|
|
panel.setExpanded("true".equals(props.getProperty("panel" + panel.getId() + ".expanded", panel.isExpandedByDefault() ? "true" : "false")), false);
|
|
panel.setStuck("true".equals(props.getProperty("panel" + panel.getId() + ".stuck", panel.isStuckByDefault() ? "true" : "false")));
|
|
}
|
|
|
|
for(int i = 0; i < brushes.length; i++) {
|
|
brushes[i] = defaultBrushes[i].copy();
|
|
}
|
|
|
|
for(int i = 0; i < defaultBrushes.length; i++) {
|
|
String name = props.getProperty("brush" + i + ".name");
|
|
String opacity = props.getProperty("brush" + i + ".opacity");
|
|
String flow = props.getProperty("brush" + i + ".flow");
|
|
String radius = props.getProperty("brush" + i + ".radius");
|
|
String hardness = props.getProperty("brush" + i + ".hardness");
|
|
String spacing = props.getProperty("brush" + i + ".spacing");
|
|
String pressureToFlow, pressureToOpacity;
|
|
if(propsVersion < 1) {
|
|
pressureToFlow = props.getProperty("brush" + i + ".pressureToOpacity");
|
|
pressureToOpacity = props.getProperty("brush" + i + ".realPressureToOpacity");
|
|
} else {
|
|
pressureToFlow = props.getProperty("brush" + i + ".pressureToFlow");
|
|
pressureToOpacity = props.getProperty("brush" + i + ".pressureToOpacity");
|
|
}
|
|
String pressureToRadius = props.getProperty("brush" + i + ".pressureToRadius");
|
|
String jitter = props.getProperty("brush" + i + ".jitter");
|
|
String water = props.getProperty("brush" + i + ".water");
|
|
String waterArea = props.getProperty("brush" + i + ".waterArea");
|
|
String lockTransparency = props.getProperty("brush" + i + ".lockTransparency");
|
|
|
|
Brush b = brushes[i];
|
|
if(name != null) {
|
|
b.setName(name);
|
|
}
|
|
if(opacity != null) {
|
|
b.setOpacity(Integer.valueOf(opacity));
|
|
}
|
|
if(flow != null) {
|
|
b.setFlow(Integer.valueOf(flow));
|
|
}
|
|
if(radius != null) {
|
|
b.setRadius(Float.valueOf(radius));
|
|
}
|
|
if(hardness != null) {
|
|
b.setHardness(Integer.valueOf(hardness));
|
|
}
|
|
if(spacing != null) {
|
|
b.setSpacing(Float.valueOf(spacing));
|
|
}
|
|
if(pressureToOpacity != null) {
|
|
b.setPressureToOpacity("true".equals(pressureToOpacity));
|
|
}
|
|
if(pressureToFlow != null) {
|
|
b.setPressureToFlow("true".equals(pressureToFlow));
|
|
}
|
|
if(pressureToRadius != null) {
|
|
b.setPressureToRadius("true".equals(pressureToRadius));
|
|
}
|
|
if(jitter != null) {
|
|
b.setJitter(Float.valueOf(jitter));
|
|
}
|
|
if(water != null) {
|
|
b.setWater(Integer.valueOf(water));
|
|
}
|
|
if(waterArea != null) {
|
|
b.setWaterArea(Float.valueOf(waterArea));
|
|
}
|
|
if(lockTransparency != null) {
|
|
b.setLockTransparency("true".equals(lockTransparency));
|
|
}
|
|
}
|
|
}
|
|
|
|
synchronized private void saveProps() {
|
|
if(propsFile == null) {
|
|
return;
|
|
}
|
|
|
|
props.setProperty("file.version", "1"); // Increase this when making format changes!
|
|
|
|
props.setProperty("sound.enabled", soundEnabled ? "true" : "false");
|
|
|
|
props.setProperty("zoom.smooth", userInterface.isSmoothZoom() ? "true" : "false");
|
|
|
|
props.setProperty("tags.enabled", userInterface.getEditor().isTagsEnabled() ? "true" : "false");
|
|
props.setProperty("cursor.software", userInterface.getEditor().isSoftwareCursorEnabled() ? "true" : "false");
|
|
|
|
for(JCollapsiblePanel panel : userInterface.getToolPanels()) {
|
|
props.setProperty("panel" + panel.getId() + ".expanded", panel.isExpanded() ? "true" : "false");
|
|
props.setProperty("panel" + panel.getId() + ".stuck", panel.isStuck() ? "true" : "false");
|
|
}
|
|
|
|
for(int i = 0; i < brushes.length; i++) {
|
|
props.setProperty("brush" + i + ".name", brushes[i].getName());
|
|
props.setProperty("brush" + i + ".opacity", String.valueOf(brushes[i].getOpacity()));
|
|
props.setProperty("brush" + i + ".flow", String.valueOf(brushes[i].getFlow()));
|
|
props.setProperty("brush" + i + ".radius", String.valueOf(brushes[i].getRadius()));
|
|
props.setProperty("brush" + i + ".hardness", String.valueOf(brushes[i].getHardness()));
|
|
props.setProperty("brush" + i + ".spacing", String.valueOf(brushes[i].getSpacing()));
|
|
props.setProperty("brush" + i + ".pressureToOpacity", brushes[i].isPressureToOpacity() ? "true" : "false");
|
|
props.setProperty("brush" + i + ".pressureToFlow", brushes[i].isPressureToFlow() ? "true" : "false");
|
|
props.setProperty("brush" + i + ".pressureToRadius", brushes[i].isPressureToRadius() ? "true" : "false");
|
|
props.setProperty("brush" + i + ".jitter", String.valueOf(brushes[i].getJitter()));
|
|
props.setProperty("brush" + i + ".noise", String.valueOf(brushes[i].getNoise()));
|
|
props.setProperty("brush" + i + ".water", String.valueOf(brushes[i].getWater()));
|
|
props.setProperty("brush" + i + ".waterArea", String.valueOf(brushes[i].getWaterArea()));
|
|
props.setProperty("brush" + i + ".lockTransparency", brushes[i].isLockTransparency() ? "true" : "false");
|
|
}
|
|
|
|
try {
|
|
FileOutputStream os = new FileOutputStream(propsFile);
|
|
props.store(os, "Sketcher Properties File");
|
|
os.close();
|
|
} catch(IOException e) {
|
|
|
|
} catch(SecurityException e) {
|
|
propsTimer.cancel();
|
|
}
|
|
}
|
|
|
|
public void close(String message) {
|
|
propsTimer.cancel();
|
|
saveProps();
|
|
|
|
/** Empty the send queue */
|
|
connection.getSendQueue().clear();
|
|
|
|
/** Send sign-out command */
|
|
connection.getSendQueue().offer(new CommandEntry(0, new SignOutCommand(message)));
|
|
|
|
/** Schedule connection death */
|
|
connection.setTimeOfDeath(System.currentTimeMillis() + 1000);
|
|
|
|
/** Play sound */
|
|
if("true".equals(props.getProperty("sound.enabled", "true"))) {
|
|
UserInterface.AUDIO_OUTTRO.play();
|
|
}
|
|
}
|
|
|
|
public TwoWayHashMap<Integer, User> getUserMap() {
|
|
return userMap;
|
|
}
|
|
|
|
public User[] getUserArray() {
|
|
return userArray;
|
|
}
|
|
|
|
public Canvas getCanvas() {
|
|
return canvas;
|
|
}
|
|
|
|
public void setCanvas(Canvas canvas) {
|
|
this.canvas = canvas;
|
|
userInterface.setCanvas(canvas);
|
|
}
|
|
|
|
public UserInterface getUserInterface() {
|
|
return userInterface;
|
|
}
|
|
|
|
public Connection getConnection() {
|
|
return connection;
|
|
}
|
|
|
|
public void run() {
|
|
try {
|
|
/** Create client connection */
|
|
connection = new Connection(SocketChannel.open());
|
|
|
|
userInterface.println("Connecting... ");
|
|
|
|
/** Enable blocking for connect */
|
|
connection.getChannel().configureBlocking(true);
|
|
|
|
/** Attempt to connect to server */
|
|
connection.getChannel().connect(new InetSocketAddress(hostname, port));
|
|
|
|
/** Disable blocking after connect */
|
|
connection.getChannel().configureBlocking(false);
|
|
|
|
userInterface.print("Success!");
|
|
|
|
/** Play audio */
|
|
if("true".equals(props.getProperty("sound.enabled", "true"))) {
|
|
UserInterface.AUDIO_INTRO.play();
|
|
}
|
|
|
|
/** Create command buffer */
|
|
commandBuffer = ByteBuffer.allocate(65538);
|
|
|
|
/** Send sign-in command */
|
|
connection.getSendQueue().offer(new CommandEntry(0, new SignInCommand(0, login, password, false)));
|
|
|
|
/** Set last ping time */
|
|
connection.setLastPing(0);
|
|
|
|
while(!Thread.interrupted()) {
|
|
if(!connection.getChannel().isConnected()) {
|
|
userInterface.println("Disconnected (Connection was closed)");
|
|
break;
|
|
} else if(connection.isTimeOfDeath()) {
|
|
try { connection.getChannel().close(); } catch(IOException e) { }
|
|
userInterface.println("Disconnected (Exit)");
|
|
break;
|
|
}
|
|
|
|
if(System.currentTimeMillis() - connection.getLastPing() >= Connection.PING_INTERVAL) {
|
|
long timestamp = System.currentTimeMillis();
|
|
connection.getSendQueue().offer(new CommandEntry(0, new PingCommand(timestamp)));
|
|
connection.setLastPing(timestamp);
|
|
}
|
|
|
|
for(CommandEntry e = commandQueue.poll(20, TimeUnit.MILLISECONDS); e != null; e = commandQueue.poll(20, TimeUnit.MILLISECONDS)) {
|
|
if(e.getCommand().perform(this, e.getSourceKey() == 0 ? connection.getUser() : userMap.get(e.getSourceKey())) == Connection.SEND_OTHERS) {
|
|
connection.getSendQueue().offer(new CommandEntry(e.getSourceKey(), e.getCommand()));
|
|
}
|
|
}
|
|
|
|
if(canvas != null && lastLayerClean + 30000 < System.currentTimeMillis()) {
|
|
lastLayerClean = System.currentTimeMillis();
|
|
for(Layer e : canvas.getLayerMap().values()) {
|
|
e.clean();
|
|
}
|
|
}
|
|
|
|
ByteBuffer inputBuffer = connection.getInputBuffer();
|
|
ByteBuffer outputBuffer = connection.getOutputBuffer();
|
|
|
|
ArrayBlockingQueue<CommandEntry> sendQueue = connection.getSendQueue();
|
|
|
|
//int startPosition = outputBuffer.position();
|
|
|
|
/** Only check queue if room for command length, peer key, name length, and one character of name */
|
|
while(outputBuffer.remaining() > 2 + 4 + 1 + 2 && sendQueue.size() > 0) {
|
|
CommandEntry e = sendQueue.peek();
|
|
Integer k = e.getSourceKey();
|
|
Command c = e.getCommand();
|
|
|
|
/** Clear command buffer */
|
|
commandBuffer.clear();
|
|
|
|
/** Write peer key */
|
|
commandBuffer.putInt(k);
|
|
|
|
/** Write command name */
|
|
String commandName = c.getClass().getSimpleName();
|
|
commandBuffer.put((byte) (commandName.length() - 1));
|
|
for(int i = 0; i < commandName.length(); i++) {
|
|
commandBuffer.putChar(commandName.charAt(i));
|
|
}
|
|
|
|
/** Write command */
|
|
c.encode(commandBuffer);
|
|
|
|
/** Flip command buffer before reading */
|
|
commandBuffer.flip();
|
|
|
|
/** Do not send this command yet if no room in output buffer */
|
|
if(commandBuffer.remaining() + 2 > outputBuffer.remaining()) {
|
|
break;
|
|
}
|
|
|
|
/** Write append command length and command data to output buffer */
|
|
outputBuffer.putShort((short) (commandBuffer.remaining() - 1));
|
|
outputBuffer.put(commandBuffer);
|
|
|
|
/** Remove command from queue */
|
|
sendQueue.remove();
|
|
}
|
|
|
|
// Primitive encryption
|
|
//for(int i = startPosition; i < outputBuffer.position(); i++) {
|
|
// outputBuffer.put(i, (byte) (outputBuffer.get(i) ^ sendRandom.nextInt(256)));
|
|
//}
|
|
|
|
/** Flip output buffer */
|
|
outputBuffer.flip();
|
|
|
|
if(outputBuffer.remaining() > 0) {
|
|
connection.getChannel().write(outputBuffer);
|
|
}
|
|
|
|
/** Compact buffer, preparing it for appending */
|
|
outputBuffer.compact();
|
|
|
|
if(canvas == null || !canvas.isDrawing()) {
|
|
try {
|
|
/** Append to input buffer */
|
|
//startPosition = inputBuffer.position();
|
|
int readResult = connection.getChannel().read(inputBuffer);
|
|
if(readResult == -1) {
|
|
try { connection.getChannel().close(); } catch(IOException e) { }
|
|
userInterface.println("Disconnected (Connection was closed)");
|
|
break;
|
|
} else if(readResult > 0) {
|
|
//for(int i = startPosition; i < inputBuffer.position(); i++) {
|
|
// inputBuffer.put(i, (byte) (inputBuffer.get(i) ^ recvRandom.nextInt(256)));
|
|
//}
|
|
|
|
/** Prepare buffer for reading */
|
|
inputBuffer.flip();
|
|
|
|
/** Long enough to peek at length? */
|
|
while((canvas == null || !canvas.isDrawing()) && inputBuffer.remaining() >= 2) {
|
|
/** Peek at length */
|
|
int commandLength = (inputBuffer.getShort(inputBuffer.position()) & 0xFFFF) + 1;
|
|
|
|
/** Don't read if not long enough to read entire command. */
|
|
if(inputBuffer.remaining() < commandLength + 2) {
|
|
break;
|
|
}
|
|
|
|
/** We already have the command length */
|
|
inputBuffer.getShort();
|
|
|
|
/** Read command buffer */
|
|
ByteBuffer commandBuffer = inputBuffer.slice();
|
|
commandBuffer.limit(commandLength);
|
|
inputBuffer.position(inputBuffer.position() + commandLength);
|
|
|
|
/** Read user key */
|
|
Integer userKey = commandBuffer.getInt();
|
|
|
|
/** Read command name */
|
|
int commandNameLength = (commandBuffer.get() & 0xFF) + 1;
|
|
StringBuffer commandNameBuffer = new StringBuffer();
|
|
for(int i = 0; i < commandNameLength; i++) {
|
|
commandNameBuffer.append(commandBuffer.getChar());
|
|
}
|
|
String commandName = commandNameBuffer.toString();
|
|
|
|
Command command = (Command) StreamableUtils.create("com.jotuntech.sketcher.client.command." + commandName, commandBuffer);
|
|
command.perform(this, userMap.get(userKey));
|
|
|
|
//++iterations;
|
|
}
|
|
|
|
/** Prepare input buffer for appending */
|
|
inputBuffer.compact();
|
|
}
|
|
} catch (IOException e) {
|
|
try { connection.getChannel().close(); } catch(IOException e2) { }
|
|
userInterface.println("Disconnected (Connection was broken: " + e.getMessage() + ")");
|
|
break;
|
|
} catch(Throwable t) {
|
|
sendQueue.clear();
|
|
sendQueue.offer(new CommandEntry(0, new SignOutCommand("Client crashed: " + t.getClass().getSimpleName())));
|
|
connection.setTimeOfDeath(System.currentTimeMillis() + 5000);
|
|
Log.error(t);
|
|
userInterface.println("Disconnected (Client crashed: " + t.getClass().getSimpleName() + ")");
|
|
}
|
|
}
|
|
}
|
|
} catch (InterruptedException e) {
|
|
Log.debug("Client interrupted.");
|
|
} catch (IOException e) {
|
|
userInterface.println("Disconnected (Connection was broken: " + e.getMessage() + ")");
|
|
Log.error(e);
|
|
}
|
|
|
|
try { connection.getChannel().close(); } catch(IOException e) { }
|
|
connection.setChannel(null);
|
|
connection.setUser(null);
|
|
|
|
if("true".equals(props.getProperty("sound.enabled", "true"))) {
|
|
UserInterface.AUDIO_OUTTRO.play();
|
|
}
|
|
}
|
|
|
|
public BlockingQueue<CommandEntry> getCommandQueue() {
|
|
return commandQueue;
|
|
}
|
|
|
|
public boolean isVoiceEnabled() {
|
|
return voiceClient != null;
|
|
}
|
|
|
|
public void setVoiceEnabled(boolean voiceEnabled) {
|
|
if(voiceEnabled) {
|
|
final Integer peerKey = getUserMap().getKeyForValue(getConnection().getUser());
|
|
voiceClient = new VoiceClient(new InetSocketAddress(hostname, port + 100), peerKey);
|
|
voiceClient.setListener(new VoiceListener() {
|
|
public void voiceEvent(VoiceEvent e) {
|
|
switch(e.getType()) {
|
|
case VoiceEvent.TYPE_CHANNEL_NEW:
|
|
Integer userKey = e.getChannel();
|
|
User user = userMap.get(userKey);
|
|
if(user == null) {
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case VoiceEvent.TYPE_CHANNEL_DEAD: {
|
|
JUserEntry ue = userInterface.getUserList().getEntry(e.getChannel());
|
|
if(ue == null) {
|
|
break;
|
|
}
|
|
ue.clearVoice();
|
|
break;
|
|
}
|
|
|
|
case VoiceEvent.TYPE_PACKET_VOLUME: {
|
|
JUserEntry ue = userInterface.getUserList().getEntry(e.getChannel());
|
|
if(ue == null) {
|
|
break;
|
|
}
|
|
if(e.getChannel() == peerKey) {
|
|
ue.setVolume(e.getVolume(), 0);
|
|
} else {
|
|
ue.setVolume(e.getVolume(), 12);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
voiceClient.start();
|
|
} else {
|
|
voiceClient.interrupt();
|
|
try { voiceClient.join(); } catch (InterruptedException e) { }
|
|
voiceClient = null;
|
|
userInterface.getUserList().clearVoice();
|
|
}
|
|
}
|
|
public VoiceClient getVoiceClient() {
|
|
return voiceClient;
|
|
}
|
|
|
|
public Properties getProps() {
|
|
return props;
|
|
}
|
|
|
|
public void setSoundEnabled(boolean soundEnabled) {
|
|
this.soundEnabled = soundEnabled;
|
|
}
|
|
|
|
public boolean isSoundEnabled() {
|
|
return soundEnabled;
|
|
}
|
|
|
|
public void setAds(boolean ads) {
|
|
this.ads = ads;
|
|
}
|
|
|
|
public boolean isAds() {
|
|
return ads;
|
|
}
|
|
|
|
public String getLogin() {
|
|
return login;
|
|
}
|
|
|
|
public String getPassword() {
|
|
return password;
|
|
}
|
|
|
|
public String getHostname() {
|
|
return hostname;
|
|
}
|
|
} |