corrade-vassal – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | vero | 1 | /* |
2 | * Copyright (c) 2006-2014, openmetaverse.org |
||
3 | * All rights reserved. |
||
4 | * |
||
5 | * - Redistribution and use in source and binary forms, with or without |
||
6 | * modification, are permitted provided that the following conditions are met: |
||
7 | * |
||
8 | * - Redistributions of source code must retain the above copyright notice, this |
||
9 | * list of conditions and the following disclaimer. |
||
10 | * - Neither the name of the openmetaverse.org nor the names |
||
11 | * of its contributors may be used to endorse or promote products derived from |
||
12 | * this software without specific prior written permission. |
||
13 | * |
||
14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||
15 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||
16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||
17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
||
18 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||
19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||
20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||
21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||
22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||
23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||
24 | * POSSIBILITY OF SUCH DAMAGE. |
||
25 | */ |
||
26 | |||
27 | using System; |
||
28 | using System.Collections.Generic; |
||
29 | using System.IO; |
||
30 | using System.Net.Sockets; |
||
31 | using System.Diagnostics; |
||
32 | using System.Threading; |
||
33 | using System.Text; |
||
34 | |||
35 | namespace OpenMetaverse.Voice |
||
36 | { |
||
37 | public partial class VoiceGateway |
||
38 | { |
||
39 | public delegate void DaemonRunningCallback(); |
||
40 | public delegate void DaemonExitedCallback(); |
||
41 | public delegate void DaemonCouldntRunCallback(); |
||
42 | public delegate void DaemonConnectedCallback(); |
||
43 | public delegate void DaemonDisconnectedCallback(); |
||
44 | public delegate void DaemonCouldntConnectCallback(); |
||
45 | |||
46 | public event DaemonRunningCallback OnDaemonRunning; |
||
47 | public event DaemonExitedCallback OnDaemonExited; |
||
48 | public event DaemonCouldntRunCallback OnDaemonCouldntRun; |
||
49 | public event DaemonConnectedCallback OnDaemonConnected; |
||
50 | public event DaemonDisconnectedCallback OnDaemonDisconnected; |
||
51 | public event DaemonCouldntConnectCallback OnDaemonCouldntConnect; |
||
52 | |||
53 | public bool DaemonIsRunning { get { return daemonIsRunning; } } |
||
54 | public bool DaemonIsConnected { get { return daemonIsConnected; } } |
||
55 | public int RequestId { get { return requestId; } } |
||
56 | |||
57 | protected Process daemonProcess; |
||
58 | protected ManualResetEvent daemonLoopSignal = new ManualResetEvent(false); |
||
59 | protected TCPPipe daemonPipe; |
||
60 | protected bool daemonIsRunning = false; |
||
61 | protected bool daemonIsConnected = false; |
||
62 | protected int requestId = 0; |
||
63 | |||
64 | #region Daemon Management |
||
65 | |||
66 | /// <summary> |
||
67 | /// Starts a thread that keeps the daemon running |
||
68 | /// </summary> |
||
69 | /// <param name="path"></param> |
||
70 | /// <param name="args"></param> |
||
71 | public void StartDaemon(string path, string args) |
||
72 | { |
||
73 | StopDaemon(); |
||
74 | daemonLoopSignal.Set(); |
||
75 | |||
76 | Thread thread = new Thread(new ThreadStart(delegate() |
||
77 | { |
||
78 | while (daemonLoopSignal.WaitOne(500, false)) |
||
79 | { |
||
80 | daemonProcess = new Process(); |
||
81 | daemonProcess.StartInfo.FileName = path; |
||
82 | daemonProcess.StartInfo.WorkingDirectory = Path.GetDirectoryName(path); |
||
83 | daemonProcess.StartInfo.Arguments = args; |
||
84 | daemonProcess.StartInfo.UseShellExecute = false; |
||
85 | |||
86 | if (Environment.OSVersion.Platform == PlatformID.Unix) |
||
87 | { |
||
88 | string ldPath = string.Empty; |
||
89 | try |
||
90 | { |
||
91 | ldPath = Environment.GetEnvironmentVariable("LD_LIBRARY_PATH"); |
||
92 | } |
||
93 | catch { } |
||
94 | string newLdPath = daemonProcess.StartInfo.WorkingDirectory; |
||
95 | if (!string.IsNullOrEmpty(ldPath)) |
||
96 | newLdPath += ":" + ldPath; |
||
97 | daemonProcess.StartInfo.EnvironmentVariables.Add("LD_LIBRARY_PATH", newLdPath); |
||
98 | } |
||
99 | |||
100 | Logger.DebugLog("Voice folder: " + daemonProcess.StartInfo.WorkingDirectory); |
||
101 | Logger.DebugLog(path + " " + args); |
||
102 | bool ok = true; |
||
103 | |||
104 | if (!File.Exists(path)) |
||
105 | ok = false; |
||
106 | |||
107 | if (ok) |
||
108 | { |
||
109 | // Attempt to start the process |
||
110 | if (!daemonProcess.Start()) |
||
111 | ok = false; |
||
112 | } |
||
113 | |||
114 | if (!ok) |
||
115 | { |
||
116 | daemonIsRunning = false; |
||
117 | daemonLoopSignal.Reset(); |
||
118 | |||
119 | if (OnDaemonCouldntRun != null) |
||
120 | { |
||
121 | try { OnDaemonCouldntRun(); } |
||
122 | catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, null, e); } |
||
123 | } |
||
124 | |||
125 | return; |
||
126 | } |
||
127 | else |
||
128 | { |
||
129 | Thread.Sleep(2000); |
||
130 | daemonIsRunning = true; |
||
131 | if (OnDaemonRunning != null) |
||
132 | { |
||
133 | try { OnDaemonRunning(); } |
||
134 | catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, null, e); } |
||
135 | } |
||
136 | |||
137 | Logger.DebugLog("Started voice daemon, waiting for exit..."); |
||
138 | daemonProcess.WaitForExit(); |
||
139 | Logger.DebugLog("Voice daemon exited"); |
||
140 | daemonIsRunning = false; |
||
141 | |||
142 | if (OnDaemonExited != null) |
||
143 | { |
||
144 | try { OnDaemonExited(); } |
||
145 | catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, null, e); } |
||
146 | } |
||
147 | } |
||
148 | } |
||
149 | })); |
||
150 | |||
151 | thread.Name = "VoiceDaemonController"; |
||
152 | thread.IsBackground = true; |
||
153 | thread.Start(); |
||
154 | } |
||
155 | |||
156 | /// <summary> |
||
157 | /// Stops the daemon and the thread keeping it running |
||
158 | /// </summary> |
||
159 | public void StopDaemon() |
||
160 | { |
||
161 | daemonLoopSignal.Reset(); |
||
162 | if (daemonProcess != null) |
||
163 | { |
||
164 | try |
||
165 | { |
||
166 | daemonProcess.Kill(); |
||
167 | } |
||
168 | catch (InvalidOperationException ex) |
||
169 | { |
||
170 | Logger.Log("Failed to stop the voice daemon", Helpers.LogLevel.Error, ex); |
||
171 | } |
||
172 | } |
||
173 | } |
||
174 | |||
175 | /// <summary> |
||
176 | /// |
||
177 | /// </summary> |
||
178 | /// <param name="address"></param> |
||
179 | /// <param name="port"></param> |
||
180 | /// <returns></returns> |
||
181 | public bool ConnectToDaemon(string address, int port) |
||
182 | { |
||
183 | daemonIsConnected = false; |
||
184 | |||
185 | daemonPipe = new TCPPipe(); |
||
186 | daemonPipe.OnDisconnected += |
||
187 | delegate(SocketException e) |
||
188 | { |
||
189 | if (OnDaemonDisconnected != null) |
||
190 | { |
||
191 | try { OnDaemonDisconnected(); } |
||
192 | catch (Exception ex) { Logger.Log(ex.Message, Helpers.LogLevel.Error, null, ex); } |
||
193 | } |
||
194 | }; |
||
195 | daemonPipe.OnReceiveLine += new TCPPipe.OnReceiveLineCallback(daemonPipe_OnReceiveLine); |
||
196 | |||
197 | SocketException se = daemonPipe.Connect(address, port); |
||
198 | if (se == null) |
||
199 | { |
||
200 | daemonIsConnected = true; |
||
201 | |||
202 | if (OnDaemonConnected != null) |
||
203 | { |
||
204 | try { OnDaemonConnected(); } |
||
205 | catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, null, e); } |
||
206 | } |
||
207 | |||
208 | return true; |
||
209 | } |
||
210 | else |
||
211 | { |
||
212 | daemonIsConnected = false; |
||
213 | |||
214 | if (OnDaemonCouldntConnect != null) |
||
215 | { |
||
216 | try { OnDaemonCouldntConnect(); } |
||
217 | catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, null, e); } |
||
218 | } |
||
219 | |||
220 | Logger.Log("Voice daemon connection failed: " + se.Message, Helpers.LogLevel.Error); |
||
221 | return false; |
||
222 | } |
||
223 | } |
||
224 | |||
225 | #endregion Daemon Management |
||
226 | |||
227 | public int Request(string action) |
||
228 | { |
||
229 | return Request(action, null); |
||
230 | } |
||
231 | |||
232 | public int Request(string action, string requestXML) |
||
233 | { |
||
234 | int returnId = requestId; |
||
235 | if (daemonIsConnected) |
||
236 | { |
||
237 | StringBuilder sb = new StringBuilder(); |
||
238 | sb.Append(String.Format("<Request requestId=\"{0}\" action=\"{1}\"", requestId++, action)); |
||
239 | if (string.IsNullOrEmpty(requestXML)) |
||
240 | { |
||
241 | sb.Append(" />"); |
||
242 | } |
||
243 | else |
||
244 | { |
||
245 | sb.Append(">"); |
||
246 | sb.Append(requestXML); |
||
247 | sb.Append("</Request>"); |
||
248 | } |
||
249 | sb.Append("\n\n\n"); |
||
250 | |||
251 | #if DEBUG |
||
252 | Logger.Log("Request: " + sb.ToString(), Helpers.LogLevel.Debug); |
||
253 | #endif |
||
254 | try |
||
255 | { |
||
256 | daemonPipe.SendData(Encoding.ASCII.GetBytes(sb.ToString())); |
||
257 | } |
||
258 | catch |
||
259 | { |
||
260 | returnId = -1; |
||
261 | } |
||
262 | |||
263 | return returnId; |
||
264 | } |
||
265 | else |
||
266 | { |
||
267 | return -1; |
||
268 | } |
||
269 | } |
||
270 | |||
271 | public static string MakeXML(string name, string text) |
||
272 | { |
||
273 | if (string.IsNullOrEmpty(text)) |
||
274 | return string.Format("<{0} />", name); |
||
275 | else |
||
276 | return string.Format("<{0}>{1}</{0}>", name, text); |
||
277 | } |
||
278 | |||
279 | private void daemonPipe_OnReceiveLine(string line) |
||
280 | { |
||
281 | #if DEBUG |
||
282 | Logger.Log(line, Helpers.LogLevel.Debug); |
||
283 | #endif |
||
284 | |||
285 | if (line.Substring(0, 10) == "<Response ") |
||
286 | { |
||
287 | VoiceResponse rsp = null; |
||
288 | try |
||
289 | { |
||
290 | rsp = (VoiceResponse)ResponseSerializer.Deserialize(new StringReader(line)); |
||
291 | } |
||
292 | catch (Exception e) |
||
293 | { |
||
294 | Logger.Log("Failed to deserialize voice daemon response", Helpers.LogLevel.Error, e); |
||
295 | return; |
||
296 | } |
||
297 | |||
298 | ResponseType genericResponse = ResponseType.None; |
||
299 | |||
300 | switch (rsp.Action) |
||
301 | { |
||
302 | // These first responses carry useful information beyond simple status, |
||
303 | // so they each have a specific Event. |
||
304 | case "Connector.Create.1": |
||
305 | if (OnConnectorCreateResponse != null) |
||
306 | { |
||
307 | OnConnectorCreateResponse( |
||
308 | rsp.InputXml.Request, |
||
309 | new VoiceConnectorEventArgs( |
||
310 | int.Parse(rsp.ReturnCode), |
||
311 | int.Parse(rsp.Results.StatusCode), |
||
312 | rsp.Results.StatusString, |
||
313 | rsp.Results.VersionID, |
||
314 | rsp.Results.ConnectorHandle)); |
||
315 | } |
||
316 | break; |
||
317 | case "Aux.GetCaptureDevices.1": |
||
318 | inputDevices = new List<string>(); |
||
319 | |||
320 | if (rsp.Results.CaptureDevices.Count == 0 || rsp.Results.CurrentCaptureDevice == null) |
||
321 | break; |
||
322 | |||
323 | foreach (CaptureDevice device in rsp.Results.CaptureDevices) |
||
324 | inputDevices.Add(device.Device); |
||
325 | currentCaptureDevice = rsp.Results.CurrentCaptureDevice.Device; |
||
326 | |||
327 | if (OnAuxGetCaptureDevicesResponse != null && rsp.Results.CaptureDevices.Count > 0) |
||
328 | { |
||
329 | OnAuxGetCaptureDevicesResponse( |
||
330 | rsp.InputXml.Request, |
||
331 | new VoiceDevicesEventArgs( |
||
332 | ResponseType.GetCaptureDevices, |
||
333 | int.Parse(rsp.ReturnCode), |
||
334 | int.Parse(rsp.Results.StatusCode), |
||
335 | rsp.Results.StatusString, |
||
336 | rsp.Results.CurrentCaptureDevice.Device, |
||
337 | inputDevices)); |
||
338 | } |
||
339 | break; |
||
340 | case "Aux.GetRenderDevices.1": |
||
341 | outputDevices = new List<string>(); |
||
342 | |||
343 | if (rsp.Results.RenderDevices.Count == 0 || rsp.Results.CurrentRenderDevice == null) |
||
344 | break; |
||
345 | |||
346 | foreach (RenderDevice device in rsp.Results.RenderDevices) |
||
347 | outputDevices.Add(device.Device); |
||
348 | |||
349 | |||
350 | currentPlaybackDevice = rsp.Results.CurrentRenderDevice.Device; |
||
351 | |||
352 | if (OnAuxGetRenderDevicesResponse != null) |
||
353 | { |
||
354 | OnAuxGetRenderDevicesResponse( |
||
355 | rsp.InputXml.Request, |
||
356 | new VoiceDevicesEventArgs( |
||
357 | ResponseType.GetCaptureDevices, |
||
358 | int.Parse(rsp.ReturnCode), |
||
359 | int.Parse(rsp.Results.StatusCode), |
||
360 | rsp.Results.StatusString, |
||
361 | rsp.Results.CurrentRenderDevice.Device, |
||
362 | outputDevices)); |
||
363 | } |
||
364 | break; |
||
365 | |||
366 | case "Account.Login.1": |
||
367 | if (OnAccountLoginResponse != null) |
||
368 | { |
||
369 | OnAccountLoginResponse(rsp.InputXml.Request, |
||
370 | new VoiceAccountEventArgs( |
||
371 | int.Parse(rsp.ReturnCode), |
||
372 | int.Parse(rsp.Results.StatusCode), |
||
373 | rsp.Results.StatusString, |
||
374 | rsp.Results.AccountHandle)); |
||
375 | } |
||
376 | break; |
||
377 | |||
378 | case "Session.Create.1": |
||
379 | if (OnSessionCreateResponse != null) |
||
380 | { |
||
381 | OnSessionCreateResponse( |
||
382 | rsp.InputXml.Request, |
||
383 | new VoiceSessionEventArgs( |
||
384 | int.Parse(rsp.ReturnCode), |
||
385 | int.Parse(rsp.Results.StatusCode), |
||
386 | rsp.Results.StatusString, |
||
387 | rsp.Results.SessionHandle)); |
||
388 | } |
||
389 | break; |
||
390 | |||
391 | // All the remaining responses below this point just report status, |
||
392 | // so they all share the same Event. Most are useful only for |
||
393 | // detecting coding errors. |
||
394 | case "Connector.InitiateShutdown.1": |
||
395 | genericResponse = ResponseType.ConnectorInitiateShutdown; |
||
396 | break; |
||
397 | case "Aux.SetRenderDevice.1": |
||
398 | genericResponse = ResponseType.SetRenderDevice; |
||
399 | break; |
||
400 | case "Connector.MuteLocalMic.1": |
||
401 | genericResponse = ResponseType.MuteLocalMic; |
||
402 | break; |
||
403 | case "Connector.MuteLocalSpeaker.1": |
||
404 | genericResponse = ResponseType.MuteLocalSpeaker; |
||
405 | break; |
||
406 | case "Connector.SetLocalMicVolume.1": |
||
407 | genericResponse = ResponseType.SetLocalMicVolume; |
||
408 | break; |
||
409 | case "Connector.SetLocalSpeakerVolume.1": |
||
410 | genericResponse = ResponseType.SetLocalSpeakerVolume; |
||
411 | break; |
||
412 | case "Aux.SetCaptureDevice.1": |
||
413 | genericResponse = ResponseType.SetCaptureDevice; |
||
414 | break; |
||
415 | case "Session.RenderAudioStart.1": |
||
416 | genericResponse = ResponseType.RenderAudioStart; |
||
417 | break; |
||
418 | case "Session.RenderAudioStop.1": |
||
419 | genericResponse = ResponseType.RenderAudioStop; |
||
420 | break; |
||
421 | case "Aux.CaptureAudioStart.1": |
||
422 | genericResponse = ResponseType.CaptureAudioStart; |
||
423 | break; |
||
424 | case "Aux.CaptureAudioStop.1": |
||
425 | genericResponse = ResponseType.CaptureAudioStop; |
||
426 | break; |
||
427 | case "Aux.SetMicLevel.1": |
||
428 | genericResponse = ResponseType.SetMicLevel; |
||
429 | break; |
||
430 | case "Aux.SetSpeakerLevel.1": |
||
431 | genericResponse = ResponseType.SetSpeakerLevel; |
||
432 | break; |
||
433 | case "Account.Logout.1": |
||
434 | genericResponse = ResponseType.AccountLogout; |
||
435 | break; |
||
436 | case "Session.Connect.1": |
||
437 | genericResponse = ResponseType.SessionConnect; |
||
438 | break; |
||
439 | case "Session.Terminate.1": |
||
440 | genericResponse = ResponseType.SessionTerminate; |
||
441 | break; |
||
442 | case "Session.SetParticipantVolumeForMe.1": |
||
443 | genericResponse = ResponseType.SetParticipantVolumeForMe; |
||
444 | break; |
||
445 | case "Session.SetParticipantMuteForMe.1": |
||
446 | genericResponse = ResponseType.SetParticipantMuteForMe; |
||
447 | break; |
||
448 | case "Session.Set3DPosition.1": |
||
449 | genericResponse = ResponseType.Set3DPosition; |
||
450 | break; |
||
451 | default: |
||
452 | Logger.Log("Unimplemented response from the voice daemon: " + line, Helpers.LogLevel.Error); |
||
453 | break; |
||
454 | } |
||
455 | |||
456 | // Send the Response Event for all the simple cases. |
||
457 | if (genericResponse != ResponseType.None && OnVoiceResponse != null) |
||
458 | { |
||
459 | OnVoiceResponse(rsp.InputXml.Request, |
||
460 | new VoiceResponseEventArgs( |
||
461 | genericResponse, |
||
462 | int.Parse(rsp.ReturnCode), |
||
463 | int.Parse(rsp.Results.StatusCode), |
||
464 | rsp.Results.StatusString)); |
||
465 | } |
||
466 | } |
||
467 | else if (line.Substring(0, 7) == "<Event ") |
||
468 | { |
||
469 | VoiceEvent evt = null; |
||
470 | try |
||
471 | { |
||
472 | evt = (VoiceEvent)EventSerializer.Deserialize(new StringReader(line)); |
||
473 | } |
||
474 | catch (Exception e) |
||
475 | { |
||
476 | Logger.Log("Failed to deserialize voice daemon event", Helpers.LogLevel.Error, e); |
||
477 | return; |
||
478 | } |
||
479 | |||
480 | switch (evt.Type) |
||
481 | { |
||
482 | case "LoginStateChangeEvent": |
||
483 | case "AccountLoginStateChangeEvent": |
||
484 | if (OnAccountLoginStateChangeEvent != null) |
||
485 | { |
||
486 | OnAccountLoginStateChangeEvent(this, |
||
487 | new AccountLoginStateChangeEventArgs( |
||
488 | evt.AccountHandle, |
||
489 | int.Parse(evt.StatusCode), |
||
490 | evt.StatusString, |
||
491 | (LoginState)int.Parse(evt.State))); |
||
492 | } |
||
493 | break; |
||
494 | |||
495 | case "SessionNewEvent": |
||
496 | if (OnSessionNewEvent != null) |
||
497 | { |
||
498 | OnSessionNewEvent(this, |
||
499 | new NewSessionEventArgs( |
||
500 | evt.AccountHandle, |
||
501 | evt.SessionHandle, |
||
502 | evt.URI, |
||
503 | bool.Parse(evt.IsChannel), |
||
504 | evt.Name, |
||
505 | evt.AudioMedia)); |
||
506 | } |
||
507 | break; |
||
508 | |||
509 | case "SessionStateChangeEvent": |
||
510 | if (OnSessionStateChangeEvent != null) |
||
511 | { |
||
512 | OnSessionStateChangeEvent(this, |
||
513 | new SessionStateChangeEventArgs( |
||
514 | evt.SessionHandle, |
||
515 | int.Parse(evt.StatusCode), |
||
516 | evt.StatusString, |
||
517 | (SessionState)int.Parse(evt.State), |
||
518 | evt.URI, |
||
519 | bool.Parse(evt.IsChannel), |
||
520 | evt.ChannelName)); |
||
521 | } |
||
522 | break; |
||
523 | |||
524 | case "ParticipantAddedEvent": |
||
525 | Logger.Log("Add participant " + evt.ParticipantUri, Helpers.LogLevel.Debug); |
||
526 | if (OnSessionParticipantAddedEvent != null) |
||
527 | { |
||
528 | OnSessionParticipantAddedEvent(this, |
||
529 | new ParticipantAddedEventArgs( |
||
530 | evt.SessionGroupHandle, |
||
531 | evt.SessionHandle, |
||
532 | evt.ParticipantUri, |
||
533 | evt.AccountName, |
||
534 | evt.DisplayName, |
||
535 | (ParticipantType)int.Parse(evt.ParticipantType), |
||
536 | evt.Application)); |
||
537 | } |
||
538 | break; |
||
539 | |||
540 | case "ParticipantRemovedEvent": |
||
541 | if (OnSessionParticipantRemovedEvent != null) |
||
542 | { |
||
543 | OnSessionParticipantRemovedEvent(this, |
||
544 | new ParticipantRemovedEventArgs( |
||
545 | evt.SessionGroupHandle, |
||
546 | evt.SessionHandle, |
||
547 | evt.ParticipantUri, |
||
548 | evt.AccountName, |
||
549 | evt.Reason)); |
||
550 | } |
||
551 | break; |
||
552 | |||
553 | case "ParticipantStateChangeEvent": |
||
554 | // Useful in person-to-person calls |
||
555 | if (OnSessionParticipantStateChangeEvent != null) |
||
556 | { |
||
557 | OnSessionParticipantStateChangeEvent(this, |
||
558 | new ParticipantStateChangeEventArgs( |
||
559 | evt.SessionHandle, |
||
560 | int.Parse(evt.StatusCode), |
||
561 | evt.StatusString, |
||
562 | (ParticipantState)int.Parse(evt.State), // Ringing, Connected, etc |
||
563 | evt.ParticipantUri, |
||
564 | evt.AccountName, |
||
565 | evt.DisplayName, |
||
566 | (ParticipantType)int.Parse(evt.ParticipantType))); |
||
567 | } |
||
568 | break; |
||
569 | |||
570 | case "ParticipantPropertiesEvent": |
||
571 | if (OnSessionParticipantPropertiesEvent != null) |
||
572 | { |
||
573 | OnSessionParticipantPropertiesEvent(this, |
||
574 | new ParticipantPropertiesEventArgs( |
||
575 | evt.SessionHandle, |
||
576 | evt.ParticipantUri, |
||
577 | bool.Parse(evt.IsLocallyMuted), |
||
578 | bool.Parse(evt.IsModeratorMuted), |
||
579 | bool.Parse(evt.IsSpeaking), |
||
580 | int.Parse(evt.Volume), |
||
581 | float.Parse(evt.Energy))); |
||
582 | } |
||
583 | break; |
||
584 | |||
585 | case "ParticipantUpdatedEvent": |
||
586 | if (OnSessionParticipantUpdatedEvent != null) |
||
587 | { |
||
588 | OnSessionParticipantUpdatedEvent(this, |
||
589 | new ParticipantUpdatedEventArgs( |
||
590 | evt.SessionHandle, |
||
591 | evt.ParticipantUri, |
||
592 | bool.Parse(evt.IsModeratorMuted), |
||
593 | bool.Parse(evt.IsSpeaking), |
||
594 | int.Parse(evt.Volume), |
||
595 | float.Parse(evt.Energy))); |
||
596 | } |
||
597 | break; |
||
598 | |||
599 | case "SessionGroupAddedEvent": |
||
600 | if (OnSessionGroupAddedEvent != null) |
||
601 | { |
||
602 | OnSessionGroupAddedEvent(this, |
||
603 | new SessionGroupAddedEventArgs( |
||
604 | evt.AccountHandle, |
||
605 | evt.SessionGroupHandle, |
||
606 | evt.Type)); |
||
607 | } |
||
608 | break; |
||
609 | |||
610 | case "SessionAddedEvent": |
||
611 | if (OnSessionAddedEvent != null) |
||
612 | { |
||
613 | OnSessionAddedEvent(this, |
||
614 | new SessionAddedEventArgs( |
||
615 | evt.SessionGroupHandle, |
||
616 | evt.SessionHandle, |
||
617 | evt.Uri, |
||
618 | bool.Parse(evt.IsChannel), |
||
619 | bool.Parse(evt.Incoming))); |
||
620 | } |
||
621 | break; |
||
622 | |||
623 | case "SessionRemovedEvent": |
||
624 | if (OnSessionRemovedEvent != null) |
||
625 | { |
||
626 | OnSessionRemovedEvent(this, |
||
627 | new SessionRemovedEventArgs( |
||
628 | evt.SessionGroupHandle, |
||
629 | evt.SessionHandle, |
||
630 | evt.Uri)); |
||
631 | } |
||
632 | break; |
||
633 | |||
634 | case "SessionUpdatedEvent": |
||
635 | if (OnSessionRemovedEvent != null) |
||
636 | { |
||
637 | OnSessionUpdatedEvent(this, |
||
638 | new SessionUpdatedEventArgs( |
||
639 | evt.SessionGroupHandle, |
||
640 | evt.SessionHandle, |
||
641 | evt.Uri, |
||
642 | int.Parse(evt.IsMuted) != 0, |
||
643 | int.Parse(evt.Volume), |
||
644 | int.Parse(evt.TransmitEnabled) != 0, |
||
645 | + int.Parse(evt.IsFocused) != 0)); |
||
646 | } |
||
647 | break; |
||
648 | |||
649 | case "AuxAudioPropertiesEvent": |
||
650 | if (OnAuxAudioPropertiesEvent != null) |
||
651 | { |
||
652 | OnAuxAudioPropertiesEvent(this, |
||
653 | new AudioPropertiesEventArgs( |
||
654 | bool.Parse(evt.MicIsActive), |
||
655 | float.Parse(evt.MicEnergy), |
||
656 | int.Parse(evt.MicVolume), |
||
657 | int.Parse(evt.SpeakerVolume))); |
||
658 | } |
||
659 | break; |
||
660 | |||
661 | case "SessionMediaEvent": |
||
662 | if (OnSessionMediaEvent != null) |
||
663 | { |
||
664 | OnSessionMediaEvent(this, |
||
665 | new SessionMediaEventArgs( |
||
666 | evt.SessionHandle, |
||
667 | bool.Parse(evt.HasText), |
||
668 | bool.Parse(evt.HasAudio), |
||
669 | bool.Parse(evt.HasVideo), |
||
670 | bool.Parse(evt.Terminated))); |
||
671 | } |
||
672 | break; |
||
673 | |||
674 | case "BuddyAndGroupListChangedEvent": |
||
675 | // TODO * <AccountHandle>c1_m1000xrjiQgi95QhCzH_D6ZJ8c5A==</AccountHandle><Buddies /><Groups /> |
||
676 | break; |
||
677 | |||
678 | case "MediaStreamUpdatedEvent": |
||
679 | // TODO <SessionGroupHandle>c1_m1000xrjiQgi95QhCzH_D6ZJ8c5A==_sg0</SessionGroupHandle> |
||
680 | // <SessionHandle>c1_m1000xrjiQgi95QhCzH_D6ZJ8c5A==0</SessionHandle> |
||
681 | //<StatusCode>0</StatusCode><StatusString /><State>1</State><Incoming>false</Incoming> |
||
682 | |||
683 | break; |
||
684 | |||
685 | default: |
||
686 | Logger.Log("Unimplemented event from the voice daemon: " + line, Helpers.LogLevel.Error); |
||
687 | break; |
||
688 | } |
||
689 | } |
||
690 | else |
||
691 | { |
||
692 | Logger.Log("Unrecognized data from the voice daemon: " + line, Helpers.LogLevel.Error); |
||
693 | } |
||
694 | } |
||
695 | } |
||
696 | } |