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.

203 lines
5.4 KiB

13 years ago
13 years ago
12 years ago
13 years ago
12 years ago
13 years ago
12 years ago
13 years ago
12 years ago
13 years ago
12 years ago
13 years ago
12 years ago
12 years ago
12 years ago
12 years ago
13 years ago
12 years ago
13 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
13 years ago
13 years ago
12 years ago
13 years ago
12 years ago
13 years ago
12 years ago
13 years ago
12 years ago
13 years ago
12 years ago
13 years ago
12 years ago
13 years ago
12 years ago
13 years ago
12 years ago
13 years ago
12 years ago
13 years ago
12 years ago
13 years ago
12 years ago
12 years ago
13 years ago
12 years ago
13 years ago
12 years ago
13 years ago
12 years ago
13 years ago
12 years ago
13 years ago
12 years ago
13 years ago
12 years ago
12 years ago
13 years ago
  1. using Newtonsoft.Json;
  2. using Newtonsoft.Json.Linq;
  3. using System;
  4. using System.Collections;
  5. using System.Collections.Generic;
  6. using System.Text;
  7. using System.Threading;
  8. using WebSocketSharp;
  9. namespace Example1
  10. {
  11. internal class AudioStreamer : IDisposable
  12. {
  13. private Dictionary<uint, Queue> _audioBox;
  14. private Timer _heartbeatTimer;
  15. private uint? _id;
  16. private string _name;
  17. private Notifier _notifier;
  18. private WebSocket _websocket;
  19. public AudioStreamer (string url)
  20. {
  21. _websocket = new WebSocket (url);
  22. _audioBox = new Dictionary<uint, Queue> ();
  23. _heartbeatTimer = new Timer (sendHeartbeat, null, -1, -1);
  24. _id = null;
  25. _notifier = new Notifier ();
  26. configure ();
  27. }
  28. private void configure ()
  29. {
  30. #if DEBUG
  31. _websocket.Log.Level = LogLevel.Trace;
  32. #endif
  33. _websocket.OnOpen += (sender, e) =>
  34. _websocket.Send (createTextMessage ("connection", String.Empty));
  35. _websocket.OnMessage += (sender, e) => {
  36. if (e.Type == Opcode.Text) {
  37. _notifier.Notify (convertTextMessage (e.Data));
  38. }
  39. else {
  40. var msg = convertBinaryMessage (e.RawData);
  41. if (msg.user_id == _id)
  42. return;
  43. if (_audioBox.ContainsKey (msg.user_id)) {
  44. _audioBox[msg.user_id].Enqueue (msg.buffer_array);
  45. return;
  46. }
  47. var queue = Queue.Synchronized (new Queue ());
  48. queue.Enqueue (msg.buffer_array);
  49. _audioBox.Add (msg.user_id, queue);
  50. }
  51. };
  52. _websocket.OnError += (sender, e) =>
  53. _notifier.Notify (
  54. new NotificationMessage {
  55. Summary = "AudioStreamer (error)",
  56. Body = e.Message,
  57. Icon = "notification-message-im"
  58. });
  59. _websocket.OnClose += (sender, e) =>
  60. _notifier.Notify (
  61. new NotificationMessage {
  62. Summary = "AudioStreamer (disconnect)",
  63. Body = String.Format ("code: {0} reason: {1}", e.Code, e.Reason),
  64. Icon = "notification-message-im"
  65. });
  66. }
  67. private AudioMessage convertBinaryMessage (byte[] data)
  68. {
  69. var id = data.SubArray (0, 4).To<uint> (ByteOrder.Big);
  70. var chNum = data.SubArray (4, 1)[0];
  71. var buffLen = data.SubArray (5, 4).To<uint> (ByteOrder.Big);
  72. var buffArr = new float[chNum, buffLen];
  73. var offset = 9;
  74. ((int) chNum).Times (
  75. i => buffLen.Times (
  76. j => {
  77. buffArr[i, j] = data.SubArray (offset, 4).To<float> (ByteOrder.Big);
  78. offset += 4;
  79. }));
  80. return new AudioMessage {
  81. user_id = id,
  82. ch_num = chNum,
  83. buffer_length = buffLen,
  84. buffer_array = buffArr
  85. };
  86. }
  87. private NotificationMessage convertTextMessage (string data)
  88. {
  89. var json = JObject.Parse (data);
  90. var id = (uint) json["user_id"];
  91. var name = (string) json["name"];
  92. var type = (string) json["type"];
  93. string body;
  94. if (type == "message") {
  95. body = String.Format ("{0}: {1}", name, (string) json["message"]);
  96. }
  97. else if (type == "start_music") {
  98. body = String.Format ("{0}: Started playing music!", name);
  99. }
  100. else if (type == "connection") {
  101. var users = (JArray) json["message"];
  102. var buff = new StringBuilder ("Now keeping connections:");
  103. foreach (JToken user in users)
  104. buff.AppendFormat (
  105. "\n- user_id: {0} name: {1}", (uint) user["user_id"], (string) user["name"]);
  106. body = buff.ToString ();
  107. }
  108. else if (type == "connected") {
  109. _id = id;
  110. _heartbeatTimer.Change (30000, 30000);
  111. body = String.Format ("user_id: {0} name: {1}", id, name);
  112. }
  113. else {
  114. body = "Received unknown type message.";
  115. }
  116. return new NotificationMessage {
  117. Summary = String.Format ("AudioStreamer ({0})", type),
  118. Body = body,
  119. Icon = "notification-message-im"
  120. };
  121. }
  122. private byte[] createBinaryMessage (float[,] bufferArray)
  123. {
  124. var msg = new List<byte> ();
  125. var id = (uint) _id;
  126. var chNum = bufferArray.GetLength (0);
  127. var buffLen = bufferArray.GetLength (1);
  128. msg.AddRange (id.ToByteArray (ByteOrder.Big));
  129. msg.Add ((byte) chNum);
  130. msg.AddRange (((uint) buffLen).ToByteArray (ByteOrder.Big));
  131. chNum.Times (
  132. i => buffLen.Times (
  133. j => msg.AddRange (bufferArray[i, j].ToByteArray (ByteOrder.Big))));
  134. return msg.ToArray ();
  135. }
  136. private string createTextMessage (string type, string message)
  137. {
  138. return JsonConvert.SerializeObject (
  139. new TextMessage {
  140. user_id = _id,
  141. name = _name,
  142. type = type,
  143. message = message
  144. });
  145. }
  146. private void sendHeartbeat (object state)
  147. {
  148. _websocket.Send (createTextMessage ("heartbeat", String.Empty));
  149. }
  150. public void Connect (string username)
  151. {
  152. _name = username;
  153. _websocket.Connect ();
  154. }
  155. public void Disconnect ()
  156. {
  157. _heartbeatTimer.Change (-1, -1);
  158. _websocket.Close (CloseStatusCode.Away);
  159. _audioBox.Clear ();
  160. _id = null;
  161. _name = null;
  162. }
  163. public void Write (string message)
  164. {
  165. _websocket.Send (createTextMessage ("message", message));
  166. }
  167. void IDisposable.Dispose ()
  168. {
  169. Disconnect ();
  170. _heartbeatTimer.Dispose ();
  171. _notifier.Close ();
  172. }
  173. }
  174. }