public SymplePlayer(SymplePlayerOptions opts) { this.options = opts; this.options.format = "MJPEG"; this.options.engine = null; this.options.onCommand = (player, cmd) => { }; this.options.onStateChange = (player, state, message) => { }; if (this.options.engine == null) { var engine = SympleMedia.Instance.preferredCompatibleEngine(this.options.format); if (engine != null) { this.options.engine = engine.id; } } //this.bindEvents(); // here we would set up the event logic to bind UI buttons to actions like play/stop/mute/unmute/etc this.playing = false; }
public void initAndStartWebRTC() { #if NETFX_CORE JObject CLIENT_OPTIONS = new JObject(); CLIENT_OPTIONS["secure"] = true; CLIENT_OPTIONS["url"] = this.SignallingServerUrl; CLIENT_OPTIONS["peer"] = new JObject(); CLIENT_OPTIONS["peer"]["user"] = this.LocalPeerUsername; CLIENT_OPTIONS["peer"]["name"] = this.LocalPeerNameLabel; CLIENT_OPTIONS["peer"]["group"] = this.LocalPeerGroup; SymplePlayerOptions playerOptions = new SymplePlayerOptions(); playerOptions.engine = "WebRTC"; switch (UserType) { case StarUserType.TRAINEE: playerOptions.initiator = true; break; case StarUserType.MENTOR: playerOptions.initiator = false; break; default: break; } // WebRTC config // This is where you would add TURN servers for use in production RTCConfiguration WEBRTC_CONFIG = new RTCConfiguration { IceServers = new List <RTCIceServer> { new RTCIceServer { Url = "stun:stun.l.google.com:19302", Username = string.Empty, Credential = string.Empty }, new RTCIceServer { Url = "stun:stun1.l.google.com:19302", Username = string.Empty, Credential = string.Empty }, new RTCIceServer { Url = "stun:stun2.l.google.com:19302", Username = string.Empty, Credential = string.Empty }, new RTCIceServer { Url = "stun:stun3.l.google.com:19302", Username = string.Empty, Credential = string.Empty }, new RTCIceServer { Url = "stun:stun4.l.google.com:19302", Username = string.Empty, Credential = string.Empty }, new RTCIceServer { Url = "turn:numb.viagenie.ca", Username = "******", Credential = "0O@S&YfP$@56" } } }; playerOptions.rtcConfig = WEBRTC_CONFIG; //playerOptions.iceMediaConstraints = asdf; // TODO: not using iceMediaConstraints in latest code? playerOptions.onStateChange = (player, state, message) => { player.displayStatus(state); }; Messenger.Broadcast(SympleLog.LogInfo, "creating player"); player = new SymplePlayer(playerOptions); Messenger.Broadcast(SympleLog.LogInfo, "creating client"); client = new SympleClient(CLIENT_OPTIONS); client.on("announce", (peer) => { Messenger.Broadcast(SympleLog.LogInfo, "Authentication success: " + peer); }); client.on("addPeer", (peerObj) => { JObject peer = (JObject)peerObj; Messenger.Broadcast(SympleLog.LogInfo, "adding peer: " + peer); if (this.UserType == StarUserType.TRAINEE) { // the TRAINEE user waits for a peer with a specific username, then once it's connected it automatically starts sending video if ((string)peer["user"] == this.ExpectedRemoteReceiverUsername && !initialized) { initialized = true; remotePeer = peer; startPlaybackAndRecording(); } } }); client.on("presence", (presence) => { Messenger.Broadcast(SympleLog.LogInfo, "Recv presence: " + presence); }); client.on("removePeer", (peerObj) => { JObject peer = (JObject)peerObj; Messenger.Broadcast(SympleLog.LogInfo, "Removing peer: " + peer); if (remotePeer != null && remotePeer["id"].Equals(peer["id"])) { initialized = false; remotePeer = null; player.engine.destroy(); player.engine = null; } }); client.on("message", (mObj) => { Messenger.Broadcast(SympleLog.LogTrace, "mObj.GetType().ToString(): " + mObj.GetType().ToString()); JObject m = (JObject)((Object[])mObj)[0]; Messenger.Broadcast(SympleLog.LogTrace, "recv message: " + m); Messenger.Broadcast(SympleLog.LogTrace, "remotePeer: " + remotePeer); var mFrom = m["from"]; JToken mFromId = null; if (mFrom.Type == JTokenType.Object) { mFromId = mFrom["id"]; } if (remotePeer != null && !remotePeer["id"].Equals(mFromId)) { Messenger.Broadcast(SympleLog.LogInfo, "Dropping message from unknown peer: " + m); return; } if (m["offer"] != null) { switch (UserType) { case StarUserType.TRAINEE: Messenger.Broadcast(SympleLog.LogInfo, "Unexpected offer for one-way streaming"); break; case StarUserType.MENTOR: Messenger.Broadcast(SympleLog.LogInfo, "Receive offer: " + m["offer"]); remotePeer = (JObject)m["from"]; JObject playParams = new JObject(); // empty params player.play(playParams); var engine = (SymplePlayerEngineWebRTC)player.engine; engine.recvRemoteSDP((JObject)m["offer"]); engine.sendLocalSDP = (desc) => { Messenger.Broadcast(SympleLog.LogInfo, "Send answer: " + desc); JObject sessionDesc = new JObject(); sessionDesc["sdp"] = desc.Sdp; if (desc.Type == Org.WebRtc.RTCSdpType.Answer) { sessionDesc["type"] = "answer"; } else if (desc.Type == Org.WebRtc.RTCSdpType.Offer) { sessionDesc["type"] = "offer"; } else if (desc.Type == Org.WebRtc.RTCSdpType.Pranswer) { sessionDesc["type"] = "pranswer"; } JObject parameters = new JObject(); parameters["to"] = remotePeer; parameters["type"] = "message"; parameters["answer"] = sessionDesc; client.send(parameters); }; engine.sendLocalCandidate = (cand) => { JObject candidateObj = new JObject(); candidateObj["candidate"] = cand.Candidate; candidateObj["sdpMid"] = cand.SdpMid; candidateObj["sdpMLineIndex"] = cand.SdpMLineIndex; JObject parameters = new JObject(); parameters["to"] = remotePeer; parameters["type"] = "message"; parameters["candidate"] = candidateObj; client.send(parameters); }; break; default: break; } } else if (m["answer"] != null) { switch (UserType) { case StarUserType.TRAINEE: SymplePlayerEngineWebRTC engine = (SymplePlayerEngineWebRTC)player.engine; string answerJsonString = JsonConvert.SerializeObject(m["answer"], Formatting.None); JObject answerParams = (JObject)m["answer"]; Messenger.Broadcast(SympleLog.LogTrace, "Receive answer: " + answerJsonString); engine.recvRemoteSDP(answerParams); break; case StarUserType.MENTOR: Messenger.Broadcast(SympleLog.LogInfo, "Unexpected answer for one-way streaming"); break; default: break; } } else if (m["candidate"] != null) { SymplePlayerEngineWebRTC engine = (SymplePlayerEngineWebRTC)player.engine; JObject candidateParams = (JObject)m["candidate"]; Messenger.Broadcast(SympleLog.LogInfo, "Using Candidate: " + candidateParams); engine.recvRemoteCandidate(candidateParams); } }); client.on("disconnect", (peer) => { Messenger.Broadcast(SympleLog.LogInfo, "Disconnected from server"); }); client.on("error", (error) => { Messenger.Broadcast(SympleLog.LogError, "Connection error: " + error); }); client.connect(); #else Messenger.Broadcast(SympleLog.LogInfo, "not actually connecting via webrtc because NETFX_CORE not defined (probably this is in the unity editor)"); #endif }