diff --git a/classes/videotime_instance.php b/classes/videotime_instance.php index e1bdbdbb..df63a23c 100644 --- a/classes/videotime_instance.php +++ b/classes/videotime_instance.php @@ -26,7 +26,7 @@ use cm_info; use core_component; -use external_description; +use core_external\external_description; use mod_videotime\local\tabs\tabs; use mod_videotime\output\next_activity_button; use renderer_base; diff --git a/classes/vimeo_embed.php b/classes/vimeo_embed.php index c51faf03..9a482c32 100644 --- a/classes/vimeo_embed.php +++ b/classes/vimeo_embed.php @@ -25,7 +25,6 @@ namespace mod_videotime; use core_component; -use external_description; use mod_videotime\local\tabs\tabs; use mod_videotime\output\next_activity_button; use renderer_base; diff --git a/plugin/live/amd/build/videotime.min.js b/plugin/live/amd/build/videotime.min.js index afc8dcbb..f12a8145 100644 --- a/plugin/live/amd/build/videotime.min.js +++ b/plugin/live/amd/build/videotime.min.js @@ -6,6 +6,6 @@ define("videotimeplugin_live/videotime",["exports","core/ajax","mod_videotime/vi * @module videotimeplugin_live/videotime * @copyright 2022 bdecent gmbh * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_ajax=_interopRequireDefault(_ajax),_videotime=_interopRequireDefault(_videotime),_janusGateway=_interopRequireDefault(_janusGateway),_log=_interopRequireDefault(_log),_notification=_interopRequireDefault(_notification),_publish=_interopRequireDefault(_publish),_subscribe=_interopRequireDefault(_subscribe),_socket=_interopRequireDefault(_socket);var rooms={};class Publish extends _publish.default{register(pluginHandle){return _ajax.default.call([{args:{handle:pluginHandle.getId(),id:Number(this.peerid),plugin:pluginHandle.plugin,room:this.roomid,ptype:"publish"==this.ptype,session:pluginHandle.session.getSessionId()},contextid:this.contextid,fail:_notification.default.exception,methodname:"videotimeplugin_live_join_room"}])[0]}getTransceiver(id){let result=null;return this.videoroom.webrtcStuff.pc&&"connected"==this.videoroom.webrtcStuff.pc.iceConnectionState&&this.videoroom.webrtcStuff.pc.getTransceivers().forEach((transceiver=>{const sender=transceiver.sender;sender.track&&sender.track.id&&(!id||sender.track.id==id)&&this.tracks[sender.track.id]&&(result=transceiver)})),result}publishFeed(){this.videoroom.webrtcStuff.pc&&"connected"==this.videoroom.webrtcStuff.pc.iceConnectionState&&setTimeout((()=>(this.videoroom.webrtcStuff.pc.getTransceivers().forEach((transceiver=>{const sender=transceiver.sender;if(sender.track&&this.selectedTrack&&sender.track.id==this.selectedTrack.id){const message=JSON.stringify({feed:Number(this.peerid),mid:transceiver.mid});this.videoroom.data({text:message,error:_log.default.debug})}})),_ajax.default.call([{args:{id:Number(this.peerid),room:this.roomid},contextid:this.contextid,fail:_notification.default.exception,methodname:"videotimeplugin_live_publish_feed"}])[0])))}unpublish(){_ajax.default.call([{args:{id:Number(this.peerid),publish:!1,room:this.roomid},contextid:this.contextid,fail:_notification.default.exception,methodname:"videotimeplugin_live_publish_feed"}]),this.videoInput&&this.videoroom.send({message:{request:"unpublish"}}),[this.currentCamera,this.currentDisplay].forEach((videoInput=>{videoInput&&videoInput.then((videoStream=>(videoStream&&videoStream.getTracks().forEach((track=>{track.stop()})),null))).catch(_notification.default.exception)})),this.currentCamera=null,this.currentDisplay=null,this.videoInput=null,this.videoroom.webrtcStuff.pc&&"connected"==this.videoroom.webrtcStuff.pc.iceConnectionState&&this.videoroom.webrtcStuff.pc.getTransceivers().forEach((transceiver=>{transceiver.stop()})),this.tracks={}}onLocalTrack(track,on){const remoteStream=new MediaStream([track]);on?(remoteStream.mid=track.mid,_log.default.debug(remoteStream),_janusGateway.default.attachMediaStream(document.getElementById("video-controls-"+this.tracks[track.id]),remoteStream)):this.videoInput.then((videoStream=>(videoStream&&videoStream.getTracks().forEach((current=>{current.id==track.id&&this.unpublish()})),videoStream))).catch(_notification.default.exception)}handleClick(e){const button=e.target.closest('[data-contextid="'+this.contextid+'"][data-action="publish"], [data-contextid="'+this.contextid+'"][data-action="unpublish"]');if(button){const action=button.getAttribute("data-action"),type=button.getAttribute("data-type")||"camera";switch(e.stopPropagation(),e.preventDefault(),document.querySelectorAll('[data-region="deft-venue"] [data-action="publish"], [data-region="deft-venue"] [data-action="unpublish"]').forEach((button=>{button.getAttribute("data-action")==action&&button.getAttribute("data-type")==type||button.classList.remove("hidden")})),action){case"publish":_log.default.debug(type),"display"==type?this.shareDisplay():this.shareCamera(),this.videoInput.then((videoStream=>{const tracks=[];if(this.tracks=this.tracks||{},videoStream){if(_log.default.debug(videoStream.getVideoTracks()),videoStream.getVideoTracks().forEach((track=>{const transceiver=this.getTransceiver(track.id);if(transceiver){const message=JSON.stringify({feed:Number(this.peerid),mid:transceiver.mid});this.videoroom.data({text:message,error:_log.default.debug}),this.selectedTrack=track.id,this.publishFeed()}else tracks.push({type:"video",capture:track,recv:!1}),this.selectedTrack=track,this.tracks[track.id]=type,_log.default.debug("New track")})),videoStream.getAudioTracks().forEach((track=>{tracks.push({type:"audio",capture:track,recv:!1})})),!tracks.length)return videoStream;this.videoroom.createOffer({tracks:tracks,success:jsep=>{this.videoroom.send({message:{request:"configure",video:!0,audio:!0},jsep:jsep})},error:function(error){_notification.default.alert("WebRTC error... ",error.message)}})}return videoStream})).catch(_notification.default.exception);break;case"unpublish":this.unpublish()}}return!0}shareCamera(){const videoInput=this.videoInput,currentCamera=this.currentCamera||Promise.resolve(null);this.videoInput=currentCamera.then((videoStream=>{if(videoStream)return videoStream;{const cameraInput=navigator.mediaDevices.getUserMedia({video:!0,audio:!1});return this.currentCamera=cameraInput.catch((()=>currentCamera)),cameraInput.then((videoStream=>(this.tracks=this.tracks||{},videoStream.getTracks().forEach((track=>{this.tracks[track.id]="camera"})),videoStream))).catch((e=>(_log.default.debug(e),videoInput)))}}))}shareDisplay(){const videoInput=this.videoInput,currentDisplay=this.currentDisplay||Promise.resolve(null),displayInput=navigator.mediaDevices.getDisplayMedia({video:!0,audio:!1});this.videoInput=displayInput.then((videoStream=>(this.tracks=this.tracks||{},videoStream.getTracks().forEach((track=>{this.tracks[track.id]="display"})),videoStream))).catch((e=>(_log.default.debug(e),videoInput))),this.currentDisplay=displayInput.then((videoStream=>(videoStream&¤tDisplay.then((videoStream=>(videoStream&&videoStream.getTracks().forEach((track=>{track.stop()})),videoStream))).catch(_notification.default.exception),videoStream))).catch((e=>(_log.default.debug(e),currentDisplay)))}}class VideoTime extends _videotime.default{initialize(contextid,token,peerid){return _log.default.debug("Initializing Video Time "+this.elementId),this.contextid=contextid,this.peerid=peerid,_ajax.default.call([{methodname:"videotimeplugin_live_get_room",args:{contextid:contextid},done:response=>{const socket=new _socket.default(contextid,token);this.iceservers=JSON.parse(response.iceservers),this.roomid=response.roomid,this.server=response.server,rooms[String(contextid)]={contextid:contextid,peerid:peerid,roomid:response.roomid,server:response.server,iceServers:JSON.parse(response.iceservers)},this.roomid=response.roomid,socket.subscribe((()=>{_ajax.default.call([{methodname:"videotimeplugin_live_get_feed",args:{contextid:contextid},done:response=>{const room=rooms[String(contextid)];room.publish&&room.publish.restart&&(response.feed==peerid&&this.unpublish(),room.publish=null),this.subscribeTo(Number(response.feed))},fail:_notification.default.exception}])}))},fail:_notification.default.exception}]),this.addListeners(),!0}addListeners(){document.querySelector("body").removeEventListener("click",handleClick),document.querySelector("body").addEventListener("click",handleClick)}subscribeTo(source){if(!this.remoteFeed||this.remoteFeed.creatingSubscription||this.remoteFeed.restart)this.remoteFeed&&this.remoteFeed.restart?this.remoteFeed.current!=source&&(this.remoteFeed&&this.remoteFeed.janus&&this.remoteFeed.janus.destroy(),this.remoteFeed=null,this.subscribeTo(source)):this.remoteFeed?setTimeout((()=>{this.subscribeTo(source)}),500):source&&(this.remoteFeed=new Subscribe(this.contextid,this.iceservers,this.roomid,this.server,this.peerid,source),this.remoteFeed.remoteVideo=document.getElementById(this.elementId),this.remoteFeed.remoteAudio=document.getElementById(this.elementId).parentNode.querySelector("audio"),this.remoteFeed.startConnection(source),document.querySelectorAll('[data-contextid="'+this.contextid+'"] img.poster-img').forEach((img=>{img.classList.add("hidden")})),document.querySelectorAll('[data-contextid="'+this.contextid+'"] video').forEach((img=>{img.classList.remove("hidden")})));else{const update={request:"update",subscribe:[{feed:Number(source)}],unsubscribe:[{feed:Number(this.remoteFeed.current)}]};if(!source&&this.remoteFeed.current?delete update.subscribe:source&&!this.remoteFeed.current&&delete update.unsubscribe,this.remoteFeed.current!=source){if(_log.default.debug('[data-contextid="'+this.contextid+'"] img.poster-img'),source?(document.querySelectorAll('[data-contextid="'+this.contextid+'"] img.poster-img').forEach((img=>{img.classList.add("hidden")})),document.querySelectorAll('[data-contextid="'+this.contextid+'"] video').forEach((img=>{img.classList.remove("hidden")}))):(document.querySelectorAll('[data-contextid="'+this.contextid+'"] img.poster-img').forEach((img=>{img.classList.remove("hidden")})),document.querySelectorAll('[data-contextid="'+this.contextid+'"] video').forEach((img=>{img.classList.add("hidden")}))),this.remoteFeed.videoroom.send({message:update}),this.remoteFeed.current==this.peerid){rooms[String(this.contextid)].publish.unpublish()}this.remoteFeed.current=source,source||(this.remoteFeed&&this.remoteFeed.janus&&this.remoteFeed.janus.destroy(),this.remoteFeed=null)}}}}_exports.default=VideoTime;const handleClick=function(e){const button=e.target.closest('[data-roomid] [data-action="publish"], [data-roomid] [data-action="unpublish"]');if(button){const action=button.getAttribute("data-action"),contextid=e.target.closest("[data-contextid]").getAttribute("data-contextid"),room=rooms[String(contextid)],iceServers=room.iceServers,peerid=room.peerid,roomid=room.roomid,server=room.server,type=button.getAttribute("data-type");e.stopPropagation(),e.preventDefault(),"unpublish"==action?_ajax.default.call([{args:{id:Number(peerid),room:roomid,publish:!1},contextid:contextid,fail:_notification.default.exception,methodname:"videotimeplugin_live_publish_feed"}]):!room.publish||room.publish.restart?(room.publish=new Publish(contextid,iceServers,roomid,server,peerid),"display"==type?room.publish.shareDisplay():room.publish.shareCamera(),room.publish.startConnection()):room.publish.handleClick(e)}};class Subscribe extends _subscribe.default{register(pluginHandle){return _ajax.default.call([{args:{handle:pluginHandle.getId(),id:Number(this.peerid),plugin:pluginHandle.plugin,room:this.roomid,ptype:!1,feed:this.feed,session:pluginHandle.session.getSessionId()},contextid:this.contextid,fail:_notification.default.exception,methodname:"videotimeplugin_live_join_room"}])[0]}}return _exports.default})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_ajax=_interopRequireDefault(_ajax),_videotime=_interopRequireDefault(_videotime),_janusGateway=_interopRequireDefault(_janusGateway),_log=_interopRequireDefault(_log),_notification=_interopRequireDefault(_notification),_publish=_interopRequireDefault(_publish),_subscribe=_interopRequireDefault(_subscribe),_socket=_interopRequireDefault(_socket);var rooms={};class Publish extends _publish.default{register(pluginHandle){return _ajax.default.call([{args:{handle:pluginHandle.getId(),id:Number(this.contextid),plugin:pluginHandle.plugin,room:this.roomid,ptype:"publish"==this.ptype,session:pluginHandle.session.getSessionId()},contextid:this.contextid,fail:_notification.default.exception,methodname:"videotimeplugin_live_join_room"}])[0].then((response=>{this.feed=response.id})).catch(_notification.default.exception)}publishFeed(){return _ajax.default.call([{args:{id:Number(this.feed),room:this.roomid},contextid:this.contextid,fail:_notification.default.exception,methodname:"videotimeplugin_live_publish_feed"}])[0]}unpublish(){return _ajax.default.call([{args:{id:Number(this.feed),publish:!1,room:this.roomid},contextid:this.contextid,fail:_notification.default.exception,methodname:"videotimeplugin_live_publish_feed"}])[0]}handleClose(){document.querySelectorAll('[data-contextid="'+this.contextid+'"][data-action="publish"]').forEach((button=>{button.classList.remove("hidden")})),this.janus.destroy(),[this.currentCamera||Promise.resolve(null),this.currentDisplay||Promise.resolve(null)].forEach((videoInput=>{videoInput.then((videoStream=>(videoStream&&videoStream.getVideoTracks().forEach((track=>{track.enabled=!1,track.stop()})),null))).catch(_notification.default.exception)}))}onLocalTrack(track,on){const remoteStream=new MediaStream([track]);on&&(remoteStream.mid=track.mid,_log.default.debug(on),_log.default.debug(remoteStream),_janusGateway.default.attachMediaStream(document.getElementById("video-controls-"+this.tracks[track.id]),remoteStream))}handleClick(e){const button=e.target.closest('[data-contextid="'+this.contextid+'"][data-action="publish"], [data-contextid="'+this.contextid+'"][data-action="unpublish"]');if(button){const action=button.getAttribute("data-action"),type=button.getAttribute("data-type")||"camera";switch(e.stopPropagation(),e.preventDefault(),document.querySelectorAll('[data-region="deft-venue"] [data-action="publish"], [data-region="deft-venue"] [data-action="unpublish"]').forEach((button=>{button.getAttribute("data-action")==action&&button.getAttribute("data-type")==type||button.classList.remove("hidden")})),action){case"publish":_log.default.debug(type),"display"==type?this.shareDisplay():this.shareCamera(),this.videoInput.then((videoStream=>{const tracks=[];if(this.tracks=this.tracks||{},videoStream){const transceiver=this.getTransceiver();if(videoStream.getVideoTracks().forEach((track=>{if(track.addEventListener("ended",(()=>{this.selectedTrack!=track.id&&this.unpublish()})),transceiver)return this.videoroom.replaceTracks({tracks:[{type:"video",mid:transceiver.mid,capture:track}],error:_notification.default.exception}),void(this.selectedTrack=track);tracks.push({type:"video",capture:track,recv:!1}),this.selectedTrack=track})),!tracks.length)return videoStream;if(videoStream.getAudioTracks().forEach((track=>{tracks.push({type:"audio",capture:track,recv:!1})})),!tracks.length)return videoStream;this.videoroom.createOffer({tracks:tracks,success:jsep=>{this.videoroom.send({message:{request:"configure",video:!0,audio:!0},jsep:jsep})},error:function(error){_notification.default.alert("WebRTC error... ",error.message)}})}return videoStream})).catch(_notification.default.exception);break;case"unpublish":this.unpublish()}}return!0}shareCamera(){const videoInput=this.videoInput,currentCamera=this.currentCamera||Promise.resolve(null);this.videoInput=currentCamera.then((videoStream=>{if(videoStream)return videoStream;{const cameraInput=navigator.mediaDevices.getUserMedia({video:!0,audio:!1});return this.currentCamera=cameraInput.catch((()=>currentCamera)),cameraInput.then((videoStream=>(this.tracks=this.tracks||{},videoStream.getTracks().forEach((track=>{this.tracks[track.id]="camera"})),videoStream))).catch((e=>(_log.default.debug(e),videoInput)))}}))}shareDisplay(){const videoInput=this.videoInput,currentDisplay=this.currentDisplay||Promise.resolve(null),displayInput=navigator.mediaDevices.getDisplayMedia({video:!0,audio:!1});this.videoInput=displayInput.then((videoStream=>(videoInput&&videoInput.then((videoStream=>(videoStream&&videoStream.getTracks().forEach((track=>{_log.default.debug(track)})),videoStream))).catch(_notification.default.exception),this.tracks=this.tracks||{},videoStream.getTracks().forEach((track=>{this.tracks[track.id]="display"})),videoStream))).catch((e=>(_log.default.debug(e),videoInput))),this.currentDisplay=displayInput.then((videoStream=>(currentDisplay.then((videoStream=>{videoStream&&videoStream.getTracks().forEach((track=>{_log.default.debug("stop track"),_log.default.debug(track),track.stop()}))})),videoStream))).catch((e=>(_log.default.debug(e),currentDisplay)))}}class VideoTime extends _videotime.default{initialize(contextid,token,peerid){return _log.default.debug("Initializing Video Time "+this.elementId),this.contextid=contextid,this.peerid=peerid,_ajax.default.call([{methodname:"videotimeplugin_live_get_room",args:{contextid:contextid},done:response=>{const socket=new _socket.default(contextid,token);this.iceservers=JSON.parse(response.iceservers),this.roomid=response.roomid,this.server=response.server,rooms[String(contextid)]={contextid:contextid,peerid:peerid,roomid:response.roomid,server:response.server,iceServers:JSON.parse(response.iceservers)},this.roomid=response.roomid,socket.subscribe((()=>{_ajax.default.call([{methodname:"videotimeplugin_live_get_feed",args:{contextid:contextid},done:response=>{const room=rooms[String(contextid)];room.publish&&room.publish.restart&&(response.feed==peerid&&this.unpublish(),room.publish=null),this.subscribeTo(Number(response.feed))},fail:_notification.default.exception}])}))},fail:_notification.default.exception}]),this.addListeners(),!0}addListeners(){document.querySelector("body").removeEventListener("click",handleClick),document.querySelector("body").addEventListener("click",handleClick)}subscribeTo(source){if(document.querySelectorAll('[data-contextid="'+this.contextid+'"][data-action="publish"]').forEach((button=>{Number(this.peerid),button.classList.remove("hidden")})),document.querySelectorAll('[data-contextid="'+this.contextid+'"][data-action="unpublish"]').forEach((button=>{Number(this.peerid),button.classList.remove("hidden")})),_log.default.debug(source),!this.remoteFeed||this.remoteFeed.creatingSubscription||this.remoteFeed.restart)this.remoteFeed&&this.remoteFeed.restart?this.remoteFeed.current!=source&&(this.remoteFeed=null,this.subscribeTo(source)):this.remoteFeed?setTimeout((()=>{this.subscribeTo(source)}),500):source&&(this.remoteFeed=new Subscribe(this.contextid,this.iceservers,this.roomid,this.server,this.peerid,source),this.remoteFeed.remoteVideo=document.getElementById(this.elementId),this.remoteFeed.remoteAudio=document.getElementById(this.elementId).parentNode.querySelector("audio"),this.remoteFeed.startConnection(source),document.querySelectorAll('[data-contextid="'+this.contextid+'"] img.poster-img').forEach((img=>{img.classList.add("hidden")})),document.querySelectorAll('[data-contextid="'+this.contextid+'"] video').forEach((img=>{img.classList.remove("hidden")})));else{const update={request:"update",subscribe:[{feed:Number(source)}],unsubscribe:[{feed:Number(this.remoteFeed.current)}]};if(!source&&this.remoteFeed.current?delete update.subscribe:source&&!this.remoteFeed.current&&delete update.unsubscribe,this.remoteFeed.current!=source){const room=rooms[String(this.contextid)];this.remoteFeed.videoroom.send({message:update}),room.publish&&this.remoteFeed.current==room.publish.feed&&(room.publish.handleClose(),room.publish=null),this.remoteFeed.current=source,!source&&this.remoteFeed.current&&(this.remoteFeed.handleClose(),this.remoteFeed=null),_log.default.debug('[data-contextid="'+this.contextid+'"] img.poster-img'),Number(source)?(document.querySelectorAll('[data-contextid="'+this.contextid+'"] img.poster-img').forEach((img=>{img.classList.add("hidden")})),document.querySelectorAll('[data-contextid="'+this.contextid+'"] video').forEach((video=>{video.classList.remove("hidden")}))):(document.querySelectorAll('[data-contextid="'+this.contextid+'"] img.poster-img').forEach((img=>{img.classList.remove("hidden")})),document.querySelectorAll('[data-contextid="'+this.contextid+'"] video').forEach((video=>{video.classList.add("hidden")})))}}}}_exports.default=VideoTime;const handleClick=function(e){const button=e.target.closest('[data-roomid] [data-action="publish"], [data-roomid] [data-action="unpublish"]');if(button){const action=button.getAttribute("data-action"),contextid=e.target.closest("[data-contextid]").getAttribute("data-contextid"),room=rooms[String(contextid)],iceServers=room.iceServers,peerid=room.peerid,roomid=room.roomid,server=room.server,type=button.getAttribute("data-type");e.stopPropagation(),e.preventDefault(),"publish"!=action||room.publish&&!room.publish.restart?room.publish.handleClick(e):(room.publish=new Publish(contextid,iceServers,roomid,server,peerid),"display"==type?room.publish.shareDisplay():room.publish.shareCamera(),room.publish.startConnection())}};class Subscribe extends _subscribe.default{register(pluginHandle){return _ajax.default.call([{args:{handle:pluginHandle.getId(),id:Number(this.contextid),plugin:pluginHandle.plugin,room:this.roomid,ptype:!1,feed:this.feed,session:pluginHandle.session.getSessionId()},contextid:this.contextid,fail:_notification.default.exception,methodname:"videotimeplugin_live_join_room"}])[0]}}return _exports.default})); //# sourceMappingURL=videotime.min.js.map \ No newline at end of file diff --git a/plugin/live/amd/build/videotime.min.js.map b/plugin/live/amd/build/videotime.min.js.map index fb43732f..13b53157 100644 --- a/plugin/live/amd/build/videotime.min.js.map +++ b/plugin/live/amd/build/videotime.min.js.map @@ -1 +1 @@ -{"version":3,"file":"videotime.min.js","sources":["../src/videotime.js"],"sourcesContent":["/*\n * Video time player specific js\n *\n * @package videotimeplugin_live\n * @module videotimeplugin_live/videotime\n * @copyright 2022 bdecent gmbh \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from \"core/ajax\";\nimport VideoTimeBase from \"mod_videotime/videotime\";\nimport Janus from 'block_deft/janus-gateway';\nimport Log from \"core/log\";\nimport Notification from \"core/notification\";\nimport PublishBase from \"block_deft/publish\";\nimport SubscribeBase from \"block_deft/subscribe\";\nimport Socket from \"videotimeplugin_live/socket\";\n\nvar rooms = {};\n\nclass Publish extends PublishBase {\n /**\n * Register the room\n *\n * @param {object} pluginHandle\n * @return {Promise}\n */\n register(pluginHandle) {\n // Try a registration\n return Ajax.call([{\n args: {\n handle: pluginHandle.getId(),\n id: Number(this.peerid),\n plugin: pluginHandle.plugin,\n room: this.roomid,\n ptype: this.ptype == 'publish',\n session: pluginHandle.session.getSessionId()\n },\n contextid: this.contextid,\n fail: Notification.exception,\n methodname: 'videotimeplugin_live_join_room'\n }])[0];\n }\n\n getTransceiver(id) {\n let result = null;\n\n if (\n this.videoroom.webrtcStuff.pc\n && this.videoroom.webrtcStuff.pc.iceConnectionState == 'connected'\n ) {\n this.videoroom.webrtcStuff.pc.getTransceivers().forEach(transceiver => {\n const sender = transceiver.sender;\n if (\n sender.track\n && sender.track.id\n && (!id || sender.track.id == id)\n && this.tracks[sender.track.id]\n ) {\n result = transceiver;\n }\n });\n }\n\n return result;\n }\n\n publishFeed() {\n if (\n this.videoroom.webrtcStuff.pc\n && this.videoroom.webrtcStuff.pc.iceConnectionState == 'connected'\n ) {\n setTimeout(() => {\n this.videoroom.webrtcStuff.pc.getTransceivers().forEach(transceiver => {\n const sender = transceiver.sender;\n if (\n sender.track\n && this.selectedTrack\n && (sender.track.id == this.selectedTrack.id)\n ) {\n const message = JSON.stringify({\n feed: Number(this.peerid),\n mid: transceiver.mid\n });\n this.videoroom.data({\n text: message,\n error: Log.debug\n });\n }\n });\n return Ajax.call([{\n args: {\n id: Number(this.peerid),\n room: this.roomid,\n },\n contextid: this.contextid,\n fail: Notification.exception,\n methodname: 'videotimeplugin_live_publish_feed'\n }])[0];\n });\n }\n }\n\n unpublish() {\n Ajax.call([{\n args: {\n id: Number(this.peerid),\n publish: false,\n room: this.roomid\n },\n contextid: this.contextid,\n fail: Notification.exception,\n methodname: 'videotimeplugin_live_publish_feed'\n }]);\n\n if (this.videoInput) {\n this.videoroom.send({\n message: {\n request: 'unpublish'\n }\n });\n }\n\n [\n this.currentCamera,\n this.currentDisplay,\n ].forEach(videoInput => {\n if (videoInput) {\n videoInput.then(videoStream => {\n if (videoStream) {\n videoStream.getTracks().forEach(track => {\n track.stop();\n });\n }\n\n return null;\n }).catch(Notification.exception);\n }\n });\n this.currentCamera = null;\n this.currentDisplay = null;\n this.videoInput = null;\n\n if (\n this.videoroom.webrtcStuff.pc\n && this.videoroom.webrtcStuff.pc.iceConnectionState == 'connected'\n ) {\n\n this.videoroom.webrtcStuff.pc.getTransceivers().forEach(transceiver => {\n transceiver.stop();\n });\n }\n this.tracks = {};\n }\n\n onLocalTrack(track, on) {\n const remoteStream = new MediaStream([track]);\n if (!on) {\n this.videoInput.then(videoStream => {\n if (videoStream) {\n videoStream.getTracks().forEach(current => {\n if (current.id == track.id) {\n this.unpublish();\n }\n });\n }\n return videoStream;\n }).catch(Notification.exception);\n\n return;\n }\n remoteStream.mid = track.mid;\n Log.debug(remoteStream);\n Janus.attachMediaStream(\n document.getElementById('video-controls-' + this.tracks[track.id]),\n remoteStream\n );\n }\n\n handleClick(e) {\n const button = e.target.closest(\n '[data-contextid=\"' + this.contextid + '\"][data-action=\"publish\"], [data-contextid=\"'\n + this.contextid + '\"][data-action=\"unpublish\"]'\n );\n if (button) {\n const action = button.getAttribute('data-action'),\n type = button.getAttribute('data-type') || 'camera';\n e.stopPropagation();\n e.preventDefault();\n document.querySelectorAll(\n '[data-region=\"deft-venue\"] [data-action=\"publish\"], [data-region=\"deft-venue\"] [data-action=\"unpublish\"]'\n ).forEach(button => {\n if ((button.getAttribute('data-action') != action) || (button.getAttribute('data-type') != type)) {\n button.classList.remove('hidden');\n }\n });\n switch (action) {\n case 'publish':\n Log.debug(type);\n if (type == 'display') {\n this.shareDisplay();\n } else {\n this.shareCamera();\n }\n\n this.videoInput.then(videoStream => {\n const tracks = [];\n this.tracks = this.tracks || {};\n if (videoStream) {\n Log.debug(videoStream.getVideoTracks());\n videoStream.getVideoTracks().forEach(track => {\n const transceiver = this.getTransceiver(track.id);\n if (!transceiver) {\n tracks.push({\n type: 'video',\n capture: track,\n recv: false\n });\n this.selectedTrack = track;\n this.tracks[track.id] = type;\n Log.debug('New track');\n } else {\n const message = JSON.stringify({\n feed: Number(this.peerid),\n mid: transceiver.mid\n });\n this.videoroom.data({\n text: message,\n error: Log.debug\n });\n this.selectedTrack = track.id;\n this.publishFeed();\n }\n });\n videoStream.getAudioTracks().forEach(track => {\n tracks.push({\n type: 'audio',\n capture: track,\n recv: false\n });\n });\n if (!tracks.length) {\n return videoStream;\n }\n this.videoroom.createOffer({\n tracks: tracks,\n success: (jsep) => {\n const publish = {\n request: \"configure\",\n video: true,\n audio: true\n };\n this.videoroom.send({\n message: publish,\n jsep: jsep\n });\n },\n error: function(error) {\n Notification.alert(\"WebRTC error... \", error.message);\n }\n });\n }\n\n return videoStream;\n }).catch(Notification.exception);\n break;\n case 'unpublish':\n this.unpublish();\n break;\n }\n }\n\n return true;\n }\n\n /**\n * Set video source to user camera\n */\n shareCamera() {\n const videoInput = this.videoInput,\n currentCamera = this.currentCamera || Promise.resolve(null);\n\n this.videoInput = currentCamera.then(videoStream => {\n if (videoStream) {\n return videoStream;\n } else {\n const cameraInput = navigator.mediaDevices.getUserMedia({\n video: true,\n audio: false\n });\n\n this.currentCamera = cameraInput.catch(() => {\n return currentCamera;\n });\n\n return cameraInput.then(videoStream => {\n this.tracks = this.tracks || {};\n videoStream.getTracks().forEach(track => {\n this.tracks[track.id] = 'camera';\n });\n\n return videoStream;\n }).catch((e) => {\n Log.debug(e);\n\n return videoInput;\n });\n }\n });\n }\n\n /**\n * Set video source to display surface\n */\n shareDisplay() {\n const videoInput = this.videoInput,\n currentDisplay = this.currentDisplay || Promise.resolve(null),\n displayInput = navigator.mediaDevices.getDisplayMedia({\n video: true,\n audio: false\n });\n\n this.videoInput = displayInput.then(videoStream => {\n this.tracks = this.tracks || {};\n videoStream.getTracks().forEach(track => {\n this.tracks[track.id] = 'display';\n });\n\n return videoStream;\n }).catch((e) => {\n Log.debug(e);\n\n return videoInput;\n });\n\n this.currentDisplay = displayInput.then(videoStream => {\n if (videoStream) {\n currentDisplay.then(videoStream => {\n if (videoStream) {\n videoStream.getTracks().forEach(track => {\n track.stop();\n });\n }\n\n return videoStream;\n }).catch(Notification.exception);\n }\n\n return videoStream;\n }).catch((e) => {\n Log.debug(e);\n\n return currentDisplay;\n });\n }\n}\n\nexport default class VideoTime extends VideoTimeBase {\n initialize(contextid, token, peerid) {\n Log.debug(\"Initializing Video Time \" + this.elementId);\n\n this.contextid = contextid;\n this.peerid = peerid;\n\n Ajax.call([{\n methodname: 'videotimeplugin_live_get_room',\n args: {contextid: contextid},\n done: (response) => {\n const socket = new Socket(contextid, token);\n\n this.iceservers = JSON.parse(response.iceservers);\n this.roomid = response.roomid;\n this.server = response.server;\n\n rooms[String(contextid)] = {\n contextid: contextid,\n peerid: peerid,\n roomid: response.roomid,\n server: response.server,\n iceServers: JSON.parse(response.iceservers)\n };\n this.roomid = response.roomid;\n\n socket.subscribe(() => {\n Ajax.call([{\n methodname: 'videotimeplugin_live_get_feed',\n args: {contextid: contextid},\n done: (response) => {\n const room = rooms[String(contextid)];\n if (room.publish && room.publish.restart) {\n if (response.feed == peerid) {\n this.unpublish();\n }\n room.publish = null;\n }\n this.subscribeTo(Number(response.feed));\n },\n fail: Notification.exception\n }]);\n });\n },\n fail: Notification.exception\n }]);\n\n this.addListeners();\n\n return true;\n }\n\n /**\n * Register player events to respond to user interaction and play progress.\n */\n addListeners() {\n document.querySelector('body').removeEventListener('click', handleClick);\n document.querySelector('body').addEventListener('click', handleClick);\n return;\n }\n\n /**\n * Subscribe to feed\n *\n * @param {int} source Feed to subscribe\n */\n subscribeTo(source) {\n\n if (this.remoteFeed && !this.remoteFeed.creatingSubscription && !this.remoteFeed.restart) {\n const update = {\n request: 'update',\n subscribe: [{\n feed: Number(source)\n }],\n unsubscribe: [{\n feed: Number(this.remoteFeed.current)\n }]\n };\n\n if (!source && this.remoteFeed.current) {\n delete update.subscribe;\n } else if (source && !this.remoteFeed.current) {\n delete update.unsubscribe;\n }\n\n if (this.remoteFeed.current != source) {\n Log.debug('[data-contextid=\"' + this.contextid + '\"] img.poster-img');\n if (source) {\n document.querySelectorAll('[data-contextid=\"' + this.contextid + '\"] img.poster-img').forEach(img => {\n img.classList.add('hidden');\n });\n document.querySelectorAll('[data-contextid=\"' + this.contextid + '\"] video').forEach(img => {\n img.classList.remove('hidden');\n });\n } else {\n document.querySelectorAll('[data-contextid=\"' + this.contextid + '\"] img.poster-img').forEach(img => {\n img.classList.remove('hidden');\n });\n document.querySelectorAll('[data-contextid=\"' + this.contextid + '\"] video').forEach(img => {\n img.classList.add('hidden');\n });\n }\n this.remoteFeed.videoroom.send({message: update});\n if (this.remoteFeed.current == this.peerid) {\n const room = rooms[String(this.contextid)];\n room.publish.unpublish();\n }\n this.remoteFeed.current = source;\n if (!source) {\n if (this.remoteFeed && this.remoteFeed.janus) {\n this.remoteFeed.janus.destroy();\n }\n this.remoteFeed = null;\n }\n }\n } else if (this.remoteFeed && this.remoteFeed.restart) {\n if (this.remoteFeed.current != source) {\n if (this.remoteFeed && this.remoteFeed.janus) {\n this.remoteFeed.janus.destroy();\n }\n this.remoteFeed = null;\n this.subscribeTo(source);\n }\n } else if (this.remoteFeed) {\n setTimeout(() => {\n this.subscribeTo(source);\n }, 500);\n } else if (source) {\n this.remoteFeed = new Subscribe(this.contextid, this.iceservers, this.roomid, this.server, this.peerid, source);\n this.remoteFeed.remoteVideo = document.getElementById(this.elementId);\n this.remoteFeed.remoteAudio = document.getElementById(this.elementId).parentNode.querySelector('audio');\n this.remoteFeed.startConnection(source);\n document.querySelectorAll('[data-contextid=\"' + this.contextid + '\"] img.poster-img').forEach(img => {\n img.classList.add('hidden');\n });\n document.querySelectorAll('[data-contextid=\"' + this.contextid + '\"] video').forEach(img => {\n img.classList.remove('hidden');\n });\n }\n }\n}\n\nconst handleClick = function(e) {\n const button = e.target.closest('[data-roomid] [data-action=\"publish\"], [data-roomid] [data-action=\"unpublish\"]');\n if (button) {\n const action = button.getAttribute('data-action'),\n contextid = e.target.closest('[data-contextid]').getAttribute('data-contextid'),\n room = rooms[String(contextid)],\n iceServers = room.iceServers,\n peerid = room.peerid,\n roomid = room.roomid,\n server = room.server,\n type = button.getAttribute('data-type');\n e.stopPropagation();\n e.preventDefault();\n if (action == 'unpublish') {\n Ajax.call([{\n args: {\n id: Number(peerid),\n room: roomid,\n publish: false\n },\n contextid: contextid,\n fail: Notification.exception,\n methodname: 'videotimeplugin_live_publish_feed'\n }]);\n } else if (!room.publish || room.publish.restart) {\n room.publish = new Publish(contextid, iceServers, roomid, server, peerid);\n if (type == 'display') {\n room.publish.shareDisplay();\n } else {\n room.publish.shareCamera();\n }\n room.publish.startConnection();\n } else {\n room.publish.handleClick(e);\n }\n }\n};\n\nclass Subscribe extends SubscribeBase {\n /**\n * Register the room\n *\n * @param {object} pluginHandle\n * @return {Promise}\n */\n register(pluginHandle) {\n // Try a registration\n return Ajax.call([{\n args: {\n handle: pluginHandle.getId(),\n id: Number(this.peerid),\n plugin: pluginHandle.plugin,\n room: this.roomid,\n ptype: false,\n feed: this.feed,\n session: pluginHandle.session.getSessionId()\n },\n contextid: this.contextid,\n fail: Notification.exception,\n methodname: 'videotimeplugin_live_join_room'\n }])[0];\n }\n}\n"],"names":["rooms","Publish","PublishBase","register","pluginHandle","Ajax","call","args","handle","getId","id","Number","this","peerid","plugin","room","roomid","ptype","session","getSessionId","contextid","fail","Notification","exception","methodname","getTransceiver","result","videoroom","webrtcStuff","pc","iceConnectionState","getTransceivers","forEach","transceiver","sender","track","tracks","publishFeed","setTimeout","selectedTrack","message","JSON","stringify","feed","mid","data","text","error","Log","debug","unpublish","publish","videoInput","send","request","currentCamera","currentDisplay","then","videoStream","getTracks","stop","catch","onLocalTrack","on","remoteStream","MediaStream","attachMediaStream","document","getElementById","current","handleClick","e","button","target","closest","action","getAttribute","type","stopPropagation","preventDefault","querySelectorAll","classList","remove","shareDisplay","shareCamera","getVideoTracks","push","capture","recv","getAudioTracks","length","createOffer","success","jsep","video","audio","alert","Promise","resolve","cameraInput","navigator","mediaDevices","getUserMedia","displayInput","getDisplayMedia","VideoTime","VideoTimeBase","initialize","token","elementId","done","response","socket","Socket","iceservers","parse","server","String","iceServers","subscribe","restart","subscribeTo","addListeners","querySelector","removeEventListener","addEventListener","source","remoteFeed","creatingSubscription","janus","destroy","Subscribe","remoteVideo","remoteAudio","parentNode","startConnection","img","add","update","unsubscribe","SubscribeBase"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"videotime.min.js","sources":["../src/videotime.js"],"sourcesContent":["/*\n * Video time player specific js\n *\n * @package videotimeplugin_live\n * @module videotimeplugin_live/videotime\n * @copyright 2022 bdecent gmbh \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from \"core/ajax\";\nimport VideoTimeBase from \"mod_videotime/videotime\";\nimport Janus from 'block_deft/janus-gateway';\nimport Log from \"core/log\";\nimport Notification from \"core/notification\";\nimport PublishBase from \"block_deft/publish\";\nimport SubscribeBase from \"block_deft/subscribe\";\nimport Socket from \"videotimeplugin_live/socket\";\n\nvar rooms = {};\n\nclass Publish extends PublishBase {\n /**\n * Register the room\n *\n * @param {object} pluginHandle\n * @return {Promise}\n */\n register(pluginHandle) {\n // Try a registration\n return Ajax.call([{\n args: {\n handle: pluginHandle.getId(),\n id: Number(this.contextid),\n plugin: pluginHandle.plugin,\n room: this.roomid,\n ptype: this.ptype == 'publish',\n session: pluginHandle.session.getSessionId()\n },\n contextid: this.contextid,\n fail: Notification.exception,\n methodname: 'videotimeplugin_live_join_room'\n }])[0].then(response => {\n this.feed = response.id;\n }).catch(Notification.exception);\n }\n\n /**\n * Publish current video feed\n */\n publishFeed() {\n return Ajax.call([{\n args: {\n id: Number(this.feed),\n room: this.roomid,\n },\n contextid: this.contextid,\n fail: Notification.exception,\n methodname: 'videotimeplugin_live_publish_feed'\n }])[0];\n }\n\n\n /**\n * Stop video feed\n */\n unpublish() {\n return Ajax.call([{\n args: {\n id: Number(this.feed),\n publish: false,\n room: this.roomid\n },\n contextid: this.contextid,\n fail: Notification.exception,\n methodname: 'videotimeplugin_live_publish_feed'\n }])[0];\n }\n\n handleClose() {\n document.querySelectorAll(\n '[data-contextid=\"' + this.contextid + '\"][data-action=\"publish\"]'\n ).forEach(button => {\n button.classList.remove('hidden');\n });\n\n this.janus.destroy();\n\n [\n this.currentCamera || Promise.resolve(null),\n this.currentDisplay || Promise.resolve(null),\n ].forEach(videoInput => {\n videoInput.then(videoStream => {\n if (videoStream) {\n videoStream.getVideoTracks().forEach(track => {\n track.enabled = false;\n track.stop();\n });\n }\n\n return null;\n }).catch(Notification.exception);\n });\n }\n\n onLocalTrack(track, on) {\n const remoteStream = new MediaStream([track]);\n if (!on) {\n return;\n }\n remoteStream.mid = track.mid;\n Log.debug(on);\n Log.debug(remoteStream);\n Janus.attachMediaStream(\n document.getElementById('video-controls-' + this.tracks[track.id]),\n remoteStream\n );\n }\n\n handleClick(e) {\n const button = e.target.closest(\n '[data-contextid=\"' + this.contextid + '\"][data-action=\"publish\"], [data-contextid=\"'\n + this.contextid + '\"][data-action=\"unpublish\"]'\n );\n if (button) {\n const action = button.getAttribute('data-action'),\n type = button.getAttribute('data-type') || 'camera';\n e.stopPropagation();\n e.preventDefault();\n document.querySelectorAll(\n '[data-region=\"deft-venue\"] [data-action=\"publish\"], [data-region=\"deft-venue\"] [data-action=\"unpublish\"]'\n ).forEach(button => {\n if ((button.getAttribute('data-action') != action) || (button.getAttribute('data-type') != type)) {\n button.classList.remove('hidden');\n }\n });\n switch (action) {\n case 'publish':\n Log.debug(type);\n if (type == 'display') {\n this.shareDisplay();\n } else {\n this.shareCamera();\n }\n\n this.videoInput.then(videoStream => {\n const tracks = [];\n this.tracks = this.tracks || {};\n if (videoStream) {\n const transceiver = this.getTransceiver();\n videoStream.getVideoTracks().forEach(track => {\n track.addEventListener('ended', () => {\n if (this.selectedTrack != track.id) {\n this.unpublish();\n }\n });\n if (transceiver) {\n this.videoroom.replaceTracks({\n tracks: [{\n type: 'video',\n mid: transceiver.mid,\n capture: track\n }],\n error: Notification.exception\n });\n\n this.selectedTrack = track;\n return;\n }\n tracks.push({\n type: 'video',\n capture: track,\n recv: false\n });\n this.selectedTrack = track;\n });\n if (!tracks.length) {\n return videoStream;\n }\n videoStream.getAudioTracks().forEach(track => {\n tracks.push({\n type: 'audio',\n capture: track,\n recv: false\n });\n });\n if (!tracks.length) {\n return videoStream;\n }\n this.videoroom.createOffer({\n tracks: tracks,\n success: (jsep) => {\n const publish = {\n request: \"configure\",\n video: true,\n audio: true\n };\n this.videoroom.send({\n message: publish,\n jsep: jsep\n });\n },\n error: function(error) {\n Notification.alert(\"WebRTC error... \", error.message);\n }\n });\n }\n\n return videoStream;\n }).catch(Notification.exception);\n break;\n case 'unpublish':\n this.unpublish();\n }\n }\n\n return true;\n }\n\n /**\n * Set video source to user camera\n */\n shareCamera() {\n const videoInput = this.videoInput,\n currentCamera = this.currentCamera || Promise.resolve(null);\n\n this.videoInput = currentCamera.then(videoStream => {\n if (videoStream) {\n return videoStream;\n } else {\n const cameraInput = navigator.mediaDevices.getUserMedia({\n video: true,\n audio: false\n });\n\n this.currentCamera = cameraInput.catch(() => {\n return currentCamera;\n });\n\n return cameraInput.then(videoStream => {\n this.tracks = this.tracks || {};\n videoStream.getTracks().forEach(track => {\n this.tracks[track.id] = 'camera';\n });\n\n return videoStream;\n }).catch((e) => {\n Log.debug(e);\n\n return videoInput;\n });\n }\n });\n }\n\n /**\n * Set video source to display surface\n */\n shareDisplay() {\n const videoInput = this.videoInput,\n currentDisplay = this.currentDisplay || Promise.resolve(null),\n displayInput = navigator.mediaDevices.getDisplayMedia({\n video: true,\n audio: false\n });\n\n this.videoInput = displayInput.then(videoStream => {\n if (videoInput) {\n videoInput.then(videoStream => {\n if (videoStream) {\n videoStream.getTracks().forEach(track => {\n Log.debug(track); //track.stop();\n });\n }\n return videoStream;\n }).catch(Notification.exception);\n }\n this.tracks = this.tracks || {};\n videoStream.getTracks().forEach(track => {\n this.tracks[track.id] = 'display';\n });\n\n return videoStream;\n }).catch((e) => {\n Log.debug(e);\n\n return videoInput;\n });\n\n this.currentDisplay = displayInput.then(videoStream => {\n currentDisplay.then(videoStream => {\n if (videoStream) {\n videoStream.getTracks().forEach(track => {\n Log.debug('stop track');\n Log.debug(track);\n track.stop();\n });\n }\n });\n\n return videoStream;\n }).catch((e) => {\n Log.debug(e);\n\n return currentDisplay;\n });\n }\n}\n\nexport default class VideoTime extends VideoTimeBase {\n initialize(contextid, token, peerid) {\n Log.debug(\"Initializing Video Time \" + this.elementId);\n\n this.contextid = contextid;\n this.peerid = peerid;\n\n Ajax.call([{\n methodname: 'videotimeplugin_live_get_room',\n args: {contextid: contextid},\n done: (response) => {\n const socket = new Socket(contextid, token);\n\n this.iceservers = JSON.parse(response.iceservers);\n this.roomid = response.roomid;\n this.server = response.server;\n\n rooms[String(contextid)] = {\n contextid: contextid,\n peerid: peerid,\n roomid: response.roomid,\n server: response.server,\n iceServers: JSON.parse(response.iceservers)\n };\n this.roomid = response.roomid;\n\n socket.subscribe(() => {\n Ajax.call([{\n methodname: 'videotimeplugin_live_get_feed',\n args: {contextid: contextid},\n done: (response) => {\n const room = rooms[String(contextid)];\n if (room.publish && room.publish.restart) {\n if (response.feed == peerid) {\n this.unpublish();\n }\n room.publish = null;\n }\n this.subscribeTo(Number(response.feed));\n },\n fail: Notification.exception\n }]);\n });\n },\n fail: Notification.exception\n }]);\n\n this.addListeners();\n\n return true;\n }\n\n /**\n * Register player events to respond to user interaction and play progress.\n */\n addListeners() {\n document.querySelector('body').removeEventListener('click', handleClick);\n document.querySelector('body').addEventListener('click', handleClick);\n return;\n }\n\n /**\n * Subscribe to feed\n *\n * @param {int} source Feed to subscribe\n */\n subscribeTo(source) {\n document.querySelectorAll('[data-contextid=\"' + this.contextid + '\"][data-action=\"publish\"]').forEach(button => {\n if (source == Number(this.peerid)) {\n button.classList.remove('hidden');\n } else {\n button.classList.remove('hidden');\n }\n });\n document.querySelectorAll('[data-contextid=\"' + this.contextid + '\"][data-action=\"unpublish\"]').forEach(button => {\n if (source == Number(this.peerid)) {\n button.classList.remove('hidden');\n } else {\n button.classList.remove('hidden');\n }\n });\n Log.debug(source);\n\n if (this.remoteFeed && !this.remoteFeed.creatingSubscription && !this.remoteFeed.restart) {\n const update = {\n request: 'update',\n subscribe: [{\n feed: Number(source)\n }],\n unsubscribe: [{\n feed: Number(this.remoteFeed.current)\n }]\n };\n\n if (!source && this.remoteFeed.current) {\n delete update.subscribe;\n } else if (source && !this.remoteFeed.current) {\n delete update.unsubscribe;\n }\n\n if (this.remoteFeed.current != source) {\n const room = rooms[String(this.contextid)];\n this.remoteFeed.videoroom.send({message: update});\n if (room.publish && this.remoteFeed.current == room.publish.feed) {\n room.publish.handleClose();\n room.publish = null;\n }\n this.remoteFeed.current = source;\n if (!source && this.remoteFeed.current) {\n this.remoteFeed.handleClose();\n this.remoteFeed = null;\n }\n Log.debug('[data-contextid=\"' + this.contextid + '\"] img.poster-img');\n if (Number(source)) {\n document.querySelectorAll('[data-contextid=\"' + this.contextid + '\"] img.poster-img').forEach(img => {\n img.classList.add('hidden');\n });\n document.querySelectorAll('[data-contextid=\"' + this.contextid + '\"] video').forEach(video => {\n video.classList.remove('hidden');\n });\n } else {\n document.querySelectorAll('[data-contextid=\"' + this.contextid + '\"] img.poster-img').forEach(img => {\n img.classList.remove('hidden');\n });\n document.querySelectorAll('[data-contextid=\"' + this.contextid + '\"] video').forEach(video => {\n video.classList.add('hidden');\n });\n }\n }\n } else if (this.remoteFeed && this.remoteFeed.restart) {\n if (this.remoteFeed.current != source) {\n this.remoteFeed = null;\n this.subscribeTo(source);\n }\n } else if (this.remoteFeed) {\n setTimeout(() => {\n this.subscribeTo(source);\n }, 500);\n } else if (source) {\n this.remoteFeed = new Subscribe(this.contextid, this.iceservers, this.roomid, this.server, this.peerid, source);\n this.remoteFeed.remoteVideo = document.getElementById(this.elementId);\n this.remoteFeed.remoteAudio = document.getElementById(this.elementId).parentNode.querySelector('audio');\n this.remoteFeed.startConnection(source);\n document.querySelectorAll('[data-contextid=\"' + this.contextid + '\"] img.poster-img').forEach(img => {\n img.classList.add('hidden');\n });\n document.querySelectorAll('[data-contextid=\"' + this.contextid + '\"] video').forEach(img => {\n img.classList.remove('hidden');\n });\n }\n }\n}\n\nconst handleClick = function(e) {\n const button = e.target.closest('[data-roomid] [data-action=\"publish\"], [data-roomid] [data-action=\"unpublish\"]');\n if (button) {\n const action = button.getAttribute('data-action'),\n contextid = e.target.closest('[data-contextid]').getAttribute('data-contextid'),\n room = rooms[String(contextid)],\n iceServers = room.iceServers,\n peerid = room.peerid,\n roomid = room.roomid,\n server = room.server,\n type = button.getAttribute('data-type');\n e.stopPropagation();\n e.preventDefault();\n if ((action == 'publish') && (!room.publish || room.publish.restart)) {\n room.publish = new Publish(contextid, iceServers, roomid, server, peerid);\n if (type == 'display') {\n room.publish.shareDisplay();\n } else {\n room.publish.shareCamera();\n }\n room.publish.startConnection();\n } else {\n room.publish.handleClick(e);\n }\n }\n};\n\nclass Subscribe extends SubscribeBase {\n /**\n * Register the room\n *\n * @param {object} pluginHandle\n * @return {Promise}\n */\n register(pluginHandle) {\n // Try a registration\n return Ajax.call([{\n args: {\n handle: pluginHandle.getId(),\n id: Number(this.contextid),\n plugin: pluginHandle.plugin,\n room: this.roomid,\n ptype: false,\n feed: this.feed,\n session: pluginHandle.session.getSessionId()\n },\n contextid: this.contextid,\n fail: Notification.exception,\n methodname: 'videotimeplugin_live_join_room'\n }])[0];\n }\n}\n"],"names":["rooms","Publish","PublishBase","register","pluginHandle","Ajax","call","args","handle","getId","id","Number","this","contextid","plugin","room","roomid","ptype","session","getSessionId","fail","Notification","exception","methodname","then","response","feed","catch","publishFeed","unpublish","publish","handleClose","document","querySelectorAll","forEach","button","classList","remove","janus","destroy","currentCamera","Promise","resolve","currentDisplay","videoInput","videoStream","getVideoTracks","track","enabled","stop","onLocalTrack","on","remoteStream","MediaStream","mid","debug","attachMediaStream","getElementById","tracks","handleClick","e","target","closest","action","getAttribute","type","stopPropagation","preventDefault","shareDisplay","shareCamera","transceiver","getTransceiver","addEventListener","selectedTrack","videoroom","replaceTracks","capture","error","push","recv","length","getAudioTracks","createOffer","success","jsep","send","message","request","video","audio","alert","cameraInput","navigator","mediaDevices","getUserMedia","getTracks","displayInput","getDisplayMedia","VideoTime","VideoTimeBase","initialize","token","peerid","elementId","done","socket","Socket","iceservers","JSON","parse","server","String","iceServers","subscribe","restart","subscribeTo","addListeners","querySelector","removeEventListener","source","remoteFeed","creatingSubscription","current","setTimeout","Subscribe","remoteVideo","remoteAudio","parentNode","startConnection","img","add","update","unsubscribe","SubscribeBase"],"mappings":"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"} \ No newline at end of file diff --git a/plugin/live/amd/src/videotime.js b/plugin/live/amd/src/videotime.js index 593fb3c4..dd8827a1 100644 --- a/plugin/live/amd/src/videotime.js +++ b/plugin/live/amd/src/videotime.js @@ -30,7 +30,7 @@ class Publish extends PublishBase { return Ajax.call([{ args: { handle: pluginHandle.getId(), - id: Number(this.peerid), + id: Number(this.contextid), plugin: pluginHandle.plugin, room: this.roomid, ptype: this.ptype == 'publish', @@ -39,137 +39,76 @@ class Publish extends PublishBase { contextid: this.contextid, fail: Notification.exception, methodname: 'videotimeplugin_live_join_room' - }])[0]; - } - - getTransceiver(id) { - let result = null; - - if ( - this.videoroom.webrtcStuff.pc - && this.videoroom.webrtcStuff.pc.iceConnectionState == 'connected' - ) { - this.videoroom.webrtcStuff.pc.getTransceivers().forEach(transceiver => { - const sender = transceiver.sender; - if ( - sender.track - && sender.track.id - && (!id || sender.track.id == id) - && this.tracks[sender.track.id] - ) { - result = transceiver; - } - }); - } - - return result; + }])[0].then(response => { + this.feed = response.id; + }).catch(Notification.exception); } + /** + * Publish current video feed + */ publishFeed() { - if ( - this.videoroom.webrtcStuff.pc - && this.videoroom.webrtcStuff.pc.iceConnectionState == 'connected' - ) { - setTimeout(() => { - this.videoroom.webrtcStuff.pc.getTransceivers().forEach(transceiver => { - const sender = transceiver.sender; - if ( - sender.track - && this.selectedTrack - && (sender.track.id == this.selectedTrack.id) - ) { - const message = JSON.stringify({ - feed: Number(this.peerid), - mid: transceiver.mid - }); - this.videoroom.data({ - text: message, - error: Log.debug - }); - } - }); - return Ajax.call([{ - args: { - id: Number(this.peerid), - room: this.roomid, - }, - contextid: this.contextid, - fail: Notification.exception, - methodname: 'videotimeplugin_live_publish_feed' - }])[0]; - }); - } + return Ajax.call([{ + args: { + id: Number(this.feed), + room: this.roomid, + }, + contextid: this.contextid, + fail: Notification.exception, + methodname: 'videotimeplugin_live_publish_feed' + }])[0]; } + + /** + * Stop video feed + */ unpublish() { - Ajax.call([{ + return Ajax.call([{ args: { - id: Number(this.peerid), + id: Number(this.feed), publish: false, room: this.roomid }, contextid: this.contextid, fail: Notification.exception, methodname: 'videotimeplugin_live_publish_feed' - }]); + }])[0]; + } - if (this.videoInput) { - this.videoroom.send({ - message: { - request: 'unpublish' - } - }); - } + handleClose() { + document.querySelectorAll( + '[data-contextid="' + this.contextid + '"][data-action="publish"]' + ).forEach(button => { + button.classList.remove('hidden'); + }); + + this.janus.destroy(); [ - this.currentCamera, - this.currentDisplay, + this.currentCamera || Promise.resolve(null), + this.currentDisplay || Promise.resolve(null), ].forEach(videoInput => { - if (videoInput) { - videoInput.then(videoStream => { - if (videoStream) { - videoStream.getTracks().forEach(track => { - track.stop(); - }); - } + videoInput.then(videoStream => { + if (videoStream) { + videoStream.getVideoTracks().forEach(track => { + track.enabled = false; + track.stop(); + }); + } - return null; - }).catch(Notification.exception); - } + return null; + }).catch(Notification.exception); }); - this.currentCamera = null; - this.currentDisplay = null; - this.videoInput = null; - - if ( - this.videoroom.webrtcStuff.pc - && this.videoroom.webrtcStuff.pc.iceConnectionState == 'connected' - ) { - - this.videoroom.webrtcStuff.pc.getTransceivers().forEach(transceiver => { - transceiver.stop(); - }); - } - this.tracks = {}; } onLocalTrack(track, on) { const remoteStream = new MediaStream([track]); if (!on) { - this.videoInput.then(videoStream => { - if (videoStream) { - videoStream.getTracks().forEach(current => { - if (current.id == track.id) { - this.unpublish(); - } - }); - } - return videoStream; - }).catch(Notification.exception); - return; } remoteStream.mid = track.mid; + Log.debug(on); Log.debug(remoteStream); Janus.attachMediaStream( document.getElementById('video-controls-' + this.tracks[track.id]), @@ -207,31 +146,36 @@ class Publish extends PublishBase { const tracks = []; this.tracks = this.tracks || {}; if (videoStream) { - Log.debug(videoStream.getVideoTracks()); + const transceiver = this.getTransceiver(); videoStream.getVideoTracks().forEach(track => { - const transceiver = this.getTransceiver(track.id); - if (!transceiver) { - tracks.push({ - type: 'video', - capture: track, - recv: false + track.addEventListener('ended', () => { + if (this.selectedTrack != track.id) { + this.unpublish(); + } + }); + if (transceiver) { + this.videoroom.replaceTracks({ + tracks: [{ + type: 'video', + mid: transceiver.mid, + capture: track + }], + error: Notification.exception }); + this.selectedTrack = track; - this.tracks[track.id] = type; - Log.debug('New track'); - } else { - const message = JSON.stringify({ - feed: Number(this.peerid), - mid: transceiver.mid - }); - this.videoroom.data({ - text: message, - error: Log.debug - }); - this.selectedTrack = track.id; - this.publishFeed(); + return; } + tracks.push({ + type: 'video', + capture: track, + recv: false + }); + this.selectedTrack = track; }); + if (!tracks.length) { + return videoStream; + } videoStream.getAudioTracks().forEach(track => { tracks.push({ type: 'audio', @@ -266,7 +210,6 @@ class Publish extends PublishBase { break; case 'unpublish': this.unpublish(); - break; } } @@ -321,6 +264,16 @@ class Publish extends PublishBase { }); this.videoInput = displayInput.then(videoStream => { + if (videoInput) { + videoInput.then(videoStream => { + if (videoStream) { + videoStream.getTracks().forEach(track => { + Log.debug(track); //track.stop(); + }); + } + return videoStream; + }).catch(Notification.exception); + } this.tracks = this.tracks || {}; videoStream.getTracks().forEach(track => { this.tracks[track.id] = 'display'; @@ -334,17 +287,15 @@ class Publish extends PublishBase { }); this.currentDisplay = displayInput.then(videoStream => { - if (videoStream) { - currentDisplay.then(videoStream => { - if (videoStream) { - videoStream.getTracks().forEach(track => { - track.stop(); - }); - } - - return videoStream; - }).catch(Notification.exception); - } + currentDisplay.then(videoStream => { + if (videoStream) { + videoStream.getTracks().forEach(track => { + Log.debug('stop track'); + Log.debug(track); + track.stop(); + }); + } + }); return videoStream; }).catch((e) => { @@ -422,6 +373,21 @@ export default class VideoTime extends VideoTimeBase { * @param {int} source Feed to subscribe */ subscribeTo(source) { + document.querySelectorAll('[data-contextid="' + this.contextid + '"][data-action="publish"]').forEach(button => { + if (source == Number(this.peerid)) { + button.classList.remove('hidden'); + } else { + button.classList.remove('hidden'); + } + }); + document.querySelectorAll('[data-contextid="' + this.contextid + '"][data-action="unpublish"]').forEach(button => { + if (source == Number(this.peerid)) { + button.classList.remove('hidden'); + } else { + button.classList.remove('hidden'); + } + }); + Log.debug(source); if (this.remoteFeed && !this.remoteFeed.creatingSubscription && !this.remoteFeed.restart) { const update = { @@ -441,40 +407,36 @@ export default class VideoTime extends VideoTimeBase { } if (this.remoteFeed.current != source) { + const room = rooms[String(this.contextid)]; + this.remoteFeed.videoroom.send({message: update}); + if (room.publish && this.remoteFeed.current == room.publish.feed) { + room.publish.handleClose(); + room.publish = null; + } + this.remoteFeed.current = source; + if (!source && this.remoteFeed.current) { + this.remoteFeed.handleClose(); + this.remoteFeed = null; + } Log.debug('[data-contextid="' + this.contextid + '"] img.poster-img'); - if (source) { + if (Number(source)) { document.querySelectorAll('[data-contextid="' + this.contextid + '"] img.poster-img').forEach(img => { img.classList.add('hidden'); }); - document.querySelectorAll('[data-contextid="' + this.contextid + '"] video').forEach(img => { - img.classList.remove('hidden'); + document.querySelectorAll('[data-contextid="' + this.contextid + '"] video').forEach(video => { + video.classList.remove('hidden'); }); } else { document.querySelectorAll('[data-contextid="' + this.contextid + '"] img.poster-img').forEach(img => { img.classList.remove('hidden'); }); - document.querySelectorAll('[data-contextid="' + this.contextid + '"] video').forEach(img => { - img.classList.add('hidden'); + document.querySelectorAll('[data-contextid="' + this.contextid + '"] video').forEach(video => { + video.classList.add('hidden'); }); } - this.remoteFeed.videoroom.send({message: update}); - if (this.remoteFeed.current == this.peerid) { - const room = rooms[String(this.contextid)]; - room.publish.unpublish(); - } - this.remoteFeed.current = source; - if (!source) { - if (this.remoteFeed && this.remoteFeed.janus) { - this.remoteFeed.janus.destroy(); - } - this.remoteFeed = null; - } } } else if (this.remoteFeed && this.remoteFeed.restart) { if (this.remoteFeed.current != source) { - if (this.remoteFeed && this.remoteFeed.janus) { - this.remoteFeed.janus.destroy(); - } this.remoteFeed = null; this.subscribeTo(source); } @@ -510,18 +472,7 @@ const handleClick = function(e) { type = button.getAttribute('data-type'); e.stopPropagation(); e.preventDefault(); - if (action == 'unpublish') { - Ajax.call([{ - args: { - id: Number(peerid), - room: roomid, - publish: false - }, - contextid: contextid, - fail: Notification.exception, - methodname: 'videotimeplugin_live_publish_feed' - }]); - } else if (!room.publish || room.publish.restart) { + if ((action == 'publish') && (!room.publish || room.publish.restart)) { room.publish = new Publish(contextid, iceServers, roomid, server, peerid); if (type == 'display') { room.publish.shareDisplay(); @@ -547,7 +498,7 @@ class Subscribe extends SubscribeBase { return Ajax.call([{ args: { handle: pluginHandle.getId(), - id: Number(this.peerid), + id: Number(this.contextid), plugin: pluginHandle.plugin, room: this.roomid, ptype: false, diff --git a/plugin/live/classes/external/join_room.php b/plugin/live/classes/external/join_room.php index fcc029d0..80986fdd 100644 --- a/plugin/live/classes/external/join_room.php +++ b/plugin/live/classes/external/join_room.php @@ -42,7 +42,7 @@ class join_room extends \block_deft\external\join_room { * Join room * * @param int $handle Janus plugin handle - * @param string $id Venue peer id + * @param string $id Context id * @param int $plugin Janus plugin name * @param bool $ptype Whether video publisher * @param int $room Room id being joined @@ -63,50 +63,21 @@ public static function execute($handle, $id, $plugin, $ptype, $room, $session, $ 'feed' => $feed, ]); - if (!empty($id) && !$DB->get_record('sessions', [ - 'id' => $id, - 'sid' => session_id(), - ])) { - return [ - 'status' => false, - ]; - } - $record = $DB->get_record( - 'block_deft_room', - [ - 'roomid' => $room, - 'component' => 'videotimeplugin_live', - ] - ); - - $cm = get_coursemodule_from_instance('videotime', $record->itemid); - $context = context_module::instance($cm->id); + $context = context::instance_by_id($id); + $cm = get_coursemodule_from_id('videotime', $context->instanceid); self::validate_context($context); require_login(); require_capability('mod/videotime:view', $context); $janus = new janus($session); - $janusroom = new janus_room($record->itemid); + + $janusroom = new janus_room($cm->instance); $token = $janusroom->get_token(); if ($plugin == 'janus.plugin.videoroom') { - if (empty($id)) { - $id = $janus->transaction_identifier(); - } - if ($ptype) { - $message = [ - 'id' => $id, - 'request' => 'kick', - 'room' => $room, - 'secret' => $janusroom->get_secret(), - ]; - - $janus->send($handle, $message); - } $message = [ - 'id' => $ptype ? $id : $id . 'subscriber', 'ptype' => $ptype ? 'publisher' : 'subscriber', 'request' => 'join', 'room' => $room, @@ -119,67 +90,28 @@ public static function execute($handle, $id, $plugin, $ptype, $room, $session, $ ] ]; } else { - require_capability('videotimeplugin/live:sharevideo', $context); - } - } else { - $textroom = $janus->attach('janus.plugin.videoroom'); - $janus->send($textroom, [ - 'request' => 'kick', - 'room' => $room, - 'secret' => $janusroom->get_secret(), - 'username' => $id, - ]); - - $janus->send($handle, [ - 'id' => $id, - 'request' => 'kick', - 'room' => $room, - 'secret' => $janusroom->get_secret(), - ]); - - $message = [ - 'id' => $id, - 'request' => 'join', - 'room' => $room, - 'token' => $token, - ]; - $params = [ - 'context' => $context, - 'objectid' => $cm->instance, - ]; - - $event = \videotimetab_venue\event\audiobridge_launched::create($params); - $event->trigger(); - - $sessionid = $DB->get_field_select('sessions', 'id', 'sid = :sid', ['sid' => session_id()]); - - $timenow = time(); - - if ($record = $DB->get_record('videotimetab_venue_peer', [ - 'sessionid' => $sessionid, - 'videotime' => $cm->instance, - 'userid' => $USER->id, - 'status' => false, - ])) { - $record->timemodified = $timenow; - $DB->update_record('videotimetab_venue_peer', $record); - } else { - $DB->insert_record('videotimetab_venue_peer', [ - 'sessionid' => $sessionid, + require_capability('block/deft:sharevideo', $context); + $DB->set_field('videotimeplugin_live_peer', 'status', 1, [ + 'videotime' => $cm->instance, + ]); + $feedid = $DB->insert_record('videotimeplugin_live_peer', [ + 'sessionid' => $DB->get_field('sessions', 'id', [ + 'sid' => session_id(), + ]), 'videotime' => $cm->instance, + 'timecreated' => time(), + 'timemodified' => time(), 'userid' => $USER->id, - 'mute' => true, - 'status' => false, - 'timecreated' => $timenow, - 'timemodified' => $timenow, ]); + $message['id'] = $feedid; } } - $response = $janus->send($handle, $message); + $janus->send($handle, $message); return [ 'status' => true, + 'id' => (int) $feedid ?? 0, ]; } } diff --git a/plugin/live/classes/external/publish_feed.php b/plugin/live/classes/external/publish_feed.php index 583afde1..b4a5525b 100644 --- a/plugin/live/classes/external/publish_feed.php +++ b/plugin/live/classes/external/publish_feed.php @@ -39,13 +39,13 @@ class publish_feed extends \block_deft\external\publish_feed { /** * Publish feed * - * @param string $id Venue peer id + * @param string $id Peer id * @param bool $publish Whether to publish * @param int $room Room id being joined * @return array */ public static function execute($id, $publish, $room): array { - global $DB, $SESSION; + global $DB, $SESSION, $USER; $params = self::validate_parameters(self::execute_parameters(), [ 'id' => $id, @@ -53,14 +53,6 @@ public static function execute($id, $publish, $room): array { 'room' => $room, ]); - if (!empty($id) && !$DB->get_record('sessions', [ - 'id' => $id, - 'sid' => session_id(), - ])) { - return [ - 'status' => false, - ]; - } $record = $DB->get_record( 'block_deft_room', [ @@ -91,9 +83,9 @@ public static function execute($id, $publish, $room): array { if ( !empty($data->feed) && ($data->feed != $id) - && $DB->get_record('sessions', [ - 'id' => $data->feed, - 'sid' => session_id(), + && $DB->get_record('videotimeplugin_live_peer', [ + 'videotime' => $cm->instance, + 'userid' => $USER->id, ]) ) { require_capability('videotimeplugin/live:moderate', $context); diff --git a/plugin/live/classes/janus_room.php b/plugin/live/classes/janus_room.php index 27036986..f3d469e7 100644 --- a/plugin/live/classes/janus_room.php +++ b/plugin/live/classes/janus_room.php @@ -48,7 +48,7 @@ class janus_room extends janus_room_base { /** * @var Plugin component using room */ - protected $component = 'videotimeplugin_live'; + protected string $component = 'videotimeplugin_live'; /** * Constructor diff --git a/plugin/live/db/install.xml b/plugin/live/db/install.xml index 3cfd95aa..0ee1a78b 100644 --- a/plugin/live/db/install.xml +++ b/plugin/live/db/install.xml @@ -1,5 +1,5 @@ - @@ -19,5 +19,23 @@ + + + + + + + + + + + + + + + + + +
diff --git a/plugin/live/templates/controls.mustache b/plugin/live/templates/controls.mustache index fe71cdce..760fb154 100644 --- a/plugin/live/templates/controls.mustache +++ b/plugin/live/templates/controls.mustache @@ -30,12 +30,6 @@ Example context (json): { "responsive": true, - "cmid": 3, - "haspro": 0, - "interval": 2.5, - "instance": "{}", - "uniqueid": "60dccff8871f6", - "video_description": "UX design tips", "video": 1, "vimeo_url": "https://vimeo.com/323424" } @@ -43,7 +37,7 @@ }} {{# instance }}
-
+
{{# posterurl }} {{/ posterurl }} @@ -54,7 +48,7 @@ >
-
+
{{# posterurl }} {{/ posterurl }}