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
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/aidl/com/morlunk/jumble/IJumbleObserver.aidl1
-rw-r--r--src/main/aidl/com/morlunk/jumble/IJumbleService.aidl4
-rw-r--r--src/main/java/com/morlunk/jumble/JumbleService.java78
-rw-r--r--src/main/java/com/morlunk/jumble/audio/AudioInput.java54
-rw-r--r--src/main/java/com/morlunk/jumble/audio/AudioOutput.java14
-rw-r--r--src/main/java/com/morlunk/jumble/audio/AudioOutputSpeech.java19
-rw-r--r--src/main/java/com/morlunk/jumble/model/Channel.java11
-rw-r--r--src/main/java/com/morlunk/jumble/model/User.java21
-rw-r--r--src/main/java/com/morlunk/jumble/net/ChannelHandler.java20
-rw-r--r--src/main/java/com/morlunk/jumble/net/JumbleConnection.java16
-rw-r--r--src/main/java/com/morlunk/jumble/net/JumbleObserver.java5
-rw-r--r--src/main/java/com/morlunk/jumble/net/Permissions.java45
-rw-r--r--src/main/java/com/morlunk/jumble/net/TextMessageHandler.java3
-rw-r--r--src/main/java/com/morlunk/jumble/net/UserHandler.java21
-rw-r--r--src/main/java/com/morlunk/jumble/util/MessageFormatter.java38
-rw-r--r--src/main/res/values/strings.xml1
16 files changed, 318 insertions, 33 deletions
diff --git a/src/main/aidl/com/morlunk/jumble/IJumbleObserver.aidl b/src/main/aidl/com/morlunk/jumble/IJumbleObserver.aidl
index 7e0d0fe..874e782 100644
--- a/src/main/aidl/com/morlunk/jumble/IJumbleObserver.aidl
+++ b/src/main/aidl/com/morlunk/jumble/IJumbleObserver.aidl
@@ -29,6 +29,7 @@ interface IJumbleObserver {
void onChannelAdded(out Channel channel);
void onChannelStateUpdated(out Channel channel);
void onChannelRemoved(out Channel channel);
+ void onChannelPermissionsUpdated(out Channel channel);
// User
void onUserConnected(out User user);
diff --git a/src/main/aidl/com/morlunk/jumble/IJumbleService.aidl b/src/main/aidl/com/morlunk/jumble/IJumbleService.aidl
index fffade7..7ba3594 100644
--- a/src/main/aidl/com/morlunk/jumble/IJumbleService.aidl
+++ b/src/main/aidl/com/morlunk/jumble/IJumbleService.aidl
@@ -34,6 +34,8 @@ interface IJumbleService {
Channel getChannel(int id);
List getUserList();
List getChannelList();
+ List getLogHistory();
+ int getPermissions();
// Audio actions
int getTransmitMode();
@@ -49,6 +51,7 @@ interface IJumbleService {
void requestBanList();
void requestUserList();
//void requestACL(int channel);
+ void requestPermissions(int channel);
void requestComment(int session);
void requestChannelDescription(int channel);
void registerUser(int session);
@@ -59,6 +62,7 @@ interface IJumbleService {
void removeChannel(int channel);
//void addChannelLink(int channel, int link);
//void requestChannelPermissions(int channel);
+ void setMuteDeafState(int session, boolean mute, boolean deaf);
void setSelfMuteDeafState(boolean mute, boolean deaf);
//void announceRecordingState(boolean recording);
diff --git a/src/main/java/com/morlunk/jumble/JumbleService.java b/src/main/java/com/morlunk/jumble/JumbleService.java
index 6702c42..24138ee 100644
--- a/src/main/java/com/morlunk/jumble/JumbleService.java
+++ b/src/main/java/com/morlunk/jumble/JumbleService.java
@@ -36,8 +36,13 @@ import com.morlunk.jumble.net.JumbleTCPMessageType;
import com.morlunk.jumble.net.TextMessageHandler;
import com.morlunk.jumble.net.UserHandler;
import com.morlunk.jumble.protobuf.Mumble;
+import com.morlunk.jumble.util.MessageFormatter;
import java.security.Security;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
import java.util.List;
public class JumbleService extends Service implements JumbleConnection.JumbleConnectionListener {
@@ -82,6 +87,12 @@ public class JumbleService extends Service implements JumbleConnection.JumbleCon
private TextMessageHandler mTextMessageHandler;
private AudioOutput mAudioOutput;
+ // Logging
+ private List<String> mLogHistory = new ArrayList<String>();
+ private SimpleDateFormat mChatDateFormat = new SimpleDateFormat("[h:mm a] ");
+
+ private int mPermissions;
+
private RemoteCallbackList<IJumbleObserver> mObservers = new RemoteCallbackList<IJumbleObserver>();
/**
@@ -147,6 +158,16 @@ public class JumbleService extends Service implements JumbleConnection.JumbleCon
}
@Override
+ public List getLogHistory() throws RemoteException {
+ return mLogHistory;
+ }
+
+ @Override
+ public int getPermissions() throws RemoteException {
+ return mPermissions;
+ }
+
+ @Override
public int getTransmitMode() throws RemoteException {
return mTransmitMode;
}
@@ -204,6 +225,13 @@ public class JumbleService extends Service implements JumbleConnection.JumbleCon
}
@Override
+ public void requestPermissions(int channel) throws RemoteException {
+ Mumble.PermissionQuery.Builder pqb = Mumble.PermissionQuery.newBuilder();
+ pqb.setChannelId(channel);
+ mConnection.sendTCPMessage(pqb.build(), JumbleTCPMessageType.PermissionQuery);
+ }
+
+ @Override
public void requestComment(int session) throws RemoteException {
Mumble.RequestBlob.Builder rbb = Mumble.RequestBlob.newBuilder();
rbb.addSessionComment(session);
@@ -240,6 +268,11 @@ public class JumbleService extends Service implements JumbleConnection.JumbleCon
tmb.addSession(session);
tmb.setMessage(message);
mConnection.sendTCPMessage(tmb.build(), JumbleTCPMessageType.TextMessage);
+
+ // Log message to chat
+ User target = getUser(session);
+ String formattedMessage = getString(R.string.chat_message_to, MessageFormatter.highlightString(target.getName()), message);
+ logMessage(formattedMessage);
}
@Override
@@ -251,6 +284,11 @@ public class JumbleService extends Service implements JumbleConnection.JumbleCon
tmb.addChannelId(channel);
tmb.setMessage(message);
mConnection.sendTCPMessage(tmb.build(), JumbleTCPMessageType.TextMessage);
+
+ // Log message to chat
+ Channel target = getChannel(channel);
+ String formattedMessage = getString(R.string.chat_message_to, MessageFormatter.highlightString(target.getName()), message);
+ logMessage(formattedMessage);
}
@Override
@@ -269,6 +307,15 @@ public class JumbleService extends Service implements JumbleConnection.JumbleCon
}
@Override
+ public void setMuteDeafState(int session, boolean mute, boolean deaf) throws RemoteException {
+ Mumble.UserState.Builder usb = Mumble.UserState.newBuilder();
+ usb.setSession(session);
+ usb.setMute(mute);
+ usb.setDeaf(deaf);
+ mConnection.sendTCPMessage(usb.build(), JumbleTCPMessageType.UserState);
+ }
+
+ @Override
public void setSelfMuteDeafState(boolean mute, boolean deaf) throws RemoteException {
Mumble.UserState.Builder usb = Mumble.UserState.newBuilder();
usb.setSelfMute(mute);
@@ -308,7 +355,7 @@ public class JumbleService extends Service implements JumbleConnection.JumbleCon
mClientName = extras.containsKey(EXTRAS_CLIENT_NAME) ? extras.getString(EXTRAS_CLIENT_NAME) : "Jumble";
connect();
}
- return START_STICKY;
+ return START_NOT_STICKY;
}
@Override
@@ -328,6 +375,10 @@ public class JumbleService extends Service implements JumbleConnection.JumbleCon
return mBinder;
}
+ public IJumbleService getBinder() {
+ return mBinder;
+ }
+
public void connect() {
try {
mConnection = new JumbleConnection(this, this, mServer, mClientName, mCertificate, mCertificatePassword, mForceTcp, mUseOpus, mUseTor);
@@ -344,6 +395,9 @@ public class JumbleService extends Service implements JumbleConnection.JumbleCon
return;
}
+ mLogHistory.clear();
+ mPermissions = 0;
+
mChannelHandler = new ChannelHandler(this);
mUserHandler = new UserHandler(this);
mTextMessageHandler = new TextMessageHandler(this);
@@ -407,6 +461,8 @@ public class JumbleService extends Service implements JumbleConnection.JumbleCon
mChannelHandler = null;
mUserHandler = null;
+
+ stopSelf();
}
@Override
@@ -441,6 +497,10 @@ public class JumbleService extends Service implements JumbleConnection.JumbleCon
return mChannelHandler;
}
+ public void setPermissions(int permissions) {
+ mPermissions = permissions;
+ }
+
/*
* --- HERE BE CALLBACKS ---
* This code will be called by components of the service like ChannelHandler.
@@ -448,10 +508,11 @@ public class JumbleService extends Service implements JumbleConnection.JumbleCon
/**
* Logs a warning message to the client.
- * @param warning An HTML warning string to be messaged to the client.
+ * @param warning An HTML warning string to be messagxz ed to the client.
*/
public void logWarning(final String warning) {
Log.w(Constants.TAG, warning);
+ mLogHistory.add(warning);
notifyObservers(new ObserverRunnable() {
@Override
public void run(IJumbleObserver observer) throws RemoteException {
@@ -465,11 +526,16 @@ public class JumbleService extends Service implements JumbleConnection.JumbleCon
* @param info An HTML info string to be messaged to the client.
*/
public void logInfo(final String info) {
- Log.v(Constants.TAG, info);
+ if(!mConnection.isSynchronized())
+ return; // Don't log messages while synchronizing.
+
+ final String formatInfo = mChatDateFormat.format(new Date())+info;
+ Log.v(Constants.TAG, formatInfo);
+ mLogHistory.add(formatInfo);
notifyObservers(new ObserverRunnable() {
@Override
public void run(IJumbleObserver observer) throws RemoteException {
- observer.onLogInfo(info);
+ observer.onLogInfo(formatInfo);
}
});
}
@@ -479,10 +545,12 @@ public class JumbleService extends Service implements JumbleConnection.JumbleCon
* @param message An HTML message to send to the client.
*/
public void logMessage(final String message) {
+ final String formatMessage = mChatDateFormat.format(new Date())+message;
+ mLogHistory.add(formatMessage);
notifyObservers(new ObserverRunnable() {
@Override
public void run(IJumbleObserver observer) throws RemoteException {
- observer.onMessageReceived(message);
+ observer.onMessageReceived(formatMessage);
}
});
}
diff --git a/src/main/java/com/morlunk/jumble/audio/AudioInput.java b/src/main/java/com/morlunk/jumble/audio/AudioInput.java
new file mode 100644
index 0000000..a73d0f3
--- /dev/null
+++ b/src/main/java/com/morlunk/jumble/audio/AudioInput.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2013 Andrew Comminos
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.morlunk.jumble.audio;
+
+import com.morlunk.jumble.audio.opus.SWIGTYPE_p_OpusEncoder;
+import com.morlunk.jumble.net.JumbleUDPMessageType;
+
+/**
+ * Created by andrew on 23/08/13.
+ */
+public class AudioInput {
+ private SWIGTYPE_p_OpusEncoder mOpusEncoder;
+ private com.morlunk.jumble.audio.celt11.SWIGTYPE_p_CELTEncoder mCelt11Encoder;
+ private com.morlunk.jumble.audio.celt7.SWIGTYPE_p_CELTEncoder mCelt7Encoder;
+
+ private JumbleUDPMessageType mCodec;
+
+ public AudioInput(JumbleUDPMessageType codec) {
+ mCodec = codec;
+ switch (codec) {
+ case UDPVoiceOpus:
+ break;
+ case UDPVoiceCELTBeta:
+ break;
+ case UDPVoiceCELTAlpha:
+ break;
+ case UDPVoiceSpeex:
+ break;
+ }
+ }
+
+ public void startRecording() {
+
+ }
+
+ public void stopRecording() {
+
+ }
+}
diff --git a/src/main/java/com/morlunk/jumble/audio/AudioOutput.java b/src/main/java/com/morlunk/jumble/audio/AudioOutput.java
index 830c91c..2691afe 100644
--- a/src/main/java/com/morlunk/jumble/audio/AudioOutput.java
+++ b/src/main/java/com/morlunk/jumble/audio/AudioOutput.java
@@ -35,6 +35,7 @@ import com.morlunk.jumble.net.PacketDataStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
@@ -43,6 +44,9 @@ import java.util.concurrent.ConcurrentHashMap;
*/
public class AudioOutput extends JumbleMessageHandler.Stub implements Runnable, AudioOutputSpeech.TalkStateListener {
+ /** Number of nanoseconds until sleeping audio output thread. */
+ private static final long SLEEP_THRESHOLD = 2000000000L;
+
private JumbleService mService;
private ConcurrentHashMap<Integer, AudioOutputSpeech> mAudioOutputs = new ConcurrentHashMap<Integer, AudioOutputSpeech>();
private AudioTrack mAudioTrack;
@@ -50,6 +54,7 @@ public class AudioOutput extends JumbleMessageHandler.Stub implements Runnable,
private Thread mThread;
private Object mInactiveLock = new Object(); // Lock that the audio thread waits on when there's no audio to play. Wake when we get a frame.
private boolean mRunning = false;
+ private long mLastPacket; // Time that the last packet was received, in nanoseconds
public AudioOutput(JumbleService service) {
mService = service;
@@ -59,7 +64,7 @@ public class AudioOutput extends JumbleMessageHandler.Stub implements Runnable,
Audio.SAMPLE_RATE,
AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT,
- bufferSize,
+ Audio.FRAME_SIZE*12,
AudioTrack.MODE_STREAM);
}
@@ -86,10 +91,11 @@ public class AudioOutput extends JumbleMessageHandler.Stub implements Runnable,
final short[] mix = new short[Audio.FRAME_SIZE*12];
while(mRunning) {
+ Arrays.fill(mix, (short)0);
boolean play = mix(mix, mix.length);
if(play) {
mAudioTrack.write(mix, 0, mix.length);
- } else {
+ } else if(System.nanoTime()-mLastPacket > SLEEP_THRESHOLD) {
Log.v(Constants.TAG, "Pausing audio output thread.");
synchronized (mInactiveLock) {
try {
@@ -131,7 +137,7 @@ public class AudioOutput extends JumbleMessageHandler.Stub implements Runnable,
}
for(AudioOutputSpeech speech : del)
- mAudioOutputs.remove(speech);
+ mAudioOutputs.remove(speech.getSession());
return !mix.isEmpty();
}
@@ -167,6 +173,8 @@ public class AudioOutput extends JumbleMessageHandler.Stub implements Runnable,
}
aop.addFrameToBuffer(packet.array(), seq);
+
+ mLastPacket = System.nanoTime();
synchronized (mInactiveLock) {
mInactiveLock.notify();
}
diff --git a/src/main/java/com/morlunk/jumble/audio/AudioOutputSpeech.java b/src/main/java/com/morlunk/jumble/audio/AudioOutputSpeech.java
index 8e8ff86..8b866a8 100644
--- a/src/main/java/com/morlunk/jumble/audio/AudioOutputSpeech.java
+++ b/src/main/java/com/morlunk/jumble/audio/AudioOutputSpeech.java
@@ -230,29 +230,29 @@ public class AudioOutputSpeech {
if(mCodec == JumbleUDPMessageType.UDPVoiceCELTAlpha) {
CELT7.celt_decode_float(mCELTAlphaDecoder,
- mFrames.isEmpty() ? null : data,
+ data,
data.length,
out);
} else if(mCodec == JumbleUDPMessageType.UDPVoiceCELTBeta) {
CELT11.celt_decode_float(mCELTBetaDecoder,
- mFrames.isEmpty() ? null : data,
+ data,
data.length,
out,
Audio.FRAME_SIZE);
} else if(mCodec == JumbleUDPMessageType.UDPVoiceOpus) {
decodedSamples = Opus.opus_decode_float(mOpusDecoder,
- mFrames.isEmpty() ? null : data,
+ data,
data.length,
out,
mAudioBufferSize,
0);
} else { // Speex
- if(mFrames.isEmpty())
- Speex.speex_decode(mSpeexDecoder, null, out);
- else {
+// if(data.isEmpty())
+// Speex.speex_decode(mSpeexDecoder, null, out);
+// else {
Speex.speex_bits_read_from(mSpeexBits, data, data.length);
Speex.speex_decode(mSpeexDecoder, mSpeexBits, out);
- }
+// }
for(int i = 0; i < Audio.FRAME_SIZE; i++)
out[i] *= (1.0f / 32767.f);
}
@@ -307,6 +307,7 @@ public class AudioOutputSpeech {
talkState = User.TalkState.WHISPERING;
break;
}
+
mTalkStateListener.onTalkStateUpdated(mSession, talkState);
boolean tmp = mLastAlive;
@@ -333,6 +334,10 @@ public class AudioOutputSpeech {
return mCodec;
}
+ public int getSession() {
+ return mSession;
+ }
+
/**
* Cleans up all JNI refs linked to this instance.
* This MUST be called eventually, otherwise we get memory leaks!
diff --git a/src/main/java/com/morlunk/jumble/model/Channel.java b/src/main/java/com/morlunk/jumble/model/Channel.java
index cedf236..2350918 100644
--- a/src/main/java/com/morlunk/jumble/model/Channel.java
+++ b/src/main/java/com/morlunk/jumble/model/Channel.java
@@ -36,6 +36,7 @@ public final class Channel implements Parcelable {
private List<Integer> mUsers = new ArrayList<Integer>();
private List<Integer> mLinks = new ArrayList<Integer>();
private int mUserCount;
+ private int mPermissions;
public static final Parcelable.Creator<Channel> CREATOR = new Parcelable.Creator<Channel>() {
@@ -77,6 +78,7 @@ public final class Channel implements Parcelable {
out.writeList(mUsers);
out.writeList(mLinks);
out.writeInt(mUserCount);
+ out.writeInt(mPermissions);
}
public void readFromParcel(Parcel in) {
@@ -93,6 +95,7 @@ public final class Channel implements Parcelable {
mUsers = in.readArrayList(null);
mLinks = in.readArrayList(null);
mUserCount = in.readInt();
+ mPermissions = in.readInt();
}
@Override
@@ -206,4 +209,12 @@ public final class Channel implements Parcelable {
public void setSubchannelUserCount(int userCount) {
mUserCount = userCount;
}
+
+ public int getPermissions() {
+ return mPermissions;
+ }
+
+ public void setPermissions(int permissions) {
+ mPermissions = permissions;
+ }
}
diff --git a/src/main/java/com/morlunk/jumble/model/User.java b/src/main/java/com/morlunk/jumble/model/User.java
index fa3e38d..e95b726 100644
--- a/src/main/java/com/morlunk/jumble/model/User.java
+++ b/src/main/java/com/morlunk/jumble/model/User.java
@@ -19,6 +19,8 @@ package com.morlunk.jumble.model;
import android.os.Parcel;
import android.os.Parcelable;
+import com.google.protobuf.ByteString;
+
public class User implements Parcelable {
public static enum TalkState {
@@ -29,10 +31,10 @@ public class User implements Parcelable {
}
private int mSession;
- private int mId;
+ private int mId = -1;
private String mName;
private String mComment;
- private byte[] mCommentHash;
+ private ByteString mCommentHash;
private String mHash;
private boolean mMuted;
@@ -85,8 +87,8 @@ public class User implements Parcelable {
out.writeInt(mId);
out.writeString(mName);
out.writeString(mComment);
- out.writeInt(mCommentHash.length);
- out.writeByteArray(mCommentHash);
+ out.writeInt(mCommentHash.size());
+ out.writeByteArray(mCommentHash.toByteArray());
out.writeString(mHash);
out.writeValue(mMuted);
out.writeValue(mDeafened);
@@ -105,8 +107,9 @@ public class User implements Parcelable {
mId = in.readInt();
mName = in.readString();
mComment = in.readString();
- mCommentHash = new byte[in.readInt()];
- in.readByteArray(mCommentHash);
+ byte[] commentHash = new byte[in.readInt()];
+ in.readByteArray(commentHash);
+ mCommentHash = ByteString.copyFrom(commentHash);
mHash = in.readString();
mMuted = (Boolean)in.readValue(null);
mDeafened = (Boolean)in.readValue(null);
@@ -161,12 +164,12 @@ public class User implements Parcelable {
this.mComment = mComment;
}
- public byte[] getCommentHash() {
+ public ByteString getCommentHash() {
return mCommentHash;
}
- public void setCommentHash(byte[] mCommentHash) {
- this.mCommentHash = mCommentHash;
+ public void setCommentHash(ByteString commentHash) {
+ mCommentHash = commentHash;
}
public String getHash() {
diff --git a/src/main/java/com/morlunk/jumble/net/ChannelHandler.java b/src/main/java/com/morlunk/jumble/net/ChannelHandler.java
index ff897d7..2366d70 100644
--- a/src/main/java/com/morlunk/jumble/net/ChannelHandler.java
+++ b/src/main/java/com/morlunk/jumble/net/ChannelHandler.java
@@ -159,4 +159,24 @@ public class ChannelHandler extends JumbleMessageHandler.Stub {
});
}
}
+
+ @Override
+ public void messagePermissionQuery(Mumble.PermissionQuery msg) {
+ if(msg.getFlush())
+ for(Channel channel : mChannels.values())
+ channel.setPermissions(0);
+
+ final Channel channel = mChannels.get(msg.getChannelId());
+ if(channel != null) {
+ channel.setPermissions(msg.getPermissions());
+ if(msg.getChannelId() == 0) // If we're provided permissions for the root channel, we'll apply these as our server permissions.
+ mService.setPermissions(msg.getPermissions());
+ mService.notifyObservers(new JumbleService.ObserverRunnable() {
+ @Override
+ public void run(IJumbleObserver observer) throws RemoteException {
+ observer.onChannelPermissionsUpdated(channel);
+ }
+ });
+ }
+ }
}
diff --git a/src/main/java/com/morlunk/jumble/net/JumbleConnection.java b/src/main/java/com/morlunk/jumble/net/JumbleConnection.java
index b507eba..37ea33e 100644
--- a/src/main/java/com/morlunk/jumble/net/JumbleConnection.java
+++ b/src/main/java/com/morlunk/jumble/net/JumbleConnection.java
@@ -87,6 +87,7 @@ public class JumbleConnection {
private boolean mUseTor;
private boolean mUsingUDP = true;
private boolean mConnected;
+ private boolean mSynchronized;
private CryptState mCryptState = new CryptState();
private long mStartTimestamp; // Time that the connection was initiated in nanoseconds
@@ -121,6 +122,7 @@ public class JumbleConnection {
mPingExecutorService.scheduleAtFixedRate(mPingRunnable, 0, 5, TimeUnit.SECONDS);
mSession = msg.getSession();
+ mSynchronized = true;
mMainHandler.post(new Runnable() {
@Override
@@ -146,7 +148,7 @@ public class JumbleConnection {
@Override
public void messageUserRemove(final Mumble.UserRemove msg) {
- if(msg.getActor() == mSession) {
+ if(msg.getSession() == mSession) {
if(mListener != null) {
mMainHandler.post(new Runnable() {
@Override
@@ -292,6 +294,7 @@ public class JumbleConnection {
public void connect() {
mConnected = false;
+ mSynchronized = false;
mUsingUDP = !mForceTCP;
mStartTimestamp = System.nanoTime();
@@ -309,6 +312,15 @@ public class JumbleConnection {
return mConnected;
}
+ /**
+ * Returns whether or not the service is fully synchronized with the remote server- this happens when we get the ServerSync message.
+ * You shouldn't log any user actions until the connection is synchronized.
+ * @return true or false, depending on whether or not we have received the ServerSync message.
+ */
+ public boolean isSynchronized() {
+ return mSynchronized;
+ }
+
public long getElapsed() {
return (System.nanoTime()-mStartTimestamp)/1000;
}
@@ -346,6 +358,7 @@ public class JumbleConnection {
*/
public void disconnect() {
mConnected = false;
+ mSynchronized = false;
mNetworkHandler.postAtFrontOfQueue(new Runnable() {
@Override
public void run() {
@@ -368,6 +381,7 @@ public class JumbleConnection {
*/
public void forceDisconnect() {
mConnected = false;
+ mSynchronized = false;
mExecutorService.shutdownNow();
mPingExecutorService.shutdownNow();
mTCP = null;
diff --git a/src/main/java/com/morlunk/jumble/net/JumbleObserver.java b/src/main/java/com/morlunk/jumble/net/JumbleObserver.java
index b95ec11..865b124 100644
--- a/src/main/java/com/morlunk/jumble/net/JumbleObserver.java
+++ b/src/main/java/com/morlunk/jumble/net/JumbleObserver.java
@@ -58,6 +58,11 @@ public class JumbleObserver extends IJumbleObserver.Stub {
}
@Override
+ public void onChannelPermissionsUpdated(Channel channel) throws RemoteException {
+
+ }
+
+ @Override
public void onUserConnected(User user) throws RemoteException {
}
diff --git a/src/main/java/com/morlunk/jumble/net/Permissions.java b/src/main/java/com/morlunk/jumble/net/Permissions.java
new file mode 100644
index 0000000..561ff9b
--- /dev/null
+++ b/src/main/java/com/morlunk/jumble/net/Permissions.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2013 Andrew Comminos
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.morlunk.jumble.net;
+
+/**
+ * Created by andrew on 21/08/13.
+ */
+public class Permissions {
+ public static final int None = 0x0,
+ Write = 0x1,
+ Traverse = 0x2,
+ Enter = 0x4,
+ Speak = 0x8,
+ MuteDeafen = 0x10,
+ Move = 0x20,
+ MakeChannel = 0x40,
+ LinkChannel = 0x80,
+ Whisper = 0x100,
+ TextMessage = 0x200,
+ MakeTempChannel = 0x400,
+
+ // Root channel only
+ Kick = 0x10000,
+ Ban = 0x20000,
+ Register = 0x40000,
+ SelfRegister = 0x80000,
+
+ Cached = 0x8000000,
+ All = 0xf07ff;
+}
diff --git a/src/main/java/com/morlunk/jumble/net/TextMessageHandler.java b/src/main/java/com/morlunk/jumble/net/TextMessageHandler.java
index bda7a53..5b63667 100644
--- a/src/main/java/com/morlunk/jumble/net/TextMessageHandler.java
+++ b/src/main/java/com/morlunk/jumble/net/TextMessageHandler.java
@@ -19,6 +19,7 @@ package com.morlunk.jumble.net;
import com.morlunk.jumble.JumbleService;
import com.morlunk.jumble.model.User;
import com.morlunk.jumble.protobuf.Mumble;
+import com.morlunk.jumble.util.MessageFormatter;
/**
* Handles receiving text messages.
@@ -41,7 +42,7 @@ public class TextMessageHandler extends JumbleMessageHandler.Stub {
return;
// TODO use more localized strings here
- String senderName = sender != null ? sender.getName() : "Server";
+ String senderName = sender != null ? MessageFormatter.highlightString(sender.getName()) : "Server";
String senderTarget = "";
if(msg.getTreeIdCount() > 0)
diff --git a/src/main/java/com/morlunk/jumble/net/UserHandler.java b/src/main/java/com/morlunk/jumble/net/UserHandler.java
index 908c27d..ee2e404 100644
--- a/src/main/java/com/morlunk/jumble/net/UserHandler.java
+++ b/src/main/java/com/morlunk/jumble/net/UserHandler.java
@@ -26,6 +26,7 @@ import com.morlunk.jumble.R;
import com.morlunk.jumble.model.Channel;
import com.morlunk.jumble.model.User;
import com.morlunk.jumble.protobuf.Mumble;
+import com.morlunk.jumble.util.MessageFormatter;
import java.util.ArrayList;
import java.util.Collections;
@@ -89,6 +90,12 @@ public class UserHandler extends JumbleMessageHandler.Stub {
user = new User(msg.getSession(), msg.getName());
mUsers.put(msg.getSession(), user);
newUser = true;
+ // Add user to root channel by default. This works because for some reason, we don't get a channel ID when the user joins into root.
+ Channel root = mService.getChannelHandler().getChannel(0);
+ user.setChannelId(0);
+ root.addUser(user.getSession());
+ root.setSubchannelUserCount(root.getSubchannelUserCount()+1);
+ sortUsers(root);
}
else
return;
@@ -110,7 +117,7 @@ public class UserHandler extends JumbleMessageHandler.Stub {
}
if(newUser)
- mService.logInfo(mService.getString(R.string.chat_notify_connected, user.getName()));
+ mService.logInfo(mService.getString(R.string.chat_notify_connected, MessageFormatter.highlightString(user.getName())));
if(msg.hasSelfDeaf() || msg.hasSelfMute()) {
if(msg.hasSelfMute())
@@ -120,11 +127,11 @@ public class UserHandler extends JumbleMessageHandler.Stub {
if(self != null && user.getSession() != self.getSession() && (user.getChannelId() == self.getChannelId())) {
if(user.isSelfMuted() && user.isSelfDeafened())
- mService.logInfo(mService.getString(R.string.chat_notify_now_muted_deafened, user.getName()));
+ mService.logInfo(mService.getString(R.string.chat_notify_now_muted_deafened, MessageFormatter.highlightString(user.getName())));
else if(user.isSelfMuted())
- mService.logInfo(mService.getString(R.string.chat_notify_now_muted, user.getName()));
+ mService.logInfo(mService.getString(R.string.chat_notify_now_muted, MessageFormatter.highlightString(user.getName())));
else
- mService.logInfo(mService.getString(R.string.chat_notify_now_unmuted, user.getName()));
+ mService.logInfo(mService.getString(R.string.chat_notify_now_unmuted, MessageFormatter.highlightString(user.getName())));
}
}
@@ -142,9 +149,9 @@ public class UserHandler extends JumbleMessageHandler.Stub {
// If in a linked channel OR the same channel as the current user, notify the user about recording
if(selfChannel != null && (selfChannel.getLinks().contains(user.getChannelId()) || self.getChannelId() == user.getChannelId())) {
if(user.isRecording())
- mService.logInfo(mService.getString(R.string.chat_notify_user_recording_started, user.getName()));
+ mService.logInfo(mService.getString(R.string.chat_notify_user_recording_started, MessageFormatter.highlightString(user.getName())));
else
- mService.logInfo(mService.getString(R.string.chat_notify_user_recording_stopped, user.getName()));
+ mService.logInfo(mService.getString(R.string.chat_notify_user_recording_stopped, MessageFormatter.highlightString(user.getName())));
}
}
}
@@ -203,7 +210,7 @@ public class UserHandler extends JumbleMessageHandler.Stub {
*/
if(msg.hasCommentHash())
- user.setCommentHash(msg.getCommentHash().toByteArray());
+ user.setCommentHash(msg.getCommentHash());
if(msg.hasComment())
user.setComment(msg.getComment());
diff --git a/src/main/java/com/morlunk/jumble/util/MessageFormatter.java b/src/main/java/com/morlunk/jumble/util/MessageFormatter.java
new file mode 100644
index 0000000..58c15cb
--- /dev/null
+++ b/src/main/java/com/morlunk/jumble/util/MessageFormatter.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2013 Andrew Comminos
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.morlunk.jumble.util;
+
+/**
+ * Formats strings into HTML.
+ * Created by andrew on 24/08/13.
+ */
+public class MessageFormatter {
+
+ public static final String HIGHLIGHT_COLOR = "33b5e5";
+
+ private static final String HTML_FONT_COLOR_FORMAT = "<font color=\"#%s\">%s</font>";
+
+ /**
+ * Highlights the passed string using the service's defined color {@link MessageFormatter#HIGHLIGHT_COLOR}.
+ * @param string The string to highlight.
+ * @return The passed string enclosed with HTML font tags specifying the color.
+ */
+ public static String highlightString(String string) {
+ return String.format(HTML_FONT_COLOR_FORMAT, HIGHLIGHT_COLOR, string);
+ }
+}
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index e68149e..bae8628 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
+ <string name="chat_message_to">To %1$s: %2$s</string>
<string name="chat_notify_moved">%1$s moved in from %2$s by %3$s.</string>
<string name="chat_notify_muted_deafened">Muted and deafened.</string>
<string name="chat_notify_muted">Muted.</string>