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.

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