// We import the settings.js file to know which address we should contact // to talk to Janus, and optionally which STUN/TURN servers should be // used as well. Specifically, that file defines the "server" and // "iceServers" properties we'll pass when creating the Janus session. /* global iceServers:readonly, Janus:readonly, server:readonly */ var janus = null; var mixertest = null; var opaqueId = "audiobridgetest-" + Janus.randomString(12); var remoteStream = null; var myroom = 1234; // Demo room if (getQueryStringValue("room") !== "") myroom = parseInt(getQueryStringValue("room")); var acodec = getQueryStringValue("acodec") !== "" ? getQueryStringValue("acodec") : null; var stereo = false; if (getQueryStringValue("stereo") !== "") stereo = getQueryStringValue("stereo") === "true"; var mygroup = null; // Forwarding group, if required by the room if (getQueryStringValue("group") !== "") mygroup = getQueryStringValue("group"); var myusername = null; var myid = null; var webrtcUp = false; var audioenabled = false; var audiosuspended = getQueryStringValue("suspended") !== "" ? getQueryStringValue("suspended") === "true" : false; $(document).ready(function () { // Initialize the library (all console debuggers enabled) Janus.init({ debug: "all", callback: function () { // Use a button to start the demo $("#start").one("click", function () { $(this).attr("disabled", true).unbind("click"); // Make sure the browser supports WebRTC if (!Janus.isWebrtcSupported()) { bootbox.alert("No WebRTC support... "); return; } // Create session janus = new Janus({ server: server, iceServers: iceServers, // Should the Janus API require authentication, you can specify either the API secret or user token here too // token: "mytoken", // or // apisecret: "serversecret", success: function () { // Attach to AudioBridge plugin janus.attach({ plugin: "janus.plugin.audiobridge", opaqueId: opaqueId, success: function (pluginHandle) { $("#details").remove(); mixertest = pluginHandle; Janus.log( "Plugin attached! (" + mixertest.getPlugin() + ", id=" + mixertest.getId() + ")" ); // Prepare the username registration $("#audiojoin").removeClass("hide"); $("#registernow").removeClass("hide"); $("#register").click(registerUsername); $("#username").focus(); $("#start") .removeAttr("disabled") .html("Stop") .click(function () { $(this).attr("disabled", true); janus.destroy(); }); }, error: function (error) { Janus.error(" -- Error attaching plugin...", error); bootbox.alert("Error attaching plugin... " + error); }, consentDialog: function (on) { Janus.debug( "Consent dialog should be " + (on ? "on" : "off") + " now" ); if (on) { // Darken screen and show hint $.blockUI({ message: '

