UNPKG

3.07 kBJavaScriptView Raw
1var grammar = require('./grammar');
2
3// customized util.format - discards excess arguments and can void middle ones
4var formatRegExp = /%[sdv%]/g;
5var format = function (formatStr) {
6 var i = 1;
7 var args = arguments;
8 var len = args.length;
9 return formatStr.replace(formatRegExp, function (x) {
10 if (i >= len) {
11 return x; // missing argument
12 }
13 var arg = args[i];
14 i += 1;
15 switch (x) {
16 case '%%':
17 return '%';
18 case '%s':
19 return String(arg);
20 case '%d':
21 return Number(arg);
22 case '%v':
23 return '';
24 }
25 });
26 // NB: we discard excess arguments - they are typically undefined from makeLine
27};
28
29var makeLine = function (type, obj, location) {
30 var str = obj.format instanceof Function ?
31 (obj.format(obj.push ? location : location[obj.name])) :
32 obj.format;
33
34 var args = [type + '=' + str];
35 if (obj.names) {
36 for (var i = 0; i < obj.names.length; i += 1) {
37 var n = obj.names[i];
38 if (obj.name) {
39 args.push(location[obj.name][n]);
40 }
41 else { // for mLine and push attributes
42 args.push(location[obj.names[i]]);
43 }
44 }
45 }
46 else {
47 args.push(location[obj.name]);
48 }
49 return format.apply(null, args);
50};
51
52// RFC specified order
53// TODO: extend this with all the rest
54var defaultOuterOrder = [
55 'v', 'o', 's', 'i',
56 'u', 'e', 'p', 'c',
57 'b', 't', 'r', 'z', 'a'
58];
59var defaultInnerOrder = ['i', 'c', 'b', 'a'];
60
61
62module.exports = function (session, opts) {
63 opts = opts || {};
64 // ensure certain properties exist
65 if (session.version == null) {
66 session.version = 0; // 'v=0' must be there (only defined version atm)
67 }
68 if (session.name == null) {
69 session.name = ' '; // 's= ' must be there if no meaningful name set
70 }
71 session.media.forEach(function (mLine) {
72 if (mLine.payloads == null) {
73 mLine.payloads = '';
74 }
75 });
76
77 var outerOrder = opts.outerOrder || defaultOuterOrder;
78 var innerOrder = opts.innerOrder || defaultInnerOrder;
79 var sdp = [];
80
81 // loop through outerOrder for matching properties on session
82 outerOrder.forEach(function (type) {
83 grammar[type].forEach(function (obj) {
84 if (obj.name in session && session[obj.name] != null) {
85 sdp.push(makeLine(type, obj, session));
86 }
87 else if (obj.push in session && session[obj.push] != null) {
88 session[obj.push].forEach(function (el) {
89 sdp.push(makeLine(type, obj, el));
90 });
91 }
92 });
93 });
94
95 // then for each media line, follow the innerOrder
96 session.media.forEach(function (mLine) {
97 sdp.push(makeLine('m', grammar.m[0], mLine));
98
99 innerOrder.forEach(function (type) {
100 grammar[type].forEach(function (obj) {
101 if (obj.name in mLine && mLine[obj.name] != null) {
102 sdp.push(makeLine(type, obj, mLine));
103 }
104 else if (obj.push in mLine && mLine[obj.push] != null) {
105 mLine[obj.push].forEach(function (el) {
106 sdp.push(makeLine(type, obj, el));
107 });
108 }
109 });
110 });
111 });
112
113 return sdp.join('\r\n') + '\r\n';
114};