├── Procfile ├── types ├── rtc │ ├── MediaStream.d.ts.tscparams │ ├── MediaStream-tests.ts.tscparams │ ├── RTCPeerConnection-tests.ts.tscparams │ ├── RTCPeerConnection.d.ts.tscparams │ ├── readme.md │ ├── MediaStream-tests.ts │ ├── RTCPeerConnection-tests.ts │ ├── MediaStream.d.ts │ └── RTCPeerConnection.d.ts ├── angular │ ├── angular-animate.d.ts │ ├── angular-cookies.d.ts │ ├── angular-sanitize.d.ts │ ├── angular-route.d.ts │ ├── angular-scenario.d.ts │ ├── angular-resource.d.ts │ ├── README.md │ └── angular-mocks.d.ts └── jasmine │ └── jasmine.d.ts ├── .bowerrc ├── .gitignore ├── public ├── fonts │ ├── sococortc.eot │ ├── sococortc.ttf │ ├── sococortc.woff │ ├── sococortc.css │ └── sococortc.svg ├── css │ ├── README.md │ ├── animate.css │ ├── bootstrap.css │ └── config.json ├── index.html ├── js │ └── adapter.js └── index.css ├── .travis.yml ├── bower.json ├── server-cluster.js ├── CHANGELOG.md ├── test ├── unit │ ├── LocalPeerTests.ts │ └── PeerConnectionTests.ts ├── karma.conf.js └── fixtures │ └── MockPubSub.ts ├── LICENSE ├── package.json ├── source ├── PubSub.ts ├── app │ └── RTCAngularApp.ts ├── Events.ts ├── LocalPeer.ts └── PeerConnection.ts ├── README.md ├── CONVENTIONS.md ├── server.js ├── Gruntfile.js └── CREDITS.md /Procfile: -------------------------------------------------------------------------------- 1 | web: node server-cluster.js 2 | -------------------------------------------------------------------------------- /types/rtc/MediaStream.d.ts.tscparams: -------------------------------------------------------------------------------- 1 | "" 2 | -------------------------------------------------------------------------------- /types/rtc/MediaStream-tests.ts.tscparams: -------------------------------------------------------------------------------- 1 | "" 2 | -------------------------------------------------------------------------------- /types/rtc/RTCPeerConnection-tests.ts.tscparams: -------------------------------------------------------------------------------- 1 | "" 2 | -------------------------------------------------------------------------------- /types/rtc/RTCPeerConnection.d.ts.tscparams: -------------------------------------------------------------------------------- 1 | "" 2 | -------------------------------------------------------------------------------- /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "public/bower_components" 3 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | public/app/ 2 | public/bower_components/ 3 | node_modules 4 | -------------------------------------------------------------------------------- /public/fonts/sococortc.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sococo/sococo-rtc/HEAD/public/fonts/sococortc.eot -------------------------------------------------------------------------------- /public/fonts/sococortc.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sococo/sococo-rtc/HEAD/public/fonts/sococortc.ttf -------------------------------------------------------------------------------- /public/fonts/sococortc.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sococo/sococo-rtc/HEAD/public/fonts/sococortc.woff -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 0.8 4 | 5 | before_script: 6 | - export DISPLAY=:99.0 7 | - sh -e /etc/init.d/xvfb start 8 | 9 | addons: 10 | firefox: "27.0" -------------------------------------------------------------------------------- /public/css/README.md: -------------------------------------------------------------------------------- 1 | This is a custom build of bootstrap: http://getbootstrap.com/customize/?id=9401868#less 2 | 3 | It includes Print Media/Typography and Basic/Responsive utilities. 4 | 5 | The output `config.json` file may be found in this directory. -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "SococoRTC", 3 | "version": "0.0.2", 4 | "homepage": "https://github.com/sococo/sococo-rtc", 5 | "authors": [ 6 | "Justin DuJardin " 7 | ], 8 | "main": "server.js", 9 | "keywords": [ 10 | "WebRTC", 11 | "Signaling", 12 | "TypeScript", 13 | "AngularJS" 14 | ], 15 | "license": "MIT", 16 | "ignore": [ 17 | "**/.*", 18 | "node_modules", 19 | "bower_components", 20 | "test", 21 | "tests" 22 | ], 23 | "dependencies": { 24 | "faye": "~1.0.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /server-cluster.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var cluster = require('cluster'); 3 | if(cluster.isMaster){ 4 | var workerCount = process.env.WORKER_COUNT || require('os').cpus().length; 5 | var workers = new Array(workerCount); 6 | for(var i = 0; i < workerCount; i++){ 7 | !function spawn(i) { 8 | workers[i] = cluster.fork(); 9 | workers[i].on('exit', function() { 10 | console.error('sococo-rtc: worker died, respawning'); 11 | spawn(i); 12 | }); 13 | }(i); 14 | } 15 | } 16 | else { 17 | require("./server"); 18 | } -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | ### 0.0.2 (2014-04-14) 3 | 4 | 5 | #### Features 6 | 7 | * **TravisCI:** add support for travis continuous integration build testing ([979f9b0b](http://github.com/sococo/sococo-rtc/commit/979f9b0b6d751fb44de8538715dfe03199c9b799)) 8 | * **testing:** add karma powered test suite ([955190df](http://github.com/sococo/sococo-rtc/commit/955190dfe9fdfb5b74a4be235f39540435c21e94)) 9 | 10 | 11 | 12 | ### 0.0.1 (2014-04-14) 13 | 14 | 15 | #### Features 16 | 17 | * **grunt:** add 'develop' task that runs express server and builds outputs ([cfed7b06](http://github.com/sococo/sococo-rtc/commit/cfed7b06df85e531ab4bf8107f06e9846e18d4ca)) 18 | 19 | 20 | -------------------------------------------------------------------------------- /types/rtc/readme.md: -------------------------------------------------------------------------------- 1 | # WebRTC Definition Notes 2 | 3 | ## The WebRTC specification 4 | 5 | The WebRTC specification is currently a work in progress, but it has been implemented at a basic level in recent versions of Chrome, Opera and (to a lesser extent) Firefox. 6 | The latest version of the specification can be found at http://dev.w3.org/2011/webrtc/editor/webrtc.html. 7 | 8 | This particular set of definitions has been annotated with the vendor-specific prefixes for Chrome (e.g., `webitkit`), 9 | but anyone who wants, feel free to add the Mozilla-specific prefixes. 10 | 11 | ### Adding the reference to your project 12 | 13 | /// 14 | /// -------------------------------------------------------------------------------- /test/unit/LocalPeerTests.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | /// 5 | module SRTC.Test { 6 | describe('SRTC.LocalPeer', () => { 7 | it('should construct in isolation', () => { 8 | var localPeer = new SRTC.LocalPeerConnection({ 9 | pubSub: new MockPubSub(), 10 | location:"testRoom", 11 | localId:"testPeerId", 12 | serverUrl:"localhost:8102", 13 | serverMount:"/faye" 14 | }); 15 | expect(localPeer).toBeTruthy(); 16 | }); 17 | }); 18 | } 19 | 20 | 21 | -------------------------------------------------------------------------------- /types/angular/angular-animate.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for Angular JS 1.2+ (ngAnimate module) 2 | // Project: http://angularjs.org 3 | // Definitions by: Michel Salib 4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 5 | 6 | /// 7 | 8 | 9 | /////////////////////////////////////////////////////////////////////////////// 10 | // ngAnimate module (angular-animate.js) 11 | /////////////////////////////////////////////////////////////////////////////// 12 | declare module ng.animate { 13 | 14 | /////////////////////////////////////////////////////////////////////////// 15 | // AnimateService 16 | // see http://docs.angularjs.org/api/ngAnimate.$animate 17 | /////////////////////////////////////////////////////////////////////////// 18 | interface IAnimateService extends ng.IAnimateService { 19 | enabled(value?: boolean, element?: JQuery): boolean; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /test/karma.conf.js: -------------------------------------------------------------------------------- 1 | /*globals module,process,require */ 2 | module.exports = function(config) { 3 | "use strict"; 4 | 5 | config.set({ 6 | basePath: '../', 7 | frameworks: ['jasmine'], 8 | files: [ 9 | "public/js/adapter.js", 10 | "public/app/sococo-rtc.js", 11 | "https://ajax.googleapis.com/ajax/libs/angularjs/1.2.12/angular.min.js", 12 | "https://ajax.googleapis.com/ajax/libs/angularjs/1.2.12/angular-cookies.min.js", 13 | "public/app/sococo-rtc-app.js", 14 | "public/app/test/*.js" 15 | ], 16 | reporters: ['dots'], 17 | port: 9876, 18 | autoWatch: true, 19 | background:true, 20 | // - Chrome, ChromeCanary, Firefox, Opera, Safari (only Mac), PhantomJS, IE (only Windows) 21 | browsers: process.env.TRAVIS ? ['Firefox'] : ['Firefox'], 22 | singleRun: false, 23 | reportSlowerThan: 500, 24 | plugins: [ 25 | 'karma-firefox-launcher', 26 | 'karma-chrome-launcher', 27 | 'karma-jasmine' 28 | ] 29 | }); 30 | }; 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Sococo.RTC 2 | 3 | The MIT License (MIT) 4 | 5 | Copyright (c) 2014 Social Communications Company 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | THE SOFTWARE. -------------------------------------------------------------------------------- /types/angular/angular-cookies.d.ts: -------------------------------------------------------------------------------- 1 | /// Type definitions for Angular JS 1.2 (ngCookies module) 2 | // Project: http://angularjs.org 3 | // Definitions by: Diego Vilar 4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 5 | 6 | 7 | /// 8 | 9 | /////////////////////////////////////////////////////////////////////////////// 10 | // ngCookies module (angular-cookies.js) 11 | /////////////////////////////////////////////////////////////////////////////// 12 | declare module ng.cookies { 13 | 14 | /////////////////////////////////////////////////////////////////////////// 15 | // CookieService 16 | // see http://docs.angularjs.org/api/ngCookies.$cookies 17 | /////////////////////////////////////////////////////////////////////////// 18 | interface ICookiesService {} 19 | 20 | /////////////////////////////////////////////////////////////////////////// 21 | // CookieStoreService 22 | // see http://docs.angularjs.org/api/ngCookies.$cookieStore 23 | /////////////////////////////////////////////////////////////////////////// 24 | interface ICookieStoreService { 25 | get(key: string): any; 26 | put(key: string, value: any): void; 27 | remove(key: string): void; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /types/rtc/MediaStream-tests.ts: -------------------------------------------------------------------------------- 1 | /// 2 | var mediaStreamConstraints: MediaStreamConstraints = { audio: true, video: true }; 3 | 4 | var mediaTrackConstraintSet: MediaTrackConstraintSet = {}; 5 | var mediaTrackConstraintArray: MediaTrackConstraint[] = []; 6 | var mediaTrackConstraints: MediaTrackConstraints = { mandatory: mediaTrackConstraintSet, optional: mediaTrackConstraintArray } 7 | 8 | navigator.getUserMedia(mediaStreamConstraints, 9 | stream => { 10 | console.log('label:' + stream.label); 11 | console.log('ended:' + stream.ended); 12 | stream.onended = event => console.log('Stream ended'); 13 | var objectUrl = URL.createObjectURL(stream); 14 | var wkObjectUrl = webkitURL.createObjectURL(stream); 15 | }, 16 | error => { 17 | console.log('Error message: ' + error.message); 18 | console.log('Error name: ' + error.name); 19 | }); 20 | 21 | navigator.webkitGetUserMedia(mediaStreamConstraints, 22 | stream => { 23 | console.log('label:' + stream.label); 24 | console.log('ended:' + stream.ended); 25 | stream.onended = event => console.log('Stream ended'); 26 | var objectUrl = URL.createObjectURL(stream); 27 | var wkObjectUrl = webkitURL.createObjectURL(stream); 28 | }, 29 | error => { 30 | console.log('Error message: ' + error.message); 31 | console.log('Error name: ' + error.name); 32 | }); -------------------------------------------------------------------------------- /types/angular/angular-sanitize.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for Angular JS 1.2 (ngSanitize module) 2 | // Project: http://angularjs.org 3 | // Definitions by: Diego Vilar 4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 5 | 6 | 7 | /// 8 | 9 | /////////////////////////////////////////////////////////////////////////////// 10 | // ngSanitize module (angular-sanitize.js) 11 | /////////////////////////////////////////////////////////////////////////////// 12 | declare module ng.sanitize { 13 | 14 | /////////////////////////////////////////////////////////////////////////// 15 | // SanitizeService 16 | // see http://docs.angularjs.org/api/ngSanitize.$sanitize 17 | /////////////////////////////////////////////////////////////////////////// 18 | interface ISanitizeService { 19 | (html: string): string; 20 | } 21 | 22 | /////////////////////////////////////////////////////////////////////////// 23 | // Filters included with the ngSanitize 24 | // see https://github.com/angular/angular.js/tree/v1.2.0/src/ngSanitize/filter 25 | /////////////////////////////////////////////////////////////////////////// 26 | export module filter { 27 | 28 | // Finds links in text input and turns them into html links. 29 | // Supports http/https/ftp/mailto and plain email address links. 30 | // see http://code.angularjs.org/1.2.0/docs/api/ngSanitize.filter:linky 31 | interface ILinky { 32 | (text: string, target?: string): string; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /test/fixtures/MockPubSub.ts: -------------------------------------------------------------------------------- 1 | /// 2 | module SRTC.Test { 3 | /** 4 | * Simple PubSub class using observer pattern exposed by Events class. 5 | */ 6 | export class MockPubSub extends SRTC.Events implements SRTC.IPubSub { 7 | public connected:boolean = false; 8 | public subscribedChannels:any = {}; 9 | 10 | defer(fn:any) { 11 | if(!fn){ 12 | return; 13 | } 14 | setTimeout(() => { 15 | fn(); 16 | }); 17 | } 18 | 19 | connect(url:string,done?:(error?: any) => void) { 20 | this.connected = true; 21 | done && this.defer(done); 22 | } 23 | disconnect() { 24 | this.connected = false; 25 | this.off(); 26 | } 27 | 28 | incrementChannel(channel:string,val:number){ 29 | if(typeof this.subscribedChannels[channel] === 'undefined'){ 30 | this.subscribedChannels[channel] = 0; 31 | } 32 | this.subscribedChannels[channel] += val; 33 | } 34 | 35 | subscribe(channel:string,process:(data:any) => void,done?:(error?:any) => void) { 36 | this.on(channel,process); 37 | this.incrementChannel(channel,1); 38 | done && this.defer(done); 39 | } 40 | unsubscribe(channel:string) { 41 | this.off(channel); 42 | this.incrementChannel(channel,-1); 43 | } 44 | publish(channel:string,data:any) { 45 | this.defer(() => { 46 | this.trigger(channel,data); 47 | }); 48 | } 49 | } 50 | } 51 | 52 | 53 | -------------------------------------------------------------------------------- /public/fonts/sococortc.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | 3 | @font-face { 4 | font-family: "sococortc"; 5 | src:url("../fonts/sococortc.eot"); 6 | src:url("../fonts/sococortc.eot?#iefix") format("embedded-opentype"), 7 | url("../fonts/sococortc.woff") format("woff"), 8 | url("../fonts/sococortc.ttf") format("truetype"), 9 | url("../fonts/sococortc.svg#sococortc") format("svg"); 10 | font-weight: normal; 11 | font-style: normal; 12 | 13 | } 14 | 15 | [class^="srtc-"]:before, 16 | [class*=" srtc-"]:before { 17 | font-family: "sococortc" !important; 18 | font-style: normal !important; 19 | font-weight: normal !important; 20 | font-variant: normal !important; 21 | text-transform: none !important; 22 | speak: none; 23 | line-height: 1; 24 | -webkit-font-smoothing: antialiased; 25 | -moz-osx-font-smoothing: grayscale; 26 | } 27 | 28 | .srtc-arrows-compress:before { 29 | content: "a"; 30 | } 31 | .srtc-arrows-expand:before { 32 | content: "b"; 33 | } 34 | .srtc-check:before { 35 | content: "c"; 36 | } 37 | .srtc-html5:before { 38 | content: "d"; 39 | } 40 | .srtc-microphone:before { 41 | content: "e"; 42 | } 43 | .srtc-social-github:before { 44 | content: "f"; 45 | } 46 | .srtc-social-facebook:before { 47 | content: "g"; 48 | } 49 | .srtc-social-linkedin:before { 50 | content: "h"; 51 | } 52 | .srtc-social-twitter:before { 53 | content: "i"; 54 | } 55 | .srtc-x:before { 56 | content: "j"; 57 | } 58 | .srtc-volume:before { 59 | content: "k"; 60 | } 61 | .srtc-video:before { 62 | content: "l"; 63 | } 64 | .srtc-volume-strike:before { 65 | content: "m"; 66 | } 67 | .srtc-fontawesome-webfont:before { 68 | content: "n"; 69 | } 70 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sococo-rtc", 3 | "version": "0.0.2", 4 | "description": "multi-peer WebRTC prototype with dynamic stream properties.", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "./node_modules/.bin/grunt && ./node_modules/.bin/grunt karma:once", 8 | "postinstall": "./node_modules/.bin/bower install" 9 | }, 10 | "licenses": [ 11 | { 12 | "type": "MIT", 13 | "url": "https://github.com/sococo/sococo-chat/blob/master/LICENSE" 14 | } 15 | ], 16 | "repository": { 17 | "type": "git", 18 | "url": "git://github.com/sococo/sococo-rtc.git" 19 | }, 20 | "keywords": [ 21 | "WebRTC", 22 | "Signaling", 23 | "PeerConnection" 24 | ], 25 | "author": "Justin DuJardin ", 26 | "dependencies": { 27 | "express": "3.4.8", 28 | "faye": "1.0.1", 29 | "grunt": "0.4.2", 30 | "grunt-cli": "0.1.13", 31 | "grunt-typescript": "0.2.8", 32 | "grunt-contrib-cssmin": "0.8.0", 33 | "grunt-contrib-uglify": "0.3.3", 34 | "grunt-contrib-concat": "0.3.0", 35 | "grunt-contrib-watch": "0.5.3", 36 | "ejs": "~0.8.5", 37 | "hashids": "~0.3.3", 38 | "faye-redis": "~0.2.0", 39 | "bower": "~1.3.2" 40 | }, 41 | "devDependencies": { 42 | "performance-now": "~0.1.3", 43 | "grunt-express-server": "~0.4.13", 44 | "grunt-conventional-changelog": "~1.1.0", 45 | "grunt-bump": "0.0.13", 46 | "grunt-npm": "0.0.2", 47 | "karma-chrome-launcher": "~0.1.3", 48 | "karma-firefox-launcher": "~0.1.3", 49 | "karma-jasmine": "~0.2.2", 50 | "karma": "~0.12.9", 51 | "grunt-karma": "~0.8.2" 52 | }, 53 | "contributors": [ 54 | "Justin DuJardin " 55 | ] 56 | } 57 | -------------------------------------------------------------------------------- /types/rtc/RTCPeerConnection-tests.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | var config: RTCConfiguration = { iceServers: [{ url: "stun.l.google.com:19302" }] }; 5 | var constraints: MediaConstraints = { mandatory: { OfferToReceiveAudio: true, OfferToReceiveVideo: true } }; 6 | 7 | var peerConnection: RTCPeerConnection = new RTCPeerConnection(config, constraints); 8 | 9 | navigator.getUserMedia({ audio: true, video: true }, 10 | stream => { 11 | peerConnection.addStream(stream); 12 | }, 13 | error => { 14 | console.log('Error message: ' + error.message); 15 | console.log('Error name: ' + error.name); 16 | }); 17 | 18 | peerConnection.onaddstream = ev => console.log(ev.type); 19 | peerConnection.ondatachannel = ev => console.log(ev.type); 20 | peerConnection.onicechange = ev => console.log(ev.type); 21 | peerConnection.onnegotiationneeded = ev => console.log(ev.type); 22 | peerConnection.onopen = ev => console.log(ev.type); 23 | peerConnection.onicecandidate = ev => console.log(ev.type); 24 | peerConnection.onremovestream = ev => console.log(ev.type); 25 | peerConnection.onstatechange = ev => console.log(ev.type); 26 | 27 | peerConnection.createOffer( 28 | offer => { 29 | peerConnection.setLocalDescription(offer, 30 | () => console.log("set local description"), 31 | error => console.log("Error setting local description: " + error)); 32 | }, 33 | error => console.log("Error creating offer: " + error)); 34 | 35 | var type: RTCSdpType = RTCSdpType.offer; 36 | var offer: RTCSessionDescriptionInit = { type: type, sdp: "some sdp" }; 37 | var sessionDescription = new RTCSessionDescription(offer); 38 | 39 | peerConnection.setRemoteDescription(sessionDescription, () => { 40 | peerConnection.createAnswer( 41 | answer => { 42 | peerConnection.setLocalDescription(answer, 43 | () => console.log('Set local description'), 44 | error => console.log("Error setting local description from created answer: " + error + "; answer.sdp=" + answer.sdp)); 45 | }, 46 | error => console.log("Error creating answer: " + error)); 47 | }, 48 | error => console.log('Error setting remote description: ' + error + "; offer.sdp=" + offer.sdp)); 49 | 50 | var wkPeerConnection: webkitRTCPeerConnection = new webkitRTCPeerConnection(config, constraints); 51 | 52 | -------------------------------------------------------------------------------- /source/PubSub.ts: -------------------------------------------------------------------------------- 1 | /*! 2 | * Sococo.RTC (http://github.com/sococo/sococo-rtc/) 3 | * Copyright 2014 Social Communications Company 4 | * Licensed under MIT (https://github.com/sococo/sococo-rtc/blob/master/LICENSE) 5 | */ 6 | 7 | module SRTC { 8 | declare var Faye:any; 9 | declare var require:any; 10 | 11 | /** 12 | * Describe a simple pub/sub interface that can serve 13 | */ 14 | export interface IPubSub { 15 | connected:boolean; 16 | connect:(url:string,done?:(error?: any) => void) => any; 17 | disconnect:() => any; 18 | subscribe:(channel:string,process:(data:any) => void,done?:(error?:any) => void) => any; 19 | unsubscribe:(channel:string) => any; 20 | publish:(channel:string,data:any) => any; 21 | } 22 | 23 | export class FayePubSub implements IPubSub { 24 | private _faye:any = null; 25 | connected:boolean = false; 26 | private _assertValidConnection(){ 27 | if(!this._faye || !this.connected){ 28 | throw new Error("Must have a valid Faye connection before subscribing to a channel"); 29 | } 30 | } 31 | connect(url:string,done?:(error?: any) => void) { 32 | if(typeof Faye === 'undefined'){ 33 | Faye = require('faye'); 34 | } 35 | this._faye = new Faye.Client(url); 36 | this._faye.connect(() => { 37 | this.connected = true; 38 | done && done(); 39 | }); 40 | } 41 | disconnect() { 42 | if(this._faye){ 43 | this._faye.disconnect(); 44 | } 45 | this.connected = false; 46 | } 47 | subscribe(channel:string,process:(data:any) => void,done?:(error?:any) => void) { 48 | this._assertValidConnection(); 49 | var sub = this._faye.subscribe(channel,process); 50 | sub.callback(() => { 51 | done && done(); 52 | }); 53 | sub.errback(() => { 54 | done && done("Failed to subscribe to channel: " + channel); 55 | }); 56 | } 57 | unsubscribe(channel:string) { 58 | this._assertValidConnection(); 59 | this._faye.unsubscribe(channel); 60 | } 61 | publish(channel:string,data:any) { 62 | this._assertValidConnection(); 63 | this._faye.publish(channel,data); 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /types/angular/angular-route.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for Angular JS 1.2 (ngRoute module) 2 | // Project: http://angularjs.org 3 | // Definitions by: Jonathan Park 4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 5 | 6 | /// 7 | 8 | 9 | /////////////////////////////////////////////////////////////////////////////// 10 | // ngRoute module (angular-route.js) 11 | /////////////////////////////////////////////////////////////////////////////// 12 | declare module ng.route { 13 | 14 | /////////////////////////////////////////////////////////////////////////// 15 | // RouteParamsService 16 | // see http://docs.angularjs.org/api/ngRoute.$routeParams 17 | /////////////////////////////////////////////////////////////////////////// 18 | interface IRouteParamsService {} 19 | 20 | /////////////////////////////////////////////////////////////////////////// 21 | // RouteService 22 | // see http://docs.angularjs.org/api/ngRoute.$route 23 | // see http://docs.angularjs.org/api/ngRoute.$routeProvider 24 | /////////////////////////////////////////////////////////////////////////// 25 | interface IRouteService { 26 | reload(): void; 27 | routes: any; 28 | 29 | // May not always be available. For instance, current will not be available 30 | // to a controller that was not initialized as a result of a route maching. 31 | current?: ICurrentRoute; 32 | } 33 | 34 | // see http://docs.angularjs.org/api/ngRoute.$routeProvider#when for options explanations 35 | interface IRoute { 36 | controller?: any; 37 | controllerAs?: any; 38 | name?: string; 39 | template?: string; 40 | templateUrl?: any; 41 | resolve?: any; 42 | redirectTo?: any; 43 | reloadOnSearch?: boolean; 44 | caseInsensitiveMatch?: boolean; 45 | } 46 | 47 | // see http://docs.angularjs.org/api/ng.$route#current 48 | interface ICurrentRoute extends IRoute { 49 | locals: { 50 | $scope: IScope; 51 | $template: string; 52 | }; 53 | 54 | params: any; 55 | } 56 | 57 | interface IRouteProvider extends IServiceProvider { 58 | otherwise(params: any): IRouteProvider; 59 | /** 60 | * This is a description 61 | * 62 | */ 63 | when(path: string, route: IRoute): IRouteProvider; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sococo.RTC [![Build Status](https://travis-ci.org/sococo/sococo-rtc.svg?branch=master)](https://travis-ci.org/sococo/sococo-rtc) 2 | 3 | A simple prototype demonstrating how to build a dynamic WebRTC meeting application using 4 | Typescript, Angular.JS, and Heroku. 5 | 6 | > The main purpose of this application is demonstrate how to build a WebRTC application 7 | > that allows for dynamic stream property changes in a cross-browser way. 8 | 9 | ## When should I care about this? 10 | 11 | * When you do not have an existing signaling server 12 | * When you do not want to worry about scaling your server at the last moment 13 | * When you're curious about how to deal with Signal Glare 14 | * When you would like to use PubSub as a stateless signaling solution 15 | 16 | ## Building and running 17 | 18 | To build and run the project you'll need Node.JS with NPM installed on your system. Once 19 | you have node installed, simply install the application dependencies from the command line: 20 | 21 | > npm install 22 | 23 | Once the dependencies have been installed you can run the server: 24 | 25 | > node server.js 26 | 27 | If you wish to run the server in a node cluster, you will need to have support for some 28 | kind of Redis database, which is used by Faye to share information about connections. 29 | 30 | > node server-cluster.js 31 | 32 | If you are deploying to heroku and using RedisToGo or RedisCloud, you need to do nothing 33 | other than add them on your application. If you're using a custom setup, make sure you 34 | set an environment variable `REDIS_URL` to define the Redis connection URL. 35 | 36 | 37 | 38 | ## Developing 39 | 40 | This project uses Typescript to add static type checking while developing code, and produces 41 | optimized outputs to reduce page load times in the browser. When making changes to the styles 42 | or sources of this application you'll need to use grunt-js. 43 | 44 | If you do not have Grunt installed you may install it with the following command: 45 | 46 | > npm install -g grunt-cli 47 | 48 | Once you have grunt installed you may build the application with the grunt command, or start an 49 | automated build when files change by using the `develop` task, which will build the source files, 50 | start a watch server, and run the express application: 51 | 52 | > grunt develop 53 | 54 | ## Contributing Back 55 | 56 | Follow the [git commit conventions](https://github.com/sococo/sococo-rtc/blob/master/CONVENTIONS.md), and submit 57 | a pull request. 58 | -------------------------------------------------------------------------------- /CONVENTIONS.md: -------------------------------------------------------------------------------- 1 | This file is a copy of the file from [conventional-changelog](https://github.com/ajoslin/conventional-changelog/blob/master/CONVENTIONS.md) 2 | 3 | ## Git Commit Guidelines 4 | 5 | These rules are adopted from [the AngularJS commit conventions](https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/). 6 | 7 | ### Commit Message Format 8 | Each commit message consists of a **header**, a **body** and a **footer**. The header has a special 9 | format that includes a **type**, a **scope** and a **subject**: 10 | 11 | ``` 12 | (): 13 | 14 | 15 | 16 |