').attr('id', 'forcesave');
forcesave.append(
$('
').text('Click the button below to force an immediate settings save. This differs from a regular save to memory and file save on exit by saving directly to file while operating. This may slow server processes for a short period of time.')
).append(
$('').click(function()
{
if(confirmDelete('Are you sure you want to force a JSON save?') == true)
{
forceJSONSave();
}
}).text( 'force save to JSON file' )
);
$('#page').append(forcesave);
break;
case 'protocols':
$table = $('');
$table.html("Protocol Status Settings ");
$tbody = $('');
var tr, i, protocol,
len = (settings.settings.config.protocols ? settings.settings.config.protocols.length : 0);
$tbody.html('');
pids = [];
for(i = 0; i < len; i++)
{
protocol = settings.settings.config.protocols[i]; // local copy
pids.push(i);
tr = $('').attr('id', 'protocol-' + i);
tr.append( $('').text( protocol.connector ) );
tr.append( $(' ').html( formatStatus( protocol.online ) ) );
s = "";
for (option in protocol)
{
if ((option != 'connector') && (option != 'online'))
{
s += option+': '+((protocol[option] == '') || (protocol[option] == 0) ? 'default' : protocol[option] )+', ';
}
}
s = s.slice(0,-2);
tr.append( $(' ').text( s ) );
tr.append( $(' ').attr('class', 'center').append( $('').text('edit').click(function()
{
id = $(this).parent().parent().attr('id').replace('protocol-', '');
showTab('editprotocol', id);
}) ).append( $('').click(function()
{
if(confirmDelete('Are you sure you want to delete this protocol?') == true)
{
var id = Number($(this).parent().parent().attr('id').replace('protocol-', ''));
var pid = pids.indexOf(id);
settings.settings.config.protocols.splice(pid, 1);
showTab('protocols');
}
}).text('delete') ) );
$tbody.append(tr);
}
$table.append($tbody);
$('#page').append($table);
$('#page').append(
$('').attr('class', 'floatright').click(function()
{
showTab('editprotocol', 'new');
}).text('add new')
);
function refreshProtocolStatus()
{
getData(function(data)
{
$('tbody tr').each(function()
{
protocolstatus = null;
pid = $(this).attr('id').split('-')[1];
if (data.config.protocols[pid] == undefined)
{
protocolstatus = 'Protocol config missing.. reloading tab';
showTab('protocol');
}
else {
if (data.config.protocols[pid].online == undefined)
{
setTimeout(function()
{
refreshProtocolStatus();
},1000);
}
protocolstatus = data.config.protocols[pid].online;
}
$(this).children()[1].innerHTML = formatStatus( protocolstatus );
});
});
}
pinterval = setInterval(function()
{
refreshProtocolStatus();
},10000);
refreshProtocolStatus();
break;
case 'editprotocol':
if (streamname != 'new')
{
currentdata = settings.settings.config.protocols[streamname];
}
currentconnectors = [];
// build a list of the current connectors to see if the dependencies are already configured
for (var index in settings.settings.config.protocols)
{
currentconnectors.push(settings.settings.config.protocols[index].connector);
}
function buildProtocolParameterFields(data,required)
{
for (fieldname in data)
{
switch(data[fieldname].type)
{
case 'str':
var inputType = 'text'
break;
case 'uint':
var inputType = 'number'
var func = 'uint'
break;
case 'int':
var inputType = 'number'
break;
}
$i = $(' ').attr('type',inputType).attr('id','protocol-parameter-'+fieldname);
if (func == 'uint')
{
$i.addClass('uint');
}
if (required)
{
$i.addClass('required');
}
$protocolfields.append(
$('').text(data[fieldname].name).attr('title',data[fieldname].help).append($i)
);
}
}
function buildProtocolFields(selectedProtocol)
{
data = settings.settings.capabilities.connectors[selectedProtocol];
$t = $('').text(data.desc);
if ((typeof data.deps != 'undefined') && (data.deps))
{
$t.append($('
').text('Dependencies:'));
$s = $('
');
deps = data.deps.split(',');
for (var index in deps)
{
t = deps[index];
if ($.inArray(deps[index],currentconnectors) < 0)
{
$u = $('').text(' (Not yet configured!)').addClass('red');
}else{
$u = $('').text(' (Configured)').addClass('green');
}
$s.append($('').text(t).append($u));
}
$t.append($s);
}
$('#protocoldesc').html( $t );
$protocolfields = $('');
if (typeof data.required != 'undefined')
{
$protocolfields.append( $('
').text('Required parameters') );
buildProtocolParameterFields(data.required,true);
}
if (typeof data.optional != 'undefined')
{
$protocolfields.append( $('
').text('Optional parameters') );
buildProtocolParameterFields(data.optional,false);
}
$('#protocolfields').html($protocolfields);
if (streamname != 'new')
{
for (fieldname in currentdata)
{
if ((fieldname != 'connector') && (fieldname != 'online'))
{
$('#protocol-parameter-'+fieldname).val(currentdata[fieldname]);
}
}
}
}
loadSettings(function()
{
if (streamname == 'new') { t = 'add new protocol'; }
else { t = 'edit protocol'; }
$('#page').append( $('
').text(t) );
$selectprotocol = $('').attr('id', 'edit-protocol').change(function()
{
buildProtocolFields($(this).children(':selected').val());
});
for(protocol in settings.settings.capabilities.connectors)
{
if ((streamname != 'new') && (currentdata.connector == protocol)) {
$selectprotocol.append(
$('').attr('value', protocol).attr('selected','selected').text(protocol)
);
}else{
$selectprotocol.append(
$(' ').attr('value', protocol).text(protocol)
);
}
}
$div = $('').attr('id', 'editprotocol');
$div.append(
$('
').attr('for', 'protocol-edit-protocol').text('protocol').append(
$selectprotocol
)
);
$('#page').append( $div );
$('#editprotocol').append( $('').attr('id','protocoldesc') );
$('#editprotocol').append( $('
').attr('id', 'protocolfields') );
$('#editprotocol').append(
$('
').text('cancel').addClass('floatright').click(function()
{
showTab('protocols');
})
);
$('#editprotocol').append(
$('').text('save').addClass('floatright').click(function()
{
error = false;
//check if all required fields have contents
$('input.required').each(function()
{
if ($(this).val() == '')
{
$(this).focus();
$(this).parent().addClass('red');
error = true;
}
});
$('input[type="number"]').each(function()
{
//make sure this is a number
if (isNaN($(this).val()))
{
$(this).focus();
$(this).parent().addClass('red');
error = true;
}
else
{
//turn all numbers into integers
$(this).val(Math.floor($(this).val()));
}
});
//check if all uints are actually uints
$('input.uint').each(function()
{
if ($(this).val() < 0)
{
$(this).focus();
$(this).parent().addClass('red');
error = true;
}
});
if (error) { return; }
if(!settings.settings.config.protocols)
{
settings.settings.config.protocols = [];
}
connectorval = $('#edit-protocol').val()
var newprotocol =
{
connector: connectorval
};
$('input').each(function(){
newprotocol[$(this).attr('id').split('-')[2]] = $(this).val();;
});
if (streamname == 'new') {
settings.settings.config.protocols.push(newprotocol);
}else{
settings.settings.config.protocols[streamname] = newprotocol;
}
loadSettings(function()
{
showTab('protocols');
});
})
);
buildProtocolFields($('select#edit-protocol :selected').val());
});
break;
case 'streams':
// the filter element containr
$div = $('').attr('id', 'streams-filter');
// filters the table. uses the streamsdisplay
function filterTable()
{
$('#streams-list-tbody').children().each(function(k, v)
{
var type = $($(v).children()[0]).text().toLowerCase();
$(v).show();
if(type == 'recorded' && streamsdisplay[0] == false)
{
$(v).hide();
}
if(type == 'live' && streamsdisplay[1] == false)
{
$(v).hide();
}
});
}
function filterOn(event, elem)
{
if(event.target.id == '')
{
return; // label click goes bubbles on checkbox, so ignore it
}
var what = $(elem).text();
if(what == 'recorded')
{
streamsdisplay[0] = !streamsdisplay[0];
$('#stream-filter-recorded').attr('checked', streamsdisplay[0]);
}else{
streamsdisplay[1] = !streamsdisplay[1];
$('#stream-filter-live').attr('checked', streamsdisplay[1]);
}
filterTable();
}
$div.append(
$('
').attr('for', 'stream-filter-recorded').text('recorded').append(
$(' ').attr('type', 'checkbox').attr('id', 'stream-filter-recorded').attr('checked', streamsdisplay[0])
).click(function(event)
{
filterOn(event, this);
})
);
$div.append(
$('').attr('for', 'stream-filter-live').text('live').append(
$(' ').attr('type', 'checkbox').attr('id', 'stream-filter-live').attr('checked', streamsdisplay[1])
).click(function(event)
{
filterOn(event, this);
})
);
$('#page').append($div);
// refresh every streams' data (status and viewer count)
function refreshStreams()
{
getStreamsData(function(streams)
{
$('tbody#streams-list-tbody tr').each(function()
{
streamstatus = null;
stream = $(this).attr('id').split('-')[1];
if (streams[stream] == undefined)
{
streamstatus = 'Stream config missing - reloading tab';
showTab('streams');
}
else
{
streamstatus = streams[stream][0];
}
$(this).children()[4].innerHTML = formatStatus(streamstatus);
$(this).children()[5].innerHTML = streams[stream][1];
});
});
};
sinterval = setInterval(function()
{
refreshStreams();
}, 10000);
refreshStreams();
$table = $('');
$table.html("Id Type Embed Name Status Viewers Edit ");
$tbody = $('');
var stream, cstr, $tr;
$tbody.html('').attr('id', 'streams-list-tbody');
for(stream in settings.settings.streams)
{
//if sid does not yet exist, create it
if (settings.settings.streams[stream].sid == undefined)
{
sid = 0;
for (strm in settings.settings.streams)
{
if (settings.settings.streams[strm].sid != undefined)
{
sid = Math.max(sid,settings.settings.streams[strm].sid);
}
}
sid += 1;
settings.settings.streams[stream].sid = sid;
}
var cstr = settings.settings.streams[stream];
$tr = $('').attr('id', 'stream-' + stream);
$tr.append( $('').text( cstr.sid ) );
$tr.append( $(' ').text( TypeofResource( cstr.channel.URL ) ) );
$tr.append( $(' ').append( $('').text('embed').click(function()
{
var sname = $(this).parent().parent().attr('id').replace('stream-', '');
showTab('embed', sname);
}) ) ); // end function, end click(), end append(), end append(). Huzzah jQuery.
$tr.append( $('').text( cstr.name ) );
$tr.append( $(' ').html( formatStatus( cstr.online ) ) );
var cviewers = 0;
if(settings.settings.statistics && settings.settings.statistics[stream])
{
if(settings.settings.statistics[stream] && settings.settings.statistics[stream].curr)
{
for(viewer in settings.settings.statistics[stream].curr)
{
cviewers++;
}
}
}else{
cviewers = 0;
}
$tr.append( $(' ').text( cviewers ) );
$tr.append( $(' ').append( $('').text('edit').click(function()
{
var sname = $(this).parent().parent().attr('id').replace('stream-', '');
showTab('editstream', sname);
}) ) ); // end function, end click, end append, end append.
$tbody.append($tr);
//quickly re-check if the streams are online now
if (cstr.online == undefined)
{
setTimeout(function()
{
refreshStreams();
}, 1000);
}
}
$table.append($tbody).addClass('sortable');
$table.stupidtable();
$('#page').append($table);
// on page load, also filter with the (users' defined) stream filter
filterTable();
$('#page').append(
$('').attr('class', 'floatright').click(function()
{
showTab('editstream', 'new');
}).text('add new')
);
break;
case 'editstream':
var sdata, title;
if(streamname == 'new')
{
sdata =
{
name: '',
channel:
{
URL: ''
},
limits: [],
preset:
{
cmd: ''
}
};
title = 'add new stream';
}else{
sdata = settings.settings.streams[streamname];
title = 'edit stream "' + sdata.name + '"';
}
$('#page').append( $('').text(title) );
$('#page').append(
$('
').attr('id', 'editserver').append(
$('
').attr('for', 'stream-edit-name').text('name').append(
$(' ').attr('type', 'text').attr('placeholder', 'NAME').attr('id', 'stream-edit-name').attr('value', sdata.name)
)
).append(
$('').attr('for', 'stream-edit-source').text('source').append(
$(' ').attr('type', 'text').attr('placeholder', 'SOURCE').attr('id', 'stream-edit-source').attr('value', sdata.channel.URL).keyup(function()
{
var text = $(this).val();
if(text.charAt(0) == '/' || text.substr(0, 7) == 'push://')
{
$('#stream-edit-preset').val('');
$('#stream-edit-preset').hide();
$('#stream-edit-preset-label').hide();
}else{
$('#stream-edit-preset').show();
$('#stream-edit-preset-label').show();
}
})
)
).append(
$('').attr('id', 'stream-edit-preset-label').attr('for', 'stream-edit-preset').text('preset').append(
$(' ').attr('type', 'text').attr('placeholder', 'PRESET').attr('id', 'stream-edit-preset').attr('value', sdata.preset.cmd)
)
)
);
// if the source is push or file, don't do a preset
var text = $('#stream-edit-source').val();
if(text.charAt(0) == '/' || text.substr(0, 7) == 'push://')
{
$('#stream-edit-preset').hide();
$('#stream-edit-preset-label').hide();
}else{
$('#stream-edit-preset').show();
$('#stream-edit-preset-label').show();
}
$('#editserver').append(
$('').attr('class', 'floatright').click(function()
{
if(streamname == 'new')
{
showTab('streams');
}else{
if(confirmDelete('Are you sure you want to delete the stream "' + settings.settings.streams[streamname].name + '"?') == true)
{
delete settings.settings.streams[streamname];
loadSettings(function()
{
showTab('streams');
});
}
}
}).text( streamname == 'new' ? 'cancel' : 'delete' )
);
$('#editserver').append(
$('').attr('class', 'floatright').click(function()
{
var n = $('#stream-edit-name');
var s = $('#stream-edit-source');
var p = $('#stream-edit-preset');
if(n.val() == ''){ n.focus(); return; }
if(s.val() == ''){ s.focus(); return; }
var newname = n.val().replace(/([^a-zA-Z0-9_])/g, '').toLowerCase();
sdata.name = newname;
sdata.channel.URL = s.val();
sdata.preset.cmd = p.val();
if(streamname == 'new')
{
streamname = newname;
sdata.sid = 0;
for (strm in settings.settings.streams)
{
sdata.sid = Math.max(sdata.sid,settings.settings.streams[strm].sid);
}
sdata.sid += 1;
}
else
{
sdata.sid = settings.settings.streams[streamname].sid;
}
if(!settings.settings.streams)
{
settings.settings.streams = {};
}
delete settings.settings.streams[streamname];
settings.settings.streams[newname] = sdata;
loadSettings(function()
{
showTab('streams');
});
}).text('save')
);
break;
case 'embed':
if(isThereAHTTPConnector())
{
var embedbase = 'http://' + parseURL(settings.server).host + ':' + getHTTPControllerPort() + '/';
$('#page').append( $('').attr('class', 'nocapitals').text('The info embed URL is "' + embedbase + 'info_' + streamname + '.js".') );
$('#page').append( $('
').attr('class', 'nocapitals').text('The embed embed URL is "' + embedbase + 'embed_' + streamname + '.js".') );
$('#page').append( $('').text('preview').click(function()
{
showTab('preview', streamname);
} ) );
}else{
$('#page').append( $('').attr('class', 'nocapitals').text('Could\'t find a HTTP connector. Please add a HTTP connector on the "protocol" page.') );
}
break;
case 'preview':
var embed = 'http://' + parseURL(settings.server).host + ':' + getHTTPControllerPort() + '/embed_' + streamname + '.js';
$('#page').append( $('
').attr('id', 'previewcontainer') );
// jQuery doesn't work -> use DOM magic
var script = document.createElement('script');
script.src = embed;
document.getElementById('previewcontainer').appendChild( script );
break;
case 'limits':
$table = $('
');
$table.html("Type Hard/soft Value applies to Action ");
$tbody = $('');
var i, tr, limit, stream, clims,
alllimits = settings.settings.config.limits;
for(stream in settings.settings.streams)
{
clims = settings.settings.streams[stream].limits;
$.each(clims, function(k, v)
{
this.appliesto = stream;
this.appliesi = k;
});
alllimits = alllimits.concat(clims);
}
len = alllimits.length;
// remove old items
$tbody.html('');
for(i = 0; i < len; i++)
{
tr = $('').attr('id', 'limits-' + i);
limit = alllimits[i];
tr.append( $('').text( shortToLongLimit(limit.name) ) );
tr.append( $(' ').text( limit.type ) );
tr.append( $(' ').text( limit.val ) );
if(limit.appliesto)
{
tr.append( $(' ').text( settings.settings.streams[limit.appliesto].name ).attr('id', 'limit-at-' + limit.appliesto + '-' + limit.appliesi) );
}else{
tr.append( $(' ').text( 'server' ) );
}
delete limit.appliesto;
delete limit.appliesi;
tr.append( $(' ').attr('class', 'center').append( $('').click(function()
{
if(confirmDelete('Are you sure you want to delete this limit?') == true)
{
var id = $(this).parent().parent().attr('id').replace('limits-', '');
var at = $($(this).parent().parent().children()[3]).attr('id');
if(at == undefined)
{
settings.settings.config.limits.splice(id, 1);
}else{
var data = at.replace('limit-at-', '').split('-');
var loc = data.pop();
data = data.join('-');
settings.settings.streams[data].limits.splice(loc, 1);
}
$(this).parent().parent().remove();
loadSettings();
}
}).text('delete') ) );
$tbody.append(tr);
}
// add new limit
$nltr = $('').attr('class', 'outsidetable');
// type selector
$ltype = $('').attr('id', 'new-limit-type');
for(i = 0; i < ltypes.length; i++)
{
$ltype.append( $('').attr('value', ltypes[i][0]).text(ltypes[i][1]) );
}
$nltr.append( $('').append( $ltype ) );
// hard/soft limit
$nltr.append( $(' ').append( $('').attr('id', 'new-limit-hs').append( $('').attr('value', 'hard').text('Hard limit') ).append( $(' ').attr('value', 'soft').text('Soft limit') ) ) );
// value
$nltr.append( $('').append( $(' ').attr('type', 'text').attr('id', 'new-limit-val') ) );
// applies to (stream)
var $appliesto = $('').attr('id', 'new-limit-appliesto').append( $('').attr('value', 'server').text('Server') );
for(var strm in settings.settings.streams)
{
$appliesto.append(
$(' ').attr('value', strm).text(settings.settings.streams[strm].name)
);
}
$nltr.append( $('').append( $appliesto ) );
$nltr.append(
$(' ').attr('class', 'center').append(
$('').click(function()
{
var obj =
{
name: $('#new-limit-type :selected').val(),
type: $('#new-limit-hs :selected').val(),
val: $('#new-limit-val').val()
};
if( $('#new-limit-appliesto').val() == 'server')
{
settings.settings.config.limits.push(obj);
}else{
settings.settings.streams[ $('#new-limit-appliesto').val() ].limits.push(obj);
}
loadSettings(function()
{
showTab('limits');
});
}).text('add new')
)
);
$tbody.append($nltr);
$table.append($tbody);
$('#page').append($table);
break;
case 'logs':
$table = $('');
$table.html("Date(MM/DD/YYYY) Type Message ");
$tbody = $('');
if(!settings.settings.log)
{
return; // no logs, so just bail
}
var i, cur, $tr,
logs = settings.settings.log,
len = logs.length;
if(len >= 2 && settings.settings.log[0][0] < settings.settings.log[len - 1][0])
{
logs.reverse();
}
$tbody.html('');
for(i = 0; i < len; i++)
{
cur = settings.settings.log[i];
$tr = $('').append(
$('').text(formatDate(cur[0]))
).append(
$(' ').text(cur[1])
).append(
$(' ').text(cur[2])
);
$tbody.append($tr);
}
$table.append($tbody);
$('#page').append($table);
$('#page').append(
$('').attr('class', 'floatright').click(function()
{
settings.settings.clearstatlogs = 1;
loadSettings(function()
{
showTab('logs');
});
}).text('Purge logs')
);
break;
case 'disconnect':
showTab('login');
setHeaderState('disconnected');
$('#nav').css('visibility', 'hidden');
settings =
{
server: '',
credentials:
{
username: "",
password: "",
authstring: ""
},
settings: {}
};
break;
} // end switch
//placeholder for older browsers
$('input[placeholder]').placeholder();
}