Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Controls encapsulate

Table of Contents

This module encapsulates code responsible for managing local media and room config. This includes creation of new tracks, stopping existing tracks and preparation of room config before connecting to server.

1. Wrapper function

createControls() code

Wrapper function which keeps controls inside the closure.

Code Block
languagejs
themeRDark
const createControls = function(config) {

2. Create controls object

code

Create controls object which will hold all the html handles. Also initialize tables for displaying local tracks configuration.

Code Block
languagejs
themeRDark
const controls = {
    entrance: {
        url: document.getElementById("url"),
        roomName: document.getElementById("roomName"),
        roomPin: document.getElementById("roomPin"),
        nickName: document.getElementById("nickName"),
        enter: document.getElementById("startButton")
    },
    addVideoTrack: {
        source: document.getElementById("addVideoTrackSource"),
        width: document.getElementById("addVideoTrackWidth"),
        height: document.getElementById("addVideoTrackHeight"),
        codec: document.getElementById("addVideoTrackCodec")
    },
    addAudioTrack: {
        source: document.getElementById("addAudioTrackSource"),
        channels: document.getElementById("addAudioTrackChannels")
    },
    addVideoEncoding: {
        rid: document.getElementById("addVideoTrackEncodingRid"),
        active: document.getElementById("addVideoTrackEncodingActive"),
        maxBitrate: document.getElementById("addVideoTrackEncodingMaxBitrate"),
        resolutionScale: document.getElementById("addVideoTrackEncodingResolutionScale")
    },
    tables: {
        video: $('#videoTracksTable').DataTable({
            "sDom": 't',
            "columns": [
                {
                    "className":      'details-control',
                    "orderable":      false,
                    "data":           null,
                    "defaultContent": ''
                },
                {"data": "source"},
                {"data": "width"},
                {"data": "height"},
                {"data": "codec"},
                {"data": "action"}
            ]
        }),
        audio: $('#audioTracksTable').DataTable({
            "sDom": 't',
            "columns": [
                {"data": "source"},
                {"data": "channels"},
                {"data": "action"}
            ]
        }),
        encodings: $('#videoTrackEncodingsTable').DataTable({
            "sDom": 't',
            "columns": [
                {"data": "rid"},
                {"data": "active"},
                {"data": "maxBitrate"},
                {"data": "resolutionScale"},
                {"data": "action"}
            ]
        })
    }
}

3. Fill entrance model window fields

code

Populate entrance modal with provided config

Code Block
languagejs
themeRDark
//apply room config
controls.entrance.url.value = config.room.url;
controls.entrance.roomName.value = config.room.name;
controls.entrance.roomPin.value = config.room.pin;
controls.entrance.nickName.value = config.room.nickName;

4. Add new audio tracks to controls

addAudioTrackRow() code

Function that will add new audio tracks to controls and notify main script.

...

Code Block
languagejs
themeRDark
trackCallback({
    stream: stream,
    encodings: track.encodings
});

5. Add new video tracks to controls

addVideoTrackRow() code

Function that will add new video tracks to controls and notify main script. This is the same as addAudioTrackRow function except it adds video.

Code Block
languagejs
themeRDark
const addVideoTrackRow = function(track) {
    getMedia([track]).then(function(stream){
        let button = '<button id="' + stream.id + '-button" class="btn btn-primary">Delete</button>';
        const row = controls.tables.video.row.add({
            source: track.source,
            width: track.width,
            height: track.height,
            codec: track.codec,
            action: button,
            stream: stream,
            encodings: track.encodings
        }).node();
        controls.tables.video.draw();

        $('#' + stream.id + "-button").on('click', function(){
            //terminate stream
            console.log("terminate stream " + stream.id);
            let track = stream.getVideoTracks()[0];
            track.stop();
            track.dispatchEvent(new Event("ended"));
        });
        stream.getTracks()[0].addEventListener("ended", function() {
            controls.tables.video.row(row).remove().draw();
        });
        trackCallback({
            stream: stream,
            encodings: track.encodings
        });
    });
}

6. Format video encodings

format() code

Helper function  to format video encodings so we can display them in the table nicely

Code Block
languagejs
themeRDark
const format = function(d) {
    if (!d.encodings) {
        return;
    }
    let details =  '<table cellpadding="5" cellspacing="0" border="0" style="padding-left:50px;">';
    d.encodings.forEach(function(encoding){
        details += '<tr>';
        for (const [key, value] of Object.entries(encoding)) {
            details += '<td>'+ key + '</td>'+
                '<td>'+ value + '</td>';
        }
        details += '</tr>';
    });
    details +='</table>';
    return details;
}

7. Add handler to display/hide track details

code

Add open and close handler for video tracks details

Code Block
languagejs
themeRDark
// Add event listener for opening and closing details
$('#videoTracksTableBody').on('click', 'td.details-control', function () {
    let tr = $(this).closest('tr');
    let row = controls.tables.video.row(tr);
    if (row.child.isShown()) {
        // This row is already open - close it
        row.child.hide();
        tr.removeClass('shown');
    } else {
        // Open this row
        row.child(format(row.data())).show();
        tr.addClass('shown');
    }
});

8. Add audio tracks to the table

code

Add all configured audio tracks to the table

Code Block
languagejs
themeRDark
config.media.audio.tracks.forEach(function(track){
    addAudioTrackRow(track);
})

9. Add audio tracks to the table

code

Add all configured video tracks to the table

Code Block
languagejs
themeRDark
config.media.video.tracks.forEach(function(track){
    addVideoTrackRow(track);
})

10. Mute forms

muteForm() code

Define helper function for muting forms

Code Block
languagejs
themeRDark
const muteForm = function(form) {
    for (const [key, value] of Object.entries(form)) {
        value.disabled = true;
    }
}

11. Unmute forms

unmuteForm() code

Define helper function for unmuting forms

Code Block
languagejs
themeRDark
const unmuteForm = function(form) {
    for (const [key, value] of Object.entries(form)) {
        value.disabled = false;
    }
}

12. Mute entrance modal window inputs

muteInput() code

Define function that mutes entrance inputs

Code Block
languagejs
themeRDark
const muteInput = function() {
    muteForm(controls.entrance);
}

13. Create room configuration object

roomConfig() code

Define function that will assemble room config

Code Block
languagejs
themeRDark
const roomConfig = function() {
    return {
        url: controls.entrance.url.value,
        roomName: controls.entrance.roomName.value,
        pin: controls.entrance.roomPin.value,
        nickname: controls.entrance.nickName.value
    }
}

14. Get local video tracks

getVideoStreams() code

Define function that will return all available local video tracks

Code Block
languagejs
themeRDark
const getVideoStreams = function() {
    let streams = [];
    controls.tables.video.rows().every(function(rowIdx, tableLoop, rowLoop) {
        let data = this.data();
        streams.push({
            stream: data.stream,
            encodings: data.encodings
        });
    });
    return streams;
}

15. Get local audio tracks

getAudioStreams() code

Define function that will return all available local audio tracks

Code Block
languagejs
themeRDark
const getAudioStreams = function() {
    let streams = [];
    controls.tables.audio.rows().every(function(rowIdx, tableLoop, rowLoop) {
        let data = this.data();
        streams.push({
            stream: data.stream,
            encodings: []
        });
    });
    return streams;
}

16. Handler to add video track to the table

code

Subscribe to "click" event of add video track button. This function will parse input and add new track to the table

Code Block
languagejs
themeRDark
document.getElementById("addVideoTrack").addEventListener("click", function(e){
    let encodings = [];
    controls.tables.encodings.rows().every(function() {
        let encoding = this.data();
        encodings.push({
            rid: encoding.rid,
            active: encoding.active,
            maxBitrate: encoding.maxBitrate,
            scaleResolutionDownBy: encoding.resolutionScale
        })
    });
    let track = {
        source: controls.addVideoTrack.source.value,
        width: controls.addVideoTrack.width.value,
        height: controls.addVideoTrack.height.value,
        codec: controls.addVideoTrack.codec.value,
        encodings: encodings
    }
    addVideoTrackRow(track);
});

17. Handler to remove encoding from the table

code

Add ability to remove encodings from the encodings table

Code Block
languagejs
themeRDark
$("#videoTrackEncodingsTable").on("click", ".remove", function(){
    controls.tables.encodings.row($(this).parents('tr')).remove().draw();
});

18. Handler to add encoding to the table

code

Subscribe to "click" event of add encoding button. This function will parse input and add a new encoding to the encodings table

Code Block
languagejs
themeRDark
document.getElementById("addVideoTrackEncoding").addEventListener("click", function(){
    let button = '<button class="btn btn-primary remove">Delete</button>';
    controls.tables.encodings.row.add({
        rid: controls.addVideoEncoding.rid.value,
        active: controls.addVideoEncoding.active.value,
        maxBitrate: controls.addVideoEncoding.maxBitrate.value,
        resolutionScale: controls.addVideoEncoding.resolutionScale.value,
        action: button
    }).draw();
});

19. Handler to add audio track to the table

code

Subscribe to "click" event of add audio track button. This function will parse input and add new track to the table

Code Block
languagejs
themeRDark
document.getElementById("addAudioTrack").addEventListener("click", function(e){
    let encodings = [];
    let track = {
        source: controls.addAudioTrack.source.value,
        channels: controls.addAudioTrack.channels.value,
        encodings: encodings
    }
    addAudioTrackRow(track);
});

20. Pass callback function to new tracks

code

Define function that will help to pass the callback function for the new tracks

Code Block
languagejs
themeRDark
const onTrack = function(callback) {
    trackCallback = callback;
}

21. Export functions

code

Export functions for the script

Code Block
languagejs
themeRDark
return {
    muteInput: muteInput,
    roomConfig: roomConfig,
    getAudioStreams: getAudioStreams,
    getVideoStreams: getVideoStreams,
    onTrack: onTrack
}

22. Get media streams from WebRTC API

getMedia() code

Requests local media streams from the WebRTC API.

...