Skip to content

Instantly share code, notes, and snippets.

@philmillman
Created June 15, 2021 14:03
Show Gist options
  • Save philmillman/736486ee30fe7c35e0f892e727413ef9 to your computer and use it in GitHub Desktop.
Save philmillman/736486ee30fe7c35e0f892e727413ef9 to your computer and use it in GitHub Desktop.
<html>
<head>
<title>call methods and events demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script src="https://unpkg.com/@daily-co/daily-js"></script>
<script src="../shared-assets/create-demo-room.js"></script>
<style>
button {
display: block;
}
#page-blocks {
height: 100%;
display: flex;
flex-direction: column;
}
#page-blocks > div {
margin-top: 1em;
}
#create-a-room {
flex: none;
}
#create-a-room > div {
margin-top: 0.25em;
}
#meeting-info-row {
flex: none;
display: flex;
}
#meeting-info-row > div {
flex: auto;
}
#buttons-row {
flex: none;
display: flex;
}
#buttons-row > div {
flex: auto;
}
#call-frame-container {
flex-grow: 1;
/* set position and height so this is the "css container" for the iframe */
position: relative;
height: 100%;
min-height: 300px;
}
.info > div {
margin: 0.25em;
}
.info > div:nth-of-type(2) {
font-size: 80%;
}
.info > div > div {
margin: 0.25em;
}
.flex-bins {
display: flex;
flex-basis: auto;
}
.flex-bin {
flex-basis: auto;
}
.disabled {
pointer-events: none;
opacity: 0.5;
}
</style>
</head>
<body onload="setup()">
<script>
function showEvent(e) {
console.log('callFrame event', e);
}
function setup() {
//
// just a little ui setup
//
buttonDisable(
'join-meeting',
'join-meeting-participant',
'leave-meeting',
'toggle-local-cam',
'toggle-local-mic',
'start-recording',
'stop-recording',
'start-screenshare',
'stop-screenshare',
'subscribe-all',
'subscribe-none'
);
}
async function createRoom() {
// hardcode links so we can easily have non-owner and owner participants accessing the samed room
room = { url: 'INSERT_ROOM' };
token = 'INSERT_TOKEN';
ownerLink = `${room.url}?t=${token}`;
nonOwnerLink = room.url;
updateRoomInfoDisplay();
setInterval(updateNetworkInfoDisplay, 5000);
}
async function createFrame() {
//
// ask the daily-js library to create an iframe inside the
// 'call-frame-container' div
//
let customLayout = !!document.querySelector(
'input[name="customLayout"]:checked'
).value,
cssFile = customLayout ? 'basics.css' : null;
callFrame = window.DailyIframe.createFrame(
document.getElementById('call-frame-container'),
{
customLayout,
cssFile,
subscribeToTracksAutomatically: false,
}
);
callFrame.on('loading', (e) => {
showEvent(e);
buttonDisable('join-meeting');
buttonDisable('join-meeting-participant');
});
callFrame
.on('loaded', showEvent)
.on('started-camera', showEvent)
.on('camera-error', showEvent)
.on('joining-meeting', showEvent)
.on('recording-stats', showEvent)
.on('recording-error', showEvent)
.on('app-message', showEvent)
.on('input-event', showEvent)
.on('error', showEvent);
callFrame.on('joined-meeting', (e) => {
showEvent(e);
buttonEnable(
'leave-meeting',
'toggle-local-cam',
'toggle-local-mic',
'start-recording',
'start-screenshare',
'subscribe-all',
'subscribe-none'
);
subscribeToOwnerTracks();
});
callFrame.on('left-meeting', (e) => {
showEvent(e);
buttonDisable(
'leave-meeting',
'toggle-local-cam',
'toggle-local-mic',
'start-recording',
'stop-recording',
'start-screenshare',
'stop-screenshare',
'subscribe-all',
'subscribe-none'
);
buttonEnable('join-meeting');
buttonEnable('join-meeting-participant');
});
callFrame.on('recording-started', (e) => {
showEvent(e);
buttonDisable('start-recording');
buttonEnable('stop-recording');
});
callFrame.on('recording-stopped', (e) => {
showEvent(e);
buttonEnable('start-recording');
buttonDisable('stop-recording');
});
callFrame
.on('participant-joined', participantJoined)
.on('participant-updated', updateParticipantInfoDisplay)
.on('participant-left', updateParticipantInfoDisplay);
}
async function createFrameAndRoom() {
document.getElementById('create-a-room').style.display = 'none';
await createRoom();
await createFrame();
buttonEnable('join-meeting');
buttonEnable('join-meeting-participant');
}
function updateRoomInfoDisplay() {
let roomInfo = document.getElementById('meeting-room-info');
roomInfo.innerHTML = `
<div><b>room info</b></div>
<div>
send to invite or click to join
<div><a href="${room.url}" target="_blank">
${room.url.replace('.co/', '.co/&#8203;')}
</a></div>
<div id='expires-countdown'></div>
</div>
`;
if (!window.expiresUpdate) {
window.expiresUpdate = setInterval(() => {
let exp = room && room.config && room.config.exp;
if (exp) {
document.getElementById('expires-countdown').innerHTML = `
room expires in
${Math.floor((new Date(exp * 1000) - Date.now()) / 1000)}
seconds
`;
}
}, 1000);
}
}
function participantJoined(e) {
// subscribe to latest participant
callFrame.updateParticipant(
e.participant.session_id,
{
setSubscribedTracks: true
}
);
// unsubscribe from latest after 30 seconds if they aren't an owner
if (!e.participant.owner) {
setTimeout( () => {
callFrame.updateParticipant(
e.participant.session_id,
{
setSubscribedTracks: false
}
);
}, 30000)
}
updateParticipantInfoDisplay(e);
}
function subscribeToOwnerTracks() {
const participants = callFrame.participants();
let idsToBeSubscribed = [];
// add non local owners to to-be-subscribed list
for (let id in participants) {
let p = participants[id]
if (p.owner === true && p.local === false) {
idsToBeSubscribed.push(participants[id].session_id);
}
}
// subscribe to list
idsToBeSubscribed.forEach((id) => {
callFrame.updateParticipant(
id,
{
setSubscribedTracks: true
}
);
})
}
function updateParticipantInfoDisplay(e) {
showEvent(e);
let infoEl = document.getElementById('meeting-participants-info'),
participants = callFrame.participants(),
infoHTML = '';
// look and make an info block for each participant
for (var id in participants) {
let p = participants[id];
infoHTML += `
<div>
<div>${p.user_name || 'guest'}</div>
<div>cam ${p.video ? 'on' : 'off'}</div>
<div>mic ${p.audio ? 'on' : 'off'}</div>
</div>
`;
}
infoEl.innerHTML =
'<div><b>meeting participants</b></div>' +
'<div>' +
infoHTML +
'</div>';
// update local screenshare button state
if (participants.local) {
if (participants.local.screen) {
buttonDisable('start-screenshare');
buttonEnable('stop-screenshare');
} else {
buttonDisable('stop-screenshare');
buttonEnable('start-screenshare');
}
}
}
async function updateNetworkInfoDisplay() {
let infoEl = document.getElementById('network-info'),
statsInfo = await callFrame.getNetworkStats();
infoEl.innerHTML = `
<div><b>network stats</b></div>
<div>
<div>
video send:
${Math.floor(statsInfo.stats.latest.videoSendBitsPerSecond / 1000)} kb/s
</div>
<div>
video recv:
${Math.floor(statsInfo.stats.latest.videoRecvBitsPerSecond / 1000)} kb/s
<div>
worst send packet loss:
${Math.floor(statsInfo.stats.worstVideoSendPacketLoss * 100)}%</div>
<div>worst recv packet loss:
${Math.floor(statsInfo.stats.worstVideoRecvPacketLoss * 100)}%</div>
</div>
`;
}
function toggleCam() {
callFrame.setLocalVideo(!callFrame.participants().local.video);
}
function toggleMic() {
callFrame.setLocalAudio(!callFrame.participants().local.audio);
}
//
// UI utility functions
//
function buttonEnable(...args) {
args.forEach((id) => {
let el = document.getElementById(id);
if (el) {
el.classList.remove('disabled');
}
});
}
function buttonDisable(...args) {
args.forEach((id) => {
let el = document.getElementById(id);
if (el) {
el.classList.add('disabled');
}
});
}
</script>
<div id="page-blocks">
<div id="create-a-room">
<button onclick="createFrameAndRoom()">create a room</button>
<div>
<label>
<input type="radio" name="customLayout" value="" checked />
standard Daily.co UI
</label>
</div>
<div>
<label>
<input type="radio" name="customLayout" value="true" />
demo custom UI
</label>
</div>
</div>
<div id="meeting-info-row">
<div id="meeting-room-info" class="info">
room info
</div>
<div id="meeting-participants-info" class="info">
meeting participants
</div>
<div id="network-info" class="info">
network stats
</div>
</div>
<div id="buttons-row">
<div>
<button
id="join-meeting"
onclick="callFrame.join({ url: ownerLink })"
>
join meeting (as owner)
</button>
<button
id="join-meeting-participant"
onclick="callFrame.join({ url: nonOwnerLink })"
>
join meeting (as participant)
</button>
<button id="leave-meeting" onclick="callFrame.leave()">
leave meeting
</button>
</div>
<div>
<button id="toggle-local-cam" onclick="toggleCam()">
toggle local cam
</button>
<button id="toggle-local-mic" onclick="toggleMic()">
toggle local mic
</button>
</div>
<div>
<button
id="start-recording"
onclick="buttonDisable('start-recording');
callFrame.startRecording()"
>
start recording
</button>
<button id="stop-recording" onclick="callFrame.stopRecording()">
stop recording
</button>
</div>
<div>
<button id="start-screenshare" onclick="callFrame.startScreenShare()">
start screenshare
</button>
<button id="stop-screenshare" onclick="callFrame.stopScreenShare()">
stop screenshare
</button>
</div>
<div>
<button
id="subscribe-all"
onclick="callFrame.setSubscribeToTracksAutomatically(true)"
title="subscribe to all media tracks"
>
subscribe
</button>
<button
id="subscribe-none"
onclick="callFrame.setSubscribeToTracksAutomatically(false)"
title="unsubscribe from all media tracks"
>
unsubscribe
</button>
</div>
</div>
<div id="call-frame-container"></div>
</div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment