join method

Future<void> join()

Implementation

Future<void> join() async {
  if (_joined) {
    //
    log("Already Joined");
    return;
  }

  //
  String baseUrl;
  try {
    //
    final jsonRes = await http.post(Uri.parse(_initConfigUrl), body: {
      'roomId': id,
    }, headers: {
      'Authorization': _token,
    });

    final jsonData = json.decode(jsonRes.body);

    if (jsonRes.statusCode != 200) {
      //
      throw jsonData['error'] ?? "Error while getting baseUrl";
    }

    //
    final data = jsonData['data'];
    baseUrl = data['baseUrl'];

    //
    try {
      String decryptedIceServer = decrypt(data['iceServers']);
      //
      List<dynamic> iceServers = json.decode(decryptedIceServer.substring(
          0, decryptedIceServer.lastIndexOf(']') + 1)) as List;
      //
      iceServers.asMap().forEach((key, value) {
        //
        if (value['url'].toString().contains("stun")) {
          //
          RTCIceServer iceServer = RTCIceServer(
              credentialType: RTCIceCredentialType.password,
              username: "",
              urls: [value['url']],
              credential: "");
          _iceServers.add(iceServer);
        } else {
          //
          RTCIceServer iceServer = RTCIceServer(
              credentialType: RTCIceCredentialType.password,
              username: value['username'],
              urls: [value['url']],
              credential: value['credential']);
          _iceServers.add(iceServer);
        }
      });
      final observability = data['observability'];
      // set meetingId, peerId for Logs
      VideoSDKLog.meetingId = id;
      VideoSDKLog.peerId = localParticipant.id;
      VideoSDKLog.logsConfig = observability['logs'];
      VideoSDKLog.jwtKey = observability['jwt'];

      // open-telemeetry
      videoSDKTelemetery = VideoSDKTelemetery(
        roomId: id,
        peerId: localParticipant.id,
        observabilityJwt: observability['jwt'],
        traces: observability['traces'],
        metaData: observability['metaData'],
      );
    } catch (error) {
      //
      VideoSDKLog.createLog(
          message: "Error in join() \n ${error.toString()}",
          logLevel: "ERROR");

      //
      log(error.toString());
    }
  } catch (err) {
    //
    VideoSDKLog.createLog(
        message: "error while getting baseUrl \n ${err.toString()}",
        logLevel: "ERROR");

    //
    log(err.toString());
    //
    throw "Error while getting baseUrl";
  }

  // send trace roomConfig
  try {
    deviceInfo = await VideoSDK.getDeviceInfo();
    _joinSpan = videoSDKTelemetery!.trace(
      spanName: 'Join() Calling',
      span: null,
      attributes: [
        Attribute.fromString('deviceInfo', deviceInfo.toString()),
        Attribute.fromString('displayName', _displayName),
        Attribute.fromBoolean('micEnabled', micEnabled),
        Attribute.fromBoolean('camEnabled', _camEnabled),
        Attribute.fromString('maxResolution', _maxResolution),
        Attribute.fromBoolean('multiStream', _multiStream),
        Attribute.fromString('mode', _mode.name.toString()),
        if (_customCameraVideoTrack != null)
          Attribute.fromString('customCameraVideoTrack',
              _customCameraVideoTrack!.toMap().toString()),
        if (_customMicrophoneAudioTrack != null)
          Attribute.fromString('customMicrophoneAudioTrack',
              _customMicrophoneAudioTrack!.toMap().toString()),
        if (_selectedAudioInput != null)
          Attribute.fromString(
              'selectedAudioInput', _selectedAudioInput!.label),
        if (_selectedVideoInput != null)
          Attribute.fromString(
              'selectedVideoInput', _selectedVideoInput!.label),
      ],
    );
  } catch (error) {}

  //
  _webSocket = WebSocket(
      baseUrl: baseUrl,
      peerId: localParticipant.id,
      meetingId: id,
      token: _token,
      mode: _mode.parseToString());

  try {
    if (videoSDKTelemetery != null) {
      videoSDKTelemetery!.traceAutoComplete(
        spanName: 'Meeting is in CONNECTING State',
      );
    }
  } catch (error) {
    log("error in webSocket OnConnecting $error");
  }

  //
  _webSocket!.onOpen = () {
    try {
      if (videoSDKTelemetery != null) {
        videoSDKTelemetery!.traceAutoComplete(
          spanName: 'Meeting is in CONNECTED State',
        );
      }
    } catch (error) {
      log("error in webSocket onOpen $error");
    }

    _requestEntry();
  };

  //
  _webSocket!.onFail = () {
    try {
      if (videoSDKTelemetery != null) {
        videoSDKTelemetery!.traceAutoComplete(
            spanName: 'Meeting is in FAILED State',
            status: StatusCode.error,
            message: 'WebSocket Connection Failed');
      }
    } catch (error) {
      log("error in webSocket onFail $error");
    }
  };

  //
  _webSocket!.onDisconnected = () {
    try {
      if (videoSDKTelemetery != null) {
        videoSDKTelemetery!.traceAutoComplete(
          spanName: 'Meeting is in DISCONNECTED State',
        );
      }
    } catch (error) {
      log("error in webSocket onDisconnected $error");
    }

    if (_micProducer != null) {
      if (!_micProducer!.closed && _micProducer!.paused) {
        _micProducer!.resume();
      }
      _micProducer!.track.stop();
      _micProducer!.close();
      _micProducer = null;
    }

    if (_sendTransport != null) {
      _sendTransport!.close();
      _sendTransport = null;
    }
    if (_recvTransport != null) {
      _recvTransport!.close();
      _recvTransport = null;
    }
  };

  //
  _webSocket!.onClose = () {
    //
    if (_closed) return;
    //
    try {
      if (videoSDKTelemetery != null) {
        videoSDKTelemetery!.traceAutoComplete(
          spanName: 'Meeting is in CLOSED State',
        );
      }
    } catch (error) {
      log("error in webSocket onClose $error");
    }
    //
    _close();
  };

  //
  _webSocket!.onRequest = (request, accept, reject) async {
    switch (request['method']) {
      case "close":
        {
          _close();
          break;
        }

      case 'newConsumer':
        {
          Span? newConsumerSpan;
          Span? span;

          try {
            if (videoSDKTelemetery != null) {
              newConsumerSpan = videoSDKTelemetery!.trace(
                spanName: 'Protoo REQ: newConsumer',
                attributes: [
                  Attribute.fromString('request', request.toString())
                ],
              );
            }
          } catch (error) {}

          if (!_consume) {
            reject(403, 'I do not want to consume');
            if (newConsumerSpan != null) {
              videoSDKTelemetery!.completeSpan(
                  span: newConsumerSpan,
                  message: 'Do not want to consume',
                  status: StatusCode.ok);
            }
            break;
          }
          try {
            try {
              if (newConsumerSpan != null) {
                span = videoSDKTelemetery!.trace(
                  spanName: 'Creating Consumer',
                  span: newConsumerSpan,
                );
              }
            } catch (error) {}

            _recvTransport!.consume(
              id: request['data']['id'],
              producerId: request['data']['producerId'],
              kind: RTCRtpMediaTypeExtension.fromString(
                  request['data']['kind']),
              rtpParameters:
                  RtpParameters.fromMap(request['data']['rtpParameters']),
              appData: Map<String, dynamic>.from(request['data']['appData']),
              peerId: request['data']['peerId'],
              accept: accept,
            );

            if (span != null) {
              videoSDKTelemetery!.completeSpan(
                  span: span,
                  message: 'Consumer Created',
                  status: StatusCode.ok);
              span = null;
            }

            if (newConsumerSpan != null) {
              videoSDKTelemetery!.completeSpan(
                  span: newConsumerSpan,
                  message: 'New Consumer Created Successfully',
                  status: StatusCode.ok);
            }
          } catch (error) {
            //
            VideoSDKLog.createLog(
                message: "Error in newConsumer \n ${error.toString()}",
                logLevel: "ERROR");

            //
            log(error.toString());

            if (span != null) {
              videoSDKTelemetery!.completeSpan(
                  span: span,
                  message: 'Consumer Creation Failed',
                  status: StatusCode.error);
              span = null;
            }

            if (newConsumerSpan != null) {
              videoSDKTelemetery!.completeSpan(
                  span: newConsumerSpan,
                  message:
                      'New Consumer Creation Failed \n ${error.toString()}',
                  status: StatusCode.error);
            }
            rethrow;
          }
          break;
        }

      case 'enableMic':
        {
          Span? enableMicSpan;
          try {
            try {
              if (videoSDKTelemetery != null) {
                enableMicSpan = videoSDKTelemetery!.trace(
                  spanName: 'Protoo REQ: enableMic',
                );
              }
            } catch (error) {}

            _eventEmitter.emit('mic-requested', {
              // 'participantId': peerId,
              "accept": () {
                try {
                  if (enableMicSpan != null) {
                    videoSDKTelemetery!.traceAutoComplete(
                      spanName: 'Accept Request of EnableMic',
                      span: enableMicSpan,
                    );
                  }
                } catch (error) {}
                _enableMicImpl(parentSpan: enableMicSpan);
              },
              "reject": () {
                try {
                  if (enableMicSpan != null) {
                    videoSDKTelemetery!.traceAutoComplete(
                      spanName: 'Reject Request of EnableMic',
                      span: enableMicSpan,
                    );
                  }
                } catch (error) {}
              },
            });

            accept();

            if (enableMicSpan != null) {
              videoSDKTelemetery!.completeSpan(
                  span: enableMicSpan,
                  message: 'EnableMic Request Completed',
                  status: StatusCode.ok);
            }
          } catch (error) {
            //
            VideoSDKLog.createLog(
                message: "Error in mic-requested \n ${error.toString()}",
                logLevel: "ERROR");

            //
            if (enableMicSpan != null) {
              videoSDKTelemetery!.completeSpan(
                  span: enableMicSpan,
                  message: 'EnableMic Request Failed \n ${error.toString()}',
                  status: StatusCode.error);
            }

            rethrow;
          }
          break;
        }
      case 'disableMic':
        {
          Span? disableMicSpan;
          try {
            try {
              if (videoSDKTelemetery != null) {
                disableMicSpan = videoSDKTelemetery!.trace(
                  spanName: 'Protoo REQ: disableMic',
                );
              }
            } catch (error) {}

            _disableMic(parentSpan: disableMicSpan);
            accept();

            if (disableMicSpan != null) {
              videoSDKTelemetery!.completeSpan(
                  span: disableMicSpan,
                  message: 'DisableMic Request Completed',
                  status: StatusCode.ok);
            }
          } catch (error) {
            //
            VideoSDKLog.createLog(
                message:
                    "error in request disableMic() \n ${error.toString()}",
                logLevel: "ERROR");

            if (disableMicSpan != null) {
              videoSDKTelemetery!.completeSpan(
                  span: disableMicSpan,
                  message: 'DisableMic Request Failed \n ${error.toString()}',
                  status: StatusCode.error);
            }

            rethrow;
          }
          break;
        }
      case 'enableWebcam':
        {
          Span? enableWebcam;
          try {
            if (videoSDKTelemetery != null) {
              enableWebcam = videoSDKTelemetery!.trace(
                spanName: 'Protoo REQ: enableWebcam',
              );
            }
          } catch (error) {}

          try {
            _eventEmitter.emit('webcam-requested', {
              // "participantId": peerId,
              "accept": () {
                _enableCamImpl(parentSpan: enableWebcam);
                try {
                  if (enableWebcam != null) {
                    videoSDKTelemetery!.traceAutoComplete(
                      spanName: 'Accept Request of EnableWebCam',
                      span: enableWebcam,
                    );
                  }
                } catch (error) {}
              },
              "reject": () {
                if (enableWebcam != null) {
                  videoSDKTelemetery!.traceAutoComplete(
                    spanName: 'Reject Request of EnableWebCam',
                    span: enableWebcam,
                  );
                }
              },
            });

            accept();

            if (enableWebcam != null) {
              videoSDKTelemetery!.completeSpan(
                message: 'EnableWebCam Request Completed',
                span: enableWebcam,
                status: StatusCode.ok,
              );
            }
          } catch (error) {
            //
            VideoSDKLog.createLog(
                message: "Error in webcam-requested \n ${error.toString()}",
                logLevel: "ERROR");

            if (enableWebcam != null) {
              videoSDKTelemetery!.completeSpan(
                message: 'EnableWebCam Request Failed \n ${error.toString()}',
                span: enableWebcam,
                status: StatusCode.error,
              );
            }
            rethrow;
          }
          break;
        }
      case 'disableWebcam':
        {
          Span? disableWebcamSpan;

          try {
            try {
              if (videoSDKTelemetery != null) {
                disableWebcamSpan = videoSDKTelemetery!.trace(
                  spanName: 'Protoo REQ: disableWebcam',
                );
              }
            } catch (error) {}

            _disableCamImpl(parentSpan: disableWebcamSpan);
            accept();

            if (disableWebcamSpan != null) {
              videoSDKTelemetery!.completeSpan(
                  span: disableWebcamSpan,
                  message: 'DisableWebCam Request Completed',
                  status: StatusCode.ok);
            }
          } catch (error) {
            //
            VideoSDKLog.createLog(
                message: "Error in request disableCam \n ${error.toString()}",
                logLevel: "ERROR");

            if (disableWebcamSpan != null) {
              videoSDKTelemetery!.completeSpan(
                  span: disableWebcamSpan,
                  message:
                      'DisableWebCam Request Failed \n ${error.toString()}',
                  status: StatusCode.error);
            }

            rethrow;
          }
          break;
        }
      case "statsData":
        {
          accept({
            "peerId": localParticipant.id,
            "statsData": _stats,
          });
          _stats = {};
          break;
        }
      case "pinStateChanged":
        {
          String peerId = request["data"]['peerId'];
          Map<dynamic, dynamic> state = request["data"]['state'];
          String? pinnedBy = request["data"]['pinnedBy'];

          Span? pinStateChangedSpan;

          try {
            if (videoSDKTelemetery != null) {
              pinStateChangedSpan = videoSDKTelemetery!.trace(
                  spanName: 'Protoo REQ: pinStateChanged',
                  attributes: [
                    Attribute.fromString('peerId', peerId),
                    Attribute.fromString('state', state.toString()),
                    if (pinnedBy != null)
                      Attribute.fromString('pinnedBy', pinnedBy),
                  ]);
            }
          } catch (error) {}

          // Update current State of participant pin
          if (!pinnedParticipants.containsKey(peerId)) {
            pinnedParticipants.putIfAbsent(
                peerId,
                () => ParticipantPinState(
                      cam: state['cam'],
                      share: state['share'],
                    ));
          }

          pinnedParticipants[peerId] = ParticipantPinState(
            cam: state['cam'],
            share: state['share'],
          );

          ParticipantPinState pinParticipantState =
              pinnedParticipants[peerId]!;

          // delete if both were false or current state is false
          if (!pinParticipantState.cam && !pinParticipantState.share) {
            pinnedParticipants.remove(peerId);
          }

          _eventEmitter.emit('pin-state-changed-$peerId', {
            'participantId': peerId,
            'state': state,
            'pinnedBy': pinnedBy,
          });

          _eventEmitter.emit('pin-state-changed', {
            'participantId': peerId,
            'state': state,
            'pinnedBy': pinnedBy,
          });

          if (pinStateChangedSpan != null) {
            videoSDKTelemetery!.traceAutoComplete(
              spanName: 'Emitted `pin-state-changed` Event',
              span: pinStateChangedSpan,
            );
          }

          accept();

          if (pinStateChangedSpan != null) {
            videoSDKTelemetery!.completeSpan(
                span: pinStateChangedSpan,
                message: 'PinStateChange Request Completed',
                status: StatusCode.ok);
          }
          break;
        }
      default:
        break;
    }
  };

  //
  _webSocket!.onNotification = (notification) async {
    switch (notification['method']) {
      case 'error':
        {
          dynamic error = notification['data'];
          //
          VideoSDKLog.createLog(
              message: "Error from server \n ${error.toString()}",
              logLevel: "ERROR");
          //
          if (VideoSDKErrors.containsKey(error['code'])) {
            _eventEmitter.emit("error", VideoSDKErrors[error['code']]);
          } else {
            _eventEmitter.emit("error", error);
          }

          try {
            if (videoSDKTelemetery != null) {
              videoSDKTelemetery!.traceAutoComplete(
                  spanName: 'Emitted `ERROR` Event',
                  attributes: [
                    Attribute.fromString('error', error.toString()),
                  ],
                  status: StatusCode.error,
                  message: 'Error from server');
            }
          } catch (error) {}

          break;
        }

      case 'producerScore':
        {
          break;
        }

      case 'consumerClosed':
        {
          String consumerId = notification['data']['consumerId'];
          _removePeerConsumer(consumerId);

          try {
            if (videoSDKTelemetery != null) {
              videoSDKTelemetery!.traceAutoComplete(
                spanName: 'Protoo Noti: consumerClosed for $consumerId',
              );
            }
          } catch (error) {}

          break;
        }

      case 'consumerPaused':
        {
          // String consumerId = notification['data']['consumerId'];
          // peersBloc.add(PeerPausedConsumer(consumerId: consumerId));
          break;
        }

      case 'consumerResumed':
        {
          // String consumerId = notification['data']['consumerId'];
          // peersBloc.add(PeerResumedConsumer(consumerId: consumerId));
          break;
        }

      case "consumerLayersChanged":
        {
          log("consumerLayersChanged server");
          String consumerId = notification['data']['consumerId'];
          int spatialLayer = notification['data']['spatialLayer'] ?? -1;
          int temporalLayer = notification['data']['temporalLayer'] ?? -1;

          _changePeerConsumerQuality(
            consumerId,
            spatialLayer: spatialLayer,
            temporalLayer: temporalLayer,
          );

          Consumer? consumer = _recvTransport?.getConsumer(consumerId);

          if (consumer != null) {
            consumer.spatialLayer = spatialLayer;
            consumer.temporalLayer = temporalLayer;
          }

          break;
        }

      case "entryRequested":
        {
          var id = notification['data']['id'];
          var name = notification['data']['name'];

          Span? entryRequestedSpan;
          try {
            if (videoSDKTelemetery != null && _joinSpan != null) {
              entryRequestedSpan = videoSDKTelemetery!.trace(
                spanName: 'Protoo Noti: entryRequested',
                attributes: [
                  Attribute.fromString('peerId', id.toString()),
                  Attribute.fromString('name', name.toString())
                ],
                span: _joinSpan,
              );
            }
          } catch (error) {}

          if (id != localParticipant.id) {
            _eventEmitter.emit("entry-requested", <String, dynamic>{
              'participantId': id,
              'name': name,
              'allow': () {
                _respondEntry(id, "allowed", entryRequestedSpan);
              },
              'deny': () {
                _respondEntry(id, "denied", entryRequestedSpan);
              },
            });

            if (entryRequestedSpan != null) {
              videoSDKTelemetery!.completeSpan(
                span: entryRequestedSpan,
                message: 'EntryRequested Received',
                status: StatusCode.ok,
              );
            }
          } else {
            if (entryRequestedSpan != null) {
              videoSDKTelemetery!.completeSpan(
                span: entryRequestedSpan,
                message: 'EntryRequested Failed',
                status: StatusCode.error,
              );
            }
          }
          break;
        }

      case "entryResponded":
        {
          var id = notification['data']['id'];
          var decision = notification['data']['decision'];
          var sessionId = notification['data']['sessionId'];

          Span? entryRespondedSpan;
          try {
            if (videoSDKTelemetery != null && _joinSpan != null) {
              entryRespondedSpan = videoSDKTelemetery!.trace(
                spanName: 'Protoo Noti: entryResponded',
                attributes: [
                  Attribute.fromString('peerId', id.toString()),
                  Attribute.fromString('decision', decision.toString()),
                  Attribute.fromString('sessionId', sessionId.toString())
                ],
                span: _joinSpan,
              );
            }
          } catch (error) {}

          _eventEmitter.emit(
            "entry-responded",
            <String, dynamic>{
              "id": id,
              "decision": decision,
            },
          );

          if (id == localParticipant.id && decision == "allowed") {
            _joinRoom();
            if (entryRespondedSpan != null) {
              videoSDKTelemetery!.completeSpan(
                span: entryRespondedSpan,
                message: 'EntryResponded Received',
                status: StatusCode.ok,
              );
            }
          } else {
            if (entryRespondedSpan != null) {
              videoSDKTelemetery!.completeSpan(
                span: entryRespondedSpan,
                message: 'Join Request Denied',
                status: StatusCode.error,
              );
            }
          }

          break;
        }

      case 'newPeer':
        {
          final Map<String, dynamic> newPeer =
              Map<String, dynamic>.from(notification['data']);

          Span? newPeerSpan;

          if (videoSDKTelemetery != null) {
            newPeerSpan = videoSDKTelemetery!.trace(
              spanName: 'Protoo Noti: newPeer for ${newPeer.toString()}',
              attributes: [
                Attribute.fromString('newPeer', newPeer.toString()),
              ],
            );
          }

          _addPeer(newPeer, newPeerSpan);

          if (newPeerSpan != null) {
            videoSDKTelemetery!.completeSpan(
              message:
                  'Protoo Noti: newPeer for ${newPeer.toString()} Completed',
              status: StatusCode.ok,
              span: newPeerSpan,
            );
          }

          break;
        }

      case 'peerClosed':
        {
          String peerId = notification['data']['peerId'];

          Span? peerClosedSpan;

          if (videoSDKTelemetery != null) {
            peerClosedSpan = videoSDKTelemetery!.trace(
              spanName: 'Protoo Noti: peerClosed for $peerId',
            );
          }

          __removePeer(peerId, peerClosedSpan);

          if (peerClosedSpan != null) {
            videoSDKTelemetery!.completeSpan(
              message: 'Protoo Noti: peerClosed for $peerId Completed',
              span: peerClosedSpan,
              status: StatusCode.ok,
            );
          }

          break;
        }

      case 'recordingStarted':
        {
          _eventEmitter.emit('recording-started');
          break;
        }

      case 'recordingStopped':
        {
          _eventEmitter.emit('recording-stopped');
          break;
        }

      case 'recordingStateChanged':
        {
          _recordingState = notification['data']['status'];

          _eventEmitter.emit('recording-state-changed', _recordingState);

          if (videoSDKTelemetery != null) {
            videoSDKTelemetery!.traceAutoComplete(
                spanName:
                    'Emitted RECORDING_STATE_CHANGED, status : ${notification['data']['status']}',
                attributes: [
                  Attribute.fromString(
                      'data', notification['data'].toString())
                ]);
          }

          break;
        }

      case "livestreamStarted":
        {
          _eventEmitter.emit('livestream-started');

          break;
        }

      case "livestreamStopped":
        {
          _eventEmitter.emit('livestream-stopped');

          break;
        }

      case 'livestreamStateChanged':
        {
          _livestreamState = notification['data']['status'];

          _eventEmitter.emit('livestream-state-changed', _livestreamState);

          if (videoSDKTelemetery != null) {
            videoSDKTelemetery!.traceAutoComplete(
                spanName:
                    'Emitted LIVESTREAM_STATE_CHANGED, status : ${notification['data']['status']}',
                attributes: [
                  Attribute.fromString(
                      'data', notification['data'].toString())
                ]);
          }
          break;
        }

      case "hlsStarted":
        {
          var downstreamUrl = notification['data']['downstreamUrl'];
          _eventEmitter.emit('hls-started', downstreamUrl);

          break;
        }

      case "hlsStopped":
        {
          _eventEmitter.emit('hls-stopped');

          break;
        }

      case 'hlsStateChanged':
        {
          _hlsState = notification['data']['status'];

          var downstreamUrl = notification['data']['downstreamUrl'];
          var playbackHlsUrl = notification['data']['playbackHlsUrl'];
          var livestreamUrl = notification['data']['livestreamUrl'];

          if (_hlsState == "HLS_STARTED") {
            _hlsDownstreamUrl = downstreamUrl;
            _hlsUrls = {
              "downstreamUrl": downstreamUrl,
              "playbackHlsUrl": playbackHlsUrl,
              "livestreamUrl": livestreamUrl,
            };
          } else if (_hlsState == "HLS_STOPPED") {
            _hlsDownstreamUrl = null;
            _hlsUrls = _hlsUrls = {
              "downstreamUrl": null,
              "playbackHlsUrl": null,
              "livestreamUrl": null,
            };
          }

          _eventEmitter.emit('hls-state-changed', <String, dynamic>{
            "status": _hlsState,
            "downstreamUrl": downstreamUrl,
            "playbackHlsUrl": playbackHlsUrl,
            "livestreamUrl": livestreamUrl,
          });

          if (videoSDKTelemetery != null) {
            videoSDKTelemetery!.traceAutoComplete(
              spanName:
                  'Emitted HLS_STATE_CHANGED, status : ${notification['data']['status']}',
              attributes: [
                Attribute.fromString('data', notification['data'].toString())
              ],
            );
          }

          break;
        }

      case 'hlsPlayableStateChanged':
        {
          bool isPlayable = notification["data"]["isPlayable"];
          if (isPlayable) {
            _hlsState = "HLS_PLAYABLE";
            var downstreamUrl = notification['data']['downstreamUrl'];
            var playbackHlsUrl = notification['data']['playbackHlsUrl'];
            var livestreamUrl = notification['data']['livestreamUrl'];

            _hlsUrls = {
              "downstreamUrl": downstreamUrl,
              "playbackHlsUrl": playbackHlsUrl,
              "livestreamUrl": livestreamUrl,
            };
            _eventEmitter.emit('hls-state-changed', <String, dynamic>{
              "status": _hlsState,
              "downstreamUrl": downstreamUrl,
              "playbackHlsUrl": playbackHlsUrl,
              "livestreamUrl": livestreamUrl,
            });

            if (videoSDKTelemetery != null) {
              videoSDKTelemetery!.traceAutoComplete(
                spanName: 'Protoo Noti: hlsPlayableStateChanged',
              );
            }
          }

          break;
        }

      case "activeSpeaker":
        {
          String? peerId = notification['data']['peerId'];

          if (peerId != _activeSpeakerId) {
            _activeSpeakerId = peerId;
            _eventEmitter.emit("speaker-changed", peerId);
          }

          break;
        }
      case "pubsubMessage":
        {
          _eventEmitter.emit("pubsub-message", notification['data']);
          break;
        }

      case "peerModeChanged":
        {
          _eventEmitter.emit(
              "participant-mode-changed-${notification['data']['peerId']}", {
            'participantId': notification['data']['peerId'],
            'mode': notification['data']['mode'],
          });
          _eventEmitter.emit("participant-mode-changed", {
            'participantId': notification['data']['peerId'],
            'mode': notification['data']['mode'],
          });

          if (videoSDKTelemetery != null) {
            videoSDKTelemetery!.traceAutoComplete(
              spanName: 'Emitted PEER_MODE_CHANGED',
              attributes: [
                Attribute.fromString('data', notification['data'].toString())
              ],
            );
          }

          break;
        }
      case "restartIce":
        {
          String transportId = notification['data']['transportId'];
          IceParameters iceParameters =
              IceParameters.fromMap(notification['data']['iceParameters']);

          Span? restartIceSpan;
          if (videoSDKTelemetery != null) {
            restartIceSpan = videoSDKTelemetery!.trace(
              spanName:
                  'Protoo Noti: restartIce for transportId : $transportId',
              attributes: [
                Attribute.fromString(
                    'iceParameters', iceParameters.toString())
              ],
            );
          }
          handleRemoteRestartIce(transportId, iceParameters, restartIceSpan);
          break;
        }

      case 'transcriptionStateChanged':
        {
          _eventEmitter.emit(
              "transcription-state-changed", notification['data']);

          if (videoSDKTelemetery != null) {
            videoSDKTelemetery!.traceAutoComplete(
              spanName:
                  'Emitted TRANSCRIPTION_STATE_CHANGED, status: ${notification['data']['status']}',
              attributes: [
                Attribute.fromString('data', notification['data'].toString())
              ],
            );
          }

          break;
        }

      case 'transcriptionText':
        {
          _eventEmitter.emit("transcription-text", notification['data']);
          break;
        }

      default:
        break;
    }
  };
}