// import { Notification } from '@arco-design/web-vue'; import { ElNotification, ElMessage } from 'element-plus' import emitter from "@/utils/eventBus.js"; // import handleCallingNotification from '../hooks/callingNotification'; let call_id; let hangup_event_cb_id; let force_hangup_event_cb_id; let answer_ack_cb_id; let incoming_cb_id; let floor_grant_cb_id; // Whether it is a pushVideoFile call // 是否为视频推送的呼叫 let pushing_video = false; // monitor call list // 值守呼叫列表 const monitor_call_list = []; export default function useCallModule() { // we allow only one call exist in demo.but actually,sdk supports more /** * make private vioce call,return nothing,receive result in callback * This interface has been expanded to support makeGroupVoiceCall、makeDispatcherVoiceCall、makeConferenceVoiceCall、makeCrosspatchVoiceCall * 这个接口已扩展,除了支持语音单呼外,还支持语音组呼、语音呼叫调度员、语音会议、群组呼叫。 * @param record who you wanna call * @returns */ const makeVoiceCall = (record) => { if (call_id) { console.warn('we allow only one call exist,please hangup first'); return; } window.lemon.call .makeVoiceCall({ basedata_id: record.basedata_id, hook_flag: 0 }) ?.then((resp) => { call_id = resp.call_id; console.info('makeVoiceCall succ,registerCallEstablishEvent', call_id); }); // test // window.lemon.call.changeCamera({ call_id, target_camera: 0 }); // also can use this makecall method,the method provides the most comprehensive call capability // For example, Voice private call, ensure that the basedata_id is a private // window.lemon.call // .makeCall({ // callee_guid: record.basedata_id, // attribute: { // call_type: 0, // call_mode: 0, // duplex_flag: 0, // }, // }) // ?.then((resp) => { // console.info('makeCall succ,resp', resp); // call_id = resp.call_id; // }); // For example, Voice group call,ensure that the basedata_id is a group // window.lemon.call // .makeCall({ // callee_guid: record.basedata_id, // attribute: { // call_type: 1, // call_mode: 0, // duplex_flag: 0, // group call ,the value must be 0 // }, // }) // ?.then((resp) => { // console.info('makeCall succ,resp', resp); // call_id = resp.call_id; // }); }; /** * make private video call,call with vioce and video,return nothing,receive result in callback * This interface has been expanded to support makeGroupVideoCall、makeDispatcherVideoCall、makeConferenceVideoCall * 这个接口已扩展,除了支持视频单呼外,还支持视频组呼、视频呼叫调度员、视频会议 * @param record who you wanna call * @returns */ const makeVideoCall = (record) => { if (call_id) { console.warn('we allow only one call exist,please hangup first'); return; } window.lemon.call .makeVideoCall({ basedata_id: record.basedata_id, video_frame_size: 3 }) ?.then((resp) => { call_id = resp.call_id; console.warn('makeVideoCall succ,call_id=', call_id); }); // also can use this makecall method,the method provides the most comprehensive call capability // For example, Video private call (with voice), ensure that the basedata_id is a private // window.lemon.call // .makeCall({ // callee_guid: record.basedata_id, // attribute: { // call_type: 11, // call_mode: 2, // duplex_flag: 1, // }, // video_frame_size: window.lemon.call.getMaxFrameSize(), // }) // ?.then((resp) => { // console.info('makeCall succ,resp', resp); // call_id = resp.call_id; // }); // For example, Video group call,ensure that the basedata_id is a group // window.lemon.call // .makeCall({ // callee_guid: record.basedata_id, // attribute: { // call_type: 13, // call_mode: 2, // duplex_flag: 0, // group call ,the value must be 0 // }, // video_frame_size: window.lemon.call.getMaxFrameSize(), // }) // ?.then((resp) => { // console.info('makeCall succ,resp', resp); // call_id = resp.call_id; // }); }; const makeGroupVideoCall = (record) => { if (call_id) { console.warn('we allow only one call exist,please hangup first'); return; } window.lemon.call .makeGroupVideoCall({ basedata_id: record.basedata_id, video_frame_size: 3, }) ?.then((resp) => { console.log('makeGroupVideoCall call_id = ', call_id); call_id = resp.call_id; }); }; const makeGroupVoiceCall = (record) => { if (call_id) { console.warn('we allow only one call exist,please hangup first'); return; } window.lemon.call .makeGroupVoiceCall({ basedata_id: record.basedata_id, }) ?.then((resp) => { call_id = resp.call_id; }); }; const makeCrosspatchVoiceCall = (record) => { window.lemon.call .makeCrosspatchVoiceCall({ basedata_id: record.basedata_id }) ?.then((resp) => { call_id = resp.call_id; }); }; /** * 视频上拉 * make pure video call,only video, no voice * @param record who you wanna call * @returns */ const pureVideoCall = (record) => { if (call_id) { console.warn('we allow only one call exist,please hangup first'); return; } window.lemon.call .pullVideo({ basedata_id: record.basedata_id, hook_flag: 0 }) ?.then((resp) => { call_id = resp.call_id; }); }; /** * 环境监听 * @param record */ const voiceDetect = (record) => { window.lemon.call .makeCall({ callee_guid: record.basedata_id, attribute: { call_type: 0, call_mode: 0, duplex_flag: 0, ambience_flag: 1, }, }) ?.then((resp) => { call_id = resp.call_id; }); }; /** * 环境监视 * @param record */ const videoDetect = (record) => { window.lemon.call .makeCall({ callee_guid: record.basedata_id, attribute: { call_type: 11, call_mode: 2, duplex_flag: 0, ambience_flag: 1, }, }) ?.then((resp) => { call_id = resp.call_id; }); }; /** * 音频会议 * @param record */ const makeConferenceVoiceCall = (record) => { window.lemon.call .makeConferenceVoiceCall({ basedata_id: record.basedata_id, }) ?.then((resp) => { call_id = resp.call_id; }); }; /** * 音视频会议 * @param record */ const makeConferenceVideoCall = (record) => { window.lemon.call .makeConferenceVideoCall({ basedata_id: record.basedata_id, }) ?.then((resp) => { call_id = resp.call_id; }); }; // 广播呼叫 // Broadcast Call const makeBroadcastCall = (record) => { window.lemon.call .makeCall({ callee_guid: record.basedata_id, attribute: { call_type: 3, call_mode: 0, }, }) ?.then((resp) => { call_id = resp.call_id; }); }; /** * hangup call */ const hangup = (id) => { console.info('try hangup,call_id=', call_id); console.info('try hangup,id=', id); window.lemon.call .hangupCall({ call_id: id || call_id }) ?.then(() => { call_id = undefined; window.calling_conference = undefined; // console.log('22222registerCallEstablishEven'); }) .catch((err) => { console.error('hangup call error,', err); }); }; /** * 接听呼叫 * answer call */ const answerCall = () => { ElNotification.close(call_id); window.lemon.call .answerCall({ call_id }) ?.then(() => { // display alert ui ElNotification.close(call_id); }) .catch((err) => { console.error('answer call error,', err); }); }; // 禁麦 // mute the microphone const setMuteMic = (mute) => { return window.lemon.call.muteMic({ call_id, is_mute: mute, }); }; // 禁摄像头 // disable the camera const setMuteCamera = (mute) => { return window.lemon.call.muteCamera({ call_id, is_mute: mute, }); }; // 静音 // mute call const setMuteCall = (mute) => { return window.lemon.call.muteCall({ call_id, is_mute: mute, }); }; const removeMonitorCall = (callId) => { const index = monitor_call_list.findIndex( (item) => item.call_id === callId ); if (index >= 0) { monitor_call_list.splice(index, 1); emitter.emit('monitorUpdate'); } }; const getMonitorCallList = () => { return monitor_call_list; }; // 添加 挂断 回调 // After hanging up the call, you can receive a notification and process the style of the current page based on the notification const registerhangupEvent = () => { if (hangup_event_cb_id !== undefined) { return; } hangup_event_cb_id = window.lemon.call.addHangupEvt((data) => { console.info('receive hangup event'); console.info( 'receive hangup event receive call id', String(data.call_id) ); console.info('receive hangup event local call id', String(call_id)); if (data.call_id === call_id) { // remove display alert ui ElNotification.close(call_id); call_id = undefined; window.calling_conference = undefined; // console.log('2222211111registerCallEstablishEvent'); } // pushVideoFile uninit // 如果是视频推送的,挂断是反初始化一些东西。 if (pushing_video) { window.video.src = undefined; window.showVideo.value = false; pushing_video = false; window.videoViewRoot.style.display = 'none'; } removeMonitorCall(data.call_id); }); }; // 添加强拆事件 const registerForceHangupEvent = () => { if (force_hangup_event_cb_id !== undefined) { return; } force_hangup_event_cb_id = window.lemon.call.addForceHangupEvt((data) => { // 目前强拆成功,都是走挂断通知事件。 当失败了,才走强拆事件通知。 if (data.result === 0) { if (data.call_id === call_id) { ElNotification.close(call_id); call_id = undefined; window.calling_conference = undefined; } removeMonitorCall(data.call_id); } else { // 强拆失败 fail ElMessage.error("强拆失败"); } }); }; // 添加接听回调通知 代表呼叫建立 // receive the answer acknowledgement asynchronously after the call is established const registerCallEstablishEvent = () => { if (answer_ack_cb_id !== undefined) { return; } answer_ack_cb_id = window.lemon.call.addAnswerAckEvt((data) => { // console.info('registerCallEstablishEvent0', call_id); console.info('registerCallEstablishEvent', String(data.call_id)); console.info('registerCallEstablishEvent', JSON.stringify(data)); call_id = data.call_id; // pushVideoFile init // 接通后,视频推送的文件开始播放 if (pushing_video) { window.videoViewRoot.style.display = 'unset'; window.showVideo.value = true; window.video.play(); } }); }; // 注册来电通知回调 // add the incoming call callback const registerReceiveCallEvent = () => { if (incoming_cb_id !== undefined) { return; } incoming_cb_id = window.lemon.call.addIncomingEvt((session) => { console.log('receive call------>', session); call_id = session.call_id; const callingReq = { callInfo: session, equipment: undefined, text: { calling: '队列', answer: '接听', hangUp: '挂断', }, }; console.log('receive this------>', useCallModule()); if (session.listen_flag) { // monitor call,auto answer call // 值守的来电呼叫,自动接听 window.lemon.call.answerCall({ call_id: session.call_id }); monitor_call_list.push(session); emitter.emit('monitorUpdate'); } else { // normal call // 正常来电,弹框询问接听 // handleCallingNotification(callingReq); } }); }; // 申请话权 // apply floor const applyFloor = () => { console.info('try applyFloor,call_id=', call_id); if (!call_id) { console.warn('no call exits'); return undefined; } return window.lemon.floor .applySpeak({ call_id }) ?.then((resp) => { if (resp.result === 0) { console.log('applyFloor request sucess'); } else { ElMessage.error("申请话权失败"); } }) .catch((err) => { console.error('applyFloor error,', err); }); }; // 释放话权 // release floor const releaseFloor = () => { console.info('try releaseFloor,call_id=', call_id); return window.lemon.floor .releaseSpeak({ call_id }) ?.then((resp) => { if (resp.result === 0) { console.log('releaseSpeak request sucess'); } else { ElMessage.error("释放话权失败"); } }) .catch((err) => { console.error('releaseSpeak error,', err); }); }; // add floor event // 添加话权通知事件 const registerFloorGrantEvent = () => { if (floor_grant_cb_id !== undefined) { return; } floor_grant_cb_id = window.lemon.floor.addGrantEvt((grantInfo) => { console.log('registerFloorGrantEvent', grantInfo); if (grantInfo.result !== 0) { ElMessage.error("话权申请失败"); } }); }; // 强拆 // override the call const forceHangupCall = (callId) => { return window.lemon.call .forceHangupCall({ call_id: callId || call_id }) ?.then((resp) => { if (resp.result === 0) { console.log('forceHangupCall request sucess'); } else { ElMessage.error("强拆失败"); } call_id = undefined; window.calling_conference = undefined; // console.log('2222233registerCallEstablishEven'); }) .catch((err) => { console.error('forceHangupCall error,', err); }); }; // 强插 // interrupt the call during monitoring const forceApplySpeak = (callId) => { return window.lemon.floor .forceApplySpeak({ call_id: callId || call_id }) ?.then((resp) => { if (resp.result === 0) { console.log('forceApplySpeak request sucess'); call_id = callId; } else { ElMessage.error("强插失败"); } }) .catch((err) => { console.error('forceApplySpeak error,', err); }); }; /** * 会议成员禁言 * mute or unmute a conference member * @param param * @param param.conference_basedata_id */ const muteMemberInConference = ( conference_basedata_id, member_basedata_id, mute ) => { return window.lemon.call.conferenceMemberSpeakSet({ conference_call_id: call_id, conference_basedata_id, member_setting: { member_basedata_id, forbid: mute ? 1 : 0, }, }); }; /** * 视频推送 * select a local video file and play then push the stream to remote * @param record * @param file * @returns */ const pushVideoFile = (record, url) => { console.info('try pushVideoFile,call_id=', call_id); if (call_id) { console.warn('call exits'); return; } console.warn('window.video', window.video); // set the file to video tag if (window.video) { const canPlayListener = () => { window.video.removeEventListener('canplay', canPlayListener); // capture stream const stream = (window.video)?.captureStream(); console.info('pushVideoFile,inited stream=', stream); // register hook listner ,play the video when remote hooked registerCallEstablishEvent(); // init the call window.lemon.call .pushVideoFile({ basedata_id: record?.basedata_id, stream, }) ?.then((resp) => { pushing_video = true; call_id = resp.call_id; }); }; const endListener = () => { console.info('pushVideoFile,video play end'); window.video.removeEventListener('ended', endListener); hangup(); }; // maybe did't finish the video,so that we has listener already,remove it window.video.removeEventListener('ended', endListener); console.info('pushVideoFile,add canplay Event Listener', canPlayListener); window.video.addEventListener('canplay', canPlayListener); // hangup the call when video finished console.info('pushVideoFile,add ended Event Listener', endListener); window.video.addEventListener('ended', endListener); window.video.autoplay = false; window.video.src = url; } }; /** * 视频转发 * share a exist call to another device * @param record * @param stop * @returns */ const forwardVideoCall = (record, stop) => { console.info('try forwardVideoCall,call_id=', call_id); if (!call_id) { console.warn('no call exits,can not forward'); ElMessage.warning('no call exits'); return undefined; } return window.lemon.call .forwardVideoCall({ basedata_id: record?.basedata_id, call_id, action: stop ? 1 : 0, }) ?.then((resp) => { if (resp.result === 0) { console.log('forwardVideoCall request sucess'); } else { ElMessage.error("视频转发失败"); } }) .catch((err) => { console.error('forwardVideoCall error,', err); }); }; const getEmitter = () => { return emitter; }; // call sdk unInit const unInit = () => { call_id = undefined; if (hangup_event_cb_id) { window.lemon.call.removeHangupEvt(hangup_event_cb_id); hangup_event_cb_id = undefined; } if (force_hangup_event_cb_id) { window.lemon.call.removeForceHangupEvt(force_hangup_event_cb_id); force_hangup_event_cb_id = undefined; } if (answer_ack_cb_id) { window.lemon.call.removeAnswerAckEvt(answer_ack_cb_id); answer_ack_cb_id = undefined; } if (incoming_cb_id) { window.lemon.call.removeIncomingEvt(incoming_cb_id); incoming_cb_id = undefined; } if (floor_grant_cb_id) { window.lemon.floor.removeGrantEvt(floor_grant_cb_id); floor_grant_cb_id = undefined; } monitor_call_list.length = 0; }; return { makeVoiceCall, makeVideoCall, pureVideoCall, registerhangupEvent, registerReceiveCallEvent, answerCall, makeGroupVoiceCall, makeGroupVideoCall, makeBroadcastCall, hangup, voiceDetect, videoDetect, applyFloor, releaseFloor, setMuteCamera, setMuteMic, setMuteCall, muteMemberInConference, makeConferenceVoiceCall, makeConferenceVideoCall, makeCrosspatchVoiceCall, registerCallEstablishEvent, pushVideoFile, forwardVideoCall, forceHangupCall, getMonitorCallList, getEmitter, forceApplySpeak, registerFloorGrantEvent, registerForceHangupEvent, unInit, }; }