2012-07-31 09:36:52 +08:00
|
|
|
using Newtonsoft.Json;
|
|
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
using System;
|
|
|
|
using System.Collections;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Text;
|
|
|
|
using System.Threading;
|
|
|
|
using WebSocketSharp;
|
|
|
|
|
2012-08-06 13:34:39 +08:00
|
|
|
namespace Example1
|
2012-07-31 09:36:52 +08:00
|
|
|
{
|
2014-03-12 19:23:37 +08:00
|
|
|
internal class AudioStreamer : IDisposable
|
2012-07-31 09:36:52 +08:00
|
|
|
{
|
|
|
|
private Dictionary<uint, Queue> _audioBox;
|
2014-03-12 19:23:37 +08:00
|
|
|
private uint? _id;
|
|
|
|
private string _name;
|
|
|
|
private Notifier _notifier;
|
2016-07-26 15:52:42 +08:00
|
|
|
private Timer _timer;
|
2014-03-12 19:23:37 +08:00
|
|
|
private WebSocket _websocket;
|
2012-07-31 09:36:52 +08:00
|
|
|
|
2014-03-12 19:23:37 +08:00
|
|
|
public AudioStreamer (string url)
|
2012-07-31 09:36:52 +08:00
|
|
|
{
|
2014-03-12 19:23:37 +08:00
|
|
|
_websocket = new WebSocket (url);
|
|
|
|
|
|
|
|
_audioBox = new Dictionary<uint, Queue> ();
|
|
|
|
_id = null;
|
|
|
|
_notifier = new Notifier ();
|
2016-07-26 15:52:42 +08:00
|
|
|
_timer = new Timer (sendHeartbeat, null, -1, -1);
|
2012-07-31 09:36:52 +08:00
|
|
|
|
2014-03-12 19:23:37 +08:00
|
|
|
configure ();
|
2012-07-31 09:36:52 +08:00
|
|
|
}
|
|
|
|
|
2014-03-12 19:23:37 +08:00
|
|
|
private void configure ()
|
|
|
|
{
|
|
|
|
#if DEBUG
|
|
|
|
_websocket.Log.Level = LogLevel.Trace;
|
|
|
|
#endif
|
|
|
|
_websocket.OnOpen += (sender, e) =>
|
2016-07-26 15:52:42 +08:00
|
|
|
_websocket.Send (createTextMessage ("connection", String.Empty));
|
2014-03-12 19:23:37 +08:00
|
|
|
|
|
|
|
_websocket.OnMessage += (sender, e) => {
|
2016-07-26 15:52:42 +08:00
|
|
|
if (e.IsText) {
|
2016-07-28 14:31:04 +08:00
|
|
|
_notifier.Notify (processTextMessage (e.Data));
|
2014-03-12 19:23:37 +08:00
|
|
|
return;
|
2016-07-26 15:52:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (e.IsBinary) {
|
2016-07-28 14:45:28 +08:00
|
|
|
processBinaryMessage (e.RawData);
|
2014-03-12 19:23:37 +08:00
|
|
|
return;
|
2012-07-31 09:36:52 +08:00
|
|
|
}
|
2016-07-26 15:52:42 +08:00
|
|
|
};
|
2012-07-31 09:36:52 +08:00
|
|
|
|
2014-03-12 19:23:37 +08:00
|
|
|
_websocket.OnError += (sender, e) =>
|
2016-07-26 15:52:42 +08:00
|
|
|
_notifier.Notify (
|
|
|
|
new NotificationMessage {
|
|
|
|
Summary = "AudioStreamer (error)",
|
|
|
|
Body = e.Message,
|
|
|
|
Icon = "notification-message-im"
|
|
|
|
}
|
|
|
|
);
|
2014-03-12 19:23:37 +08:00
|
|
|
|
|
|
|
_websocket.OnClose += (sender, e) =>
|
2016-07-26 15:52:42 +08:00
|
|
|
_notifier.Notify (
|
|
|
|
new NotificationMessage {
|
|
|
|
Summary = "AudioStreamer (disconnect)",
|
|
|
|
Body = String.Format ("code: {0} reason: {1}", e.Code, e.Reason),
|
|
|
|
Icon = "notification-message-im"
|
|
|
|
}
|
|
|
|
);
|
2012-07-31 09:36:52 +08:00
|
|
|
}
|
|
|
|
|
2016-07-28 14:31:04 +08:00
|
|
|
private byte[] createBinaryMessage (float[,] bufferArray)
|
2014-10-02 15:16:15 +08:00
|
|
|
{
|
2016-08-02 14:46:56 +08:00
|
|
|
return new BinaryMessage {
|
|
|
|
UserID = (uint) _id,
|
|
|
|
ChannelNumber = (byte) bufferArray.GetLength (0),
|
|
|
|
BufferLength = (uint) bufferArray.GetLength (1),
|
|
|
|
BufferArray = bufferArray
|
|
|
|
}
|
|
|
|
.ToArray ();
|
2016-07-28 14:31:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
private string createTextMessage (string type, string message)
|
|
|
|
{
|
2016-07-31 16:02:25 +08:00
|
|
|
return new TextMessage {
|
|
|
|
UserID = _id,
|
|
|
|
Name = _name,
|
|
|
|
Type = type,
|
|
|
|
Message = message
|
|
|
|
}
|
|
|
|
.ToString ();
|
2016-07-28 14:31:04 +08:00
|
|
|
}
|
|
|
|
|
2016-07-28 14:45:28 +08:00
|
|
|
private void processBinaryMessage (byte[] data)
|
|
|
|
{
|
2016-08-02 14:46:56 +08:00
|
|
|
var msg = BinaryMessage.Parse (data);
|
|
|
|
|
|
|
|
var id = msg.UserID;
|
|
|
|
if (id == _id)
|
2016-07-28 14:45:28 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
Queue queue;
|
2016-08-02 14:46:56 +08:00
|
|
|
if (_audioBox.TryGetValue (id, out queue)) {
|
|
|
|
queue.Enqueue (msg.BufferArray);
|
2016-07-28 14:45:28 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
queue = Queue.Synchronized (new Queue ());
|
2016-08-02 14:46:56 +08:00
|
|
|
queue.Enqueue (msg.BufferArray);
|
|
|
|
_audioBox.Add (id, queue);
|
2016-07-28 14:45:28 +08:00
|
|
|
}
|
|
|
|
|
2016-07-28 14:31:04 +08:00
|
|
|
private NotificationMessage processTextMessage (string data)
|
|
|
|
{
|
|
|
|
var json = JObject.Parse (data);
|
2014-10-02 15:16:15 +08:00
|
|
|
var id = (uint) json["user_id"];
|
|
|
|
var name = (string) json["name"];
|
|
|
|
var type = (string) json["type"];
|
|
|
|
|
|
|
|
string body;
|
|
|
|
if (type == "message") {
|
|
|
|
body = String.Format ("{0}: {1}", name, (string) json["message"]);
|
|
|
|
}
|
|
|
|
else if (type == "start_music") {
|
|
|
|
body = String.Format ("{0}: Started playing music!", name);
|
|
|
|
}
|
|
|
|
else if (type == "connection") {
|
|
|
|
var users = (JArray) json["message"];
|
|
|
|
var buff = new StringBuilder ("Now keeping connections:");
|
2016-07-26 15:52:42 +08:00
|
|
|
foreach (JToken user in users) {
|
2014-10-02 15:16:15 +08:00
|
|
|
buff.AppendFormat (
|
2016-07-26 15:52:42 +08:00
|
|
|
"\n- user_id: {0} name: {1}", (uint) user["user_id"], (string) user["name"]
|
|
|
|
);
|
|
|
|
}
|
2014-10-02 15:16:15 +08:00
|
|
|
|
|
|
|
body = buff.ToString ();
|
|
|
|
}
|
|
|
|
else if (type == "connected") {
|
|
|
|
_id = id;
|
2016-07-26 15:52:42 +08:00
|
|
|
_timer.Change (30000, 30000);
|
2016-07-28 14:31:04 +08:00
|
|
|
|
2014-10-02 15:16:15 +08:00
|
|
|
body = String.Format ("user_id: {0} name: {1}", id, name);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
body = "Received unknown type message.";
|
|
|
|
}
|
|
|
|
|
|
|
|
return new NotificationMessage {
|
2016-07-26 15:52:42 +08:00
|
|
|
Summary = String.Format ("AudioStreamer ({0})", type),
|
|
|
|
Body = body,
|
|
|
|
Icon = "notification-message-im"
|
|
|
|
};
|
2014-10-02 15:16:15 +08:00
|
|
|
}
|
|
|
|
|
2014-03-12 19:23:37 +08:00
|
|
|
private void sendHeartbeat (object state)
|
2012-07-31 09:36:52 +08:00
|
|
|
{
|
2014-03-12 19:23:37 +08:00
|
|
|
_websocket.Send (createTextMessage ("heartbeat", String.Empty));
|
2012-07-31 09:36:52 +08:00
|
|
|
}
|
|
|
|
|
2016-07-30 15:19:24 +08:00
|
|
|
public void Close ()
|
|
|
|
{
|
|
|
|
Disconnect ();
|
|
|
|
_timer.Dispose ();
|
|
|
|
_notifier.Close ();
|
|
|
|
}
|
|
|
|
|
2014-03-13 15:08:28 +08:00
|
|
|
public void Connect (string username)
|
2012-07-31 09:36:52 +08:00
|
|
|
{
|
2014-03-13 15:08:28 +08:00
|
|
|
_name = username;
|
2014-03-12 19:23:37 +08:00
|
|
|
_websocket.Connect ();
|
2012-07-31 09:36:52 +08:00
|
|
|
}
|
|
|
|
|
2014-03-12 19:23:37 +08:00
|
|
|
public void Disconnect ()
|
2012-07-31 09:36:52 +08:00
|
|
|
{
|
2016-07-26 15:52:42 +08:00
|
|
|
_timer.Change (-1, -1);
|
2014-03-13 15:08:28 +08:00
|
|
|
_websocket.Close (CloseStatusCode.Away);
|
|
|
|
_audioBox.Clear ();
|
|
|
|
_id = null;
|
|
|
|
_name = null;
|
2012-07-31 09:36:52 +08:00
|
|
|
}
|
|
|
|
|
2014-03-12 19:23:37 +08:00
|
|
|
public void Write (string message)
|
2012-07-31 09:36:52 +08:00
|
|
|
{
|
2014-03-12 19:23:37 +08:00
|
|
|
_websocket.Send (createTextMessage ("message", message));
|
2012-07-31 09:36:52 +08:00
|
|
|
}
|
|
|
|
|
2014-03-12 19:23:37 +08:00
|
|
|
void IDisposable.Dispose ()
|
2012-07-31 09:36:52 +08:00
|
|
|
{
|
2016-07-30 15:19:24 +08:00
|
|
|
Close ();
|
2012-07-31 09:36:52 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|