Apparently room " +
myroom +
" (the one this demo uses as a test room) " +
"does not exist...
Do you have an updated janus.plugin.audiobridge.jcfg " +
"configuration file? If not, make sure you copy the details of room " +
myroom +
" " +
"from that sample in your current configuration file, then restart Janus and try again."
);
} else {
bootbox.alert(msg["error"]);
}
return;
}
// Any new feed to attach to?
if (msg["leaving"]) {
// One of the participants has gone away?
let leaving = msg["leaving"];
Janus.log(
"Participant left: " +
leaving +
" (we have " +
$("#rp" + leaving).length +
" elements with ID #rp" +
leaving +
")"
);
$("#rp" + leaving).remove();
}
}
}
if (jsep) {
Janus.debug("Handling SDP as well...", jsep);
mixertest.handleRemoteJsep({ jsep: jsep });
}
},
onlocaltrack: function (track, on) {
Janus.debug(
"Local track " + (on ? "added" : "removed") + ":",
track
);
// We're not going to attach the local audio stream
$("#audiojoin").addClass("hide");
$("#room").removeClass("hide");
$("#participant")
.removeClass("hide")
.html(myusername)
.removeClass("hide");
},
onremotetrack: function (track, mid, on, metadata) {
Janus.debug(
"Remote track (mid=" +
mid +
") " +
(on ? "added" : "removed") +
(metadata ? " (" + metadata.reason + ") " : "") +
":",
track
);
if (remoteStream || track.kind !== "audio") return;
if (!on) {
// Track removed, get rid of the stream and the rendering
remoteStream = null;
$("#roomaudio").remove();
return;
}
$("#spinner").remove();
remoteStream = new MediaStream([track]);
$("#room").removeClass("hide");
if ($("#roomaudio").length === 0) {
$("#mixedaudio").append(
''
);
$("#roomaudio").get(0).volume = 0;
}
Janus.attachMediaStream($("#roomaudio").get(0), remoteStream);
$("#roomaudio").get(0).play();
$("#roomaudio").get(0).volume = 1;
// Mute button
audioenabled = true;
$("#toggleaudio")
.click(function () {
audioenabled = !audioenabled;
if (audioenabled)
$("#toggleaudio")
.html("Mute")
.removeClass("btn-success")
.addClass("btn-danger");
else
$("#toggleaudio")
.html("Unmute")
.removeClass("btn-danger")
.addClass("btn-success");
mixertest.send({
message: { request: "configure", muted: !audioenabled },
});
})
.removeClass("hide");
// Suspend button
if (!audiosuspended)
$("#togglesuspend")
.html("Suspend")
.removeClass("btn-info")
.addClass("btn-secondary");
else
$("#togglesuspend")
.html("Resume")
.removeClass("btn-secondary")
.addClass("btn-info");
$("#togglesuspend")
.click(function () {
audiosuspended = !audiosuspended;
if (!audiosuspended)
$("#togglesuspend")
.html("Suspend")
.removeClass("btn-info")
.addClass("btn-secondary");
else
$("#togglesuspend")
.html("Resume")
.removeClass("btn-secondary")
.addClass("btn-info");
mixertest.send({
message: {
request: audiosuspended ? "suspend" : "resume",
room: myroom,
id: myid,
},
});
})
.removeClass("hide");
// Spatial position, if enabled
$("#position").click(function () {
bootbox.prompt(
"Insert new spatial position: [0-100] (0=left, 50=center, 100=right)",
function (result) {
let spatial = parseInt(result);
if (isNaN(spatial) || spatial < 0 || spatial > 100) {
bootbox.alert("Invalid value");
return;
}
mixertest.send({
message: {
request: "configure",
spatial_position: spatial,
},
});
}
);
});
},
oncleanup: function () {
webrtcUp = false;
Janus.log(" ::: Got a cleanup notification :::");
$("#participant").empty().addClass("hide");
$("#list").empty();
$("#mixedaudio").empty();
$("#room").addClass("hide");
remoteStream = null;
},
});
},
error: function (error) {
Janus.error(error);
bootbox.alert(error, function () {
window.location.reload();
});
},
destroyed: function () {
window.location.reload();
},
});
});
},
});
});
// eslint-disable-next-line no-unused-vars
function checkEnter(field, event) {
let theCode = event.keyCode
? event.keyCode
: event.which
? event.which
: event.charCode;
if (theCode == 13) {
registerUsername();
return false;
} else {
return true;
}
}
function registerUsername() {
if ($("#username").length === 0) {
// Create fields to register
$("#register").click(registerUsername);
$("#username").focus();
} else {
// Try a registration
$("#username").attr("disabled", true);
$("#register").attr("disabled", true).unbind("click");
let username = $("#username").val();
if (username === "") {
$("#you")
.removeClass()
.addClass("badge bg-warning")
.html("Insert your display name (e.g., pippo)");
$("#username").removeAttr("disabled");
$("#register").removeAttr("disabled").click(registerUsername);
return;
}
if (/[^a-zA-Z0-9]/.test(username)) {
$("#you")
.removeClass()
.addClass("badge bg-warning")
.html("Input is not alphanumeric");
$("#username").removeAttr("disabled").val("");
$("#register").removeAttr("disabled").click(registerUsername);
return;
}
let register = {
request: "join",
room: myroom,
display: username,
suspended: audiosuspended,
};
myusername = escapeXmlTags(username);
// Check if we need to join using G.711 instead of (default) Opus
if (acodec === "opus" || acodec === "pcmu" || acodec === "pcma")
register.codec = acodec;
// If the room uses forwarding groups, this is how we state ours
if (mygroup) register["group"] = mygroup;
// Send the message
mixertest.send({ message: register });
}
}
// Helper to parse query string
function getQueryStringValue(name) {
name = name.replace(/[[]/, "\\[").replace(/[\]]/, "\\]");
let regex = new RegExp("[\\?&]" + name + "=([^]*)"),
results = regex.exec(location.search);
return results === null
? ""
: decodeURIComponent(results[1].replace(/\+/g, " "));
}
// Helper to escape XML tags
function escapeXmlTags(value) {
if (value) {
let escapedValue = value.replace(new RegExp("<", "g"), "<");
escapedValue = escapedValue.replace(new RegExp(">", "g"), ">");
return escapedValue;
}
}