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);
 | 
						||
    }
 | 
						||
} |