398 lines
12 KiB
JavaScript
398 lines
12 KiB
JavaScript
import DWindow from "./window.js";
|
||
import { AddCell, FilterCell, memory, RemoveCell } from "./sdb.js";
|
||
|
||
export const InputDevicesWindow = new class InputDevicesWindow extends DWindow{
|
||
constructor(){
|
||
super();
|
||
this.initContent();
|
||
this.headtext.text("Giriş Aygıtları");
|
||
this.hide();
|
||
this.panel.css("min-width","640px");
|
||
this.panel.css("min-height","250px");
|
||
this.panel.css("width","max-content");
|
||
this.initEvent();
|
||
}
|
||
/**
|
||
* @type {JQuery<HTMLElement>}
|
||
*/
|
||
table = null;
|
||
initContent(){
|
||
this.table = $(`
|
||
<table class="table table-sm table-bordered table-striped text-nowrap">
|
||
<thead>
|
||
<tr>
|
||
<th>Cihaz Türü</th>
|
||
<th>Sağlanan Kanallar</th>
|
||
<th>Akış ID</th>
|
||
<th></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
</tbody>
|
||
<tfoot>
|
||
<tr>
|
||
<td colspan="4">
|
||
<button class="btn btn-success w-100 newdevice">
|
||
Yeni Giriş Cihazı Ekle
|
||
</button>
|
||
</td>
|
||
</tr>
|
||
</tfoot>
|
||
</table>
|
||
`);
|
||
|
||
this.updateDevices();
|
||
|
||
this.content.append(this.table);
|
||
}
|
||
initEvent(){
|
||
this.content.find(".newdevice").on('click', this.generateDevice.bind(this));
|
||
this.addEventListener("close",()=>{
|
||
this.hide();
|
||
})
|
||
}
|
||
updateDevices(){
|
||
let tbody = this.table.find("tbody");
|
||
tbody.text('');
|
||
for (const cell of FilterCell("rawstream", () => true))
|
||
{
|
||
let tr = $(`
|
||
<tr class="text-nowrap">
|
||
<td>${cell.source}</td>
|
||
<td>${cell.kind}</td>
|
||
<td>${cell.payload.id}</td>
|
||
<td>
|
||
<button class="btn btn-outline-primary action-view">Görüntüle</button>
|
||
<button class="btn btn-outline-danger action-close">Kapat</button>
|
||
</td>
|
||
</tr>
|
||
`);
|
||
tr.attr("data-declare", cell.payload.id);
|
||
cell.addEventListener("stop",() => tr.remove());
|
||
tbody.append(tr);
|
||
}
|
||
tbody.find(".action-view").on('click', e => this.viewSource($(e.target)));
|
||
tbody.find(".action-close").on('click', e => this.closeSource($(e.target)));
|
||
}
|
||
closeSource(btn){
|
||
let streamid = btn.closest("tr").attr("data-declare");
|
||
for (const brain of FilterCell("rawstream",e => e.payload.id == streamid)) {
|
||
brain.stop();
|
||
}
|
||
}
|
||
viewSource(btn){
|
||
let streamid = btn.closest("tr").attr("data-declare");
|
||
/**
|
||
* @type {MediaStream}
|
||
*/
|
||
let p = null;
|
||
for (const rawstream of FilterCell("rawstream",e => e.payload.id == streamid)) {
|
||
p = rawstream.payload;
|
||
}
|
||
|
||
let modal = new ViewSourceDialog(p.getTracks()[0]);
|
||
modal.enableDialog(this);
|
||
modal.bringToFront();
|
||
}
|
||
generateDevice(){
|
||
let modal = new AddDeviceDialog();
|
||
modal.enableDialog(this);
|
||
modal.bringToFront();
|
||
modal.addEventListener("stream:added",()=>{
|
||
this.updateDevices();
|
||
});
|
||
}
|
||
}
|
||
|
||
class StreamRecord extends EventTarget {
|
||
lockedby = 0;
|
||
stop(){
|
||
this.payload.getTracks().forEach(e => e.stop());
|
||
this.dispatchEvent(new Event("stop"));
|
||
}
|
||
isLocked(){
|
||
return this.lockedby != 0;
|
||
}
|
||
lock(){
|
||
this.lockedby++;
|
||
}
|
||
unlock(){
|
||
this.lockedby--;
|
||
}
|
||
}
|
||
|
||
class AddDeviceDialog extends DWindow {
|
||
constructor(){
|
||
super();
|
||
this.initContent();
|
||
this.headtext.text("Aygıt Ekleme Sihirbazı");
|
||
this.addEventListener('close',()=>{
|
||
this.disableDialog();
|
||
this.exit();
|
||
})
|
||
}
|
||
initContent(){
|
||
let table = $(`
|
||
<div style="display:flex;flex-direction:column;gap:5px">
|
||
<button class="btn btn-success w-100 action-sdcam">
|
||
SD Kamara Ekle
|
||
</button>
|
||
|
||
<button class="btn btn-success w-100 action-hdcam">
|
||
HD Kamara Ekle
|
||
</button>
|
||
|
||
<button class="btn btn-success w-100 action-mic">
|
||
Mikrofon Ekle
|
||
</button>
|
||
|
||
<button class="btn btn-success w-100 action-displaycam">
|
||
Ekran Görüntüsü Ekle
|
||
</button>
|
||
</div>
|
||
`);
|
||
|
||
table.find(".action-sdcam").on("click",this.sdcam.bind(this));
|
||
table.find(".action-hdcam").on("click",this.hdcam.bind(this));
|
||
table.find(".action-mic").on("click",this.mic.bind(this));
|
||
table.find(".action-displaycam").on("click",this.displaycam.bind(this));
|
||
this.content.append(table);
|
||
}
|
||
|
||
async sdcam(){
|
||
let stream = await navigator.mediaDevices.getUserMedia({
|
||
video: {
|
||
advanced: [
|
||
{ width: { exact: 640 } },
|
||
{ width: { exact: 320 } },
|
||
{ width: { exact: 240 } }
|
||
],
|
||
facingMode: "user"
|
||
}
|
||
});
|
||
|
||
AddCell("rawstream", new class extends StreamRecord {
|
||
source = "Kamera";
|
||
kind = "Görüntü";
|
||
payload = stream;
|
||
constructor(){
|
||
super();
|
||
this.onEnded(() => {
|
||
this.dispatchEvent(new Event("stop"));
|
||
})
|
||
this.addEventListener("stop",() => {
|
||
RemoveCell("rawstream",cell => {
|
||
return cell.payload.id == stream.id
|
||
})
|
||
})
|
||
}
|
||
onEnded(event){
|
||
/** @type {MediaStreamTrack} */
|
||
let track;
|
||
stream.getVideoTracks().forEach(e => track = e);
|
||
if(track)
|
||
{
|
||
track.addEventListener("ended",event);
|
||
}
|
||
}
|
||
});
|
||
this.dispatchEvent(new Event("stream:added"));
|
||
this.disableDialog();
|
||
this.exit();
|
||
}
|
||
async hdcam(){
|
||
let stream = await navigator.mediaDevices.getUserMedia({
|
||
video: {
|
||
advanced: [
|
||
{ width: { exact: 1920 } },
|
||
{ width: { exact: 1600 } },
|
||
{ width: { exact: 1366 } },
|
||
{ width: { exact: 1280 } },
|
||
{ width: { exact: 1024 } },
|
||
{ width: { exact: 900 } },
|
||
{ width: { exact: 800 } },
|
||
{ width: { exact: 640 } },
|
||
{ width: { exact: 320 } },
|
||
{ width: { exact: 240 } }
|
||
],
|
||
facingMode: "user"
|
||
}
|
||
});
|
||
AddCell("rawstream", new class extends StreamRecord {
|
||
source = "Kamera";
|
||
kind = "Görüntü";
|
||
payload = stream;
|
||
constructor(){
|
||
super();
|
||
this.onEnded(() => {
|
||
this.dispatchEvent(new Event("stop"));
|
||
})
|
||
this.addEventListener("stop",() => {
|
||
RemoveCell("rawstream",cell => {
|
||
return cell.payload.id == stream.id
|
||
})
|
||
})
|
||
}
|
||
onEnded(event){
|
||
/** @type {MediaStreamTrack} */
|
||
let track;
|
||
stream.getVideoTracks().forEach(e => track = e);
|
||
if(track)
|
||
{
|
||
track.addEventListener("ended",event);
|
||
}
|
||
}
|
||
});
|
||
this.dispatchEvent(new Event("stream:added"));
|
||
this.disableDialog();
|
||
this.exit();
|
||
}
|
||
async mic(){
|
||
let stream = await navigator.mediaDevices.getUserMedia({
|
||
audio: true
|
||
});
|
||
AddCell("rawstream", new class extends StreamRecord {
|
||
source = "Kamera";
|
||
kind = "Ses";
|
||
payload = stream;
|
||
constructor(){
|
||
super();
|
||
this.onEnded(() => {
|
||
this.dispatchEvent(new Event("stop"));
|
||
})
|
||
this.addEventListener("stop",() => {
|
||
RemoveCell("rawstream",cell => {
|
||
return cell.payload.id == stream.id
|
||
})
|
||
})
|
||
}
|
||
onEnded(event){
|
||
/** @type {MediaStreamTrack} */
|
||
let track;
|
||
stream.getAudioTracks().forEach(e => track = e);
|
||
if(track)
|
||
{
|
||
track.addEventListener("ended",event);
|
||
}
|
||
}
|
||
});
|
||
this.dispatchEvent(new Event("stream:added"));
|
||
this.disableDialog();
|
||
this.exit();
|
||
}
|
||
async displaycam(){
|
||
let stream = await navigator.mediaDevices.getDisplayMedia({
|
||
video: true
|
||
});
|
||
AddCell("rawstream", new class extends StreamRecord{
|
||
source = "Ekran";
|
||
kind = "Görüntü";
|
||
payload = stream;
|
||
constructor(){
|
||
super();
|
||
this.onEnded(() => {
|
||
this.dispatchEvent(new Event("stop"));
|
||
})
|
||
this.addEventListener("stop",() => {
|
||
RemoveCell("rawstream",cell => {
|
||
return cell.payload.id == stream.id
|
||
})
|
||
})
|
||
}
|
||
onEnded(event){
|
||
/** @type {MediaStreamTrack} */
|
||
let track;
|
||
stream.getTracks().forEach(e => track = e);
|
||
if(track)
|
||
{
|
||
track.addEventListener("ended",event);
|
||
}
|
||
}
|
||
});
|
||
this.dispatchEvent(new Event("stream:added"));
|
||
this.disableDialog();
|
||
this.exit();
|
||
}
|
||
}
|
||
class ViewSourceDialog extends DWindow {
|
||
/**
|
||
* @type {MediaStreamTrack}
|
||
*/
|
||
track = null;
|
||
extra = {};
|
||
constructor(track){
|
||
super();
|
||
this.headtext.text("Giriş Kaynağı Görüntüleme");
|
||
this.addEventListener('close',()=>{
|
||
this.disableDialog();
|
||
this.exit();
|
||
})
|
||
this.track = track;
|
||
this.initContent();
|
||
}
|
||
initContent(){
|
||
if(this.track.kind == "video")
|
||
{
|
||
this.initVideoContent();
|
||
}else{
|
||
this.initAudioContent();
|
||
}
|
||
this.table = $(`<table class="table">
|
||
<tbody>
|
||
<tr>
|
||
<td>Track ID</td>
|
||
<td>${this.track.id}</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Data Type</td>
|
||
<td>${this.track.kind}</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Status</td>
|
||
<td>${this.track.enabled ? "Active" : "Passive"}</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Track Label</td>
|
||
<td>${this.track.label}</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>`);
|
||
this.content.append(this.table);
|
||
}
|
||
initVideoContent(){
|
||
let player = $(`<video
|
||
style="height: 450px"
|
||
controls
|
||
/>`);
|
||
let stream = new MediaStream();
|
||
stream.addTrack(this.track);
|
||
player.on('canplay', e => e.target.play());
|
||
player.get(0).srcObject = stream;
|
||
this.content.append(player);
|
||
player.on('play', e => {
|
||
this.table.find("tbody").append(`
|
||
<tr>
|
||
<td>Video Width</td>
|
||
<td>${e.target.videoWidth}px</td>
|
||
</tr>
|
||
`);
|
||
this.table.find("tbody").append(`
|
||
<tr>
|
||
<td>Video Height</td>
|
||
<td>${e.target.videoHeight}px</td>
|
||
</tr>
|
||
`);
|
||
});
|
||
}
|
||
initAudioContent(){
|
||
let player = $(`<audio
|
||
style="width: 500px"
|
||
controls
|
||
/>`);
|
||
let stream = new MediaStream();
|
||
stream.addTrack(this.track);
|
||
player.get(0).srcObject = stream;
|
||
player.on('canplay', e => e.target.play());
|
||
this.content.append(player);
|
||
}
|
||
} |