commit 28/10/2025
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
#Configuration file
|
#Configuration file
|
||||||
#Mon Oct 27 17:19:33 WIB 2025
|
#Tue Oct 28 14:18:19 WIB 2025
|
||||||
auto.delete.result.days=10
|
auto.delete.result.days=7
|
||||||
database.host=localhost
|
database.host=localhost
|
||||||
database.name=aas
|
database.name=aas
|
||||||
database.password=admin
|
database.password=admin
|
||||||
|
|||||||
28905
html/webpage/assets/css/all.min.css
vendored
Normal file
28905
html/webpage/assets/css/all.min.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -93,7 +93,6 @@ function change_droparea_enable() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
console.log(`Selected Category: ${selected_category}, Language: ${selected_language}, Voice: ${selected_voice}`);
|
|
||||||
if (selected_category && selected_language && selected_voice) {
|
if (selected_category && selected_language && selected_voice) {
|
||||||
$("#drop-area").removeClass("disabled");
|
$("#drop-area").removeClass("disabled");
|
||||||
getSoundBankFiles(selected_category, selected_language, selected_voice);
|
getSoundBankFiles(selected_category, selected_language, selected_voice);
|
||||||
@@ -112,7 +111,6 @@ function get_soundbank_path() {
|
|||||||
fetchAPI("Settings/SoundbankDirectory", "GET", {}, null, (okdata) => {
|
fetchAPI("Settings/SoundbankDirectory", "GET", {}, null, (okdata) => {
|
||||||
if (okdata.message && okdata.message.trim().length > 0) {
|
if (okdata.message && okdata.message.trim().length > 0) {
|
||||||
let path = okdata.message.trim();
|
let path = okdata.message.trim();
|
||||||
//console.log("Soundbank path retrieved: " + path);
|
|
||||||
$("#setting_path").val(path);
|
$("#setting_path").val(path);
|
||||||
}
|
}
|
||||||
}, (errdata) => {
|
}, (errdata) => {
|
||||||
@@ -164,17 +162,12 @@ function play(path, filename, cbplay = null) {
|
|||||||
const player = document.getElementById("audioplayer");
|
const player = document.getElementById("audioplayer");
|
||||||
if (player) {
|
if (player) {
|
||||||
player.pause();
|
player.pause();
|
||||||
if (window.lastplaybutton){
|
|
||||||
let $icon = $(window.lastplaybutton).find("i");
|
|
||||||
$icon.removeClass("fa-stop").addClass("fa-play");
|
|
||||||
|
|
||||||
}
|
|
||||||
player.src = url;
|
player.src = url;
|
||||||
player.load();
|
player.load();
|
||||||
$("#audioplayer").show();
|
$("#audioplayer").show();
|
||||||
player.play();
|
player.play();
|
||||||
player.onplay = () => {
|
player.onplay = () => {
|
||||||
console.log("Playing audio file: " + filename);
|
|
||||||
if (cbplay && typeof cbplay === "function") {
|
if (cbplay && typeof cbplay === "function") {
|
||||||
cbplay();
|
cbplay();
|
||||||
}
|
}
|
||||||
@@ -198,35 +191,38 @@ function get_pagingresult_files() {
|
|||||||
$("#tbody_resultpaging").empty();
|
$("#tbody_resultpaging").empty();
|
||||||
fetchAPI(url, "GET", {}, null, (okdata) => {
|
fetchAPI(url, "GET", {}, null, (okdata) => {
|
||||||
if (Array.isArray(okdata) && okdata.length > 0) {
|
if (Array.isArray(okdata) && okdata.length > 0) {
|
||||||
console.log("Paging result files: ", JSON.stringify(okdata));
|
|
||||||
okdata.forEach((file) => {
|
okdata.forEach((file) => {
|
||||||
let filename = file.split(/[/\\]/).pop();
|
let filename = file.split(/[/\\]/).pop();
|
||||||
let $tr = $("<tr></tr>");
|
let $tr = $("<tr></tr>");
|
||||||
let $tdtitle = $("<td></td>").text(filename);
|
let $tdtitle = $("<td></td>").text(filename);
|
||||||
// add button inside td to download the file
|
// add button inside td to download the file
|
||||||
let $btndownload = $("<button></button>").addClass("btn btn-primary").html("<i class='fa-solid fa-download'></i>");
|
let $btndownload = $("<button></button>").addClass("btn btn-primary").html("<i class='fa fa-download'></i>");
|
||||||
let $btnplay = $("<button></button>").addClass("btn btn-primary").html("<i class='fa-solid fa-play'></i>");
|
let $btnplay = $("<button></button>").addClass("btn btn-success pad-btn").html("<i class='fa fa-play'></i>");
|
||||||
$btndownload.on('click', function () {
|
$btndownload.off('click').on('click', function () {
|
||||||
download("DownloadPagingResultFile", filename);
|
download("DownloadPagingResultFile", filename);
|
||||||
});
|
});
|
||||||
$btnplay.on('click', function () {
|
$btnplay.off('click').on('click', function () {
|
||||||
let $icon = $(this).find("i");
|
const $icon = $(this).find("svg");
|
||||||
if ($icon.hasClass("fa-stop")) {
|
if ($icon.hasClass("fa-stop")) {
|
||||||
// stop playback
|
// stop playback
|
||||||
const player = document.getElementById("audioplayer");
|
const player = document.getElementById("audioplayer");
|
||||||
if (player) {
|
if (player) {
|
||||||
player.pause();
|
player.pause();
|
||||||
window.URL.revokeObjectURL(player.src);
|
window.URL.revokeObjectURL(player.src);
|
||||||
window.lastplaybutton = null;
|
|
||||||
$icon.removeClass("fa-stop").addClass("fa-play");
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// start playback
|
// start playback
|
||||||
play("PlayPagingResultFile", filename, () => {
|
play("PlayPagingResultFile", filename, () => {
|
||||||
window.lastplaybutton = $btnplay;
|
if (window.lastplaybutton){
|
||||||
$icon.removeClass("fa-play").addClass("fa-stop");
|
if (window.lastplaybutton !== $(this)){
|
||||||
|
const $lasticon = window.lastplaybutton.find("svg");
|
||||||
|
$lasticon.removeClass("fa-stop").addClass("fa-play");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window.lastplaybutton = $(this);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
$icon.toggleClass("fa-play fa-stop");
|
||||||
});
|
});
|
||||||
|
|
||||||
let $tdbutton = $("<td></td>").append($btndownload).append($btnplay).addClass("text-center");
|
let $tdbutton = $("<td></td>").append($btndownload).append($btnplay).addClass("text-center");
|
||||||
@@ -245,37 +241,40 @@ function get_soundbankresult_files() {
|
|||||||
$("#tbody_resultsoundbank").empty();
|
$("#tbody_resultsoundbank").empty();
|
||||||
fetchAPI(url, "GET", {}, null, (okdata) => {
|
fetchAPI(url, "GET", {}, null, (okdata) => {
|
||||||
if (Array.isArray(okdata) && okdata.length > 0) {
|
if (Array.isArray(okdata) && okdata.length > 0) {
|
||||||
console.log("Soundbank result files: ", JSON.stringify(okdata));
|
|
||||||
okdata.forEach((file) => {
|
okdata.forEach((file) => {
|
||||||
let filename = file.split(/[/\\]/).pop();
|
let filename = file.split(/[/\\]/).pop();
|
||||||
let $tr = $("<tr></tr>");
|
let $tr = $("<tr></tr>");
|
||||||
let $tdtitle = $("<td></td>").text(filename);
|
let $tdtitle = $("<td></td>").text(filename);
|
||||||
// add button inside td to download and play the file
|
// add button inside td to download and play the file
|
||||||
let $btndownload = $("<button></button>").addClass("btn btn-primary").html("<i class='fa-solid fa-download'></i>");
|
let $btndownload = $("<button></button>").addClass("btn btn-primary").html("<i class='fa fa-download'></i>");
|
||||||
let $btnplay = $("<button></button>").addClass("btn btn-primary").html("<i class='fa-solid fa-play'></i>");
|
let $btnplay = $("<button></button>").addClass("btn btn-success").html("<i class='fa fa-play'></i>");
|
||||||
let $tdbutton = $("<td></td>").append($btndownload).append($btnplay).addClass("text-center");
|
let $tdbutton = $("<td></td>").append($btndownload).append($btnplay).addClass("text-center");
|
||||||
|
|
||||||
$btndownload.on('click', function () {
|
$btndownload.off('click').on('click', function () {
|
||||||
download("DownloadSoundbankResultFile", filename);
|
download("DownloadSoundbankResultFile", filename);
|
||||||
});
|
});
|
||||||
$btnplay.on('click', function () {
|
$btnplay.off('click').on('click', function () {
|
||||||
let $icon = $(this).find("i");
|
const $icon = $(this).find("svg");
|
||||||
if ($icon.hasClass("fa-stop")) {
|
if ($icon.hasClass("fa-stop")) {
|
||||||
// stop playback
|
// stop playback
|
||||||
const player = document.getElementById("audioplayer");
|
const player = document.getElementById("audioplayer");
|
||||||
if (player) {
|
if (player) {
|
||||||
player.pause();
|
player.pause();
|
||||||
window.URL.revokeObjectURL(player.src);
|
window.URL.revokeObjectURL(player.src);
|
||||||
window.lastplaybutton = null;
|
|
||||||
$icon.removeClass("fa-stop").addClass("fa-play");
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// start playback
|
// start playback
|
||||||
play("PlaySoundbankResultFile", filename, () => {
|
play("PlaySoundbankResultFile", filename, () => {
|
||||||
window.lastplaybutton = $btnplay;
|
if (window.lastplaybutton){
|
||||||
$icon.removeClass("fa-play").addClass("fa-stop");
|
if (window.lastplaybutton !== $(this)){
|
||||||
|
const $lasticon = window.lastplaybutton.find("svg");
|
||||||
|
$lasticon.removeClass("fa-stop").addClass("fa-play");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window.lastplaybutton = $(this);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
$icon.toggleClass("fa-play fa-stop");
|
||||||
});
|
});
|
||||||
$tr.append($tdtitle);
|
$tr.append($tdtitle);
|
||||||
$tr.append($tdbutton);
|
$tr.append($tdbutton);
|
||||||
@@ -290,7 +289,7 @@ function get_soundbankresult_files() {
|
|||||||
|
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
console.log("filemanagement.js xx loaded");
|
console.log("filemanagement.js x3 loaded");
|
||||||
|
|
||||||
load_setting_category();
|
load_setting_category();
|
||||||
load_setting_language();
|
load_setting_language();
|
||||||
@@ -380,4 +379,55 @@ $(document).ready(function () {
|
|||||||
} else alert("Please select Language before uploading files.");
|
} else alert("Please select Language before uploading files.");
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$("#clear_soundbank").off('click').on('click', function () {
|
||||||
|
if (confirm("Are you sure want to delete all soundbank result files from the server? This action cannot be undone.")) {
|
||||||
|
fetchAPI("FileManager/ClearSoundbankResultFiles","DELETE",{},null,(okdata)=>{
|
||||||
|
alert("All soundbank result files have been deleted from the server.");
|
||||||
|
get_soundbankresult_files();
|
||||||
|
},(errdata)=>{
|
||||||
|
alert("Error deleting soundbank result files : " + errdata.message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$("#reload_soundbank").off('click').on('click', function () {
|
||||||
|
get_soundbankresult_files();
|
||||||
|
});
|
||||||
|
$("#search_soundbank").off('input').on('input', function () {
|
||||||
|
let searchTerm = $(this).val().toLowerCase();
|
||||||
|
// find inside tbody_resultsoundbank, <tr> that have <td> with <p> containing the search term
|
||||||
|
$("#tbody_resultsoundbank tr").each(function () {
|
||||||
|
let fileName = $(this).find("td:first").text().toLowerCase();
|
||||||
|
if (fileName.includes(searchTerm)) {
|
||||||
|
$(this).show();
|
||||||
|
} else {
|
||||||
|
$(this).hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
$("#clear_paging").off('click').on('click', function () {
|
||||||
|
if (confirm("Are you sure want to delete all paging result files from the server? This action cannot be undone.")) {
|
||||||
|
fetchAPI("FileManager/ClearPagingResultFiles","DELETE",{},null,(okdata)=>{
|
||||||
|
alert("All paging result files have been deleted from the server.");
|
||||||
|
get_pagingresult_files();
|
||||||
|
},(errdata)=>{
|
||||||
|
alert("Error deleting paging result files : " + errdata.message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$("#reload_paging").off('click').on('click', function () {
|
||||||
|
get_pagingresult_files();
|
||||||
|
});
|
||||||
|
$("#search_paging").off('input').on('input', function () {
|
||||||
|
let searchTerm = $(this).val().toLowerCase();
|
||||||
|
// find inside tbody_resultpaging, <tr> that have <td> with <p> containing the search term
|
||||||
|
$("#tbody_resultpaging tr").each(function () {
|
||||||
|
let fileName = $(this).find("td:first").text().toLowerCase();
|
||||||
|
if (fileName.includes(searchTerm)) {
|
||||||
|
$(this).show();
|
||||||
|
} else {
|
||||||
|
$(this).hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
@@ -69,7 +69,7 @@ function UpdateStreamerCard(values) {
|
|||||||
if (card.title) card.title.text(vv.channel ? vv.channel : `Channel ${i.toString().padStart(2, '0')}`);
|
if (card.title) card.title.text(vv.channel ? vv.channel : `Channel ${i.toString().padStart(2, '0')}`);
|
||||||
if (card.ip) card.ip.text(`IP Address: ${vv.ipaddress ? vv.ipaddress : 'N/A'}`);
|
if (card.ip) card.ip.text(`IP Address: ${vv.ipaddress ? vv.ipaddress : 'N/A'}`);
|
||||||
if (card.buffer) card.buffer.text(`Buffer: ${vv.bufferRemain !== undefined && vv.bufferRemain !== null ? vv.bufferRemain.toString() : 'N/A'}`);
|
if (card.buffer) card.buffer.text(`Buffer: ${vv.bufferRemain !== undefined && vv.bufferRemain !== null ? vv.bufferRemain.toString() : 'N/A'}`);
|
||||||
if (card.status) card.status.text(`Status: ${vv.isPlaying ? 'Playing' : 'Stopped'}`);
|
if (card.status) card.status.text(`Status: ${vv.isPlaying ? 'Playing' : 'Idle'}`);
|
||||||
if (card.vu) {
|
if (card.vu) {
|
||||||
setProgress(i, card.vu, vv.vu, 100);
|
setProgress(i, card.vu, vv.vu, 100);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
<link rel="stylesheet" href="assets/css/Font%20Awesome%206%20Pro.css">
|
<link rel="stylesheet" href="assets/css/Font%20Awesome%206%20Pro.css">
|
||||||
<link rel="stylesheet" href="assets/css/FontAwesome.css">
|
<link rel="stylesheet" href="assets/css/FontAwesome.css">
|
||||||
<link rel="stylesheet" href="assets/css/bss-overrides.css">
|
<link rel="stylesheet" href="assets/css/bss-overrides.css">
|
||||||
|
<link rel="stylesheet" href="assets/css/all.min.css">
|
||||||
<link rel="stylesheet" href="assets/css/Login-Form-Basic-icons.css">
|
<link rel="stylesheet" href="assets/css/Login-Form-Basic-icons.css">
|
||||||
<link rel="stylesheet" href="assets/css/styles.css">
|
<link rel="stylesheet" href="assets/css/styles.css">
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
<link rel="stylesheet" href="assets/css/Font%20Awesome%206%20Pro.css">
|
<link rel="stylesheet" href="assets/css/Font%20Awesome%206%20Pro.css">
|
||||||
<link rel="stylesheet" href="assets/css/FontAwesome.css">
|
<link rel="stylesheet" href="assets/css/FontAwesome.css">
|
||||||
<link rel="stylesheet" href="assets/css/bss-overrides.css">
|
<link rel="stylesheet" href="assets/css/bss-overrides.css">
|
||||||
|
<link rel="stylesheet" href="assets/css/all.min.css">
|
||||||
<link rel="stylesheet" href="assets/css/Login-Form-Basic-icons.css">
|
<link rel="stylesheet" href="assets/css/Login-Form-Basic-icons.css">
|
||||||
<link rel="stylesheet" href="assets/css/styles.css">
|
<link rel="stylesheet" href="assets/css/styles.css">
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
<link rel="stylesheet" href="assets/css/Font%20Awesome%206%20Pro.css">
|
<link rel="stylesheet" href="assets/css/Font%20Awesome%206%20Pro.css">
|
||||||
<link rel="stylesheet" href="assets/css/FontAwesome.css">
|
<link rel="stylesheet" href="assets/css/FontAwesome.css">
|
||||||
<link rel="stylesheet" href="assets/css/bss-overrides.css">
|
<link rel="stylesheet" href="assets/css/bss-overrides.css">
|
||||||
|
<link rel="stylesheet" href="assets/css/all.min.css">
|
||||||
<link rel="stylesheet" href="assets/css/select2.min.css">
|
<link rel="stylesheet" href="assets/css/select2.min.css">
|
||||||
<link rel="stylesheet" href="assets/css/Login-Form-Basic-icons.css">
|
<link rel="stylesheet" href="assets/css/Login-Form-Basic-icons.css">
|
||||||
<link rel="stylesheet" href="assets/css/styles.css">
|
<link rel="stylesheet" href="assets/css/styles.css">
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
<link rel="stylesheet" href="assets/css/Font%20Awesome%206%20Pro.css">
|
<link rel="stylesheet" href="assets/css/Font%20Awesome%206%20Pro.css">
|
||||||
<link rel="stylesheet" href="assets/css/FontAwesome.css">
|
<link rel="stylesheet" href="assets/css/FontAwesome.css">
|
||||||
<link rel="stylesheet" href="assets/css/bss-overrides.css">
|
<link rel="stylesheet" href="assets/css/bss-overrides.css">
|
||||||
|
<link rel="stylesheet" href="assets/css/all.min.css">
|
||||||
<link rel="stylesheet" href="assets/css/Login-Form-Basic-icons.css">
|
<link rel="stylesheet" href="assets/css/Login-Form-Basic-icons.css">
|
||||||
<link rel="stylesheet" href="assets/css/styles.css">
|
<link rel="stylesheet" href="assets/css/styles.css">
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
<link rel="stylesheet" href="assets/css/Font%20Awesome%206%20Pro.css">
|
<link rel="stylesheet" href="assets/css/Font%20Awesome%206%20Pro.css">
|
||||||
<link rel="stylesheet" href="assets/css/FontAwesome.css">
|
<link rel="stylesheet" href="assets/css/FontAwesome.css">
|
||||||
<link rel="stylesheet" href="assets/css/bss-overrides.css">
|
<link rel="stylesheet" href="assets/css/bss-overrides.css">
|
||||||
|
<link rel="stylesheet" href="assets/css/all.min.css">
|
||||||
<link rel="stylesheet" href="assets/css/Login-Form-Basic-icons.css">
|
<link rel="stylesheet" href="assets/css/Login-Form-Basic-icons.css">
|
||||||
<link rel="stylesheet" href="assets/css/styles.css">
|
<link rel="stylesheet" href="assets/css/styles.css">
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
<link rel="stylesheet" href="assets/css/Font%20Awesome%206%20Pro.css">
|
<link rel="stylesheet" href="assets/css/Font%20Awesome%206%20Pro.css">
|
||||||
<link rel="stylesheet" href="assets/css/FontAwesome.css">
|
<link rel="stylesheet" href="assets/css/FontAwesome.css">
|
||||||
<link rel="stylesheet" href="assets/css/bss-overrides.css">
|
<link rel="stylesheet" href="assets/css/bss-overrides.css">
|
||||||
|
<link rel="stylesheet" href="assets/css/all.min.css">
|
||||||
<link rel="stylesheet" href="assets/css/Login-Form-Basic-icons.css">
|
<link rel="stylesheet" href="assets/css/Login-Form-Basic-icons.css">
|
||||||
<link rel="stylesheet" href="assets/css/styles.css">
|
<link rel="stylesheet" href="assets/css/styles.css">
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
<link rel="stylesheet" href="assets/css/Font%20Awesome%206%20Pro.css">
|
<link rel="stylesheet" href="assets/css/Font%20Awesome%206%20Pro.css">
|
||||||
<link rel="stylesheet" href="assets/css/FontAwesome.css">
|
<link rel="stylesheet" href="assets/css/FontAwesome.css">
|
||||||
<link rel="stylesheet" href="assets/css/bss-overrides.css">
|
<link rel="stylesheet" href="assets/css/bss-overrides.css">
|
||||||
|
<link rel="stylesheet" href="assets/css/all.min.css">
|
||||||
<link rel="stylesheet" href="assets/css/Login-Form-Basic-icons.css">
|
<link rel="stylesheet" href="assets/css/Login-Form-Basic-icons.css">
|
||||||
<link rel="stylesheet" href="assets/css/styles.css">
|
<link rel="stylesheet" href="assets/css/styles.css">
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
<link rel="stylesheet" href="assets/css/Font%20Awesome%206%20Pro.css">
|
<link rel="stylesheet" href="assets/css/Font%20Awesome%206%20Pro.css">
|
||||||
<link rel="stylesheet" href="assets/css/FontAwesome.css">
|
<link rel="stylesheet" href="assets/css/FontAwesome.css">
|
||||||
<link rel="stylesheet" href="assets/css/bss-overrides.css">
|
<link rel="stylesheet" href="assets/css/bss-overrides.css">
|
||||||
|
<link rel="stylesheet" href="assets/css/all.min.css">
|
||||||
<link rel="stylesheet" href="assets/css/Login-Form-Basic-icons.css">
|
<link rel="stylesheet" href="assets/css/Login-Form-Basic-icons.css">
|
||||||
<link rel="stylesheet" href="assets/css/styles.css">
|
<link rel="stylesheet" href="assets/css/styles.css">
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
<link rel="stylesheet" href="assets/css/Font%20Awesome%206%20Pro.css">
|
<link rel="stylesheet" href="assets/css/Font%20Awesome%206%20Pro.css">
|
||||||
<link rel="stylesheet" href="assets/css/FontAwesome.css">
|
<link rel="stylesheet" href="assets/css/FontAwesome.css">
|
||||||
<link rel="stylesheet" href="assets/css/bss-overrides.css">
|
<link rel="stylesheet" href="assets/css/bss-overrides.css">
|
||||||
|
<link rel="stylesheet" href="assets/css/all.min.css">
|
||||||
<link rel="stylesheet" href="assets/css/Login-Form-Basic-icons.css">
|
<link rel="stylesheet" href="assets/css/Login-Form-Basic-icons.css">
|
||||||
<link rel="stylesheet" href="assets/css/styles.css">
|
<link rel="stylesheet" href="assets/css/styles.css">
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
<link rel="stylesheet" href="assets/css/Font%20Awesome%206%20Pro.css">
|
<link rel="stylesheet" href="assets/css/Font%20Awesome%206%20Pro.css">
|
||||||
<link rel="stylesheet" href="assets/css/FontAwesome.css">
|
<link rel="stylesheet" href="assets/css/FontAwesome.css">
|
||||||
<link rel="stylesheet" href="assets/css/bss-overrides.css">
|
<link rel="stylesheet" href="assets/css/bss-overrides.css">
|
||||||
|
<link rel="stylesheet" href="assets/css/all.min.css">
|
||||||
<link rel="stylesheet" href="assets/css/Login-Form-Basic-icons.css">
|
<link rel="stylesheet" href="assets/css/Login-Form-Basic-icons.css">
|
||||||
<link rel="stylesheet" href="assets/css/styles.css">
|
<link rel="stylesheet" href="assets/css/styles.css">
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
<link rel="stylesheet" href="assets/css/Font%20Awesome%206%20Pro.css">
|
<link rel="stylesheet" href="assets/css/Font%20Awesome%206%20Pro.css">
|
||||||
<link rel="stylesheet" href="assets/css/FontAwesome.css">
|
<link rel="stylesheet" href="assets/css/FontAwesome.css">
|
||||||
<link rel="stylesheet" href="assets/css/bss-overrides.css">
|
<link rel="stylesheet" href="assets/css/bss-overrides.css">
|
||||||
|
<link rel="stylesheet" href="assets/css/all.min.css">
|
||||||
<link rel="stylesheet" href="assets/css/Login-Form-Basic-icons.css">
|
<link rel="stylesheet" href="assets/css/Login-Form-Basic-icons.css">
|
||||||
<link rel="stylesheet" href="assets/css/styles.css">
|
<link rel="stylesheet" href="assets/css/styles.css">
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
<link rel="stylesheet" href="assets/css/Font%20Awesome%206%20Pro.css">
|
<link rel="stylesheet" href="assets/css/Font%20Awesome%206%20Pro.css">
|
||||||
<link rel="stylesheet" href="assets/css/FontAwesome.css">
|
<link rel="stylesheet" href="assets/css/FontAwesome.css">
|
||||||
<link rel="stylesheet" href="assets/css/bss-overrides.css">
|
<link rel="stylesheet" href="assets/css/bss-overrides.css">
|
||||||
|
<link rel="stylesheet" href="assets/css/all.min.css">
|
||||||
<link rel="stylesheet" href="assets/css/Login-Form-Basic-icons.css">
|
<link rel="stylesheet" href="assets/css/Login-Form-Basic-icons.css">
|
||||||
<link rel="stylesheet" href="assets/css/styles.css">
|
<link rel="stylesheet" href="assets/css/styles.css">
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
<link rel="stylesheet" href="assets/css/Font%20Awesome%206%20Pro.css">
|
<link rel="stylesheet" href="assets/css/Font%20Awesome%206%20Pro.css">
|
||||||
<link rel="stylesheet" href="assets/css/FontAwesome.css">
|
<link rel="stylesheet" href="assets/css/FontAwesome.css">
|
||||||
<link rel="stylesheet" href="assets/css/bss-overrides.css">
|
<link rel="stylesheet" href="assets/css/bss-overrides.css">
|
||||||
|
<link rel="stylesheet" href="assets/css/all.min.css">
|
||||||
<link rel="stylesheet" href="assets/css/Login-Form-Basic-icons.css">
|
<link rel="stylesheet" href="assets/css/Login-Form-Basic-icons.css">
|
||||||
<link rel="stylesheet" href="assets/css/styles.css">
|
<link rel="stylesheet" href="assets/css/styles.css">
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -1,157 +0,0 @@
|
|||||||
package audio
|
|
||||||
|
|
||||||
import audio.Bass.BASS_STREAMPROC_END
|
|
||||||
import audio.BassEnc.BASS_ENCODE_PCM
|
|
||||||
import kotlinx.coroutines.CoroutineName
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.delay
|
|
||||||
import org.tinylog.Logger
|
|
||||||
import java.io.PipedInputStream
|
|
||||||
import java.io.PipedOutputStream
|
|
||||||
import java.net.DatagramPacket
|
|
||||||
import java.net.DatagramSocket
|
|
||||||
import java.net.InetSocketAddress
|
|
||||||
import java.util.function.BiConsumer
|
|
||||||
import java.util.function.Consumer
|
|
||||||
|
|
||||||
@Deprecated("Sepertinya gak jadi pake")
|
|
||||||
@Suppress("unused")
|
|
||||||
/**
|
|
||||||
* UDPReceiverToFile is a class that listens for UDP packets on a specified address and port
|
|
||||||
* and writes the received data to a specified file.
|
|
||||||
* It is designed to run in a separate thread and can be stopped when no longer needed.
|
|
||||||
* @param listeningAddress The address to listen for incoming UDP packets.
|
|
||||||
* @param listeningPort The port to listen for incoming UDP packets.
|
|
||||||
* @param samplingrate The sampling rate for the audio data, default is 44,100 Hz.
|
|
||||||
* @param channel The number of audio channels, default is 1 (mono).
|
|
||||||
* @param outputFilePath The path to the file where the received data will be written.
|
|
||||||
* @param senderIP The IP address of the sender from which to accept packets.
|
|
||||||
*/
|
|
||||||
class UDPReceiverToFile(listeningAddress: String, listeningPort: Int, val samplingrate: Int=44100, val channel: Int=1, val outputFilePath: String, val senderIP: String) {
|
|
||||||
|
|
||||||
private var socket: DatagramSocket? = null
|
|
||||||
private val bass : Bass = Bass.Instance
|
|
||||||
private val bassenc : BassEnc = BassEnc.Instance
|
|
||||||
private var isReceiving: Boolean = false
|
|
||||||
private val pipeIn= PipedInputStream(16*1024) // 16K
|
|
||||||
var isReady: Boolean = false; private set
|
|
||||||
var bytesReceived: Long = 0; private set
|
|
||||||
var bytesWritten: Long = 0; private set
|
|
||||||
|
|
||||||
|
|
||||||
init {
|
|
||||||
try{
|
|
||||||
val socketaddress = InetSocketAddress(listeningAddress, listeningPort)
|
|
||||||
socket = DatagramSocket(socketaddress)
|
|
||||||
isReady = true
|
|
||||||
} catch (e : Exception) {
|
|
||||||
Logger.error {"Failed to create UDP socket: ${e.message}" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val streamProc = Bass.STREAMPROC { handle, buffer, length, user ->
|
|
||||||
try{
|
|
||||||
val dd = ByteArray(length)
|
|
||||||
val bytesread = pipeIn.read(dd)
|
|
||||||
|
|
||||||
if (bytesread>0){
|
|
||||||
buffer?.write(0, dd, 0, bytesread) // Write the data to the buffer
|
|
||||||
bytesWritten += bytesread
|
|
||||||
// Return the number of bytes read
|
|
||||||
bytesread
|
|
||||||
} else {
|
|
||||||
// if bytesread is 0, it means the pipe is empty, return BASS_STREAMPROC_END
|
|
||||||
BASS_STREAMPROC_END
|
|
||||||
}
|
|
||||||
} catch (e : Exception){
|
|
||||||
// If an error occurs, log it and return BASS_STREAMPROC_END
|
|
||||||
Logger.error { "STREAMPROC exception on UDPReceiverToFile $senderIP $outputFilePath" }
|
|
||||||
BASS_STREAMPROC_END
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts receiving data from the UDP socket and writing it to the specified file.
|
|
||||||
* This method runs in a separate thread.
|
|
||||||
* @param callback A BiConsumer that accepts a Boolean indicating success or failure and a String message.
|
|
||||||
* @param udpIsReceiving A Consumer that accepts a Boolean indicating whether UDP is currently receiving
|
|
||||||
*/
|
|
||||||
fun startReceiving(callback : BiConsumer<Boolean, String>, udpIsReceiving: Consumer<Boolean>) {
|
|
||||||
var isReceiving = false
|
|
||||||
if (isReady){
|
|
||||||
|
|
||||||
val scope = CoroutineScope(Dispatchers.Default)
|
|
||||||
scope.launch(CoroutineName("UDPReceiverToFile UDP $senderIP $outputFilePath")) {
|
|
||||||
Logger.info { "UDPReceiverToFile started, listening on ${socket?.localSocketAddress} , saving to $outputFilePath" }
|
|
||||||
|
|
||||||
PipedOutputStream(pipeIn).use { pipeOut ->
|
|
||||||
while (isReceiving) {
|
|
||||||
try{
|
|
||||||
val xx = DatagramPacket(ByteArray(1500),1500)
|
|
||||||
socket?.receive(xx)
|
|
||||||
if (xx.address.hostAddress!= senderIP) continue
|
|
||||||
if (xx.length < 1) continue
|
|
||||||
pipeOut.write(xx.data, 0, xx.length)
|
|
||||||
bytesReceived += xx.length
|
|
||||||
if (!isReceiving){
|
|
||||||
isReceiving = true
|
|
||||||
udpIsReceiving.accept(true)
|
|
||||||
}
|
|
||||||
} catch (e : Exception){
|
|
||||||
Logger.error { "Error receiving UDP packet: ${e.message}" }
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Logger.info { "UDPReceiverToFile ended" }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
scope.launch(CoroutineName("UDPReceiverToFile BASS $senderIP $outputFilePath")) {
|
|
||||||
bass.BASS_SetDevice(0) // Set to No Sound device, we are not playing audio
|
|
||||||
val streamhandle = bass.BASS_StreamCreate(samplingrate, channel, 0, streamProc, null)
|
|
||||||
if (streamhandle!=0){
|
|
||||||
bass.BASS_ChannelPlay(streamhandle,false)
|
|
||||||
val encodehandle = bassenc.BASS_Encode_Start(streamhandle, outputFilePath, BASS_ENCODE_PCM, null, null)
|
|
||||||
if (encodehandle!=0){
|
|
||||||
Logger.info { "UDPReceiverToFile started writing to $outputFilePath" }
|
|
||||||
callback.accept(true, "UDPReceiverToFile started successfully, writing to $outputFilePath")
|
|
||||||
while (isReceiving) {
|
|
||||||
try {
|
|
||||||
delay(1000)
|
|
||||||
} catch (e: InterruptedException) {
|
|
||||||
Logger.error { "UDPReceiverToFile thread interrupted: ${e.message}" }
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bassenc.BASS_Encode_Stop(encodehandle)
|
|
||||||
bass.BASS_StreamFree(streamhandle)
|
|
||||||
Logger.info { "UDPReceiverToFile stopped writing to $outputFilePath" }
|
|
||||||
callback.accept(false, "UDPReceiverToFile stopped successfully, written bytes: $bytesWritten")
|
|
||||||
|
|
||||||
} else {
|
|
||||||
callback.accept(false, "Failed to start encoding: ${bass.BASS_ErrorGetCode()}")
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
callback.accept(false, "Failed to create stream: ${bass.BASS_ErrorGetCode()}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} else callback.accept(false, "UDPReceiverToFile is not ready. Check if the socket was created successfully.")
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop UDPReceiverToFile from receiving data.
|
|
||||||
*/
|
|
||||||
fun stopReceiving() {
|
|
||||||
isReceiving = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
package audio
|
|
||||||
|
|
||||||
import audio.Bass.BASS_STREAM_DECODE
|
|
||||||
import codes.Somecodes.Companion.ValidFile
|
|
||||||
import com.sun.jna.Memory
|
|
||||||
import java.net.DatagramPacket
|
|
||||||
import java.net.DatagramSocket
|
|
||||||
import java.net.InetSocketAddress
|
|
||||||
import java.net.SocketAddress
|
|
||||||
import java.util.function.BiConsumer
|
|
||||||
import kotlinx.coroutines.CoroutineName
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
|
|
||||||
@Deprecated("Sepertinya gak jadi pake ini")
|
|
||||||
@Suppress("unused")
|
|
||||||
class UDPSenderFromFile(val fileName: String, val bytesPerPackage: Int=1024, targetIP: Array<String>, targetPort: Int ) {
|
|
||||||
val bass: Bass = Bass.Instance
|
|
||||||
var filehandle: Int = 0
|
|
||||||
var listSocketAddress = ArrayList<SocketAddress>()
|
|
||||||
|
|
||||||
var initialized: Boolean = false; private set
|
|
||||||
var isRunning: Boolean = false; private set
|
|
||||||
var bytesSent: Int = 0; private set
|
|
||||||
|
|
||||||
init {
|
|
||||||
if (ValidFile(fileName)){
|
|
||||||
bass.BASS_SetDevice(0)
|
|
||||||
val handle = bass.BASS_StreamCreateFile(false, fileName, 0,0, BASS_STREAM_DECODE)
|
|
||||||
if (handle!=0){
|
|
||||||
// test buka file berhasil, tutup lagi
|
|
||||||
bass.BASS_StreamFree(handle)
|
|
||||||
//if (targetPort>0 && targetPort<65535){
|
|
||||||
if (targetPort in 0..65535){
|
|
||||||
if (targetIP.isNotEmpty()){
|
|
||||||
var validIPs = true
|
|
||||||
for(ip in targetIP){
|
|
||||||
try{
|
|
||||||
var so = InetSocketAddress(ip, targetPort)
|
|
||||||
listSocketAddress.add(so)
|
|
||||||
} catch (e : Exception){
|
|
||||||
validIPs = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (validIPs){
|
|
||||||
initialized = true
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Start(callback: BiConsumer<Boolean, String>){
|
|
||||||
if (initialized){
|
|
||||||
|
|
||||||
val scope = CoroutineScope(Dispatchers.Default)
|
|
||||||
scope.launch(CoroutineName("UDPSenderFromFile $fileName")) {
|
|
||||||
try {
|
|
||||||
val socket = DatagramSocket()
|
|
||||||
bass.BASS_SetDevice(0) // Set to No Sound Device
|
|
||||||
val handle = bass.BASS_StreamCreateFile(false, fileName, 0, 0, BASS_STREAM_DECODE)
|
|
||||||
if (handle!=0){
|
|
||||||
isRunning = true
|
|
||||||
bytesSent = 0
|
|
||||||
callback.accept(true,"UDPSenderFromFile started, sending $fileName to ${listSocketAddress.size} targets")
|
|
||||||
while(isRunning){
|
|
||||||
val buffer = Memory(bytesPerPackage.toLong())
|
|
||||||
val bytesRead = bass.BASS_ChannelGetData(handle, buffer, bytesPerPackage)
|
|
||||||
if (bytesRead > 0) {
|
|
||||||
for(so in listSocketAddress){
|
|
||||||
val bytes = buffer.getByteArray(0, bytesRead)
|
|
||||||
socket.send(DatagramPacket(bytes, bytes.size, so))
|
|
||||||
bytesSent += bytes.size
|
|
||||||
}
|
|
||||||
|
|
||||||
} else isRunning = false
|
|
||||||
}
|
|
||||||
callback.accept(false,"UDPSenderFromFile finished sending $fileName")
|
|
||||||
bass.BASS_StreamFree(handle)
|
|
||||||
socket.close()
|
|
||||||
} else callback.accept(false, "Failed to open file $fileName for reading")
|
|
||||||
} catch (e : Exception){
|
|
||||||
callback.accept(false, "Error in UDPSenderFromFile: ${e.message}")
|
|
||||||
isRunning = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} else callback.accept(false, "UDP Sender not initialized, check file and target IP/Port")
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Stop(){
|
|
||||||
isRunning = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,6 +7,7 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.tinylog.Logger
|
import org.tinylog.Logger
|
||||||
|
import java.io.PipedOutputStream
|
||||||
import java.net.DatagramPacket
|
import java.net.DatagramPacket
|
||||||
import java.net.DatagramSocket
|
import java.net.DatagramSocket
|
||||||
import java.net.InetSocketAddress
|
import java.net.InetSocketAddress
|
||||||
@@ -23,8 +24,35 @@ class BarixConnection(val index: UInt, var channel: String, val ipaddress: Strin
|
|||||||
private val inet = InetSocketAddress(ipaddress, port)
|
private val inet = InetSocketAddress(ipaddress, port)
|
||||||
private val maxUDPsize = 1000
|
private val maxUDPsize = 1000
|
||||||
private var _tcp: Socket? = null
|
private var _tcp: Socket? = null
|
||||||
|
private val PipeOuts = mutableMapOf<String,PipedOutputStream>()
|
||||||
|
|
||||||
|
fun AddPipeOut(key: String, pipeOut: PipedOutputStream) {
|
||||||
|
RemovePipeOut(key)
|
||||||
|
PipeOuts[key] = pipeOut
|
||||||
|
}
|
||||||
|
|
||||||
|
fun RemovePipeOut(key: String) {
|
||||||
|
if (PipeOuts.contains(key)){
|
||||||
|
val pipe = PipeOuts[key]
|
||||||
|
try {
|
||||||
|
pipe?.close()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
PipeOuts.remove(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ClearPipeOuts() {
|
||||||
|
PipeOuts.values.forEach { piped ->
|
||||||
|
try {
|
||||||
|
piped.close()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PipeOuts.clear()
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Buffer remain in bytes
|
* Buffer remain in bytes
|
||||||
*/
|
*/
|
||||||
@@ -113,10 +141,20 @@ class BarixConnection(val index: UInt, var channel: String, val ipaddress: Strin
|
|||||||
//println("Buffer remain: $bufferRemain, sending chunk size: ${chunk.size}")
|
//println("Buffer remain: $bufferRemain, sending chunk size: ${chunk.size}")
|
||||||
while(bufferRemain<chunk.size){
|
while(bufferRemain<chunk.size){
|
||||||
delay(10)
|
delay(10)
|
||||||
//println("Waiting until buffer enough..")
|
|
||||||
}
|
}
|
||||||
udp.send(DatagramPacket(chunk, chunk.size, inet))
|
udp.send(DatagramPacket(chunk, chunk.size, inet))
|
||||||
delay(2)
|
delay(2)
|
||||||
|
PipeOuts.keys.forEach { kk ->
|
||||||
|
val pp = PipeOuts[kk]
|
||||||
|
try {
|
||||||
|
pp?.write(chunk)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Logger.error { "Failed to write to pipeOut $kk, message: ${e.message}" }
|
||||||
|
pp?.close()
|
||||||
|
PipeOuts.remove(kk)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
cbFail.accept("SendData to $ipaddress failed, message: ${e.message}")
|
cbFail.accept("SendData to $ipaddress failed, message: ${e.message}")
|
||||||
return@launch
|
return@launch
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
package codes
|
|
||||||
|
|
||||||
@Suppress("unused")
|
|
||||||
interface QuadConsumer<A,B,C,D> {
|
|
||||||
/**
|
|
||||||
* Performs this operation on the given arguments.
|
|
||||||
*
|
|
||||||
* @param a the first input argument
|
|
||||||
* @param b the second input argument
|
|
||||||
* @param c the third input argument
|
|
||||||
* @param d the fourth input argument
|
|
||||||
*/
|
|
||||||
fun accept(a: A, b: B, c: C, d: D)
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package codes
|
|
||||||
|
|
||||||
@Suppress("unused")
|
|
||||||
interface TriConsumer<A,B,C> {
|
|
||||||
/**
|
|
||||||
* Performs this operation on the given arguments.
|
|
||||||
*
|
|
||||||
* @param a the first input argument
|
|
||||||
* @param b the second input argument
|
|
||||||
* @param c the third input argument
|
|
||||||
*/
|
|
||||||
fun accept(a: A, b: B, c: C)
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package web
|
package web
|
||||||
|
|
||||||
import StreamerOutputs
|
import StreamerOutputs
|
||||||
|
import barix.BarixConnection
|
||||||
import codes.Somecodes
|
import codes.Somecodes
|
||||||
import codes.Somecodes.Companion.GetSensorsInfo
|
import codes.Somecodes.Companion.GetSensorsInfo
|
||||||
import codes.Somecodes.Companion.GetUptime
|
import codes.Somecodes.Companion.GetUptime
|
||||||
@@ -46,6 +47,8 @@ import java.time.LocalDateTime
|
|||||||
import codes.configKeys
|
import codes.configKeys
|
||||||
import org.tinylog.Logger
|
import org.tinylog.Logger
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.io.PipedInputStream
|
||||||
|
import java.io.PipedOutputStream
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
|
||||||
|
|
||||||
@@ -188,7 +191,9 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
println("Error processing WebSocket message: ${e.message}")
|
if (e.message!=null && (e.message is String) && e.message!!.isNotEmpty()) {
|
||||||
|
Logger.error { "Error processing WebSocket message: ${e.message}" }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -234,6 +239,36 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
|
|||||||
before { CheckUsers(it) }
|
before { CheckUsers(it) }
|
||||||
}
|
}
|
||||||
path("api") {
|
path("api") {
|
||||||
|
path("LiveAudio"){
|
||||||
|
get("Open/{broadcastzone}"){ ctx ->
|
||||||
|
val param = ctx.pathParam("broadcastzone")
|
||||||
|
if (param.isNotEmpty()){
|
||||||
|
val bc = Get_Barix_Connection_by_ZoneName(param)
|
||||||
|
if (bc!=null){
|
||||||
|
val key = ctx.req().remoteAddr+":"+ctx.req().remotePort
|
||||||
|
val pipeIN = PipedInputStream(8192)
|
||||||
|
val pipeOUT = PipedOutputStream(pipeIN)
|
||||||
|
bc.AddPipeOut(key,pipeOUT)
|
||||||
|
ctx.contentType("audio/wav")
|
||||||
|
ctx.header("Cache-Control", "no-cache")
|
||||||
|
ctx.header("Connection", "keep-alive")
|
||||||
|
ctx.result(pipeIN)
|
||||||
|
} else ctx.status(400).result(objectmapper.writeValueAsString(resultMessage("Broadcastzone not found")))
|
||||||
|
} else ctx.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid broadcastzone")))
|
||||||
|
|
||||||
|
}
|
||||||
|
get("Close/{broadcastzone}"){ ctx ->
|
||||||
|
val param = ctx.pathParam("broadcastzone")
|
||||||
|
if (param.isNotEmpty()){
|
||||||
|
val bc = Get_Barix_Connection_by_ZoneName(param)
|
||||||
|
if (bc!=null){
|
||||||
|
val key = ctx.req().remoteAddr+":"+ctx.req().remotePort
|
||||||
|
bc.RemovePipeOut(key)
|
||||||
|
ctx.result(objectmapper.writeValueAsString(resultMessage("OK")))
|
||||||
|
} else ctx.status(400).result(objectmapper.writeValueAsString(resultMessage("Broadcastzone not found")))
|
||||||
|
} else ctx.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid broadcastzone")))
|
||||||
|
}
|
||||||
|
}
|
||||||
path("VoiceType") {
|
path("VoiceType") {
|
||||||
get {
|
get {
|
||||||
it.result(objectmapper.writeValueAsString(VoiceType.entries.map { vt -> vt.name }))
|
it.result(objectmapper.writeValueAsString(VoiceType.entries.map { vt -> vt.name }))
|
||||||
@@ -2001,6 +2036,20 @@ fun CheckUsers(ctx: Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Get_Barix_Connection_by_ZoneName(zonename: String) : BarixConnection? {
|
||||||
|
if (ValidString(zonename)){
|
||||||
|
val bz = db.broadcastDB.List.find{ it.description == zonename }
|
||||||
|
val sc = if (bz!=null) db.soundchannelDB.List.find { it.channel == bz.SoundChannel } else null
|
||||||
|
val ip = sc?.ip ?: ""
|
||||||
|
if (ValidIPV4(ip)){
|
||||||
|
// ketemu ip-nya
|
||||||
|
return StreamerOutputs[ip]
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
fun Stop() {
|
fun Stop() {
|
||||||
app?.stop()
|
app?.stop()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user