Mac/BasicDemo/BasicDemo/ChannelViewController.m [213:252]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        if (isMute) {
            [self displayMessage:[NSString stringWithFormat:@"User %@(%@) mute video.", uid, user.userName]];
        } else {
            [self displayMessage:[NSString stringWithFormat:@"User %@(%@) unmute video.", uid, user.userName]];
        }
    });
}

- (void)onAudioPublishStateChanged:(DingRtcPublishState)oldState newState:(DingRtcPublishState)newState elapseSinceLastState:(NSInteger)elapseSinceLastState channel:(NSString *_Nonnull)channel  {
    dispatch_async(dispatch_get_main_queue(), ^{
        [self displayMessage:[NSString stringWithFormat:@"Audio publish state changed with oldState: %ld newState: %ld.", (long)oldState, (long)newState]];
    });
}

- (void)onVideoPublishStateChanged:(DingRtcPublishState)oldState newState:(DingRtcPublishState)newState elapseSinceLastState:(NSInteger)elapseSinceLastState channel:(NSString *_Nonnull)channel {
    dispatch_async(dispatch_get_main_queue(), ^{
        [self displayMessage:[NSString stringWithFormat:@"Video publish state changed with oldState: %ld newState: %ld.", (long)oldState, (long)newState]];
    });
}

- (void)createEngineKit {
    self.engine = [DingRtcEngine sharedInstance:self extras:nil];
}

- (void)destroyEngineKit {
    [DingRtcEngine destroy];
    self.engine = nil;
}

- (void)joinChannel {
    DingRtcAuthInfo *info = [[DingRtcAuthInfo alloc] init];
    info.channelId = ChannelInfo.channelId;
    info.userId = ChannelInfo.userId;
    info.appId = ChannelInfo.appId;
    info.token = ChannelInfo.token;
    info.gslbServer = ChannelInfo.gslbServer;
    
    [self.engine publishLocalAudioStream:YES];
    [self.engine publishLocalVideoStream:YES];
    [self.engine subscribeAllRemoteVideoStreams:NO];
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



iOS/BasicVideoCall/BasicVideoCall/ChannelViewController.m [175:214]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        if (isMute) {
            [self displayMessage:[NSString stringWithFormat:@"User %@(%@) mute video.", uid, user.userName]];
        } else {
            [self displayMessage:[NSString stringWithFormat:@"User %@(%@) unmute video.", uid, user.userName]];
        }
    });
}

- (void)onAudioPublishStateChanged:(DingRtcPublishState)oldState newState:(DingRtcPublishState)newState elapseSinceLastState:(NSInteger)elapseSinceLastState channel:(NSString *_Nonnull)channel  {
    dispatch_async(dispatch_get_main_queue(), ^{
        [self displayMessage:[NSString stringWithFormat:@"Audio publish state changed with oldState: %ld newState: %ld.", (long)oldState, (long)newState]];
    });
}

- (void)onVideoPublishStateChanged:(DingRtcPublishState)oldState newState:(DingRtcPublishState)newState elapseSinceLastState:(NSInteger)elapseSinceLastState channel:(NSString *_Nonnull)channel {
    dispatch_async(dispatch_get_main_queue(), ^{
        [self displayMessage:[NSString stringWithFormat:@"Video publish state changed with oldState: %ld newState: %ld.", (long)oldState, (long)newState]];
    });
}

- (void)createEngineKit {
    self.engine = [DingRtcEngine sharedInstance:self extras:nil];
}

- (void)destroyEngineKit {
    [DingRtcEngine destroy];
    self.engine = nil;
}

- (void)joinChannel {
    DingRtcAuthInfo *info = [[DingRtcAuthInfo alloc] init];
    info.channelId = ChannelInfo.channelId;
    info.userId = ChannelInfo.userId;
    info.appId = ChannelInfo.appId;
    info.token = ChannelInfo.token;
    info.gslbServer = ChannelInfo.gslbServer;
    
    [self.engine publishLocalAudioStream:YES];
    [self.engine publishLocalVideoStream:YES];
    [self.engine subscribeAllRemoteVideoStreams:NO];
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



