Skip to content

Instantly share code, notes, and snippets.

@richtr
Last active August 29, 2015 13:57

Revisions

  1. richtr revised this gist Mar 21, 2014. 1 changed file with 6 additions and 6 deletions.
    12 changes: 6 additions & 6 deletions broadcastwebsocket_pure_p2p_webrtc_screensharing_example.html
    Original file line number Diff line number Diff line change
    @@ -33,7 +33,7 @@ <h1>DEMO: Pure P2P (signaling + streaming) Screen Casting via WebRTC over Broadc

    socket.onmessage = function () {

    var message = socket.data;
    var message = JSON.parse(socket.data);

    // Connected service is advertising itself as a second screen
    if( message.action == 'isSecondScreen' ) {
    @@ -105,10 +105,10 @@ <h1>DEMO: Pure P2P (signaling + streaming) Screen Casting via WebRTC over Broadc

    pc.onicecandidate = function ( event ) {
    if ( event.candidate ) {
    signalingChannel.send({
    signalingChannel.send(JSON.stringify({
    "action": "rtc_IceCandidate",
    "candidate": event.candidate
    });
    }));
    }
    };

    @@ -122,16 +122,16 @@ <h1>DEMO: Pure P2P (signaling + streaming) Screen Casting via WebRTC over Broadc

    function localSDPCreated( sdp ) {
    pc.setLocalDescription(sdp, function() {
    signalingChannel.send({
    signalingChannel.send(JSON.stringify({
    "action": "rtc_SDPDescription",
    "sdp": pc.localDescription
    });
    }));
    });
    };

    signalingChannel.onmessage = function ( event ) {

    var message = event.data
    var message = JSON.parse(event.data);

    if ( message.action == "rtc_SDPDescription" ) {

  2. richtr revised this gist Mar 21, 2014. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions broadcastwebsocket_basic_example.html
    Original file line number Diff line number Diff line change
    @@ -17,9 +17,9 @@ <h1>BroadcastWebSocket usage demo</h1>
    // void terminate([Clamp] optional unsigned short code, optional DOMString reason);
    // }
    //
    // Create a web socket object that also broadcasts its availability in the local network
    // and/or connects with any existing BroadcastWebSocket services that share the same
    // channel.
    // Create an object that broadcasts the availability of the provided channel id in the
    // local network and connect all existing BroadcastWebSocket services that share the same
    // channel id within the local network.
    //
    // The network advertisement broadcast of this BroadcastWebSocket service could
    // potentially be agnostic to the underlying Discovery Protocol used.
  3. richtr revised this gist Mar 21, 2014. 1 changed file with 3 additions and 1 deletion.
    Original file line number Diff line number Diff line change
    @@ -18,8 +18,10 @@ <h1>DEMO: Pure P2P (signaling + streaming) Screen Casting via WebRTC over Broadc
    return Math.floor(Math.random() * 1e16);
    }

    // Use a BroadcastWebSocket to collect screencast-capable candidate web pages and devices.

    // Second screen capable devices advertise 'web+broadcast:screencast_devices'
    // services on the local network.
    // services on the local network via e.g. DNS-SD/mDNS.
    var displaysBroadcast = new BroadcastWebSocket('screencast_devices');

    var availableDisplays = {};
  4. richtr revised this gist Mar 21, 2014. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions broadcastwebsocket_pure_p2p_webrtc_screensharing_example.html
    Original file line number Diff line number Diff line change
    @@ -1,10 +1,10 @@
    <!DOCTYPE html>
    <html>
    <head>
    <title>DEMO: Pure P2P (signaling + streaming) Screen Casting via WebRTC example</title>
    <title>DEMO: Pure P2P (signaling + streaming) Screen Casting via WebRTC over BroadcastWebSocket</title>
    </head>
    <body>
    <h1>DEMO: Pure P2P (signaling + streaming) Screen Casting via WebRTC example</h1>
    <h1>DEMO: Pure P2P (signaling + streaming) Screen Casting via WebRTC over BroadcastWebSocket</h1>

    <select disabled>
    <option disabled>Select a second screen to cast this tab to</option>
  5. richtr revised this gist Mar 21, 2014. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions broadcastwebsocket_pure_p2p_webrtc_screensharing_example.html
    Original file line number Diff line number Diff line change
    @@ -1,10 +1,10 @@
    <!DOCTYPE html>
    <html>
    <head>
    <title>DEMO: Pure P2P Screen Casting via WebRTC example</title>
    <title>DEMO: Pure P2P (signaling + streaming) Screen Casting via WebRTC example</title>
    </head>
    <body>
    <h1>DEMO: Pure P2P Screen Casting via WebRTC example</h1>
    <h1>DEMO: Pure P2P (signaling + streaming) Screen Casting via WebRTC example</h1>

    <select disabled>
    <option disabled>Select a second screen to cast this tab to</option>
  6. richtr revised this gist Mar 21, 2014. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion broadcastwebsocket_basic_example.html
    Original file line number Diff line number Diff line change
    @@ -18,7 +18,7 @@ <h1>BroadcastWebSocket usage demo</h1>
    // }
    //
    // Create a web socket object that also broadcasts its availability in the local network
    // and/or connects with an existing BroadcastWebSocket service that share the same
    // and/or connects with any existing BroadcastWebSocket services that share the same
    // channel.
    //
    // The network advertisement broadcast of this BroadcastWebSocket service could
  7. richtr created this gist Mar 21, 2014.
    78 changes: 78 additions & 0 deletions broadcastwebsocket_basic_example.html
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,78 @@
    <!DOCTYPE html>
    <html>
    <head>
    <title>BroadcastWebSocket usage demo</title>
    </head>
    <body>
    <h1>BroadcastWebSocket usage demo</h1>

    <script>

    // [Constructor(DOMString channel)]
    // interface BroadcastWebSocket {
    // // events
    // attribute EventHandler onconnect; // provides WebSocket objects (one per event)
    //
    // // methods
    // void terminate([Clamp] optional unsigned short code, optional DOMString reason);
    // }
    //
    // Create a web socket object that also broadcasts its availability in the local network
    // and/or connects with an existing BroadcastWebSocket service that share the same
    // channel.
    //
    // The network advertisement broadcast of this BroadcastWebSocket service could
    // potentially be agnostic to the underlying Discovery Protocol used.
    // i.e. it could be broadcast over SSDP, Zeroconf and/or DIAL by the UA
    // as this mechanism is not exposed in the JavaScript API.
    //
    // The BroadcastWebSocket service type would be 'web+broadcast:<channel>' where <channel>
    // is the channel name chosen by the developer.
    //
    // Here we build on top of the WebSocket interface rather than MessageChannel or MessagePort
    // interfaces which do not have well-defined network communication or serialization
    // features.
    //
    var authSocketHandler = new BroadcastWebSocket('auth' + (window.location.search || '?0')); // key the channel name by its URL parameters

    var connectedSockets = [];

    authSocketHandler.onconnect = function( webSocket ) {

    connectedSockets.push( webSocket );

    webSocket.onmessage = function (event) {
    // we only want to allow same-origin cross-document communication in our app.
    if( event.origin !== location.origin )
    return;

    if (event.data == 'logout') {
    doLogout();
    showLogout();
    }
    }

    }

    function logoutRequested() {
    // called when the user asks us to log them out
    doLogout();
    showLogout();
    for(var i in connectedSockets) {
    connectedSockets[i].send('logout');
    }
    }

    function doLogout() {
    // actually log the user out (e.g. clearing cookies)
    // ...
    }

    function showLogout() {
    // update the UI to indicate we're logged out
    // ...
    }

    </script>
    </body>
    </html>
    159 changes: 159 additions & 0 deletions broadcastwebsocket_pure_p2p_webrtc_screensharing_example.html
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,159 @@
    <!DOCTYPE html>
    <html>
    <head>
    <title>DEMO: Pure P2P Screen Casting via WebRTC example</title>
    </head>
    <body>
    <h1>DEMO: Pure P2P Screen Casting via WebRTC example</h1>

    <select disabled>
    <option disabled>Select a second screen to cast this tab to</option>
    </select>

    <script>

    var castMenu = document.querySelector('select');

    function generateUUID() {
    return Math.floor(Math.random() * 1e16);
    }

    // Second screen capable devices advertise 'web+broadcast:screencast_devices'
    // services on the local network.
    var displaysBroadcast = new BroadcastWebSocket('screencast_devices');

    var availableDisplays = {};
    var availableDisplaysCount = 0;

    displaysBroadcast.onconnect = function( socket ) {

    var displayIndex;

    socket.onmessage = function () {

    var message = socket.data;

    // Connected service is advertising itself as a second screen
    if( message.action == 'isSecondScreen' ) {
    displayIndex = generateUUID();
    availableDisplays[ displayIndex ] = {
    'endpointName' : message.name || 'Second Screen',
    'endpointSocket': socket
    };

    var castOption = document.createElement('option');
    castOption.value = castOption.id = displayIndex;
    castOption.textContent = availableDisplays[ displayIndex ];
    castMenu.appendChild( castOption );

    availableDisplaysCount++;
    castMenu.disabled = false;
    }

    }

    socket.onclose = function () {

    // Remove this previously registered second screen
    if( displayIndex ) {
    var castOption = document.querySelector('#' + displayIndex);
    castOption.parentNode.removeChild( castOption );
    delete availableDisplays[ displayIndex ];
    availableDisplaysCount--;
    }

    if(availableDisplaysCount === 0) {
    castMenu.disabled = true;
    }
    };

    }

    castMenu.onchange = function () {

    var selectedDisplayIndex = castMenu.options[castMenu.selectedIndex].value;

    var selectedDisplayObject = availableDisplays[ selectedDisplayIndex ];
    var selectedDisplaySocket = selectedDisplayObject.endpointSocket;

    var streamConfig = {
    audio: false,
    video: {
    mandatory: {
    mediaSource: 'screen' // share the current screen
    }
    }
    };

    // Start a WebRTC screen sharing session
    navigator.getUserMedia(
    streamConfig,
    function( stream ) { startScreenStreaming( stream, selectedDisplaySocket ) },
    logError
    );

    };

    function startScreenStreaming( screenStream, signalingChannel ) {

    var pc = new RTCPeerConnection({ "iceServers": [{ "url": "stun:stun.example.org" }] });

    // Add screen sharing MediaStream object to the PeerConnection
    pc.addStream( screenStream );

    pc.onicecandidate = function ( event ) {
    if ( event.candidate ) {
    signalingChannel.send({
    "action": "rtc_IceCandidate",
    "candidate": event.candidate
    });
    }
    };

    pc.onnegotiationneeded = function () {
    // enforce 'sendonly' streaming to second screen
    pc.createOffer(localSDPCreated, logError, {
    offerToReceiveVideo: false,
    offerToReceiveAudio: false
    });
    };

    function localSDPCreated( sdp ) {
    pc.setLocalDescription(sdp, function() {
    signalingChannel.send({
    "action": "rtc_SDPDescription",
    "sdp": pc.localDescription
    });
    });
    };

    signalingChannel.onmessage = function ( event ) {

    var message = event.data

    if ( message.action == "rtc_SDPDescription" ) {

    pc.setRemoteDescription(new RTCSessionDescription(message.sdp), function () {
    if (pc.remoteDescription.type == "offer") {
    pc.createAnswer(localSDPCreated, logError);
    }
    }, logError);

    } else if ( message.action == "rtc_IceCandidate" ) {

    pc.addIceCandidate( new RTCIceCandidate( message.candidate ) );

    }

    };

    }

    function logError( error ) {
    console.log( error.name + ": " + error.message );
    }

    </script>

    </body>
    </html>