streamsetting.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. function showErrorSections() {
  2. $(".errors").each(function(i){
  3. if($(this).length > 0){
  4. var div = $(this).closest("div")
  5. if(div.attr('class') == "stream-setting-content"){
  6. $(this).closest("div").show();
  7. $(this).closest("fieldset").removeClass('closed');
  8. $(window).scrollTop($(this).closest("div").position().top);
  9. }
  10. }
  11. });
  12. }
  13. function rebuildStreamURL(ele){
  14. var div = ele.closest("div")
  15. host = div.find("input[id$=-host]").val()
  16. port = div.find("input[id$=-port]").val()
  17. mount = div.find("input[id$=-mount]").val()
  18. streamurl = ""
  19. if(div.find("select[id$=-output]").val()=="icecast"){
  20. streamurl = "http://"+host
  21. if($.trim(port) != ""){
  22. streamurl += ":"+port
  23. }
  24. if($.trim(mount) != ""){
  25. streamurl += "/"+mount
  26. }
  27. }else{
  28. streamurl = "http://"+host+":"+port+"/"
  29. }
  30. div.find("#stream_url").text(streamurl)
  31. }
  32. function restrictOggBitrate(ele, on){
  33. var div = ele.closest("div")
  34. if(on){
  35. if(parseInt(div.find("select[id$=data-bitrate]").val(),10) < 48){
  36. div.find("select[id$=data-bitrate]").find("option[value='48']").attr("selected","selected");
  37. }
  38. div.find("select[id$=data-bitrate]").find("option[value='24']").attr("disabled","disabled");
  39. div.find("select[id$=data-bitrate]").find("option[value='32']").attr("disabled","disabled");
  40. }else{
  41. div.find("select[id$=data-bitrate]").find("option[value='24']").removeAttr("disabled");
  42. div.find("select[id$=data-bitrate]").find("option[value='32']").removeAttr("disabled");
  43. }
  44. }
  45. function hideForShoutcast(ele){
  46. var div = ele.closest("div")
  47. div.find("#outputMountpoint-label").hide()
  48. div.find("#outputMountpoint-element").hide()
  49. div.find("#outputUser-label").hide()
  50. div.find("#outputUser-element").hide()
  51. div.find("select[id$=data-type]").find("option[value='mp3']").attr('selected','selected');
  52. div.find("select[id$=data-type]").find("option[value='ogg']").attr("disabled","disabled");
  53. div.find("select[id$=data-type]").find("option[value='opus']").attr("disabled","disabled");
  54. restrictOggBitrate(ele, false)
  55. }
  56. function validate(ele,evt) {
  57. var theEvent = evt || window.event;
  58. var key = theEvent.keyCode || theEvent.which;
  59. if ((ele.val().length >= 5 || (key < 48 || key > 57)) && !(key == 8 || key == 9 || key == 13 || key == 37 || key == 39 || key == 46)) {
  60. theEvent.returnValue = false;
  61. if(theEvent.preventDefault) theEvent.preventDefault();
  62. }
  63. }
  64. function showForIcecast(ele){
  65. var div = ele.closest("div");
  66. div.find("#outputMountpoint-label").show();
  67. div.find("#outputMountpoint-element").show();
  68. div.find("#outputUser-label").show();
  69. div.find("#outputUser-element").show();
  70. div.find("select[id$=data-type]").find("option[value='ogg']").removeAttr("disabled");
  71. div.find("select[id$=data-type]").find("option[value='opus']").removeAttr("disabled");
  72. }
  73. function checkLiquidsoapStatus(){
  74. var url = baseUrl+'Preference/get-liquidsoap-status/format/json';
  75. var id = $(this).attr("id");
  76. $.post(url, function(json_obj){
  77. for(var i=0;i<json_obj.length;i++){
  78. var obj = json_obj[i];
  79. var id;
  80. var status;
  81. for(var key in obj){
  82. if(key == "id"){
  83. id = obj[key];
  84. }
  85. if(key == "status"){
  86. status = obj[key];
  87. }
  88. }
  89. var html;
  90. if(status == "OK"){
  91. html = '<div class="stream-status status-good"><h3>'+$.i18n._("Connected to the streaming server")+'</h3></div>';
  92. }else if(status == "N/A"){
  93. html = '<div class="stream-status status-disabled"><h3>'+$.i18n._("The stream is disabled")+'</h3></div>';
  94. }else if(status == "waiting"){
  95. html = '<div class="stream-status status-info"><h3>'+$.i18n._("Getting information from the server...")+'</h3></div>';
  96. }else{
  97. html = '<div class="stream-status status-error"><h3>'+$.i18n._("Can not connect to the streaming server")+'</h3><p>'+status+'</p></div>';
  98. }
  99. $("#s"+id+"Liquidsoap-error-msg-element").html(html);
  100. }
  101. setTimeout(checkLiquidsoapStatus, 2000);
  102. });
  103. }
  104. function setLiveSourceConnectionOverrideListener(){
  105. $("[id=connection_url_override]").click(function(event){
  106. var url_input = $(this).parent().find("#stream_url").children();
  107. url_input.removeAttr("readonly");
  108. $(this).parent().find("div[id$='_dj_connection_url_actions']").show();
  109. event.preventDefault();
  110. });
  111. // set action for "OK" and "X"
  112. var live_dj_actions = $("#live_dj_connection_url_actions");
  113. var live_dj_input = live_dj_actions.parent().find("#stream_url").children();
  114. var master_dj_actions = $("#master_dj_connection_url_actions");
  115. var master_dj_input = master_dj_actions.parent().find("#stream_url").children();
  116. live_dj_actions.find("#ok").click(function(event){
  117. event.preventDefault();
  118. var url = live_dj_input.val();
  119. live_dj_input.val(url);
  120. live_dj_input.attr("readonly", "readonly");
  121. live_dj_actions.hide();
  122. $.get(baseUrl+"Preference/set-source-connection-url/", {format: "json", type: "livedj", url:encodeURIComponent(url), override: 1});
  123. event.preventDefault();
  124. });
  125. live_dj_actions.find("#reset").click(function(event){
  126. event.preventDefault();
  127. var port = $("#dj_harbor_input_port").val();
  128. var mount = $("#dj_harbor_input_mount_point").val();
  129. var url = "http://"+location.hostname+":"+port+"/"+mount;
  130. if (port == '' || mount == '') {
  131. url = 'N/A';
  132. }
  133. live_dj_input.val(url);
  134. live_dj_input.attr("readonly", "readonly");
  135. live_dj_actions.hide();
  136. $.get(baseUrl+"Preference/set-source-connection-url", {format: "json", type: "livedj", url:encodeURIComponent(url), override: 0});
  137. event.preventDefault();
  138. });
  139. master_dj_actions.find("#ok").click(function(event){
  140. var url = master_dj_input.val();
  141. master_dj_input.val(url);
  142. master_dj_input.attr("readonly", "readonly");
  143. master_dj_actions.hide();
  144. $.get(baseUrl+"Preference/set-source-connection-url", {format: "json", type: "masterdj", url:encodeURIComponent(url), override: 1});
  145. event.preventDefault();
  146. });
  147. master_dj_actions.find("#reset").click(function(event){
  148. var port = $("#master_harbor_input_port").val();
  149. var mount = $("#master_harbor_input_mount_point").val();
  150. var url = "http://"+location.hostname+":"+port+"/"+mount;
  151. if (port == '' || mount == '') {
  152. url = 'N/A';
  153. }
  154. master_dj_input.val(url);
  155. master_dj_input.attr("readonly", "readonly");
  156. master_dj_actions.hide();
  157. $.get(baseUrl+"Preference/set-source-connection-url", {format: "json", type: "masterdj", url:encodeURIComponent(url), override: 0});
  158. event.preventDefault();
  159. });
  160. }
  161. function setupEventListeners() {
  162. // initial stream url
  163. $("dd[id=outputStreamURL-element]").each(function(){
  164. rebuildStreamURL($(this));
  165. })
  166. $("input[id$=-host], input[id$=-port], input[id$=-mount]").keyup(function(){
  167. rebuildStreamURL($(this));
  168. });
  169. $("input[id$=-port]").keypress(function(e){
  170. validate($(this),e);
  171. });
  172. $("select[id$=-output]").change(function(){
  173. rebuildStreamURL($(this));
  174. });
  175. if(!$("#output_sound_device").is(':checked')){
  176. $("select[id=output_sound_device_type]").attr('disabled', 'disabled');
  177. }else{
  178. $("select[id=output_sound_device_type]").removeAttr('disabled');
  179. }
  180. $("#output_sound_device").change(function(){
  181. if($(this).is(':checked')){
  182. $("select[id=output_sound_device_type]").removeAttr('disabled');
  183. }else{
  184. $("select[id=output_sound_device_type]").attr('disabled', 'disabled');
  185. }
  186. });
  187. $("select[id$=data-type]").change(function(){
  188. if($(this).val() == 'ogg'){
  189. restrictOggBitrate($(this), true);
  190. }else{
  191. restrictOggBitrate($(this), false);
  192. }
  193. });
  194. $("select[id$=data-type]").each(function(){
  195. if($(this).val() == 'ogg'){
  196. restrictOggBitrate($(this), true);
  197. }
  198. });
  199. $("select[id$=data-output]").change(function(){
  200. if($(this).val() == 'shoutcast'){
  201. hideForShoutcast($(this));
  202. }else{
  203. showForIcecast($(this));
  204. }
  205. });
  206. $("select[id$=data-output]").each(function(){
  207. if($(this).val() == 'shoutcast'){
  208. hideForShoutcast($(this));
  209. }
  210. });
  211. $('.toggle legend').click(function() {
  212. $(this).parent().toggleClass('closed');
  213. return false;
  214. });
  215. $('.collapsible-header').click(function() {
  216. $(this).next().toggle('fast');
  217. $(this).toggleClass("closed");
  218. return false;
  219. });
  220. setLiveSourceConnectionOverrideListener();
  221. showErrorSections();
  222. checkLiquidsoapStatus();
  223. var userManualAnchorOpen = "<a target='_blank' href='" + USER_MANUAL_URL + "'>";
  224. // qtip for help text
  225. $(".override_help_icon").qtip({
  226. content: {
  227. text: sprintf($.i18n._("If %s is behind a router or firewall, you may need to configure port forwarding and this field information will be incorrect. In this case you will need to manually update this field so it shows the correct host/port/mount that your DJ's need to connect to. The allowed range is between 1024 and 49151."), PRODUCT_NAME)+" "+
  228. sprintf($.i18n._(
  229. "For more details, please read the %s%s Manual%s"), userManualAnchorOpen, PRODUCT_NAME, "</a>")
  230. },
  231. hide: {
  232. delay: 500,
  233. fixed: true
  234. },
  235. style: {
  236. border: {
  237. width: 0,
  238. radius: 4
  239. },
  240. classes: "ui-tooltip-dark ui-tooltip-rounded"
  241. },
  242. position: {
  243. my: "left bottom",
  244. at: "right center"
  245. },
  246. });
  247. $(".icecast_metadata_help_icon").qtip({
  248. content: {
  249. text: $.i18n._("Check this option to enable metadata for OGG streams (stream metadata is the track title, artist, and show name that is displayed in an audio player). VLC and mplayer have a serious bug when playing an OGG/VORBIS stream that has metadata information enabled: they will disconnect from the stream after every song. If you are using an OGG stream and your listeners do not require support for these audio players, then feel free to enable this option.")
  250. },
  251. hide: {
  252. delay: 500,
  253. fixed: true
  254. },
  255. style: {
  256. border: {
  257. width: 0,
  258. radius: 4
  259. },
  260. classes: "ui-tooltip-dark ui-tooltip-rounded"
  261. },
  262. position: {
  263. my: "left bottom",
  264. at: "right center"
  265. },
  266. });
  267. $("#auto_transition_help").qtip({
  268. content: {
  269. text: $.i18n._("Check this box to automatically switch off Master/Show source upon source disconnection.")
  270. },
  271. hide: {
  272. delay: 500,
  273. fixed: true
  274. },
  275. style: {
  276. border: {
  277. width: 0,
  278. radius: 4
  279. },
  280. classes: "ui-tooltip-dark ui-tooltip-rounded"
  281. },
  282. position: {
  283. my: "left bottom",
  284. at: "right center"
  285. },
  286. });
  287. $("#auto_switch_help").qtip({
  288. content: {
  289. text: $.i18n._("Check this box to automatically switch on Master/Show source upon source connection.")
  290. },
  291. hide: {
  292. delay: 500,
  293. fixed: true
  294. },
  295. style: {
  296. border: {
  297. width: 0,
  298. radius: 4
  299. },
  300. classes: "ui-tooltip-dark ui-tooltip-rounded"
  301. },
  302. position: {
  303. my: "left bottom",
  304. at: "right center"
  305. },
  306. });
  307. $(".stream_username_help_icon").qtip({
  308. content: {
  309. text: $.i18n._("If your Icecast server expects a username of 'source', this field can be left blank.")
  310. },
  311. hide: {
  312. delay: 500,
  313. fixed: true
  314. },
  315. style: {
  316. border: {
  317. width: 0,
  318. radius: 4
  319. },
  320. classes: "ui-tooltip-dark ui-tooltip-rounded"
  321. },
  322. position: {
  323. my: "left bottom",
  324. at: "right center"
  325. },
  326. });
  327. $(".admin_username_help_icon").qtip({
  328. content: {
  329. text: $.i18n._("This is the admin username and password for Icecast/SHOUTcast to get listener statistics.")
  330. },
  331. hide: {
  332. delay: 500,
  333. fixed: true
  334. },
  335. style: {
  336. border: {
  337. width: 0,
  338. radius: 4
  339. },
  340. classes: "ui-tooltip-dark ui-tooltip-rounded"
  341. },
  342. position: {
  343. my: "left bottom",
  344. at: "right center"
  345. },
  346. });
  347. $(".master_username_help_icon").qtip({
  348. content: {
  349. text: $.i18n._("If your live streaming client does not ask for a username, this field should be 'source'.")
  350. },
  351. hide: {
  352. delay: 500,
  353. fixed: true
  354. },
  355. style: {
  356. border: {
  357. width: 0,
  358. radius: 4
  359. },
  360. classes: "ui-tooltip-dark ui-tooltip-rounded"
  361. },
  362. position: {
  363. my: "left bottom",
  364. at: "right center"
  365. },
  366. });
  367. $(".stream_type_help_icon").qtip({
  368. content: {
  369. text: sprintf(
  370. $.i18n._("Some stream types require extra configuration. Details about enabling %sAAC+ Support%s or %sOpus Support%s are provided."),
  371. "<a target='_blank' href='https://wiki.sourcefabric.org/x/NgPQ'>",
  372. "</a>",
  373. "<a target='_blank' href='https://wiki.sourcefabric.org/x/KgPQ'>",
  374. "</a>")
  375. },
  376. hide: {
  377. delay: 500,
  378. fixed: true
  379. },
  380. style: {
  381. border: {
  382. width: 0,
  383. radius: 4
  384. },
  385. classes: "ui-tooltip-dark ui-tooltip-rounded"
  386. },
  387. position: {
  388. my: "left bottom",
  389. at: "right center"
  390. },
  391. });
  392. }
  393. function setSliderForReplayGain(){
  394. $( "#slider-range-max" ).slider({
  395. range: "max",
  396. min: -10,
  397. max: 10,
  398. value: $("#rg_modifier_value").html(),
  399. slide: function( event, ui ) {
  400. $( "#replayGainModifier" ).val( ui.value );
  401. $("#rg_modifier_value").html(ui.value);
  402. }
  403. });
  404. $( "#replayGainModifier" ).val( $( "#slider-range-max" ).slider( "value" ) );
  405. }
  406. function setPseudoAdminPassword(s1, s2, s3) {
  407. if (s1) {
  408. $('#s1_data-admin_pass').val('xxxxxx');
  409. }
  410. if (s2) {
  411. $('#s2_data-admin_pass').val('xxxxxx');
  412. }
  413. if (s3) {
  414. $('#s3_data-admin_pass').val('xxxxxx');
  415. }
  416. }
  417. function getAdminPasswordStatus() {
  418. $.ajax({ url: baseUrl+'Preference/get-admin-password-status/format/json', dataType:"json", success:function(data){
  419. setPseudoAdminPassword(data.s1, data.s2, data.s3);
  420. }});
  421. }
  422. $(document).ready(function() {
  423. setupEventListeners();
  424. setSliderForReplayGain();
  425. getAdminPasswordStatus();
  426. $('#stream_save').live('click', function(){
  427. var confirm_pypo_restart_text = sprintf($.i18n._("If you change the username or password values for an enabled stream the playout engine will be rebooted and your listeners will hear silence for 5-10 seconds. Changing the following fields will NOT cause a reboot: Stream Label (Global Settings), and Switch Transition Fade(s), Master Username, and Master Password (Input Stream Settings). If %s is recording, and if the change causes a playout engine restart, the recording will be interrupted."), PRODUCT_NAME);
  428. if (confirm(confirm_pypo_restart_text)) {
  429. var data = $('#stream_form').serialize();
  430. var url = baseUrl+'Preference/stream-setting';
  431. $.post(url, {format:"json", data: data}, function(json){
  432. $('#content').empty().append(json.html);
  433. setupEventListeners();
  434. setSliderForReplayGain();
  435. setPseudoAdminPassword(json.s1_set_admin_pass, json.s2_set_admin_pass, json.s3_set_admin_pass);
  436. });
  437. }
  438. });
  439. });