$(function(){ showTab('login'); }); var settings = { credentials:{}, settings: {} }; var debug = false; function consolelog() { if (debug) { console.log.apply(console,arguments); } } function confirmDelete(question){ return confirm(question); } /** * Add thousand seperator to a number * @param number the number to format * @param seperator the seperator to use */ function seperateThousands(number,seperator){ if (isNaN(Number(number))) return number; number = number.toString().split('.'); var regex = /(\d+)(\d{3})/; while (regex.test(number[0])) { number[0] = number[0].replace(regex,'$1'+seperator+'$2'); } return number.join('.'); } /** * Format a date to mmm d yyyy, hh:mm:ss format * @param date the date to format (timestamp in seconds) */ function formatDateLong(date){ var d = new Date(date * 1000); return [ nameMonth(d.getMonth()), d.getDate(), d.getFullYear() ].join(' ') + ', ' + formatTime(date); } function nameMonth(monthNum){ months = Array('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'); return months[monthNum]; } function formatTime(date){ var d = new Date(date * 1000); return [ ('00' + d.getHours()).slice(-2), ('00' + d.getMinutes()).slice(-2), ('00' + d.getSeconds()).slice(-2) ].join(':'); } /** * Check if an URL points to a live datastream or a recorded file * @param url the url in question */ function isLive(url){ var protocol = /([a-zA-Z]+):\/\//.exec(url); if ((protocol === null) || ((protocol[1]) && (protocol[1] === 'file'))) { return false; } else { return true; } } /** * parses an url and returns the parts of it. * @return object containing the parts of the URL: protocol, host and port. */ function parseURL(url) { var pattern = /(https?)\:\/\/([^:\/]+)\:(\d+)?/i; var retobj = {protocol: '', host: '', port: ''}; var results = url.match(pattern); if(results != null) { retobj.protocol = results[1]; retobj.host = results[2]; retobj.port = results[3]; } return retobj; } /** * Return html describing the status of the stream or protocol * @param theStream the stream or protocol object in question */ function formatStatus(theStream) { if (theStream.online == undefined) { return $('').text('Unknown, checking..'); } if (theStream.error == undefined) { switch (theStream.online) { case -1: return $('').text('Unknown, checking..'); break; case 0: return $('').addClass('red').text('Unavailable'); break; case 1: return $('').addClass('green').text('Active'); break; case 2: return $('').addClass('orange').text('Inactive'); break; default: return $('').text(theStream.online); break; } } else { switch (theStream.online) { case -1: return $('').text('Unknown, checking..'); break; case 0: return $('').addClass('red').text(theStream.error); break; case 1: return $('').addClass('green').text(theStream.error); break; case 2: return $('').addClass('orange').text(theStream.error); break; default: return $('').text(theStream.error); break; } } } /** * Apply entered data in input and select fields to their corresponding object adress */ function applyInput(){ //check if all required fields have something in them $('#input-validation-info').remove(); var error = false; $('input.isSetting.validate-required').each(function(){ if ($(this).val() == '') { $(this).focus(); $(this).parent().append( $('
').attr('id','input-validation-info').html( 'This is a required field.' ).addClass('red') ); error = true; return false; } }); if (error == true) { return false; } //apply the inputs $('input.isSetting,select.isSetting').each(function(){ var objpath = findObjPath($(this)); if ($(this).val() == '') { eval('delete '+objpath+';'); } else { eval(objpath+' = $(this).val();'); } }); return true; } /** * Apply data from the settings object to the page elements */ //this function has been placed in footer.html /** * Find the path to the setting for this element */ function findObjPath($element) { if ($element.attr('objpath')) { return 'settings.'+$element.attr('objpath'); } else { return 'settings.'+$element.attr('id').replace(/-/g,'.'); } } function getData(callBack,sendData,timeOut,doShield){ timeOut = timeOut | 30000; var data = {}; data.authorize = $.extend(true,{},settings.credentials); delete data.authorize.authstring; data.authorize.password = settings.credentials.authstring ? MD5(MD5(settings.credentials.password)+settings.credentials.authstring) : ''; $.extend(true,data,sendData); consolelog('['+(new Date).toTimeString().split(' ')[0]+']','Sending data:',data); $('#message').removeClass('red').text('Data sent, waiting for a reply..').append( $('
') ).append( $('').text('Cancel request').click(function(){ jqxhr.abort(); }) ); if (doShield) { $('body').append( $('
').attr('id', 'shield').text('Loading, please wait..') ); } var obj = { 'url': settings.server, 'type': 'POST', 'data': { 'command': JSON.stringify(data) }, 'dataType': 'jsonp', 'crossDomain': true, 'timeout': timeOut, 'error':function(jqXHR,textStatus,errorThrown){ switch (textStatus) { case 'timeout': textStatus = $('').text('The connection timed out. '); break; case 'abort': textStatus = $('').text('The connection was aborted. '); break; default: textStatus = $('').text(textStatus+'. ').css('text-transform','capitalize'); } $('#message').addClass('red').text('An error occurred while attempting to communicate with MistServer:').append( $('
') ).append( textStatus ).append( $('
').text('Send server request again').click(function(){ getData(callBack,sendData,timeOut,doShield); }) ); $('#shield').remove(); }, 'success': function(returnedData){ $('#message').text('Data received, processing..'); consolelog('['+(new Date).toTimeString().split(' ')[0]+']','Received data:',returnedData); if ((returnedData) && (returnedData.authorize)) { if (returnedData.authorize.challenge){ if (settings.credentials.authstring != returnedData.authorize.challenge){ if (returnedData.authorize.status == 'ACC_MADE') { delete settings.credentials.new_password; delete settings.credentials.new_username; $('#page').html( $('
').addClass('description').text('Account made! Logging in..') ); } else { $('#page').html( $('
').addClass('description').text('Logging in..') ); } settings.credentials.authstring = returnedData.authorize.challenge; getData(callBack,sendData,timeOut); return; } else { $('#message').addClass('red').text('The credentials you provided are incorrect.'); $('#connection').addClass('red').removeClass('green').text('Disconnected'); showTab('login'); $('#shield').remove(); return; } } else if (returnedData.authorize.status == 'NOACC') { $('#message').addClass('red').text('The server does not have any accounts set.'); $('#connection').addClass('green').removeClass('red').text('Connected'); showTab('create new account'); $('#shield').remove(); return; } else { $('#connection').addClass('green').removeClass('red').text('Connected'); } } if (callBack) { callBack(returnedData); } $('#message').text('Last communication with the server at '+formatTime((new Date).getTime()/1000)); if (returnedData.log) { var lastlog = returnedData.log[returnedData.log.length-1]; $('#message').append( $('
') ).append( $('').text('Last log entry: '+formatTime(lastlog[0])+' ['+lastlog[1]+'] '+lastlog[2]) ); } $('#shield').remove(); } }; var jqxhr = $.ajax(obj); } function saveAndReload(tabName){ var sendData = $.extend(true,{},settings.settings); delete sendData.logs; delete sendData.statistics; if (settings.credentials.authstring) { sendData.capabilities = true; sendData = $.extend(true,{conversion: {'encoders': true, 'status': true}},sendData); } getData(function(returnedData){ settings.settings = returnedData; if (tabName) { showTab(tabName); } },sendData,0,true); } var countrylist = {'AF':'Afghanistan','AX':'Åland Islands','AL':'Albania','DZ':'Algeria','AS':'American Samoa','AD':'Andorra', 'AO':'Angola','AI':'Anguilla','AQ':'Antarctica','AG':'Antigua and Barbuda','AR':'Argentina','AM':'Armenia','AW':'Aruba', 'AU':'Australia','AT':'Austria','AZ':'Azerbaijan','BS':'Bahamas','BH':'Bahrain','BD':'Bangladesh','BB':'Barbados', 'BY':'Belarus','BE':'Belgium','BZ':'Belize','BJ':'Benin','BM':'Bermuda','BT':'Bhutan','BO':'Bolivia, Plurinational State of', 'BQ':'Bonaire, Sint Eustatius and Saba','BA':'Bosnia and Herzegovina','BW':'Botswana','BV':'Bouvet Island','BR':'Brazil', 'IO':'British Indian Ocean Territory','BN':'Brunei Darussalam','BG':'Bulgaria','BF':'Burkina Faso','BI':'Burundi','KH':'Cambodia', 'CM':'Cameroon','CA':'Canada','CV':'Cape Verde','KY':'Cayman Islands','CF':'Central African Republic','TD':'Chad','CL':'Chile', 'CN':'China','CX':'Christmas Island','CC':'Cocos (Keeling) Islands','CO':'Colombia','KM':'Comoros','CG':'Congo', 'CD':'Congo, the Democratic Republic of the','CK':'Cook Islands','CR':'Costa Rica','CI':'Côte d\'Ivoire','HR':'Croatia', 'CU':'Cuba','CW':'Curaçao','CY':'Cyprus','CZ':'Czech Republic','DK':'Denmark','DJ':'Djibouti','DM':'Dominica', 'DO':'Dominican Republic','EC':'Ecuador','EG':'Egypt','SV':'El Salvador','GQ':'Equatorial Guinea','ER':'Eritrea','EE':'Estonia', 'ET':'Ethiopia','FK':'Falkland Islands (Malvinas)','FO':'Faroe Islands','FJ':'Fiji','FI':'Finland','FR':'France','GF':'French Guiana', 'PF':'French Polynesia','TF':'French Southern Territories','GA':'Gabon','GM':'Gambia','GE':'Georgia','DE':'Germany','GH':'Ghana', 'GI':'Gibraltar','GR':'Greece','GL':'Greenland','GD':'Grenada','GP':'Guadeloupe','GU':'Guam','GT':'Guatemala','GG':'Guernsey', 'GN':'Guinea','GW':'Guinea-Bissau','GY':'Guyana','HT':'Haiti','HM':'Heard Island and McDonald Islands', 'VA':'Holy See (Vatican City State)','HN':'Honduras','HK':'Hong Kong','HU':'Hungary','IS':'Iceland','IN':'India','ID':'Indonesia', 'IR':'Iran, Islamic Republic of','IQ':'Iraq','IE':'Ireland','IM':'Isle of Man','IL':'Israel','IT':'Italy','JM':'Jamaica', 'JP':'Japan','JE':'Jersey','JO':'Jordan','KZ':'Kazakhstan','KE':'Kenya','KI':'Kiribati', 'KP':'Korea, Democratic People\'s Republic of','KR':'Korea, Republic of','KW':'Kuwait','KG':'Kyrgyzstan', 'LA':'Lao People\'s Democratic Republic','LV':'Latvia','LB':'Lebanon','LS':'Lesotho','LR':'Liberia','LY':'Libya', 'LI':'Liechtenstein','LT':'Lithuania','LU':'Luxembourg','MO':'Macao','MK':'Macedonia, the former Yugoslav Republic of', 'MG':'Madagascar','MW':'Malawi','MY':'Malaysia','MV':'Maldives','ML':'Mali','MT':'Malta','MH':'Marshall Islands', 'MQ':'Martinique','MR':'Mauritania','MU':'Mauritius','YT':'Mayotte','MX':'Mexico','FM':'Micronesia, Federated States of', 'MD':'Moldova, Republic of','MC':'Monaco','MN':'Mongolia','ME':'Montenegro','MS':'Montserrat','MA':'Morocco','MZ':'Mozambique', 'MM':'Myanmar','NA':'Namibia','NR':'Nauru','NP':'Nepal','NL':'Netherlands','NC':'New Caledonia','NZ':'New Zealand','NI':'Nicaragua', 'NE':'Niger','NG':'Nigeria','NU':'Niue','NF':'Norfolk Island','MP':'Northern Mariana Islands','NO':'Norway','OM':'Oman', 'PK':'Pakistan','PW':'Palau','PS':'Palestine, State of','PA':'Panama','PG':'Papua New Guinea','PY':'Paraguay','PE':'Peru', 'PH':'Philippines','PN':'Pitcairn','PL':'Poland','PT':'Portugal','PR':'Puerto Rico','QA':'Qatar','RE':'Réunion', 'RO':'Romania','RU':'Russian Federation','RW':'Rwanda','BL':'Saint Barthélemy','SH':'Saint Helena, Ascension and Tristan da Cunha', 'KN':'Saint Kitts and Nevis','LC':'Saint Lucia','MF':'Saint Martin (French part)','PM':'Saint Pierre and Miquelon', 'VC':'Saint Vincent and the Grenadines','WS':'Samoa','SM':'San Marino','ST':'Sao Tome and Principe','SA':'Saudi Arabia', 'SN':'Senegal','RS':'Serbia','SC':'Seychelles','SL':'Sierra Leone','SG':'Singapore','SX':'Sint Maarten (Dutch part)','SK':'Slovakia', 'SI':'Slovenia','SB':'Solomon Islands','SO':'Somalia','ZA':'South Africa','GS':'South Georgia and the South Sandwich Islands', 'SS':'South Sudan','ES':'Spain','LK':'Sri Lanka','SD':'Sudan','SR':'Suriname','SJ':'Svalbard and Jan Mayen','SZ':'Swaziland', 'SE':'Sweden','CH':'Switzerland','SY':'Syrian Arab Republic','TW':'Taiwan, Province of China','TJ':'Tajikistan', 'TZ':'Tanzania, United Republic of','TH':'Thailand','TL':'Timor-Leste','TG':'Togo','TK':'Tokelau','TO':'Tonga', 'TT':'Trinidad and Tobago','TN':'Tunisia','TR':'Turkey','TM':'Turkmenistan','TC':'Turks and Caicos Islands','TV':'Tuvalu', 'UG':'Uganda','UA':'Ukraine','AE':'United Arab Emirates','GB':'United Kingdom','US':'United States', 'UM':'United States Minor Outlying Islands','UY':'Uruguay','UZ':'Uzbekistan','VU':'Vanuatu','VE':'Venezuela, Bolivarian Republic of', 'VN':'Viet Nam','VG':'Virgin Islands, British','VI':'Virgin Islands, U.S.','WF':'Wallis and Futuna','EH':'Western Sahara','YE':'Yemen', 'ZM':'Zambia','ZW':'Zimbabwe' }; function updateOverview() { getData(function(data){ var viewers = 0; var streams = 0; var streamsOnline = 0; for (var index in data.statistics) { if (data.statistics[index].curr) { for (viewer in data.statistics[index].curr) { viewers++; } } } for (var index in data.streams) { streams++; if ((data.streams[index].online) && (data.streams[index].online != 0)) { streamsOnline++; } } $('#cur_streams_online').text(streamsOnline+'/'+streams+' online'); $('#cur_num_viewers').text(seperateThousands(viewers,' ')); $('#settings-config-time').text(formatDateLong(data.config.time)); }); } function updateProtocols() { getData(function(data){ if (!data.config.protocols) { data.config.protocols = []; } if (data.config.protocols.length != $('#protocols-tbody').children().length) { saveAndReload('protocols'); return; } for (var index in data.config.protocols) { $('#status-of-'+index).html(formatStatus(data.config.protocols[index])) } }); } function displayProtocolSettings(theProtocol) { var capabilities = settings.settings.capabilities.connectors[theProtocol.connector]; var settingsList = []; for (var index in capabilities.required) { if ((theProtocol[index]) && (theProtocol[index] != '')) { settingsList.push(index+': '+theProtocol[index]); } else { if (capabilities.required[index]['default']) { settingsList.push(index+': '+capabilities.required[index]['default']); } } } for (var index in capabilities.optional) { if ((theProtocol[index]) && (theProtocol[index] != '')) { settingsList.push(index+': '+theProtocol[index]); } else { if (capabilities.optional[index]['default']) { settingsList.push(index+': '+capabilities.optional[index]['default']); } } } return settingsList.join(', '); } function buildProtocolFields(selectedProtocol,objpath,streamName) { data = settings.settings.capabilities.connectors[selectedProtocol]; $('#protocol-description').html(data.desc); if (data.deps) { $ul = $('
    '); $('#protocol-description').append('
    Dependencies:').append($ul); var dependencies = data.deps.split(','); for (var index in dependencies) { if ($.inArray(dependencies[index],currentConnectors) < 0) { $ul.append( $('
  • ').text(dependencies[index]).append( $('').text(' (Not yet configured)').addClass('red') ) ); } else { $ul.append( $('
  • ').text(dependencies[index]).append( $('').text(' (Configured)').addClass('green') ) ); } } } $('#protocol-fields').html(''); if (data.required) { $('#protocol-fields').append( $('

    ').text('Required parameters') ).append( buildProtocolParameterFields(data.required,true,objpath) ); } if (data.optional) { $('#protocol-fields').append( $('

    ').text('Optional parameters') ).append( buildProtocolParameterFields(data.optional,false,objpath) ); } if ((streamName != '_new_') && (selectedProtocol == settings.settings.config.protocols[streamName].connector)) { enterSettings(); } } function buildProtocolParameterFields(data,required,objpath) { var $container = $('

    '); for (var index in data) { var $label = $('