/// <summary>
    ///   Join a RTC channel
    /// </summary>
    /// <param name="channel"></param>
    public virtual void Join(string channel)
    {
        Debug.Log("calling join (channel = " + channel + ")");

        if (mRtcEngine == null)
        {
            return;
        }

        // set callbacks (optional)
        mRtcEngine.OnJoinChannelSuccess = OnJoinChannelSuccess;
        mRtcEngine.OnUserJoined         = OnUserJoined;
        mRtcEngine.OnUserOffline        = OnUserOffline;

        // enable video
        mRtcEngine.EnableVideo();
        // allow camera output callback
        mRtcEngine.EnableVideoObserver();
        mRtcEngine.EnableLocalAudio(false);
        mRtcEngine.MuteLocalAudioStream(true);

        // join channel
        mRtcEngine.JoinChannel(channel, null, 0);

        Debug.Log("initializeEngine done");
    }
    public void Mic()
    {
        string buttontext = isMuted ? "MicMute" : "MicUnmute";
        Text   labeltext  = mic.GetComponentInChildren <Text>();

        labeltext.text = buttontext;
        isMuted        = !isMuted;
        mRtcEngine.EnableLocalAudio(!isMuted);
    }
    void MuteButtonTapped()
    {
        string labeltext = isMuted ? "Mute" : "Unmute";

        //if (label != null)
        //{
        //    label.text = labeltext;
        //}
        isMuted = !isMuted;
        mRtcEngine.EnableLocalAudio(!isMuted);
    }
    void MuteButtonTapped()
    {
        string labeltext = isMuted ? "Mute" : "Unmute";
        Text   label     = muteButton.GetComponentInChildren <Text>();

        if (label != null)
        {
            label.text = labeltext;
        }
        isMuted = !isMuted;
        mRtcEngine.EnableLocalAudio(!isMuted);
    }
    private void SetupToggleMic()
    {
        GameObject go = GameObject.Find("ToggleButton");

        if (go != null)
        {
            ToggleButton toggle = go.GetComponent <ToggleButton>();
            if (toggle != null)
            {
                toggle.button1.onClick.AddListener(() =>
                {
                    toggle.Tap();
                    mRtcEngine.EnableLocalAudio(false);
                    mRtcEngine.MuteLocalAudioStream(true);
                });
                toggle.button2.onClick.AddListener(() =>
                {
                    toggle.Tap();
                    mRtcEngine.EnableLocalAudio(true);
                    mRtcEngine.MuteLocalAudioStream(false);
                });
            }
        }
    }
    protected virtual void SetupUI()
    {
        GameObject go = GameObject.Find(SelfVideoName);

        if (go != null)
        {
            UserVideoDict[0] = go.AddComponent <VideoSurface>();
            go.AddComponent <UIElementDragger>();
        }

        Button button = GameObject.Find("LeaveButton").GetComponent <Button>();

        if (button != null)
        {
            button.onClick.AddListener(OnLeaveButtonClicked);
        }

        Button mutton = GameObject.Find("MuteButton").GetComponent <Button>();

        if (mutton != null)
        {
            mutton.onClick.AddListener(() =>
            {
                MicMuted = !MicMuted;
                mRtcEngine.EnableLocalAudio(!MicMuted);
                mRtcEngine.MuteLocalAudioStream(MicMuted);
                Text text = mutton.GetComponentInChildren <Text>();
                text.text = MicMuted ? "Unmute" : "Mute";
            });
        }

        go = GameObject.Find("Toggle360p");
        if (go != null)
        {
            Toggle toggle = go.GetComponent <Toggle>();
            _enforcing360p = toggle.isOn; // initial value
            toggle.onValueChanged.AddListener((val) =>
            {
                _enforcing360p = val;
            });
        }
    }
    //Called to join or leave a session. Engine must be loaded first!
    public void join(string channel)
    {
        if (String.IsNullOrEmpty(channel))
        {
            Debug.LogWarning("Empty channel name. Ignoring join request."); return;
        }

        loadEngine(AppID); // load engine

        if (mRtcEngine == null)
        {
            return;
        }
        Debug.Log("calling join (channel = " + channel + ")");

        // set callbacks (optional)
        mRtcEngine.OnJoinChannelSuccess = onJoinChannelSuccess;
        mRtcEngine.OnLeaveChannel       = onLeaveChannel;
        mRtcEngine.OnUserJoined         = onUserJoined;
        mRtcEngine.OnUserOffline        = onUserOffline;
        mRtcEngine.OnStreamMessage      = onStreamMessage;
        mRtcEngine.OnRtcStats           = onRtcStats;

        //set timeout timer (optional)
        if (timeout > 0)
        {
            timeoutTimer = timeout; hideWarningLabel();
        }

        //Audio settings
        if (useAudio)
        {
            mRtcEngine.EnableAudio();                              // enable audio in general
            mRtcEngine.EnableLocalAudio(!muteLocalAudio);          //controls sending local out HARD STOP

            mRtcEngine.MuteLocalAudioStream(muteLocalAudio);       //still sending, but not audible
            mRtcEngine.MuteAllRemoteAudioStreams(muteRemoteAudio); //still sending, but not audible

            mRtcEngine.AdjustRecordingSignalVolume(localVolume);
            mRtcEngine.AdjustPlaybackSignalVolume(remoteVolume);
        }
        else
        {
            mRtcEngine.DisableAudio();
        }                                     // disable video in general

        //Begin video feed
        if (useVideo)
        {
            mRtcEngine.EnableVideo();                              // enable video in general
            mRtcEngine.EnableVideoObserver();
            mRtcEngine.EnableLocalVideo(!muteLocalVideo);          //controls sending local out HARD STOP

            mRtcEngine.MuteLocalVideoStream(muteLocalVideo);       //Send local video to remote?
            mRtcEngine.MuteAllRemoteVideoStreams(muteRemoteVideo); //still receiving, but not visible

            //if(muteRemoteVideo) { mRtcEngine.DisableVideoObserver(); } //controls receiving video HARD STOP
            //else                { mRtcEngine.EnableVideoObserver(); }

            //Change Video feed settings
            VideoEncoderConfiguration videoConfig = new VideoEncoderConfiguration();
            videoConfig.dimensions.width  = 1280;
            videoConfig.dimensions.height = 720;
            videoConfig.frameRate         = FRAME_RATE.FRAME_RATE_FPS_15;
            mRtcEngine.SetVideoEncoderConfiguration(videoConfig);

            //WEBCAMS: Show list of all webcam devices
            mRtcEngine.GetVideoDeviceManager().CreateAVideoDeviceManager();
            int deviceCount = mRtcEngine.GetVideoDeviceManager().GetVideoDeviceCount();
            Debug.Log("Video device count: " + deviceCount);
            string deviceName = ""; string deviceId = "";
            for (int i = 0; i < deviceCount; i++)  //Show list of webcams
            {
                mRtcEngine.GetVideoDeviceManager().GetVideoDevice(i, ref deviceName, ref deviceId);
                Debug.Log("Device[i] deviceName = \"" + deviceName + "\" | deviceId = \"" + deviceId + "\"");
            }
            //---Show current video device---
            mRtcEngine.GetVideoDeviceManager().GetCurrentVideoDevice(ref deviceId);
            Debug.Log("CurrentVideoDevice deviceId = \"" + deviceId + "\"");
            //---Pick the first one?---
            mRtcEngine.GetVideoDeviceManager().GetVideoDevice(0, ref deviceName, ref deviceId);
            mRtcEngine.GetVideoDeviceManager().SetVideoDevice(deviceId);
        }
        else
        {
            mRtcEngine.DisableVideo();
        }                                     // disable video in general

        //Join Channel
        UID = mRtcEngine.JoinChannel(channel, null, 0); // join channel

        // Optional: if a data stream is required, here is a good place to create it.
        streamID = mRtcEngine.CreateDataStream(true, true);
        Debug.Log("initializeEngine done, data stream id = " + streamID);

        //Show local video
        showLocalVideo();

        //Hide Join Button and Show Leave button if assigned
        joinButton.SetActive(false);
        leaveButton.SetActive(true);

        //Hide warning label if still there
        hideWarningLabel();
    }