123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text.Json;
- using Vinno.IUS.Common.Log;
- using Vinno.vCloud.Common.FIS.Helper;
- using Vinno.vCloud.FIS.CrossPlatform.Common;
- using Vinno.vCloud.FIS.CrossPlatform.Common.Consultation;
- using Vinno.vCloud.FIS.CrossPlatform.Common.Enum;
- using Vinno.vCloud.Protocol.Infrastructures;
- using WingInterfaceLibrary.Interface;
- using WingInterfaceLibrary.LiveConsultation;
- namespace Vinno.vCloud.Common.FIS.Consultation
- {
- internal abstract class ConsultationClientV2 : IDisposable
- {
- private ConsultationInfo _consultationInfo;
- private double _usInkCanvasWidth = 800;
- private double _usInkCanvasHeight = 600;
- private double _flyinsonoWidth = 10000;
- private double _flyinsonoHeight = 10000;
- private List<string> _muteVideoUserList;
- private readonly object _interactiveBoardLocker = new object();
- protected Dictionary<string, List<StrokePointList>> StrokeDict = new Dictionary<string, List<StrokePointList>>();
- protected readonly object ConsultationInfoLocker = new object();
- protected readonly ILiveConsultationService LiveConsultationService;
- protected readonly IUserService UserService;
- protected readonly IDeviceService DeviceService;
- protected string AccountId;
- protected string AccountToken;
- protected string AccountName;
- protected bool IsOnlyForRtmpPushing;
- protected int count = 0;
- protected ConsultationLiveVideoProviderV2 VideoProvider { get; }
- protected ConsultationManagerV2 ConsultationManager { get; }
- public bool IsSecondViewMode { get; protected set; }
- /// <summary>
- /// Gets or sets the current live status
- /// </summary>
- public LiveStates CurrentLiveStatus { get; set; }
- /// <summary>
- /// Raised when meeting disconnected.
- /// </summary>
- public event EventHandler<ConsultationDisconnectedType> ConsultationDisconnected;
- /// <summary>
- /// Raised when meeting member changed
- /// </summary>
- public event EventHandler<ConsultationMemberNotificaiton> ConsultationMemberChangedNotificationArrived;
- /// <summary>
- /// 接收到其他用户的白板信息
- /// </summary>
- public event EventHandler<InteractiveBoardInfo> InteractiveBoardInfoArrived;
- /// <summary>
- /// 接收到清除白板信息
- /// </summary>
- public event EventHandler<string> ClearInteractiveBoardArrived;
- public event EventHandler<List<string>> MuteVideoUserListNotifyArrived;
- public ConsultationInfo ConsultationInfo
- {
- get => _consultationInfo;
- set
- {
- if (_consultationInfo != value)
- {
- _consultationInfo = value;
- count = 0;
- }
- }
- }
- protected ConsultationClientV2(ConsultationLiveVideoProviderV2 videoProvider, ConsultationManagerV2 consultationManager, ILiveConsultationService liveConsultationService, IUserService userService, IDeviceService deviceService)
- {
- _muteVideoUserList = new List<string>();
- LiveConsultationService = liveConsultationService;
- UserService = userService;
- DeviceService = deviceService;
- CurrentLiveStatus = LiveStates.Idle;
- ConsultationManager = consultationManager;
- VideoProvider = videoProvider;
- VideoProvider.RemoteUserLeaveRoomArrived += OnRemoteUserLeaveRoomArrived;
- VideoProvider.CloseConsultation += OnCloseMeeting;
- VideoProvider.TryToReconnect += OnTryToReconnect;
- }
- protected void OnTryToReconnect(object sender, EventArgs e)
- {
- }
- private void OnRemoteUserLeaveRoomArrived(object sender, RemoteUserLeaveRoomArgs e)
- {
- }
- private void OnCloseMeeting(object sender, EventArgs e)
- {
- OnDisconnected(ConsultationDisconnectedType.SelfClientOffline);
- }
- protected void OnDisconnected(ConsultationDisconnectedType e)
- {
- try
- {
- StopConsultation();
- }
- catch (Exception ex)
- {
- Logger.WriteLineError($"Consultationclient- error happended while disconnectting: {ex}");
- }
- finally
- {
- if (!IsOnlyForRtmpPushing)
- {
- ConsultationDisconnected?.Invoke(this, e);
- }
- lock (ConsultationInfoLocker)
- {
- Logger.WriteLineInfo($"Current consultation info is set to null on reson: {e}");
- ConsultationInfo = null;
- }
- lock (_interactiveBoardLocker)
- {
- StrokeDict.Clear();
- }
- CurrentLiveStatus = LiveStates.Disconnected;
- }
- }
- protected void StopConsultation()
- {
- var isMeetting = CurrentLiveStatus == LiveStates.RecipientAcceptted || CurrentLiveStatus == LiveStates.RecipientAcceptting;
- if (isMeetting)
- {
- VideoProvider.Hangup();
- CurrentLiveStatus = LiveStates.Idle;
- }
- else
- {
- Logger.WriteLineInfo($"Don't do stop consultation video since no rtc consultation is not started");
- }
- }
- protected void StartConsultation(string cameraHardwareId, string micHardwareId, string speakerHardwareId, bool isOnlyForRtmpPushing)
- {
- try
- {
- VideoProvider.StartConsultationVideo(ConsultationInfo, AccountId, AccountName, AccountToken, cameraHardwareId, micHardwareId, speakerHardwareId, isOnlyForRtmpPushing);
- }
- catch (Exception ex)
- {
- Logger.WriteLineError($"Error happened while start meeting {ex}");
- }
- }
- public ResultInfoDTO Hangup(bool isFakeHangup = false)
- {
- try
- {
- if (ConsultationInfo == null)
- {
- Logger.WriteLineWarn($"ConsultationHangup Fail: Current is not Consultating");
- return new ResultInfoDTO
- {
- IsSuccess = false,
- FailMessage = "ConsultationHangup Fail: Current is not Consultating"
- };
- }
- if (isFakeHangup)
- {
- lock (ConsultationInfoLocker)
- {
- ConsultationInfo = null;
- _muteVideoUserList.Clear();
- }
- lock (_interactiveBoardLocker)
- {
- StrokeDict.Clear();
- }
- return new ResultInfoDTO
- {
- IsSuccess = true,
- };
- }
- var leaveLiveConsultationRequest = new LeaveLiveConsultationRequest
- {
- ConsultationCode = ConsultationInfo?.ConsultationId,
- Token = AccountToken,
- };
- var leaveResult = JsonRpcHelper.LeaveLiveConsultation(LiveConsultationService, leaveLiveConsultationRequest);
- if (leaveResult == null || leaveResult.ConsultationCode != ConsultationInfo?.ConsultationId)
- {
- Logger.WriteLineError($"Hangup Fail, leaveResult.ConsultationCode is {leaveResult?.ConsultationCode}");
- }
- lock (ConsultationInfoLocker)
- {
- ConsultationInfo = null;
- _muteVideoUserList.Clear();
- }
- lock (_interactiveBoardLocker)
- {
- StrokeDict.Clear();
- }
- StopConsultation();
- CurrentLiveStatus = LiveStates.ChatHangup;
- Logger.WriteLineInfo($"ConsultationLive-- {AccountName} hangup end with result {CurrentLiveStatus}");
- return new ResultInfoDTO
- {
- IsSuccess = true,
- };
- }
- catch (Exception ex)
- {
- Logger.WriteLineWarn($"ConsultationHangup error: {ex}");
- return new ResultInfoDTO
- {
- IsSuccess = false,
- FailMessage = $"ConsultationHangup Fail: {ex}"
- };
- }
- finally
- {
- IsOnlyForRtmpPushing = false;
- IsSecondViewMode = false;
- }
- }
- protected virtual void HandleConsultationMemberNotificationArrived(ConsultationMemberNotificaiton consultationMemberNotificaiton)
- {
- ConsultationMemberChangedNotificationArrived?.Invoke(this, consultationMemberNotificaiton);
- }
- protected void ConsultationMemberChange(ConsultationMemberChangeDTO meetingChangeMember)
- {
- VideoProvider.ConsultationMemberChange(meetingChangeMember);
- }
- internal ResultInfoDTO ReceiveWhiteBoardData(WhiteBoardDataDTO whiteBoardDataDTO)
- {
- if (whiteBoardDataDTO == null)
- {
- Logger.WriteLineError($"ReceiveWhiteBoardData Error:Args is invalid");
- return new ResultInfoDTO
- {
- IsSuccess = false,
- FailMessage = "Args is invalid",
- };
- }
- if (string.IsNullOrEmpty(whiteBoardDataDTO.UserId))
- {
- Logger.WriteLineError($"ReceiveWhiteBoardData Error:Args:UserId is empty");
- return new ResultInfoDTO
- {
- IsSuccess = false,
- FailMessage = "Args:UserId is empty",
- };
- }
- if (whiteBoardDataDTO.IsClear == "true")
- {
- lock (_interactiveBoardLocker)
- {
- if (StrokeDict.ContainsKey(whiteBoardDataDTO.UserId))
- {
- StrokeDict.Remove(whiteBoardDataDTO.UserId);
- }
- InteractiveBoardInfoArrived?.Invoke(this, new InteractiveBoardInfo(whiteBoardDataDTO.UserId, AccountId, null, ""));
- }
- return new ResultInfoDTO
- {
- IsSuccess = true
- };
- }
- else
- {
- if (uint.TryParse(whiteBoardDataDTO.Color, out var color))
- {
- if (whiteBoardDataDTO.Points.Length % 8 != 0)
- {
- Logger.WriteLineError($"ReceiveWhiteBoardData Error:Args:Point is invalid,is not divisible by 8");
- return new ResultInfoDTO
- {
- IsSuccess = false,
- FailMessage = "Args:Point is invalid,is not divisible by 8",
- };
- }
- List<StrokePointList> strokePointLists;
- var strokePointList = ConvertToSrokePointList(whiteBoardDataDTO.Points);
- if (strokePointList != null)
- {
- lock (_interactiveBoardLocker)
- {
- if (StrokeDict.ContainsKey(whiteBoardDataDTO.UserId))
- {
- StrokeDict[whiteBoardDataDTO.UserId].Add(strokePointList);
- }
- else
- {
- StrokeDict[whiteBoardDataDTO.UserId] = new List<StrokePointList>
- {
- strokePointList
- };
- }
- strokePointLists = StrokeDict[whiteBoardDataDTO.UserId].ToList();
- }
- if (CrossPlatformHelper.Instance.Platform == EnumPlatform.Windows)
- {
- var jsonData = CrossPlatformHelper.Instance.StrokeHelper.GetStrokeJson(strokePointLists, color);
- InteractiveBoardInfoArrived?.Invoke(this, new InteractiveBoardInfo(whiteBoardDataDTO.UserId, AccountId, null, jsonData));
- return new ResultInfoDTO
- {
- IsSuccess = true,
- };
- }
- else
- {
- var strokePointsInfo = new StrokePointsInfo(color, strokePointLists);
- var jsonData = JsonSerializer.Serialize(strokePointsInfo);
- InteractiveBoardInfoArrived?.Invoke(this, new InteractiveBoardInfo(whiteBoardDataDTO.UserId, AccountId, null, jsonData));
- return new ResultInfoDTO
- {
- IsSuccess = true,
- };
- }
- }
- else
- {
- Logger.WriteLineError($"ReceiveWhiteBoardData Error:Args is invalid");
- return new ResultInfoDTO
- {
- IsSuccess = false,
- FailMessage = "Args is invalid",
- };
- }
- }
- else
- {
- Logger.WriteLineError($"ReceiveWhiteBoardData Error:Args:Color is invalid");
- return new ResultInfoDTO
- {
- IsSuccess = false,
- FailMessage = "Args:Color is invalid",
- };
- }
- }
- }
- private StrokePointList ConvertToSrokePointList(string pointstring)
- {
- try
- {
- List<StrokePoint> pointsList = new List<StrokePoint>();
- for (int i = 0; i < pointstring.Length; i += 8)
- {
- var xString = pointstring.Substring(i, 4);
- var yString = pointstring.Substring(i + 4, 4);
- var xBeforeAdjust = double.Parse(xString);
- var yBeforeAdjust = double.Parse(yString);
- var xAfterAdjust = xBeforeAdjust / _flyinsonoWidth * _usInkCanvasWidth;
- var yAfterAdjust = yBeforeAdjust / _flyinsonoHeight * _usInkCanvasHeight;
- pointsList.Add(new StrokePoint(xAfterAdjust, yAfterAdjust));
- }
- return new StrokePointList() { StrokePoints = pointsList };
- }
- catch (Exception ex)
- {
- Logger.WriteLineError($"ConvertToSrokePointList Error:{ex}");
- return null;
- }
- }
- internal ResultInfoDTO SwitchVideoPlay(string userId, bool isVideoOpen)
- {
- var existUser = ConsultationInfo?.ConsultationMemberInfos?.FirstOrDefault(x => x.Id == userId);
- if (existUser != null)
- {
- if (isVideoOpen)
- {
- if (_muteVideoUserList.Contains(userId))
- {
- _muteVideoUserList.Remove(userId);
- MuteVideoUserListNotifyArrived?.Invoke(this, _muteVideoUserList.ToList());
- }
- }
- else
- {
- if (!_muteVideoUserList.Contains(userId))
- {
- _muteVideoUserList.Add(userId);
- MuteVideoUserListNotifyArrived?.Invoke(this, _muteVideoUserList.ToList());
- }
- }
- }
- return new ResultInfoDTO
- {
- IsSuccess = true,
- };
- }
- public virtual void Dispose()
- {
- VideoProvider.RemoteUserLeaveRoomArrived -= OnRemoteUserLeaveRoomArrived;
- VideoProvider.CloseConsultation -= OnCloseMeeting;
- VideoProvider.TryToReconnect -= OnTryToReconnect;
- }
- }
- }
|