Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Morlunk/Jumble.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Comminos <andrewcomminos@gmail.com>2013-12-09 04:35:36 +0400
committerAndrew Comminos <andrewcomminos@gmail.com>2013-12-09 04:35:36 +0400
commit32906ccddb0ae0186928ea56692ae088c22525df (patch)
tree00f3c29364e699a7c3824cdeb176fcd844a8e1fe
parenteae58cca15df72ee7b3cc2d0a0311b38ed739f23 (diff)
Implemented reconnection procedure, generic audio and user fixes.
-rw-r--r--src/main/aidl/com/morlunk/jumble/IJumbleService.aidl2
-rw-r--r--src/main/java/com/morlunk/jumble/JumbleService.java50
-rw-r--r--src/main/java/com/morlunk/jumble/audio/AudioInput.java19
-rw-r--r--src/main/java/com/morlunk/jumble/audio/AudioOutput.java2
-rw-r--r--src/main/java/com/morlunk/jumble/net/JumbleConnection.java53
-rw-r--r--src/main/java/com/morlunk/jumble/protocol/UserHandler.java21
6 files changed, 104 insertions, 43 deletions
diff --git a/src/main/aidl/com/morlunk/jumble/IJumbleService.aidl b/src/main/aidl/com/morlunk/jumble/IJumbleService.aidl
index 04ab76e..d044c85 100644
--- a/src/main/aidl/com/morlunk/jumble/IJumbleService.aidl
+++ b/src/main/aidl/com/morlunk/jumble/IJumbleService.aidl
@@ -26,6 +26,8 @@ interface IJumbleService {
void disconnect();
boolean isConnected();
boolean isConnecting();
+ boolean isReconnecting();
+ void cancelReconnect();
/**
* Gets the TCP latency, in nanoseconds.
*/
diff --git a/src/main/java/com/morlunk/jumble/JumbleService.java b/src/main/java/com/morlunk/jumble/JumbleService.java
index 279fe61..1ec785d 100644
--- a/src/main/java/com/morlunk/jumble/JumbleService.java
+++ b/src/main/java/com/morlunk/jumble/JumbleService.java
@@ -53,6 +53,7 @@ import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
+import java.util.concurrent.Executors;
public class JumbleService extends Service implements JumbleConnection.JumbleConnectionListener {
@@ -64,8 +65,8 @@ public class JumbleService extends Service implements JumbleConnection.JumbleCon
/** Intent to connect to a Mumble server. See extras. **/
public static final String ACTION_CONNECT = "com.morlunk.jumble.CONNECT";
public static final String EXTRAS_SERVER = "server";
- public static final String EXTRAS_SHOW_CHAT_NOTIFICATION = "show_chat_notifications";
public static final String EXTRAS_AUTO_RECONNECT = "auto_reconnect";
+ public static final String EXTRAS_AUTO_RECONNECT_DELAY = "auto_reconnect_delay";
public static final String EXTRAS_CERTIFICATE = "certificate";
public static final String EXTRAS_CERTIFICATE_PASSWORD = "certificate_password";
public static final String EXTRAS_DETECTION_THRESHOLD = "detection_threshold";
@@ -80,8 +81,8 @@ public class JumbleService extends Service implements JumbleConnection.JumbleCon
// Service settings
public Server mServer;
- public boolean mShowChatNotifications;
public boolean mAutoReconnect;
+ public int mAutoReconnectDelay;
public byte[] mCertificate;
public String mCertificatePassword;
public float mDetectionThreshold;
@@ -171,6 +172,7 @@ public class JumbleService extends Service implements JumbleConnection.JumbleCon
};
private int mPermissions;
+ private boolean mReconnecting;
private RemoteCallbackList<IJumbleObserver> mObservers = new RemoteCallbackList<IJumbleObserver>();
@@ -185,7 +187,8 @@ public class JumbleService extends Service implements JumbleConnection.JumbleCon
@Override
public void disconnect() throws RemoteException {
- JumbleService.this.disconnect();
+ if(isConnected())
+ JumbleService.this.disconnect();
}
@Override
@@ -201,6 +204,16 @@ public class JumbleService extends Service implements JumbleConnection.JumbleCon
}
@Override
+ public boolean isReconnecting() throws RemoteException {
+ return mReconnecting;
+ }
+
+ @Override
+ public void cancelReconnect() throws RemoteException {
+ mReconnecting = false;
+ }
+
+ @Override
public long getTCPLatency() throws RemoteException {
return mConnection.getTCPLatency();
}
@@ -482,8 +495,8 @@ public class JumbleService extends Service implements JumbleConnection.JumbleCon
// Get connection parameters
Bundle extras = intent.getExtras();
mServer = extras.getParcelable(EXTRAS_SERVER);
- mShowChatNotifications = extras.getBoolean(EXTRAS_SHOW_CHAT_NOTIFICATION, true);
mAutoReconnect = extras.getBoolean(EXTRAS_AUTO_RECONNECT, true);
+ mAutoReconnectDelay = extras.getInt(EXTRAS_AUTO_RECONNECT_DELAY, 5000);
mCertificate = extras.getByteArray(EXTRAS_CERTIFICATE);
mCertificatePassword = extras.getString(EXTRAS_CERTIFICATE_PASSWORD);
mDetectionThreshold = extras.getFloat(EXTRAS_DETECTION_THRESHOLD, 0.5f);
@@ -534,7 +547,7 @@ public class JumbleService extends Service implements JumbleConnection.JumbleCon
}
mPermissions = 0;
-
+ mReconnecting = false;
mChannelHandler = new ChannelHandler(this);
mUserHandler = new UserHandler(this);
mTextMessageHandler = new TextMessageHandler(this);
@@ -546,8 +559,13 @@ public class JumbleService extends Service implements JumbleConnection.JumbleCon
}
public void disconnect() {
- mConnection.disconnect();
- mConnection = null;
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ mConnection.disconnect();
+ mConnection = null;
+ }
+ }).start();
}
public boolean isConnected() {
@@ -585,7 +603,11 @@ public class JumbleService extends Service implements JumbleConnection.JumbleCon
@Override
public void onConnectionDisconnected() {
Log.v(Constants.TAG, "Disconnected");
- unregisterReceiver(mBluetoothReceiver);
+ try {
+ unregisterReceiver(mBluetoothReceiver);
+ } catch (IllegalArgumentException e) {
+ e.printStackTrace();
+ }
mAudioOutput.stopPlaying();
mAudioInput.stopRecordingAndWait();
@@ -605,13 +627,21 @@ public class JumbleService extends Service implements JumbleConnection.JumbleCon
mChannelHandler = null;
mUserHandler = null;
-
- stopSelf();
}
@Override
public void onConnectionError(final JumbleConnectionException e) {
Log.e(Constants.TAG, "Connection error: "+e.getMessage());
+ if(mAutoReconnect) {
+ mReconnecting = true;
+ Handler mainHandler = new Handler();
+ mainHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ if(mReconnecting) connect();
+ }
+ }, mAutoReconnectDelay);
+ }
notifyObservers(new ObserverRunnable() {
@Override
public void run(IJumbleObserver observer) throws RemoteException {
diff --git a/src/main/java/com/morlunk/jumble/audio/AudioInput.java b/src/main/java/com/morlunk/jumble/audio/AudioInput.java
index cdc3e35..21bef55 100644
--- a/src/main/java/com/morlunk/jumble/audio/AudioInput.java
+++ b/src/main/java/com/morlunk/jumble/audio/AudioInput.java
@@ -149,8 +149,7 @@ public class AudioInput extends ProtocolHandler implements Runnable {
* Based off of Mumble project's AudioInput method resetAudioProcessor().
*/
private void configurePreprocessState() {
- if(mPreprocessState != null)
- mPreprocessState.destroy();
+ if(mPreprocessState != null) mPreprocessState.destroy();
mPreprocessState = new Speex.SpeexPreprocessState(mFrameSize, Audio.SAMPLE_RATE);
@@ -181,14 +180,22 @@ public class AudioInput extends ProtocolHandler implements Runnable {
return;
mCodec = codec;
- if(mOpusEncoder != null)
+ if(mOpusEncoder != null) {
Opus.opus_encoder_destroy(mOpusEncoder);
- if(mCELTBetaEncoder != null)
+ mOpusEncoder = null;
+ }
+ if(mCELTBetaEncoder != null) {
CELT11.celt_encoder_destroy(mCELTBetaEncoder);
- if(mCELTAlphaEncoder != null)
+ mCELTBetaEncoder = null;
+ }
+ if(mCELTAlphaEncoder != null) {
CELT7.celt_encoder_destroy(mCELTAlphaEncoder);
- if(mCELTAlphaMode != null)
+ mCELTAlphaEncoder = null;
+ }
+ if(mCELTAlphaMode != null) {
CELT7.celt_mode_destroy(mCELTAlphaMode);
+ mCELTAlphaMode = null;
+ }
IntPointer error = new IntPointer(1);
switch (codec) {
diff --git a/src/main/java/com/morlunk/jumble/audio/AudioOutput.java b/src/main/java/com/morlunk/jumble/audio/AudioOutput.java
index 32104c4..0bdb8ad 100644
--- a/src/main/java/com/morlunk/jumble/audio/AudioOutput.java
+++ b/src/main/java/com/morlunk/jumble/audio/AudioOutput.java
@@ -210,7 +210,7 @@ public class AudioOutput extends ProtocolHandler implements Runnable, AudioOutpu
@Override
public void onTalkStateUpdated(int session, User.TalkState state) {
final User user = getService().getUserHandler().getUser(session);
- if(user.getTalkState() != state) {
+ if(user != null && user.getTalkState() != state) {
user.setTalkState(state);
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
diff --git a/src/main/java/com/morlunk/jumble/net/JumbleConnection.java b/src/main/java/com/morlunk/jumble/net/JumbleConnection.java
index 9da8440..ecd8054 100644
--- a/src/main/java/com/morlunk/jumble/net/JumbleConnection.java
+++ b/src/main/java/com/morlunk/jumble/net/JumbleConnection.java
@@ -40,9 +40,12 @@ import java.security.cert.CertificateException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
public class JumbleConnection {
@@ -83,7 +86,9 @@ public class JumbleConnection {
// Networking and protocols
private InetAddress mHost;
private JumbleTCP mTCP;
+ private Future mTCPTask;
private JumbleUDP mUDP;
+ private ScheduledFuture mPingTask;
private boolean mForceTCP;
private boolean mUseOpus = true;
private boolean mUseTor;
@@ -124,7 +129,7 @@ public class JumbleConnection {
}
// Start TCP/UDP ping thread. FIXME is this the right place?
- mPingExecutorService.scheduleAtFixedRate(mPingRunnable, 0, 5, TimeUnit.SECONDS);
+ mPingTask = mPingExecutorService.scheduleAtFixedRate(mPingRunnable, 0, 5, TimeUnit.SECONDS);
mSession = msg.getSession();
mSynchronized = true;
@@ -297,7 +302,7 @@ public class JumbleConnection {
mUDP = new JumbleUDP();
mNetworkSendThread = new NetworkSendThread();
mExecutorService.submit(mNetworkSendThread);
- mExecutorService.submit(mTCP);
+ mTCPTask = mExecutorService.submit(mTCP);
// We'll start UDP thread after TCP is established. FIXME?
}
@@ -356,26 +361,35 @@ public class JumbleConnection {
}
/**
- * Gracefully shuts down all networking.
+ * Gracefully shuts down all networking. Blocks until all network threads have stopped.
*/
public void disconnect() {
mConnected = false;
mSynchronized = false;
- mNetworkSendHandler.postAtFrontOfQueue(new Runnable() {
- @Override
- public void run() {
- try {
- mTCP.disconnect();
- if (mUDP != null) mUDP.disconnect();
- } catch (IOException e) {
- e.printStackTrace();
- }
- mTCP = null;
- mUDP = null;
- }
- });
- mExecutorService.shutdown();
- mPingExecutorService.shutdown();
+
+ // Stop running network resources
+ if(mPingTask != null) mPingTask.cancel(true);
+ try {
+ if(mTCP != null) mTCP.disconnect();
+ if(mUDP != null) mUDP.disconnect();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ // Block until main listening thread has stopped
+ try {
+ if(mTCPTask != null) mTCPTask.get();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ } catch (ExecutionException e) {
+ e.printStackTrace();
+ }
+ mTCP = null;
+ mTCPTask = null;
+ mUDP = null;
+ mPingTask = null;
+ mExecutorService.shutdownNow();
+ mPingExecutorService.shutdownNow();
}
/**
@@ -412,7 +426,7 @@ public class JumbleConnection {
}
});
}
- forceDisconnect();
+ disconnect();
}
/**
@@ -831,6 +845,7 @@ public class JumbleConnection {
public void disconnect() {
mUDPSocket.disconnect();
+ mUDPSocket.close();
}
@Override
diff --git a/src/main/java/com/morlunk/jumble/protocol/UserHandler.java b/src/main/java/com/morlunk/jumble/protocol/UserHandler.java
index 48c1121..c8ac313 100644
--- a/src/main/java/com/morlunk/jumble/protocol/UserHandler.java
+++ b/src/main/java/com/morlunk/jumble/protocol/UserHandler.java
@@ -135,6 +135,13 @@ public class UserHandler extends ProtocolHandler {
getService().logInfo(getService().getString(R.string.chat_notify_now_muted, MessageFormatter.highlightString(user.getName())));
else
getService().logInfo(getService().getString(R.string.chat_notify_now_unmuted, MessageFormatter.highlightString(user.getName())));
+ } else if(self != null && user.getSession() == self.getSession()) {
+ if(user.isSelfMuted() && user.isSelfDeafened())
+ getService().logInfo(getService().getString(R.string.chat_notify_muted_deafened, MessageFormatter.highlightString(user.getName())));
+ else if(user.isSelfMuted())
+ getService().logInfo(getService().getString(R.string.chat_notify_muted, MessageFormatter.highlightString(user.getName())));
+ else
+ getService().logInfo(getService().getString(R.string.chat_notify_unmuted, MessageFormatter.highlightString(user.getName())));
}
}
@@ -168,13 +175,13 @@ public class UserHandler extends ProtocolHandler {
if(msg.hasPrioritySpeaker())
user.setPrioritySpeaker(msg.getPrioritySpeaker());
-/* if(self != null && ((user.getChannelId() == self.getChannelId()) || (actor.getSession() == self.getSession()))) {
- if(user.getSession() == self.getSession()) {
- if(msg.hasMute() && msg.hasDeaf() && user.isMuted() && user.isDeafened()) {
- getService().logInfo();
- }
- }
- }*/
+// if(self != null && ((user.getChannelId() == self.getChannelId()) || (actor.getSession() == self.getSession()))) {
+// if(user.getSession() == self.getSession()) {
+// if(msg.hasMute() && msg.hasDeaf() && user.isMuted() && user.isDeafened()) {
+// getService().logInfo();
+// }
+// }
+// }
/*
* TODO: logging